Booster for WooCommerce - Version 5.6.0

Version Description

29/06/2022 =

  • FIXED - PRICES & CURRENCIES - Wholesale Price - Fixed debug.log warning.
  • FIXED - PAYMENT GATEWAYS - Gateways Fees and Discounts - Updated the payment fee calculation.
  • FIXED - PRODUCTS - User Products - Fixed conflict with product owner notification.
  • FIXED - Added Security vulnerability fixes.
  • WooCommerce 6.6.1 tested
  • WordPress 6.0 tested
Download this release

Release Info

Developer ronyp
Plugin Icon 128x128 Booster for WooCommerce
Version 5.6.0
Comparing to
See all releases

Code changes from version 5.5.9 to 5.6.0

Files changed (57) hide show
  1. includes/add-to-cart/class-wcj-add-to-cart-per-category.php +61 -40
  2. includes/add-to-cart/class-wcj-add-to-cart-per-product-type.php +75 -61
  3. includes/add-to-cart/class-wcj-add-to-cart-per-product.php +121 -110
  4. includes/admin/class-wc-settings-jetpack.php +1041 -1001
  5. includes/admin/class-wcj-settings-custom-fields.php +265 -221
  6. includes/admin/class-wcj-settings-manager.php +134 -125
  7. includes/admin/class-wcj-tools.php +99 -83
  8. includes/admin/class-wcj-welcome.php +110 -100
  9. includes/admin/wcj-modules-cats.php +181 -177
  10. includes/admin/wcj-welcome-screen-content.php +171 -169
  11. includes/background-process/class-wcj-multicurrency-price-updater.php +16 -4
  12. includes/background-process/class-wcj-price-by-country-updater.php +15 -3
  13. includes/class-wcj-add-to-cart-button-visibility.php +192 -175
  14. includes/class-wcj-add-to-cart.php +28 -20
  15. includes/class-wcj-address-formats.php +97 -87
  16. includes/class-wcj-admin-bar.php +590 -563
  17. includes/class-wcj-admin-orders-list.php +355 -339
  18. includes/class-wcj-admin-products-list.php +102 -91
  19. includes/class-wcj-admin-tools.php +314 -281
  20. includes/class-wcj-breadcrumbs.php +75 -66
  21. includes/class-wcj-call-for-price.php +166 -142
  22. includes/class-wcj-cart-customization.php +109 -89
  23. includes/class-wcj-cart.php +73 -60
  24. includes/class-wcj-checkout-core-fields.php +265 -233
  25. includes/class-wcj-checkout-custom-fields.php +600 -550
  26. includes/class-wcj-checkout-custom-info.php +51 -42
  27. includes/class-wcj-checkout-customization.php +259 -235
  28. includes/class-wcj-checkout-fees.php +237 -220
  29. includes/class-wcj-checkout-files-upload.php +872 -705
  30. includes/class-wcj-coupon-by-user-role.php +99 -76
  31. includes/class-wcj-coupon-code-generator.php +123 -112
  32. includes/class-wcj-cross-sells.php +198 -172
  33. includes/class-wcj-crowdfunding.php +74 -63
  34. includes/class-wcj-currency-exchange-rates.php +246 -222
  35. includes/class-wcj-currency-external-products.php +38 -32
  36. includes/class-wcj-currency-per-product.php +252 -243
  37. includes/class-wcj-currency.php +176 -161
  38. includes/class-wcj-custom-css.php +70 -64
  39. includes/class-wcj-custom-js.php +47 -42
  40. includes/class-wcj-custom-php.php +74 -61
  41. includes/class-wcj-debug-tools.php +91 -82
  42. includes/class-wcj-email-options.php +152 -136
  43. includes/class-wcj-emails-verification.php +270 -206
  44. includes/class-wcj-emails.php +127 -101
  45. includes/class-wcj-empty-cart-button.php +65 -54
  46. includes/class-wcj-eu-vat-number.php +569 -516
  47. includes/class-wcj-export-import.php +338 -311
  48. includes/class-wcj-free-price.php +155 -137
  49. includes/class-wcj-general.php +240 -208
  50. includes/class-wcj-global-discount.php +386 -351
  51. includes/class-wcj-left-to-free-shipping.php +79 -73
  52. includes/class-wcj-max-products-per-user.php +330 -290
  53. includes/class-wcj-mini-cart.php +46 -41
  54. includes/class-wcj-modules-by-user-roles.php +22 -17
  55. includes/class-wcj-more-button-labels.php +45 -38
  56. includes/class-wcj-multicurrency-product-base-price.php +130 -101
  57. includes/class-wcj-multicurrency.php +743 -692
includes/add-to-cart/class-wcj-add-to-cart-per-category.php CHANGED
@@ -4,61 +4,82 @@
4
  *
5
  * @version 2.2.6
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Add_To_Cart_Per_Category' ) ) :
12
-
13
- class WCJ_Add_To_Cart_Per_Category {
14
-
15
  /**
16
- * Constructor.
17
  */
18
- function __construct() {
19
- if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_per_category_enabled' ) ) {
20
- add_filter( 'woocommerce_product_single_add_to_cart_text', array( $this, 'change_add_to_cart_button_text_single' ), PHP_INT_MAX );
21
- add_filter( 'woocommerce_product_add_to_cart_text', array( $this, 'change_add_to_cart_button_text_archive' ), PHP_INT_MAX );
 
 
 
 
 
 
22
  }
23
- }
24
 
25
- /**
26
- * change_add_to_cart_button_text_single.
27
- */
28
- function change_add_to_cart_button_text_single( $add_to_cart_text ) {
29
- return $this->change_add_to_cart_button_text( $add_to_cart_text, 'single' );
30
- }
 
 
31
 
32
- /**
33
- * change_add_to_cart_button_text_archive.
34
- */
35
- function change_add_to_cart_button_text_archive( $add_to_cart_text ) {
36
- return $this->change_add_to_cart_button_text( $add_to_cart_text, 'archive' );
37
- }
 
 
38
 
39
- /**
40
- * change_add_to_cart_button_text.
41
- *
42
- * @version 2.2.6
43
- */
44
- function change_add_to_cart_button_text( $add_to_cart_text, $single_or_archive ) {
45
- $product_categories = get_the_terms( get_the_ID(), 'product_cat' );
46
- if ( empty( $product_categories ) ) return $add_to_cart_text;
47
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_add_to_cart_per_category_total_groups_number', 1 ) ); $i++ ) {
48
- if ( 'yes' !== wcj_get_option( 'wcj_add_to_cart_per_category_enabled_group_' . $i ) ) continue;
49
- $categories = wcj_get_option( 'wcj_add_to_cart_per_category_ids_group_' . $i );
50
- if ( empty( $categories ) ) continue;
51
- foreach ( $product_categories as $product_category ) {
52
- foreach ( $categories as $category ) {
53
- if ( $product_category->term_id == $category ) {
54
- return wcj_get_option( 'wcj_add_to_cart_per_category_text_' . $single_or_archive . '_group_' . $i, $add_to_cart_text );
 
 
 
 
 
 
 
 
 
 
 
 
 
55
  }
56
  }
57
  }
 
58
  }
59
- return $add_to_cart_text;
60
  }
61
- }
62
 
63
  endif;
64
 
4
  *
5
  * @version 2.2.6
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Add_To_Cart_Per_Category' ) ) :
 
 
 
15
  /**
16
+ * WCJ_Add_To_Cart_Per_Category.
17
  */
18
+ class WCJ_Add_To_Cart_Per_Category {
19
+
20
+ /**
21
+ * Constructor.
22
+ */
23
+ public function __construct() {
24
+ if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_per_category_enabled' ) ) {
25
+ add_filter( 'woocommerce_product_single_add_to_cart_text', array( $this, 'change_add_to_cart_button_text_single' ), PHP_INT_MAX );
26
+ add_filter( 'woocommerce_product_add_to_cart_text', array( $this, 'change_add_to_cart_button_text_archive' ), PHP_INT_MAX );
27
+ }
28
  }
 
29
 
30
+ /**
31
+ * Change_add_to_cart_button_text_single.
32
+ *
33
+ * @param string $add_to_cart_text Add to cart button text change.
34
+ */
35
+ public function change_add_to_cart_button_text_single( $add_to_cart_text ) {
36
+ return $this->change_add_to_cart_button_text( $add_to_cart_text, 'single' );
37
+ }
38
 
39
+ /**
40
+ * Change_add_to_cart_button_text_archive.
41
+ *
42
+ * @param string $add_to_cart_text Add to cart button text change.
43
+ */
44
+ public function change_add_to_cart_button_text_archive( $add_to_cart_text ) {
45
+ return $this->change_add_to_cart_button_text( $add_to_cart_text, 'archive' );
46
+ }
47
 
48
+ /**
49
+ * Change_add_to_cart_button_text.
50
+ *
51
+ * @param string $add_to_cart_text Add to cart button text change.
52
+ * @param string $single_or_archive Get single or archive product.
53
+ *
54
+ * @version 2.2.6
55
+ */
56
+ public function change_add_to_cart_button_text( $add_to_cart_text, $single_or_archive ) {
57
+ $product_categories = get_the_terms( get_the_ID(), 'product_cat' );
58
+ if ( empty( $product_categories ) ) {
59
+ return $add_to_cart_text;
60
+ }
61
+ $category_total_groups_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_add_to_cart_per_category_total_groups_number', 1 ) );
62
+ for ( $i = 1; $i <= $category_total_groups_number; $i++ ) {
63
+ if ( 'yes' !== wcj_get_option( 'wcj_add_to_cart_per_category_enabled_group_' . $i ) ) {
64
+ continue;
65
+ }
66
+ $categories = wcj_get_option( 'wcj_add_to_cart_per_category_ids_group_' . $i );
67
+ if ( empty( $categories ) ) {
68
+ continue;
69
+ }
70
+ foreach ( $product_categories as $product_category ) {
71
+ foreach ( $categories as $category ) {
72
+ settype( $product_category->term_id, 'string' );
73
+
74
+ if ( $product_category->term_id === $category ) {
75
+ return wcj_get_option( 'wcj_add_to_cart_per_category_text_' . $single_or_archive . '_group_' . $i, $add_to_cart_text );
76
+ }
77
  }
78
  }
79
  }
80
+ return $add_to_cart_text;
81
  }
 
82
  }
 
83
 
84
  endif;
85
 
includes/add-to-cart/class-wcj-add-to-cart-per-product-type.php CHANGED
@@ -4,87 +4,101 @@
4
  *
5
  * @version 4.2.0
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Add_To_Cart_Per_Product_Type' ) ) :
12
-
13
- class WCJ_Add_To_Cart_Per_Product_Type {
14
-
15
- /**
16
- * Constructor.
17
- *
18
- * @version 3.4.0
19
- */
20
- function __construct() {
21
- if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_text_enabled', 'no' ) ) {
22
- add_filter( 'woocommerce_product_single_add_to_cart_text', array( $this, 'custom_add_to_cart_button_text' ), 100 );
23
- add_filter( 'woocommerce_product_add_to_cart_text', array( $this, 'custom_add_to_cart_button_text' ), 100 );
 
 
 
 
 
24
  }
25
- }
26
 
27
- /**
28
- * custom_add_to_cart_button_text.
29
- *
30
- * @version 4.2.0
31
- * @todo (maybe) add checkbox options to enable/disable custom labels for each product type (or even for each label)
32
- */
33
- function custom_add_to_cart_button_text( $add_to_cart_text ) {
 
34
 
35
- global $woocommerce, $product;
36
- $product = is_string( $product ) ? wc_get_product( get_the_ID() ) : $product;
37
 
38
- if ( ! $product || is_string( $product ) ) {
39
- return $add_to_cart_text;
40
- }
41
 
42
- $product_type = ( WCJ_IS_WC_VERSION_BELOW_3 ? $product->product_type : $product->get_type() );
43
- if ( ! in_array( $product_type, array( 'external', 'grouped', 'simple', 'variable' ) ) ) {
44
- $product_type = 'other';
45
- }
46
 
47
- $single_or_archive = ( 'woocommerce_product_single_add_to_cart_text' == current_filter() ? 'single' : 'archives' );
48
 
49
- // Already in cart
50
- if ( '' != ( $text_already_in_cart = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_in_cart_' . $product_type, '' ) ) && isset( $woocommerce->cart ) ) {
51
- foreach( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
52
- $_product = $values['data'];
53
- if( get_the_ID() == wcj_get_product_id_or_variation_parent_id( $_product ) ) {
54
- return do_shortcode( $text_already_in_cart );
 
 
55
  }
56
  }
57
- }
58
 
59
- // Not in stock
60
- if ( '' != ( $text_on_not_in_stock = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_not_in_stock_' . $product_type, '' ) ) && ! $product->is_in_stock() ) {
61
- return do_shortcode( $text_on_not_in_stock );
62
- }
 
63
 
64
- // On sale
65
- if ( '' != ( $text_on_sale = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_sale_' . $product_type, '' ) ) && $product->is_on_sale() ) {
66
- return do_shortcode( $text_on_sale );
67
- }
 
68
 
69
- // Empty price
70
- if ( '' != ( $text_on_no_price = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_no_price_' . $product_type, '' ) ) && '' === $product->get_price() ) {
71
- return do_shortcode( $text_on_no_price );
72
- }
 
73
 
74
- // Free (i.e. zero price)
75
- if ( '' != ( $text_on_zero_price = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_zero_price_' . $product_type, '' ) ) && 0 == $product->get_price() ) {
76
- return do_shortcode( $text_on_zero_price );
77
- }
 
78
 
79
- // General
80
- if ( '' != ( $text_general = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_' . $product_type, '' ) ) ) {
81
- return do_shortcode( $text_general );
82
- }
 
83
 
84
- // Default
85
- return $add_to_cart_text;
 
86
  }
87
- }
88
 
89
  endif;
90
 
4
  *
5
  * @version 4.2.0
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Add_To_Cart_Per_Product_Type' ) ) :
15
+ /**
16
+ * WCJ_Add_To_Cart_Per_Product_Type.
17
+ *
18
+ * @version 3.4.0
19
+ */
20
+ class WCJ_Add_To_Cart_Per_Product_Type {
21
+
22
+ /**
23
+ * Constructor.
24
+ *
25
+ * @version 3.4.0
26
+ */
27
+ public function __construct() {
28
+ if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_text_enabled', 'no' ) ) {
29
+ add_filter( 'woocommerce_product_single_add_to_cart_text', array( $this, 'custom_add_to_cart_button_text' ), 100 );
30
+ add_filter( 'woocommerce_product_add_to_cart_text', array( $this, 'custom_add_to_cart_button_text' ), 100 );
31
+ }
32
  }
 
33
 
34
+ /**
35
+ * Custom_add_to_cart_button_text.
36
+ *
37
+ * @version 4.2.0
38
+ * @todo (maybe) add checkbox options to enable/disable custom labels for each product type (or even for each label)
39
+ * @param string $add_to_cart_text Add to cart button text change.
40
+ */
41
+ public function custom_add_to_cart_button_text( $add_to_cart_text ) {
42
 
43
+ global $woocommerce, $product;
44
+ $product = is_string( $product ) ? wc_get_product( get_the_ID() ) : $product;
45
 
46
+ if ( ! $product || is_string( $product ) ) {
47
+ return $add_to_cart_text;
48
+ }
49
 
50
+ $product_type = ( WCJ_IS_WC_VERSION_BELOW_3 ? $product->product_type : $product->get_type() );
51
+ if ( ! in_array( $product_type, array( 'external', 'grouped', 'simple', 'variable' ), true ) ) {
52
+ $product_type = 'other';
53
+ }
54
 
55
+ $single_or_archive = ( 'woocommerce_product_single_add_to_cart_text' === current_filter() ? 'single' : 'archives' );
56
 
57
+ // Already in cart.
58
+ $text_already_in_cart = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_in_cart_' . $product_type, '' );
59
+ if ( '' !== ( $text_already_in_cart ) && isset( $woocommerce->cart ) ) {
60
+ foreach ( $woocommerce->cart->get_cart() as $cart_item_key => $values ) {
61
+ $_product = $values['data'];
62
+ if ( get_the_ID() === wcj_get_product_id_or_variation_parent_id( $_product ) ) {
63
+ return do_shortcode( $text_already_in_cart );
64
+ }
65
  }
66
  }
 
67
 
68
+ // Not in stock.
69
+ $text_on_not_in_stock = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_not_in_stock_' . $product_type, '' );
70
+ if ( '' !== ( $text_on_not_in_stock ) && ! $product->is_in_stock() ) {
71
+ return do_shortcode( $text_on_not_in_stock );
72
+ }
73
 
74
+ // On sale.
75
+ $text_on_sale = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_sale_' . $product_type, '' );
76
+ if ( '' !== ( $text_on_sale ) && $product->is_on_sale() ) {
77
+ return do_shortcode( $text_on_sale );
78
+ }
79
 
80
+ // Empty price.
81
+ $text_on_no_price = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_no_price_' . $product_type, '' );
82
+ if ( '' !== ( $text_on_no_price ) && '' === $product->get_price() ) {
83
+ return do_shortcode( $text_on_no_price );
84
+ }
85
 
86
+ // Free (i.e. zero price).
87
+ $text_on_zero_price = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_zero_price_' . $product_type, '' );
88
+ if ( '' !== ( $text_on_zero_price ) && 0 === $product->get_price() ) {
89
+ return do_shortcode( $text_on_zero_price );
90
+ }
91
 
92
+ // General.
93
+ $text_general = wcj_get_option( 'wcj_add_to_cart_text_on_' . $single_or_archive . '_' . $product_type, '' );
94
+ if ( '' !== ( $text_general ) ) {
95
+ return do_shortcode( $text_general );
96
+ }
97
 
98
+ // Default.
99
+ return $add_to_cart_text;
100
+ }
101
  }
 
102
 
103
  endif;
104
 
includes/add-to-cart/class-wcj-add-to-cart-per-product.php CHANGED
@@ -4,132 +4,143 @@
4
  *
5
  * @version 2.7.0
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Add_To_Cart_Per_Product' ) ) :
12
-
13
- class WCJ_Add_To_Cart_Per_Product {
14
-
15
- /**
16
- * Constructor.
17
- */
18
- function __construct() {
19
- if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_per_product_enabled' ) ) {
20
- add_filter( 'woocommerce_product_single_add_to_cart_text', array( $this, 'change_add_to_cart_button_text_single' ), PHP_INT_MAX );
21
- add_filter( 'woocommerce_product_add_to_cart_text', array( $this, 'change_add_to_cart_button_text_archive' ), PHP_INT_MAX );
22
- add_action( 'add_meta_boxes', array( $this, 'add_custom_add_to_cart_meta_box' ) );
23
- add_action( 'save_post_product', array( $this, 'save_custom_add_to_cart_meta_box' ), 100, 2 );
 
 
 
24
  }
25
- }
26
 
27
- /**
28
- * change_add_to_cart_button_text_single.
29
- */
30
- function change_add_to_cart_button_text_single( $add_to_cart_text ) {
31
- return $this->change_add_to_cart_button_text( $add_to_cart_text, 'single' );
32
- }
 
 
33
 
34
- /**
35
- * change_add_to_cart_button_text_archive.
36
- */
37
- function change_add_to_cart_button_text_archive( $add_to_cart_text ) {
38
- return $this->change_add_to_cart_button_text( $add_to_cart_text, 'archive' );
39
- }
 
 
40
 
41
- /**
42
- * change_add_to_cart_button_text.
43
- *
44
- * @version 2.7.0
45
- */
46
- function change_add_to_cart_button_text( $add_to_cart_text, $single_or_archive ) {
47
- global $product;
48
- if ( ! $product ) {
 
 
 
 
 
 
 
 
 
 
49
  return $add_to_cart_text;
50
  }
51
- $local_custom_add_to_cart_option_id = 'wcj_custom_add_to_cart_local_' . $single_or_archive;
52
- $local_custom_add_to_cart_option_value = get_post_meta( wcj_get_product_id_or_variation_parent_id( $product ), '_' . $local_custom_add_to_cart_option_id, true );
53
- if ( '' != $local_custom_add_to_cart_option_value ) {
54
- return $local_custom_add_to_cart_option_value;
55
- }
56
- return $add_to_cart_text;
57
- }
58
 
59
- /**
60
- * save_custom_add_to_cart_meta_box.
61
- */
62
- function save_custom_add_to_cart_meta_box( $post_id, $post ) {
63
- // Check that we are saving with custom add to cart metabox displayed.
64
- if ( ! isset( $_POST['woojetpack_custom_add_to_cart_save_post'] ) ) {
65
- return;
 
 
 
 
 
 
 
 
66
  }
67
- $option_name = 'wcj_custom_add_to_cart_local_' . 'single';
68
- update_post_meta( $post_id, '_' . $option_name, $_POST[ $option_name ] );
69
- $option_name = 'wcj_custom_add_to_cart_local_' . 'archive';
70
- update_post_meta( $post_id, '_' . $option_name, $_POST[ $option_name ] );
71
- }
72
 
73
- /**
74
- * add_custom_add_to_cart_meta_box.
75
- *
76
- * @version 2.4.8
77
- */
78
- function add_custom_add_to_cart_meta_box() {
79
- add_meta_box(
80
- 'wc-jetpack-custom-add-to-cart',
81
- __( 'Booster: Custom Add to Cart', 'woocommerce-jetpack' ),
82
- array( $this, 'create_custom_add_to_cart_meta_box' ),
83
- 'product',
84
- 'normal',
85
- 'high'
86
- );
87
- }
88
 
89
- /**
90
- * create_custom_add_to_cart_meta_box.
91
- */
92
- function create_custom_add_to_cart_meta_box() {
93
-
94
- $current_post_id = get_the_ID();
95
-
96
- $options = array(
97
- 'single' => __( 'Single product view', 'woocommerce-jetpack' ),
98
- 'archive' => __( 'Product category (archive) view', 'woocommerce-jetpack' ),
99
- );
100
-
101
- $html = '<table style="width:50%;min-width:300px;">';
102
- foreach ( $options as $option_key => $option_desc ) {
103
- $option_type = 'textarea';
104
- if ( 'url' == $option_key )
105
- $option_type = 'text';
106
- $html .= '<tr>';
107
- $html .= '<th>' . $option_desc . '</th>';
108
-
109
- $option_id = 'wcj_custom_add_to_cart_local_' . $option_key;
110
- $option_value = get_post_meta( $current_post_id, '_' . $option_id, true );
111
-
112
- if ( 'textarea' === $option_type )
113
- $html .= '<td style="width:80%;">';
114
- else
115
- $html .= '<td>';
116
- //switch ( $option_type ) {
117
- //case 'number':
118
- //case 'text':
119
- // $html .= '<input style="width:100%;" type="' . $option_type . '" id="' . $option_id . '" name="' . $option_id . '" value="' . $option_value . '">';
120
- // break;
121
- //case 'textarea':
122
- $html .= '<textarea style="width:100%;" id="' . $option_id . '" name="' . $option_id . '">' . $option_value . '</textarea>';
123
- // break;
124
- //}
125
- $html .= '</td>';
126
- $html .= '</tr>';
127
  }
128
- $html .= '</table>';
129
- $html .= '<input type="hidden" name="woojetpack_custom_add_to_cart_save_post" value="woojetpack_custom_add_to_cart_save_post">';
130
- echo $html;
131
  }
132
- }
133
 
134
  endif;
135
 
4
  *
5
  * @version 2.7.0
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Add_To_Cart_Per_Product' ) ) :
15
+ /**
16
+ * WCJ_Add_To_Cart_Per_Product.
17
+ */
18
+ class WCJ_Add_To_Cart_Per_Product {
19
+
20
+ /**
21
+ * Constructor.
22
+ */
23
+ public function __construct() {
24
+ if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_per_product_enabled' ) ) {
25
+ add_filter( 'woocommerce_product_single_add_to_cart_text', array( $this, 'change_add_to_cart_button_text_single' ), PHP_INT_MAX );
26
+ add_filter( 'woocommerce_product_add_to_cart_text', array( $this, 'change_add_to_cart_button_text_archive' ), PHP_INT_MAX );
27
+ add_action( 'add_meta_boxes', array( $this, 'add_custom_add_to_cart_meta_box' ) );
28
+ add_action( 'save_post_product', array( $this, 'save_custom_add_to_cart_meta_box' ), 100, 2 );
29
+ }
30
  }
 
31
 
32
+ /**
33
+ * Change_add_to_cart_button_text_single.
34
+ *
35
+ * @param string $add_to_cart_text Add to cart button text change.
36
+ */
37
+ public function change_add_to_cart_button_text_single( $add_to_cart_text ) {
38
+ return $this->change_add_to_cart_button_text( $add_to_cart_text, 'single' );
39
+ }
40
 
41
+ /**
42
+ * Change_add_to_cart_button_text_archive.
43
+ *
44
+ * @param string $add_to_cart_text Add to cart button text change.
45
+ */
46
+ public function change_add_to_cart_button_text_archive( $add_to_cart_text ) {
47
+ return $this->change_add_to_cart_button_text( $add_to_cart_text, 'archive' );
48
+ }
49
 
50
+ /**
51
+ * Change_add_to_cart_button_text.
52
+ *
53
+ * @param string $add_to_cart_text Add to cart button text change.
54
+ * @param string $single_or_archive Get single or archive product.
55
+ *
56
+ * @version 2.7.0
57
+ */
58
+ public function change_add_to_cart_button_text( $add_to_cart_text, $single_or_archive ) {
59
+ global $product;
60
+ if ( ! $product ) {
61
+ return $add_to_cart_text;
62
+ }
63
+ $local_custom_add_to_cart_option_id = 'wcj_custom_add_to_cart_local_' . $single_or_archive;
64
+ $local_custom_add_to_cart_option_value = get_post_meta( wcj_get_product_id_or_variation_parent_id( $product ), '_' . $local_custom_add_to_cart_option_id, true );
65
+ if ( '' !== $local_custom_add_to_cart_option_value ) {
66
+ return $local_custom_add_to_cart_option_value;
67
+ }
68
  return $add_to_cart_text;
69
  }
 
 
 
 
 
 
 
70
 
71
+ /**
72
+ * Save_custom_add_to_cart_meta_box.
73
+ *
74
+ * @param int $post_id Get post Id.
75
+ * @param Array $post Get post.
76
+ */
77
+ public function save_custom_add_to_cart_meta_box( $post_id, $post ) {
78
+ // Check that we are saving with custom add to cart metabox displayed.
79
+ if ( ! isset( $_POST['woojetpack_custom_add_to_cart_save_post'] ) ) {
80
+ return;
81
+ }
82
+ $option_name = 'wcj_custom_add_to_cart_local_single';
83
+ ! empty( update_post_meta( $post_id, '_' . $option_name, sanitize_text_field( wp_unslash( $_POST[ $option_name ] ) ) ) );
84
+ $option_name = 'wcj_custom_add_to_cart_local_archive';
85
+ update_post_meta( $post_id, '_' . $option_name, sanitize_text_field( wp_unslash( $_POST[ $option_name ] ) ) );
86
  }
 
 
 
 
 
87
 
88
+ /**
89
+ * Add_custom_add_to_cart_meta_box.
90
+ *
91
+ * @version 2.4.8
92
+ */
93
+ public function add_custom_add_to_cart_meta_box() {
94
+ add_meta_box(
95
+ 'wc-jetpack-custom-add-to-cart',
96
+ __( 'Booster: Custom Add to Cart', 'woocommerce-jetpack' ),
97
+ array( $this, 'create_custom_add_to_cart_meta_box' ),
98
+ 'product',
99
+ 'normal',
100
+ 'high'
101
+ );
102
+ }
103
 
104
+ /**
105
+ * Create_custom_add_to_cart_meta_box.
106
+ */
107
+ public function create_custom_add_to_cart_meta_box() {
108
+
109
+ $current_post_id = get_the_ID();
110
+
111
+ $options = array(
112
+ 'single' => __( 'Single product view', 'woocommerce-jetpack' ),
113
+ 'archive' => __( 'Product category (archive) view', 'woocommerce-jetpack' ),
114
+ );
115
+
116
+ $html = '<table style="width:50%;min-width:300px;">';
117
+ foreach ( $options as $option_key => $option_desc ) {
118
+ $option_type = 'textarea';
119
+ if ( 'url' === $option_key ) {
120
+ $option_type = 'text';
121
+ }
122
+ $html .= '<tr>';
123
+ $html .= '<th>' . $option_desc . '</th>';
124
+
125
+ $option_id = 'wcj_custom_add_to_cart_local_' . $option_key;
126
+ $option_value = get_post_meta( $current_post_id, '_' . $option_id, true );
127
+
128
+ if ( 'textarea' === $option_type ) {
129
+ $html .= '<td style="width:80%;">';
130
+ } else {
131
+ $html .= '<td>';
132
+ }
133
+
134
+ $html .= '<textarea style="width:100%;" id="' . $option_id . '" name="' . $option_id . '">' . $option_value . '</textarea>';
135
+
136
+ $html .= '</td>';
137
+ $html .= '</tr>';
138
+ }
139
+ $html .= '</table>';
140
+ $html .= '<input type="hidden" name="woojetpack_custom_add_to_cart_save_post" value="woojetpack_custom_add_to_cart_save_post">';
141
+ echo $html;
142
  }
 
 
 
143
  }
 
144
 
145
  endif;
146
 
includes/admin/class-wc-settings-jetpack.php CHANGED
@@ -1,1071 +1,1111 @@
1
  <?php
2
-
3
  /**
4
  * Booster for WooCommerce - Settings
5
  *
6
  * @version 5.5.6
7
  * @since 1.0.0
8
  * @author Pluggabl LLC.
 
9
  */
10
 
11
- if (!defined('ABSPATH')) {
12
- exit;
13
  }
14
- // Exit if accessed directly
15
-
16
- if (!class_exists('WC_Settings_Jetpack')) :
17
 
18
- class WC_Settings_Jetpack extends WC_Settings_Page
19
- {
 
 
 
 
 
20
 
21
- /**
22
- * Constructor.
23
- *
24
- * @version 5.3.1
25
- */
26
- public function __construct()
27
- {
28
 
29
- $this->id = 'jetpack';
30
- $this->label = __('Booster', 'woocommerce-jetpack');
 
 
 
 
31
 
32
- $this->cats = include 'wcj-modules-cats.php';
 
33
 
34
- $this->custom_dashboard_modules = apply_filters('wcj_custom_dashboard_modules', array());
35
 
36
- add_filter('woocommerce_settings_tabs_array', array($this, 'add_settings_page'), 20);
37
- add_action('woocommerce_settings_' . $this->id, array($this, 'output'));
38
- add_action('woocommerce_settings_save_' . $this->id, array($this, 'save'));
39
- //add_action('woocommerce_sections_' . $this->id, array($this, 'output_cats_submenu'));
40
- //add_action('woocommerce_sections_' . $this->id, array($this, 'output_sections_submenu'));
41
- add_action('woocommerce_sections_' . $this->id, array($this, 'dasboard_menu'));
42
- // Created New Dashborad desing css
43
- add_action( 'admin_enqueue_scripts', array($this,'wcj_new_desing_dashboard') );
44
 
45
- // Create free version notices
46
- add_action('woocommerce_after_settings_' . $this->id, array($this, 'create_free_version_footer_review_notice'));
47
- add_action('woocommerce_settings_' . $this->id, array($this, 'create_free_version_notice_about_plus'));
48
-
49
 
50
- // Create a PRO version ratting notice
51
- add_action('woocommerce_after_settings_' . $this->id, array($this, 'create_pro_version_footer_review_notice'));
 
52
 
53
- add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_script'));
 
 
54
 
55
- require_once 'class-wcj-settings-custom-fields.php';
56
- }
57
 
58
- /**
59
- * wcj_new_desing_dashboard.
60
- *
61
- * @version 5.5.6
62
- * @since 5.5.6
63
- */
64
-
65
- public function wcj_new_desing_dashboard(){
66
- $page=$_GET['tab'];
67
-
68
- if( $page ==='jetpack'){
69
- wp_enqueue_style('wcj-admin-wcj-new_desing', wcj_plugin_url() . '/includes/css/admin-style.css');
70
- wp_enqueue_script('wcj-admin-script', wcj_plugin_url() . '/includes/js/admin-script.js', array('jquery'), '5.0.0', true);
71
- //wp_enqueue_script('wcj-admin-dasboard-js', wcj_plugin_url() . '/includes/js/wcj-new_desing.js');
72
- }
73
- }
74
 
 
 
75
 
76
-
77
- /**
78
- * create_free_version_notice_about_plus.
79
- *
80
- * @version 5.5.6
81
- * @since 5.3.0
82
- */
83
- public function create_free_version_notice_about_plus()
84
- {
85
- if ('woocommerce-jetpack.php' !== basename(WCJ_PLUGIN_FILE)) {
86
- return;
87
- }
88
- $class = 'notice notice-info';
89
- $message = sprintf(__('You\'re using Booster free version. To unlock more features please consider <a target="_blank" href="%s">Upgrade Booster to unlock this feature</a>.', 'woocommerce-jetpack'), 'https://booster.io/buy-booster/');
90
- $booster_icon = '<span class="wcj-booster-logo"></span>';
91
- ?>
92
- <style>
93
- .wcj-booster-logo { width: 19px; height: 19px; display: inline-block; background: url('https://ps.w.org/woocommerce-jetpack/assets/icon-128x128.png?rev=1813426') center/cover; vertical-align: middle; position: relative; top: -1px; margin: 0 6px 0 0; }
94
- </style>
95
- <?php
96
- echo '<div class="' . $class . '"><p>' . $booster_icon . $message . '</p></div>';
97
- }
98
 
99
- /**
100
- * create_free_version_footer_review_notice.
101
- *
102
- * @version 5.5.6
103
- * @since 5.3.0
104
- */
105
- public function create_free_version_footer_review_notice()
106
- {
107
- if ('woocommerce-jetpack.php' !== basename(WCJ_PLUGIN_FILE)) {
108
- return;
109
- }
110
- $class = 'notice notice-info inline';
111
- $link = 'https://wordpress.org/support/plugin/woocommerce-jetpack/reviews/?filter=5#new-post';
112
- $star = '<span class="wcj-review-icon dashicons dashicons-star-filled"></span>';
113
- $stars_link = '<a href="' . $link . '" target="_blank">' . $star . $star . $star . $star . $star . '</a>';
114
- $message = sprintf(__('Please rate <strong>Booster for WooCommerce</strong> %s on <a href="%s" target="_blank">WordPress.org</a> to help us spread the word. Thank you from Booster team!', 'woocommerce-jetpack'), $stars_link, $link);
115
- ?>
116
- <style>
117
- .wcj-review-icon { vertical-align: middle; margin: -6px 0 0 0; }
118
- </style>
119
- <?php
120
- // echo '<div class="' . $class . '"><p>' . $message . '</p></div>';
121
- }
122
- /**
123
- * create_pro_version_footer_review_notice.
124
- *
125
- * @version 5.5.6
126
- * @since 5.3.1
127
- */
128
- public function create_pro_version_footer_review_notice()
129
- {
130
- $sec_link = wcj_plugin_url();
131
- ?>
132
- <div class="circleBox">
133
- <div class="circle-badge" style="float:right">
134
- <img src="<?php echo $sec_link ?>/assets/images/pop_icon.png">
135
- </div>
136
- <div class="subCircles">
137
- <div class="sub-circle">
138
- <div class="form_label">
139
- <a href="https://booster.io/submit-idea/" target="_blank">
140
- <label>Suggest a feature</label>
141
- <div class="ic_list">
142
- <img src="<?php echo $sec_link ?>/assets/images/suggestion-w.png">
143
- </div>
144
- </a>
145
- </div>
146
- </div>
147
- <div class="sub-circle">
148
- <a href="https://wordpress.org/support/plugin/woocommerce-jetpack/#new-topic-0" target="_blank">
149
- <div class="form_label">
150
- <label>Booster Free Support (72 business hours response)</label>
151
- <div class="ic_list"><img src="<?php echo $sec_link ?>/assets/images/support-3d-w.png"></div>
152
- </div>
153
- </a>
154
- </div>
155
- <div class="sub-circle">
156
- <a href="https://booster.io/my-account/booster-contact/" target="_blank">
157
- <div class="form_label">
158
- <label>Booster Plus Premium Support (4 hours - 24 hours response)</label>
159
- <div class="ic_list"><img src="<?php echo $sec_link ?>/assets/images/support-24-h-w.png"></div>
160
- </div>
161
- </a>
162
- </div>
163
- </div>
164
- </div>
165
- <?php
166
- if ('booster-plus-for-woocommerce.php' !== basename(WCJ_PLUGIN_FILE)) {
167
- return;
168
- }
169
- $class = 'notice notice-info inline';
170
- $link = 'https://wordpress.org/support/plugin/woocommerce-jetpack/reviews/?filter=5#new-post';
171
- $star = '<span class="wcj-review-icon dashicons dashicons-star-filled"></span>';
172
- $stars_link = '<a href="' . $link . '" target="_blank">' . $star . $star . $star . $star . $star . '</a>';
173
- $message = sprintf(__('Please rate <strong>Booster for WooCommerce</strong> %s on <a href="%s" target="_blank">WordPress.org</a> to help us spread the word. Thank you from Booster team!', 'woocommerce-jetpack'), $stars_link, $link);
174
- ?>
175
- <style>
176
- .wcj-review-icon { vertical-align: middle; margin: -6px 0 0 0; }
177
- </style>
178
- <?php
179
- echo '<div class="' . $class . '"><p>' . $message . '</p></div>';
180
- }
181
 
182
- /**
183
- * enqueue_admin_script.
184
- *
185
- * @version 5.4.3
186
- * @since 5.4.2
187
- */
188
- function enqueue_admin_script()
189
- {
190
- wp_enqueue_script('wcj-admin-js', trailingslashit(wcj_plugin_url()) . 'includes/js/wcj-admin.js', array('jquery'), WCJ()->version, true);
191
- wp_localize_script('wcj-admin-js', 'admin_object', array('admin_object'), false);
192
- }
 
 
 
 
 
 
 
 
 
 
193
 
194
- /**
195
- * Output cats
196
- *
197
- * @version 5.5.6
198
- */
199
- public function output_cats_submenu(){
200
- global $current_section;
201
- $current_cat = empty($_REQUEST['wcj-cat']) ? 'dashboard' : sanitize_title($_REQUEST['wcj-cat']);
202
- if (empty($this->cats)) { return; }
203
- echo '<ul class="wcj-dashboard-header">';
204
- $array_keys = array_keys($this->cats);
205
- foreach ($this->cats as $id => $label_info) {
206
- $dashboard_section = "";
207
- if($id == "dashboard"){
208
- $dashboard_section = "&section=by_category";
209
- }
210
- echo '<li class="wcj-header-item ' . ($current_cat == $id ? 'active' : '') . '"><a
211
- href="' . admin_url('admin.php?page=wc-settings&tab=' . $this->id . '&wcj-cat=' . sanitize_title($id)."".$dashboard_section) . '"
212
- class="' . ($current_cat == $id ? 'current' : '') . '">' . $label_info['label'] . '</a> ' .
213
- (end($array_keys) == $id ? '' : '') . ' </li>';
214
- }
215
- echo '</ul>' . '<br class="clear" />';
216
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
217
 
218
- /**
219
- * Output sections (modules) sub menu
220
- *
221
- * @version 5.5.6
222
- * @todo (maybe) for case insensitive sorting: `array_multisort( array_map( 'strtolower', $menu ), $menu );` instead of `asort( $menu );` (see http://php.net/manual/en/function.asort.php)
223
- */
224
- public function output_sections_submenu()
225
- {
226
- global $current_section;
227
- $sections = $this->get_sections();
228
- $current_cat = empty($_REQUEST['wcj-cat']) ? 'dashboard' : sanitize_title($_REQUEST['wcj-cat']);
229
- if ('dashboard' === $current_cat) {
230
 
231
- // Counting modules
232
- $all = 0;
233
- $active = 0;
234
- foreach ($this->module_statuses as $module_status) {
235
- if (isset($module_status['id']) && isset($module_status['default'])) {
236
- if ('yes' === wcj_get_option($module_status['id'], $module_status['default'])) {
237
- $active++;
238
- } elseif (wcj_is_module_deprecated($module_status['id'], true)) {
239
- continue;
240
- }
241
- $all++;
242
- }
243
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
244
 
245
- $sections['by_category'] = '<span><img src="'.wcj_plugin_url().'/assets/images/home.png"></span>'.__('Dashboard', 'woocommerce-jetpack');
246
- $sections['all_module'] = '<span><img src="'.wcj_plugin_url().'/assets/images/multiple 1.png"></span>'.__('All Module', 'woocommerce-jetpack');
247
- $sections['active'] = '<span><img src="'.wcj_plugin_url().'/assets/images/t-swich.png"></span>' .__('Active Modules', 'woocommerce-jetpack');
248
- $sections['manager'] = '<span><img src="'.wcj_plugin_url().'/assets/images/setting.png"></span>'.__('Manage Settings', 'woocommerce-jetpack');
249
- if (!empty($this->custom_dashboard_modules)) {
250
- foreach ($this->custom_dashboard_modules as $custom_dashboard_module_id => $custom_dashboard_module_data)
251
- {
252
- $sections[$custom_dashboard_module_id] = $custom_dashboard_module_data['title'];
253
- }
254
- }
255
- if ('' == $current_section) {
256
- $current_section = 'by_category';
257
- }
258
- }
259
- if (!empty($this->cats[$current_cat]['all_cat_ids'])) {
260
- foreach ($sections as $id => $label) {
261
- if (!in_array($id, $this->cats[$current_cat]['all_cat_ids'])) {
262
- unset($sections[$id]);
263
- }
264
- }
265
- }
266
- if (empty($sections) || 1 === count($sections)) {
267
- return;
268
- }
269
- foreach ($this->cats[$current_cat]['all_cat_ids'] as $key => $id) {
270
- if (wcj_is_module_deprecated($id, false, true)) {
271
- unset($this->cats[$current_cat]['all_cat_ids'][$key]);
272
- }
273
- }
274
- $menu = array();
275
- foreach ($this->cats[$current_cat]['all_cat_ids'] as $id) {
276
- $menu[$id] = $sections[$id];
277
- }
278
- if ('dashboard' !== $current_cat && 'pdf_invoicing' !== $current_cat) {
279
- asort($menu);
280
- }
281
 
282
- $menu_links = array();
 
 
 
 
 
 
 
 
 
 
 
 
283
 
284
- foreach ($menu as $id => $label) {
285
- $url = admin_url('admin.php?page=wc-settings&tab=' . $this->id . '&wcj-cat=' . $current_cat . '&section=' . sanitize_title($id));
286
- $menu_links[] = '<li class="wcj-sidebar-item ' . ($current_section == $id ? 'active' : '') . '"><a href="' . $url . '" class="' . ($current_section == $id ? 'current' : '') . '">' . $label . '</a></li>';
287
- }
288
- echo implode(' ', $menu_links) . '<br class="clear" />';
289
- }
290
- /**
291
- * get_cat_by_section
292
- */
293
- public function get_cat_by_section($section)
294
- {
295
- foreach ($this->cats as $id => $label_info) {
296
- if (!empty($label_info['all_cat_ids'])) {
297
- if (in_array($section, $label_info['all_cat_ids'])) {
298
- return $id;
299
- }
300
- }
301
- }
302
- return '';
303
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
 
305
- /**
306
- * Get sections (modules)
307
- *
308
- * @return array
309
- */
310
- public function get_sections()
311
- {
312
- return apply_filters('wcj_settings_sections', array('' => __('Dashboard', 'woocommerce-jetpack')));
313
- }
314
 
315
- /**
316
- * active.
317
- *
318
- * @version 2.8.0
319
- */
320
- public function active($active)
321
- {
322
- return ('yes' === $active) ? 'active' : 'inactive';
323
- }
 
 
 
 
 
 
 
 
 
 
 
 
324
 
325
- /**
326
- * is_dashboard_section.
327
- *
328
- * @version 5.5.6
329
- * @since 3.0.0
330
- */
331
- public function is_dashboard_section($current_section)
332
- {
333
- return in_array($current_section, array_merge(array('', 'all_module', 'by_category', 'active', 'manager'), array_keys($this->custom_dashboard_modules)));
334
- }
335
 
336
- /**
337
- * Output the settings.
338
- *
339
- * @version 5.5.6
340
- * @todo (maybe) admin_notices
341
- */
342
- public function output()
343
- {
 
344
 
345
- global $current_section, $wcj_notice;
 
 
 
 
 
 
 
 
 
346
 
347
- if ('' != $wcj_notice) {
348
- echo '<div id="wcj_message" class="updated"><p><strong>' . $wcj_notice . '</strong></p></div>';
349
- }
350
- if($current_section !=='by_category'){
351
- $is_dashboard = $this->is_dashboard_section($current_section);
 
 
352
 
353
- // Deprecated message
354
- if ($replacement_module = wcj_is_module_deprecated($current_section)) {
355
- echo '<div id="wcj_message" class="error">';
356
- echo '<p>';
357
- echo '<strong>';
358
- echo sprintf(
359
- __('Please note that current <em>%s</em> module is deprecated and will be removed in future updates. Please use <em>%s</em> module instead.', 'woocommerce-jetpack'),
360
- WCJ()->modules[$current_section]->short_desc,
361
- '<a href="' . admin_url('admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $replacement_module['cat'] . '&section=' . $replacement_module['module']) . '">' .
362
- $replacement_module['title'] . '</a>'
363
- );
364
- echo ' <span style="color:red;">' . __('Module will be removed from the module\'s list as soon as you disable it.', 'woocommerce-jetpack') . '</span>';
365
- echo '</strong>';
366
- echo '</p>';
367
- echo '</div>';
368
- }
369
 
370
- // "Under development" message
371
- if (isset(WCJ()->modules[$current_section]->dev) && true === WCJ()->modules[$current_section]->dev) {
372
- echo '<div id="wcj_message" class="error">';
373
- echo '<p>';
374
- echo '<strong>';
375
- echo sprintf(__('Please note that <em>%s</em> module is currently under development. Until stable module version is released, options can be changed or some options can be moved to paid plugin version.', 'woocommerce-jetpack'), WCJ()->modules[$current_section]->short_desc);
376
- echo '</strong>';
377
- echo '</p>';
378
- echo '</div>';
379
- }
380
 
381
- if ('yes' === wcj_get_option('wcj_debug_tools_enabled', 'no') && 'yes' === wcj_get_option('wcj_debuging_enabled', 'no')) {
382
- // Breadcrumbs
383
- $breadcrumbs_html = '';
384
- $breadcrumbs_html .= '<p>';
385
- $breadcrumbs_html .= '<code>';
386
- $breadcrumbs_html .= __('WooCommerce', 'woocommerce-jetpack');
387
- $breadcrumbs_html .= ' > ';
388
- $breadcrumbs_html .= __('Settings', 'woocommerce-jetpack');
389
- $breadcrumbs_html .= ' > ';
390
- $breadcrumbs_html .= __('Booster', 'woocommerce-jetpack');
391
- $breadcrumbs_html .= ' > ';
392
- foreach ($this->cats as $id => $label_info) {
393
- if ($this->get_cat_by_section($current_section) === $id) {
394
- $breadcrumbs_html .= $label_info['label'];
395
- break;
396
- }
397
- }
398
- if ($is_dashboard && isset($_GET['wcj-cat']) && 'dashboard' != $_GET['wcj-cat']) {
399
- $breadcrumbs_html .= $this->cats[$_GET['wcj-cat']]['label'];
400
- }
401
- if (!$is_dashboard) {
402
- $breadcrumbs_html .= ' > ';
403
- $sections = $this->get_sections();
404
- $breadcrumbs_html .= $sections[$current_section];
405
- }
406
- $breadcrumbs_html .= '</code>';
407
- $breadcrumbs_html .= '</p>';
408
- echo $breadcrumbs_html;
409
- }
410
 
411
- $settings = $this->get_settings($current_section);
 
 
 
 
 
 
 
 
 
412
 
413
- if (!$is_dashboard) {
414
- WC_Admin_Settings::output_fields($settings);
415
- } else {
416
- $this->output_dashboard($current_section);
417
- }
418
- }
419
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
420
 
421
- /**
422
- * output_dashboard.
423
- *
424
- * @version 5.5.6
425
- */
426
- public function output_dashboard($current_section)
427
- {
428
 
429
- if ('' == $current_section) {
430
- $current_section = 'by_category';
431
- }
 
 
 
 
432
 
433
- $the_settings = $this->get_settings();
 
 
 
 
 
 
434
 
435
- echo '<h3>' . $the_settings[0]['title'] . '</h3>';
436
- if (isset($this->custom_dashboard_modules[$current_section])) {
437
- echo '<p>' . $this->custom_dashboard_modules[$current_section]['desc'] . '</p>';
438
- } elseif ('manager' != $current_section) {
439
- echo '<p>' . $the_settings[0]['desc'] . '</p>';
440
- } else {
441
- echo '<p>' . __('This section lets you export, import or reset all Booster\'s modules settings.', 'woocommerce-jetpack') . '</p>';
442
- }
443
 
444
- if ('all_module' === $current_section) {
445
- $this->output_dashboard_modules($the_settings);
446
- } elseif ('by_category' === $current_section) {
447
- foreach ($this->cats as $cat_id => $cat_label_info) {
448
- if ('dashboard' === $cat_id) {
449
- continue;
450
- }
451
- if (isset($_GET['wcj-cat']) && 'dashboard' != $_GET['wcj-cat']) {
452
- if ($cat_id != $_GET['wcj-cat']) {
453
- continue;
454
- }
455
- } else {
456
- echo '<h4>' . $cat_label_info['label'] . '</h4>';
457
- }
458
- $this->output_dashboard_modules($the_settings, $cat_id);
459
- }
460
- } elseif ('active' === $current_section) {
461
- $this->output_dashboard_modules($the_settings, 'active_modules_only');
462
- } elseif ('manager' === $current_section) {
463
- $table_data = array(
464
- array(
465
- '<button style="width:100px;" class="button-primary" type="submit" name="booster_export_settings">' . __('Export', 'woocommerce-jetpack') . '</button>',
466
- '<em>' . __('Export all Booster\'s options to a file.', 'woocommerce-jetpack') . '</em>',
467
- ),
468
- array(
469
- '<button style="width:100px;" class="button-primary" type="submit" name="booster_import_settings">' . __('Import', 'woocommerce-jetpack') . '</button>' .
470
- ' ' . '<input type="file" name="booster_import_settings_file">',
471
- '<em>' . __('Import all Booster\'s options from a file.', 'woocommerce-jetpack') . '</em>',
472
- ),
473
- array(
474
- '<button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings"' .
475
- wcj_get_js_confirmation(__('This will reset settings to defaults for all Booster modules. Are you sure?', 'woocommerce-jetpack')) . '>' .
476
- __('Reset', 'woocommerce-jetpack') . '</button>',
477
- '<em>' . __('Reset all Booster\'s options.', 'woocommerce-jetpack') . '</em>',
478
- ),
479
- array(
480
- '<button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings_meta"' .
481
- wcj_get_js_confirmation(__('This will delete all Booster meta. Are you sure?', 'woocommerce-jetpack')) . '>' .
482
- __('Reset meta', 'woocommerce-jetpack') . '</button>',
483
- '<em>' . __('Reset all Booster\'s meta.', 'woocommerce-jetpack') . '</em>',
484
- ),
485
- );
486
- $manager_settings = $this->get_manager_settings();
487
- foreach ($manager_settings as $manager_settings_field) {
488
- $table_data[] = array(
489
- '<label for="' . $manager_settings_field['id'] . '">' .
490
- '<input name="' . $manager_settings_field['id'] . '" id="' . $manager_settings_field['id'] . '" type="' . $manager_settings_field['type'] . '"' .
491
- ' class="" value="1" ' . checked(wcj_get_option($manager_settings_field['id'], $manager_settings_field['default']), 'yes', false) . '>' .
492
- ' ' . '<strong>' . $manager_settings_field['title'] . '</strong>' .
493
- '</label>',
494
- '<em>' . $manager_settings_field['desc'] . '</em>',
495
- );
496
- }
497
- echo wcj_get_table_html($table_data, array('table_class' => 'widefat striped', 'table_heading_type' => 'none'));
498
- }
499
 
500
- if (isset($this->custom_dashboard_modules[$current_section])) {
501
- $table_data = array();
502
- foreach ($this->custom_dashboard_modules[$current_section]['settings'] as $_settings) {
503
- $table_data[] = array(
504
- $_settings['title'],
505
- '<label class="'.$_settings['id'].'_label" for="' . $_settings['id'] . '">' .
506
- '<input name="' . $_settings['id'] .
507
- '" id="' . $_settings['id'] .
508
- '" type="' . $_settings['type'] .
509
- '" class="' . $_settings['class'] .
510
- '" value="' . wcj_get_option($_settings['id'], $_settings['default']) . '">' . ' ' . '<em>' . $_settings['desc'] . '</em>' .'</label>',
511
- );
512
- }
513
- echo wcj_get_table_html($table_data, array('table_class' => 'widefat striped', 'table_heading_type' => 'vertical'));
514
- }
515
 
516
- $plugin_data = get_plugin_data(WCJ_PLUGIN_FILE);
517
- $plugin_title = (isset($plugin_data['Name']) ? '[' . $plugin_data['Name'] . '] ' : '');
518
- echo '<p style="text-align:right;color:gray;font-size:x-small;font-style:italic;">' . $plugin_title .
519
- __('Version', 'woocommerce-jetpack') . ': ' . wcj_get_option(WCJ_VERSION_OPTION, 'N/A') . '</p>';
520
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
521
 
522
- /**
523
- * compare_for_usort.
524
- */
525
- private function compare_for_usort($a, $b)
526
- {
527
- return strcmp($a['title'], $b['title']);
528
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
529
 
530
- /**
531
- * output_dashboard_modules.
532
- *
533
- * @version 3.3.0
534
- */
535
- public function output_dashboard_modules($settings, $cat_id = '')
536
- {
537
- ?>
538
- <div class="wcj-active-modules">
539
- <table class="wp-list-table widefat striped plugins">
540
- <thead>
541
- <tr>
542
- <th scope="col" id="cb" class="manage-column column-cb check-column" style=""><label class="screen-reader-text" for="cb-select-all-1"><?php _e('Select All', 'woocommerce-jetpack'); ?></label><input id="cb-select-all-1" type="checkbox" style="margin-top:15px;"></th>
543
- <th scope="col" id="name" class="manage-column column-name" style="">
544
- <?php _e('Module', 'woocommerce-jetpack'); ?></th>
545
- <th scope="col" id="description" class="manage-column column-description" style="">
546
- <?php _e('Description', 'woocommerce-jetpack'); ?></th>
547
- </tr>
548
- </thead>
549
- <tfoot>
550
- <tr>
551
- <th scope="col" class="manage-column column-cb check-column" style=""><label class="screen-reader-text" for="cb-select-all-2"><?php _e('Select All', 'woocommerce-jetpack'); ?></label><input id="cb-select-all-2" type="checkbox" style="margin-top:15px;"></th>
552
- <th scope="col" class="manage-column column-name" style=""><?php _e('Module', 'woocommerce-jetpack'); ?>
553
- </th>
554
- <th scope="col" class="manage-column column-description" style="">
555
- <?php _e('Description', 'woocommerce-jetpack'); ?></th>
556
- </tr>
557
- </tfoot>
558
- <tbody id="the-list"><?php
559
- $html = '';
560
- usort($settings, array($this, 'compare_for_usort'));
561
- $total_modules = 0;
562
- foreach ($settings as $the_feature) {
563
- if ('checkbox' !== $the_feature['type']) {
564
- continue;
565
- }
566
- $section = $the_feature['id'];
567
- $section = str_replace('wcj_', '', $section);
568
- $section = str_replace('_enabled', '', $section);
569
- if (wcj_is_module_deprecated($section, false, true)) {
570
- continue;
571
- }
572
- if ('' != $cat_id) {
573
- if ('active_modules_only' === $cat_id) {
574
- if ('no' === wcj_get_option($the_feature['id'], 'no')) {
575
- continue;
576
- }
577
- } elseif ($cat_id != $this->get_cat_by_section($section)) {
578
- continue;
579
- }
580
- }
581
- $total_modules++;
582
- $html .= '<tr id="' . $the_feature['id'] . '" ' . 'class="' . $this->active(wcj_get_option($the_feature['id'])) . '">';
583
- $html .= '<th scope="row" class="check-column">';
584
- $html .= '<label class="screen-reader-text" for="' . $the_feature['id'] . '">' . $the_feature['desc'] . '</label>';
585
- $html .= '<input type="checkbox" name="' . $the_feature['id'] . '" value="1" id="' . $the_feature['id'] . '" ' . checked(wcj_get_option($the_feature['id']), 'yes', false) . '>';
586
- $html .= '</th>';
587
- $html .= '<td class="plugin-title">' . '<strong>' . $the_feature['title'] . '</strong>';
588
- $html .= '<div class="row-actions visible">';
589
- $html .= '<span class="0"><a href="' . admin_url() . 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $this->get_cat_by_section($section) . '&section=' . $section . '">' . __('Settings', 'woocommerce') . '</a></span>';
590
- if (isset($the_feature['wcj_link']) && '' != $the_feature['wcj_link']) {
591
- $html .= ' | <span class="0"><a href="' . $the_feature['wcj_link'] . '?utm_source=module_documentation&utm_medium=dashboard_link&utm_campaign=booster_documentation" target="_blank">' . __('Documentation', 'woocommerce') . '</a></span>';
592
- }
593
- $html .= '</div>';
594
- $html .= '</td>';
595
- $html .= '<td class="column-description desc">';
596
- $html .= '<div class="plugin-description"><p>' . ((isset($the_feature['wcj_desc'])) ? $the_feature['wcj_desc'] : $the_feature['desc_tip']) . '</p></div>';
597
- $html .= '</td>';
598
- $html .= '</tr>';
599
- }
600
- echo $html;
601
- if (0 == $total_modules && 'active_modules_only' === $cat_id) {
602
- echo '<tr><td colspan="3">' . '<em>' . __('No active modules found.', 'woocommerce-jetpack') . '</em>' . '</td></tr>';
603
- }
604
- ?></tbody>
605
- </table>
606
- <p style="color:#000;font-size:12px;font-style:italic;">
607
- <?php echo __('Total Modules:') . ' ' . $total_modules; ?>
608
- </p>
609
- </div><?php
610
- }
611
 
612
- /**
613
- * Save settings.
614
- *
615
- * @version 5.3.8
616
- */
617
- function save()
618
- {
619
- global $current_section;
620
- $settings = $this->get_settings($current_section);
621
- WC_Admin_Settings::save_fields($settings);
622
- $this->disable_autoload_options_from_section($settings);
623
- add_action('admin_notices', array($this, 'booster_message_global'));
624
- do_action('woojetpack_after_settings_save', $this->get_sections(), $current_section);
625
- }
626
 
627
- /**
628
- * disable_autoload_options.
629
- *
630
- * @version 5.3.3
631
- * @since 5.3.3
632
- *
633
- * @param $settings
634
- */
635
- public function disable_autoload_options_from_section($settings)
636
- {
637
- $fields = wp_list_filter($settings, array('autoload' => false));
638
- $fields = wp_list_filter($fields, array('type' => 'title'), 'NOT');
639
- $fields = wp_list_filter($fields, array('type' => 'sectionend'), 'NOT');
640
- $field_ids = wp_list_pluck($fields, 'id');
641
- $fields_ids_str = '\'' . implode('\',\'', $field_ids) . '\'';
642
- global $wpdb;
643
- $sql = "
644
- UPDATE {$wpdb->options} SET autoload = 'no'
645
- WHERE option_name IN ({$fields_ids_str}) AND autoload != 'no'
646
- ";
647
- $wpdb->query($sql);
648
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
649
 
650
- /**
651
- * booster_message_global.
652
- *
653
- * @version 3.6.0
654
- * @since 3.6.0
655
- */
656
- public function booster_message_global()
657
- {
658
- if ('' != ($message = apply_filters('booster_message', '', 'global'))) {
659
- echo $message;
660
- }
661
- }
 
662
 
663
- /**
664
- * get_manager_settings.
665
- *
666
- * @version 3.5.0
667
- * @since 2.6.0
668
- * @return array
669
- */
670
- public function get_manager_settings()
671
- {
672
- return array(
673
- array(
674
- 'title' => __('Autoload Booster\'s Options', 'woocommerce-jetpack'),
675
- 'type' => 'checkbox',
676
- 'desc' => __('Choose if you want Booster\'s options to be autoloaded when calling add_option. After saving this option, you need to Reset all Booster\'s settings. Leave default value (i.e. Enabled) if not sure.', 'woocommerce-jetpack'),
677
- 'id' => 'wcj_autoload_options',
678
- 'default' => 'yes',
679
- ),
680
- array(
681
- 'title' => __('Load Modules on Init Hook', 'woocommerce-jetpack'),
682
- 'type' => 'checkbox',
683
- 'desc' => __('Choose if you want to load Booster Modules on Init hook.', 'woocommerce-jetpack') . ' ' . __('It will load the locale appropriately if users change it from the profile page.', 'woocommerce-jetpack'),
684
- 'id' => 'wcj_load_modules_on_init',
685
- 'default' => 'no',
686
- ),
687
- array(
688
- 'title' => __('Use List Instead of Comma Separated Text for Products in Settings', 'woocommerce-jetpack'),
689
- 'type' => 'checkbox',
690
- 'desc' => sprintf(__('Supported modules: %s.', 'woocommerce-jetpack'), implode(', ', array(
691
- __('Gateways per Product or Category', 'woocommerce-jetpack'),
692
- __('Global Discount', 'woocommerce-jetpack'),
693
- __('Product Info', 'woocommerce-jetpack'),
694
- __('Product Input Fields', 'woocommerce-jetpack'),
695
- __('Products XML', 'woocommerce-jetpack'),
696
- __('Related Products', 'woocommerce-jetpack'),
697
- ))),
698
- 'id' => 'wcj_list_for_products',
699
- 'default' => 'yes',
700
- ),
701
- array(
702
- 'title' => __('Use List Instead of Comma Separated Text for Products Categories in Settings', 'woocommerce-jetpack'),
703
- 'type' => 'checkbox',
704
- 'desc' => sprintf(__('Supported modules: %s.', 'woocommerce-jetpack'), implode(', ', array(
705
- __('Product Info', 'woocommerce-jetpack'),
706
- ))),
707
- 'id' => 'wcj_list_for_products_cats',
708
- 'default' => 'yes',
709
- ),
710
- array(
711
- 'title' => __('Use List Instead of Comma Separated Text for Products Tags in Settings', 'woocommerce-jetpack'),
712
- 'type' => 'checkbox',
713
- 'desc' => sprintf(__('Supported modules: %s.', 'woocommerce-jetpack'), implode(', ', array(
714
- __('Product Info', 'woocommerce-jetpack'),
715
- ))),
716
- 'id' => 'wcj_list_for_products_tags',
717
- 'default' => 'yes',
718
- ),
719
- );
720
- }
721
 
722
- /**
723
- * Get settings array
724
- *
725
- * @version 3.0.0
726
- * @return array
727
- */
728
- public function get_settings($current_section = '')
729
- {
730
- if (!$this->is_dashboard_section($current_section)) {
731
- return apply_filters('wcj_settings_' . $current_section, array());
732
- } elseif ('manager' === $current_section) {
733
- return $this->get_manager_settings();
734
- } elseif (isset($this->custom_dashboard_modules[$current_section])) {
735
- return $this->custom_dashboard_modules[$current_section]['settings'];
736
- } else {
737
- $cat_id = (isset($_GET['wcj-cat']) && '' != $_GET['wcj-cat']) ? $_GET['wcj-cat'] : 'dashboard';
738
- $settings[] = array(
739
- 'title' => __('Booster for WooCommerce', 'woocommerce-jetpack') . ' - ' . $this->cats[$cat_id]['label'],
740
- 'type' => 'title',
741
- 'desc' => $this->cats[$cat_id]['desc'],
742
- 'id' => 'wcj_' . $cat_id . '_options',
743
- );
744
- if ('dashboard' === $cat_id) {
745
- $settings = array_merge($settings, $this->module_statuses);
746
- } else {
747
- $cat_module_statuses = array();
748
- foreach ($this->module_statuses as $module_status) {
749
- $section = $module_status['id'];
750
- $section = str_replace('wcj_', '', $section);
751
- $section = str_replace('_enabled', '', $section);
752
- if ($cat_id === $this->get_cat_by_section($section)) {
753
- $cat_module_statuses[] = $module_status;
754
- }
755
- }
756
- $settings = array_merge($settings, $cat_module_statuses);
757
- }
758
- $settings[] = array(
759
- 'type' => 'sectionend',
760
- 'id' => 'wcj_' . $cat_id . '_options',
761
- 'title' => '', // for usort
762
- );
763
- return $settings;
764
- }
765
- }
766
 
767
- /**
768
- * add_module_statuses
769
- */
770
- public function add_module_statuses($statuses)
771
- {
772
- $this->module_statuses = $statuses;
773
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
774
 
775
- function version_details (){
 
 
 
 
 
776
 
777
- $file=wcj_plugin_path()."/version-details.txt";
778
- if (file_exists($file)) {
779
 
780
- $doc=file_get_contents($file);
781
- $line=explode("\n",$doc);
782
- foreach($line as $newline){
783
- echo $newline.'<br>';
784
- }
785
- }
786
-
787
- }
788
 
 
 
 
 
 
 
789
 
790
- /**
791
- * dasboard_menu
792
- *
793
- * @version 5.5.6
794
- * @return array
795
- */
796
 
797
- public function dasboard_menu (){
798
- global $current_section;
799
- $_section = isset( $_GET['section'] ) ? $_GET['section'] : "" ;
800
- $_wcj_cat = isset( $_GET['wcj-cat'] ) ? $_GET['wcj-cat'] : "" ;
801
- $_wcj_tab = isset( $_GET['tab'] ) ? $_GET['tab'] : "" ;
802
- if($_wcj_tab == "jetpack" && ($_section=="" || $_section=="by_category") && ($_wcj_cat=="" || $_wcj_cat=="dashboard")){
803
- ?><style>
804
- button.button-primary.woocommerce-save-button {
805
- display: none;
806
- }
807
- </style> <?php
808
- }
809
- ?>
810
- <div class="wcj-main-container dashboard">
811
- <div class="wcj-body">
812
- <section class="wcj-sidebar">
813
- <div class="wcj-dashboard-logo">
814
- <img src="<?php echo wcj_plugin_url().'/assets/images/logo.png'; ?>">
815
- </div>
816
- <div class="wcj-nav-sidebar">
817
- <ul>
818
- <?php echo $this->output_sections_submenu(); ?>
819
- <a href="https://booster.io/contact-us/" class="wcj-button" target="_blank"><?php _e('Need Help?', 'woocommerce-jetpack');?><span><img src="<?php echo wcj_plugin_url().'/assets/images/need-help.png'; ?>"></span></a>
820
- </ul>
821
- </div>
822
- </section>
823
- <section class="wcj-body-container wcj-setting-jetpack">
824
- <header>
825
- <?php echo $this->output_cats_submenu(); ?>
826
- </header>
827
- <div class="wcj-setting-jetpack-body <?php if($_section === 'pdf_invoicing_extra_columns'){ echo 'wcj_invoice_pdf_dtl'; }?>" style="<?php if($_section === 'by_category'){ echo 'display:none;'; } if($_wcj_tab == "jetpack" && $_wcj_cat==""){ echo "padding: 0px;"; } ?>">
828
- <?php if($current_section === 'by_category') { ?>
829
- </div>
830
- <div class="wcj-body-part">
831
- <div class="wcj-sub-cnt-top">
832
- <div class="wcj-sub-cnt-top-left">
833
- <div class="wcj-tit">
834
- <h1><?php _e('My Account', 'woocommerce-jetpack');?></h1>
835
- </div>
836
- </div>
837
- <div class="wcj-btn-main">
838
- <a href="https://booster.io/buy-booster/" class="wcj-button" target="_blank"><?php _e('Get Booster Plus', 'woocommerce-jetpack');?></a>
839
- </div>
840
- </div>
841
- <div class="wcj-body-sec-part-main">
842
- <div class="wcj-body-parts wcj-body-left">
843
- <div class="wcj-info-section wcj-box">
844
- <div class="wcj-tit">
845
- <h3><?php _e('Getting Started', 'woocommerce-jetpack');?></h3>
846
- </div>
847
- <ul class="wcj-dashboard-info-ul">
848
- <li><a target="_blank" href="https://booster.io/docs/dashboard"><?php _e('Dashboard', 'woocommerce-jetpack');?></a></li>
849
- <li><a target="_blank" href="https://booster.io/docs/how-to-navigate-through-booster-categories-and-modules-smoothly"><?php _e('Navigating Categories', 'woocommerce-jetpack');?></a></li>
850
- <li><a target="_blank" href="https://booster.io/docs/how-to-get-started-with-booster"><?php _e('How to get started with booster', 'woocommerce-jetpack');?></a></li>
851
- </ul>
852
- </div>
853
- <div class="wcj-faq-section wcj-box">
854
- <div class="wcj-tit">
855
- <h3><?php _e('Frequently Asked Questions', 'woocommerce-jetpack');?></h3>
856
- </div>
857
- <div class="wcj-faq-body">
858
- <div class="wcj-faq-sing-box">
859
- <div class="wcj-accordion">
860
- <h6><?php _e('Do I need to have coding skills to use Booster Plus?', 'woocommerce-jetpack');?></h6>
861
- <span><img src="<?php echo wcj_plugin_url().'/assets/images/down-arw.png'; ?>"></span>
862
- </div>
863
- <div class="wcj-panel">
864
- <p><?php _e('Absolutely not. You can configure pretty much everything Booster Plus has to offer without any coding knowledge.', 'woocommerce-jetpack');?></p>
865
- </div>
866
- </div>
867
- <div class="wcj-faq-sing-box">
868
- <div class="wcj-accordion">
869
- <h6><?php _e('Will Booster Plus slow down my website?', 'woocommerce-jetpack');?></h6>
870
- <span><img src="<?php echo wcj_plugin_url().'/assets/images/down-arw.png'; ?>"></span>
871
- </div>
872
- <div class="wcj-panel">
873
- <p><?php _e('Absolutely not. Booster Plus is carefully built with performance in mind.', 'woocommerce-jetpack');?></p>
874
- </div>
875
- </div>
876
- <div class="wcj-faq-sing-box">
877
- <div class="wcj-accordion">
878
- <h6><?php _e('Do you offer refunds?', 'woocommerce-jetpack');?></h6>
879
- <span><img src="<?php echo wcj_plugin_url().'/assets/images/down-arw.png'; ?>"></span>
880
- </div>
881
- <div class="wcj-panel">
882
- <p><?php _e('If you are not completely satisfied with Booster Plus within the fist 30 days, you can request a refund and we will give you 100% of your money back – no questions asked.', 'woocommerce-jetpack');?></p>
883
- </div>
884
- </div>
885
- <div class="wcj-faq-sing-box">
886
- <div class="wcj-accordion">
887
- <h6><?php _e('Can I use Booster Plus on client sites?', 'woocommerce-jetpack');?></h6>
888
- <span><img src="<?php echo wcj_plugin_url().'/assets/images/down-arw.png'; ?>"></span>
889
- </div>
890
- <div class="wcj-panel">
891
- <p><?php _e('Yes, you can use Booster Plus on client sites. You can purchase the multiple sites license of Booster Plus.', 'woocommerce-jetpack');?></p>
892
- </div>
893
- </div>
894
- <div class="wcj-faq-sing-box">
895
- <div class="wcj-accordion">
896
- <h6><?php _e('Do you have an affiliate program?', 'woocommerce-jetpack');?></h6>
897
- <span><img src="<?php echo wcj_plugin_url().'/assets/images/down-arw.png'; ?>"></span>
898
- </div>
899
- <div class="wcj-panel">
900
- <p><?php _e('Yes, We do have an affiliate program. ', 'woocommerce-jetpack');?><a href="https://booster.io/affiliate-program/" target="_blannk"><?php _e('Click here', 'woocommerce-jetpack');?></a><?php _e(' for the details.', 'woocommerce-jetpack');?></p>
901
- </div>
902
- </div>
903
- <div class="wcj-faq-sing-box">
904
- <div class="wcj-accordion">
905
- <h6><?php _e('Why should I choose the Booster Plus suite over other individual plugins?', 'woocommerce-jetpack');?></h6>
906
- <span><img src="<?php echo wcj_plugin_url().'/assets/images/down-arw.png'; ?>"></span>
907
- </div>
908
- <div class="wcj-panel">
909
- <p><?php _e("Oh, that's an easy one! Implementing just a few modules from the Booster Plus suite is more cost-effective than using dozens of individual plugins often priced at $15-$30 each. On top of that, stacking your site with a lot of different plugins can make it bloated and slow. What's worse, all those individual plugins don't always play nice together. But Booster Plus is the solution to all that nonsense. The Booster Plus suite features over 100 compatible modules that allow you to add custom features and functionality to your WooCommerce site easily.", "woocommerce-jetpack");?></p>
910
- </div>
911
- </div>
912
- <div class="wcj-faq-sing-box">
913
- <div class="wcj-accordion">
914
- <h6><?php _e('What features does Booster Plus have?', 'woocommerce-jetpack');?></h6>
915
- <span><img src="<?php echo wcj_plugin_url().'/assets/images/down-arw.png'; ?>"></span>
916
- </div>
917
- <div class="wcj-panel">
918
- <p><?php _e('You can see all the features at ', 'woocommerce-jetpack');?><a href="https://booster.io/about/" target="_blank"><?php _e('About Booster', 'woocommerce-jetpack');?></a><?php _e(' page.', 'woocommerce-jetpack');?></p>
919
- </div>
920
- </div>
921
- <div class="wcj-additional-que">
922
- <h6><?php _e('Still have a question?', 'woocommerce-jetpack');?></h6>
923
- <a href="https://booster.io/contact-us/" class="wcj-button" target="_blank"><?php _e('CONTACT BOOSTER SUPPORT', 'woocommerce-jetpack');?></a>
924
- </div>
925
- </div>
926
- </div>
927
- <div class="wcj-social-connect wcj-box">
928
- <div class="wcj-tit">
929
- <h3><?php _e('Connect with Booster', 'woocommerce-jetpack');?></h3>
930
- </div>
931
- <div class="wcj-socialmedia-connect">
932
- <div class="wcj-btn-main">
933
- <a href="https://booster.io/" class="wcj-button" target="_blank"><?php _e('BOOSTER WEBSITE', 'woocommerce-jetpack');?></a>
934
- </div>
935
- <ul class="wcj-social-icn">
936
- <li><a href="https://www.youtube.com/channel/UCVQg0c4XIirUI3UnGoX9HVg?sub_confirmation=1"><img src="<?php echo wcj_plugin_url().'/assets/images/YouTube.png'; ?>"></a></li>
937
- <li><a href="https://www.facebook.com/booster.for.woocommerce"><img src="<?php echo wcj_plugin_url().'/assets/images/Facebook.png'; ?>"></a></li>
938
- <li><a href="https://twitter.com/intent/follow?screen_name=BoosterForWoo"><img src="<?php echo wcj_plugin_url().'/assets/images/Twitter.png'; ?>"></a></li>
939
- <li><a href="https://www.linkedin.com/company/booster-for-woocommerce"><img src="<?php echo wcj_plugin_url().'/assets/images/Linkedin.png'; ?>"></a></li>
940
- </ul>
941
- </div>
942
- </div>
943
- </div>
944
- <div class="wcj-body-parts wcj-body-right">
945
- <div class="wcj-partitions action-section">
946
- <div class="wcj-tit">
947
- <h3><?php _e('Actions', 'woocommerce-jetpack');?></h3>
948
- </div>
949
- <div class="wcj-action-sub-part">
950
- <div class="wcj-action-sub-sing-box">
951
- <div class="wcj-action-single-bx">
952
- <div class="wcj-action-sub-sing-icon">
953
- <img src="<?php echo wcj_plugin_url().'/assets/images/ArrowSquareIn.png'; ?>">
954
- </div>
955
- <div class="wcj-actions-part">
956
- <input type="file" name="booster_import_settings_file">
957
- <h6><button style="width:100px;" class="button-primary" type="submit" name="booster_import_settings"><?php _e('Import', 'woocommerce-jetpack');?></button></h6>
958
- <p><?php _e('Import Booster options', 'woocommerce-jetpack');?></p>
959
- </div>
960
- </div>
961
- <div class="wcj-action-single-bx">
962
- <div class="wcj-action-sub-sing-icon">
963
- <img src="<?php echo wcj_plugin_url().'/assets/images/Export.png'; ?>">
964
- </div>
965
- <div class="wcj-actions-part">
966
- <h6><button style="width:100px;" class="button-primary wcj-export-btn" type="submit" name="booster_export_settings"><?php _e('Export', 'woocommerce-jetpack');?></button></h6>
967
- <p><?php _e('Export Booster options', 'woocommerce-jetpack');?></p>
968
- </div>
969
- </div>
970
- </div>
971
- <div class="wcj-action-sub-sing-box">
972
- <div class="wcj-action-single-bx">
973
- <div class="wcj-action-sub-sing-icon">
974
- <img src="<?php echo wcj_plugin_url().'/assets/images/Repeat.png'; ?>">
975
- </div>
976
- <div class="wcj-actions-part">
977
- <h6><button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings" onclick="return confirm('This will reset settings to defaults for all Booster modules. Are you sure?')"><?php _e('Reset', 'woocommerce-jetpack');?></button></h6>
978
- <p><?php _e("Reset all Booster's options", "woocommerce-jetpack");?></p>
979
- </div>
980
- </div>
981
- <div class="wcj-action-single-bx">
982
- <div class="wcj-action-sub-sing-icon">
983
- <img src="<?php echo wcj_plugin_url().'/assets/images/RepeatOnce.png'; ?>">
984
- </div>
985
- <div class="wcj-actions-part">
986
- <h6><button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings_meta" onclick="return confirm('This will delete all Booster meta. Are you sure?')"><?php _e('Reset meta', 'woocommerce-jetpack');?></button></h6>
987
- <p><?php _e("Reset all Booster's meta", "woocommerce-jetpack");?></p>
988
- </div>
989
- </div>
990
- </div>
991
- </div>
992
- </div>
993
- <div class="wcj-partitions documentation-section">
994
- <div class="wcj-tit">
995
- <h3><?php _e('Documentation', 'woocommerce-jetpack');?></h3>
996
- </div>
997
- <div class="wcj-documentation-dtl">
998
- <div class="wcj-documentation-icon">
999
- <img src="<?php echo wcj_plugin_url().'/assets/images/documentation.png'; ?>">
1000
- </div>
1001
- <div class="wcj-documentation-sm-rh-dtl">
1002
- <p><?php _e('Here you can find all documentation of Booster', 'woocommerce-jetpack');?></p>
1003
- <div class="wcj-btn-main">
1004
- <a href="https://booster.io/docs/" class="wcj-button" target="_blank"><?php _e('See Documentation', 'woocommerce-jetpack');?></a>
1005
- </div>
1006
- </div>
1007
- </div>
1008
- </div>
1009
- <div class="wcj-partitions updates-section">
1010
- <div class="wcj-tit">
1011
- <h3><?php _e('Latest updates', 'woocommerce-jetpack');?></h3>
1012
- </div>
1013
- <div class="wcj-partitions-sub-dtl">
1014
- <h6><?php _e('Version ', 'woocommerce-jetpack');?><?php echo WCJ()->version; ?></h6>
1015
- <ul class="wcj-updates-ul">
1016
- <li><?php $this->version_details() ?></li>
1017
- </ul>
1018
- <div class="wcj-btn-main">
1019
- <a href="https://booster.io/changelog/" class="wcj-button" target="_blank"><?php _e('SEE MORE', 'woocommerce-jetpack');?></a>
1020
- </div>
1021
- </div>
1022
- </div>
1023
- </div>
1024
- </div>
1025
- </div>
1026
- </section>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1027
  </div>
1028
  <div class="wcj-footer">
1029
- <div class="wcj-review-footer">
1030
- <p><?php _e('Please rate ', 'woocommerce-jetpack');?><strong><?php _e('Booster for Woocommerce', 'woocommerce-jetpack');?></strong>
1031
- <span class="wcj-woo-star">
1032
- <img src="<?php echo wcj_plugin_url().'/assets/images/star.png'; ?>">
1033
- <img src="<?php echo wcj_plugin_url().'/assets/images/star.png'; ?>">
1034
- <img src="<?php echo wcj_plugin_url().'/assets/images/star.png'; ?>">
1035
- <img src="<?php echo wcj_plugin_url().'/assets/images/star.png'; ?>">
1036
- <img src="<?php echo wcj_plugin_url().'/assets/images/star.png'; ?>">
1037
- </span>
1038
- <strong><a href="https://wordpress.org/support/plugin/woocommerce-jetpack/reviews/?rate=5#new-post" target="_blank"><?php _e('WordPress.org', 'woocommerce-jetpack');?></a></strong><?php _e(' to help us spread the word. Thank you from Booster team!', 'woocommerce-jetpack');?>
1039
- </p>
1040
- </div>
1041
- <div class="wcj-review-footer wcj-premium-features-footer">
1042
- <h6><?php _e('Upgrade today to unlock these popular premium features:', 'woocommerce-jetpack');?></h6>
1043
- <ul>
1044
- <li><strong><?php _e('+ PDF Invoices and Packing slips –', 'woocommerce-jetpack');?></strong><?php _e('Add ability to create Proforma Invoices, Credit Notes and Packaging slips', 'woocommerce-jetpack');?></li>
1045
- <li><strong><?php _e('+ Empty Cart –', 'woocommerce-jetpack');?></strong><?php _e('customize empty cart button text, different button positions on cart page', 'woocommerce-jetpack');?></li>
1046
- <li><strong><?php _e('+ Cart and checkout –', 'woocommerce-jetpack');?></strong><?php _e('add multiple – custom fields, custom info blocks, check out file uploads', 'woocommerce-jetpack');?></li>
1047
- <li><strong><?php _e('+ Mini cart –', 'woocommerce-jetpack');?></strong><?php _e('More custom information options', 'woocommerce-jetpack');?> </li>
1048
- <li><strong><?php _e('+ Prices and currencies –', 'woocommerce-jetpack');?></strong><?php _e('add more unlimited number of currencies to WooCommerce', 'woocommerce-jetpack');?> </li>
1049
- <li><strong><?php _e('+ Export options –', 'woocommerce-jetpack');?></strong><?php _e('more fields enabled', 'woocommerce-jetpack');?> </li>
1050
- <li><strong><?php _e('+ Add to cart –', 'woocommerce-jetpack');?></strong><?php _e('customize add to cart messages, Button labels - multiple category groups allowed+ +', 'woocommerce-jetpack');?></li>
1051
- <li><?php _e('+ More configuration options for payments and shipping', 'woocommerce-jetpack');?></li>
1052
- </ul>
1053
- <div class="wcj-btn-main">
1054
- <a href="https://booster.io/buy-booster/" class="wcj-button" target="_blank"><?php _e('Upgrade to Booster Plus', 'woocommerce-jetpack');?></a>
1055
- </div>
1056
- </div>
1057
-
1058
- </div>
1059
  </div>
1060
- <?php
1061
- }
1062
- }
1063
 
1064
-
1065
-
1066
-
1067
-
1068
- }
1069
 
1070
  endif;
1071
 
1
  <?php
 
2
  /**
3
  * Booster for WooCommerce - Settings
4
  *
5
  * @version 5.5.6
6
  * @since 1.0.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/admin
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
  }
14
+ // Exit if accessed directly.
 
 
15
 
16
+ if ( ! class_exists( 'WC_Settings_Jetpack' ) ) :
17
+ /**
18
+ * WC_Settings_Jetpack.
19
+ *
20
+ * @version 5.5.6
21
+ */
22
+ class WC_Settings_Jetpack extends WC_Settings_Page {
23
 
 
 
 
 
 
 
 
24
 
25
+ /**
26
+ * Constructor.
27
+ *
28
+ * @version 5.3.1
29
+ */
30
+ public function __construct() {
31
 
32
+ $this->id = 'jetpack';
33
+ $this->label = __( 'Booster', 'woocommerce-jetpack' );
34
 
35
+ $this->cats = include 'wcj-modules-cats.php';
36
 
37
+ $this->custom_dashboard_modules = apply_filters( 'wcj_custom_dashboard_modules', array() );
 
 
 
 
 
 
 
38
 
39
+ add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
40
+ add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
41
+ add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
 
42
 
43
+ add_action( 'woocommerce_sections_' . $this->id, array( $this, 'dasboard_menu' ) );
44
+ // Created New Dashborad desing css.
45
+ add_action( 'admin_enqueue_scripts', array( $this, 'wcj_new_desing_dashboard' ) );
46
 
47
+ // Create free version notices.
48
+ add_action( 'woocommerce_after_settings_' . $this->id, array( $this, 'create_free_version_footer_review_notice' ) );
49
+ add_action( 'woocommerce_settings_' . $this->id, array( $this, 'create_free_version_notice_about_plus' ) );
50
 
51
+ // Create a PRO version ratting notice.
52
+ add_action( 'woocommerce_after_settings_' . $this->id, array( $this, 'create_pro_version_footer_review_notice' ) );
53
 
54
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_script' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
55
 
56
+ require_once 'class-wcj-settings-custom-fields.php';
57
+ }
58
 
59
+ /**
60
+ * Wcj_new_desing_dashboard.
61
+ *
62
+ * @version 5.5.6
63
+ * @since 5.5.6
64
+ */
65
+ public function wcj_new_desing_dashboard() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
 
67
+ if ( isset( $_GET['tab'] ) && 'jetpack' === $_GET['tab'] ) {
68
+ wp_enqueue_style( 'wcj-admin-wcj-new_desing', wcj_plugin_url() . '/includes/css/admin-style.css' );
69
+ wp_enqueue_script( 'wcj-admin-script', wcj_plugin_url() . '/includes/js/admin-script.js', array( 'jquery' ), '5.0.0', true );
70
+ // wp_enqueue_script('wcj-admin-dasboard-js', wcj_plugin_url() . '/includes/js/wcj-new_desing.js').
71
+ }
72
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
+ /**
75
+ * Create_free_version_notice_about_plus.
76
+ *
77
+ * @version 5.5.6
78
+ * @since 5.3.0
79
+ */
80
+ public function create_free_version_notice_about_plus() {
81
+ if ( 'woocommerce-jetpack.php' !== basename( WCJ_PLUGIN_FILE ) ) {
82
+ return;
83
+ }
84
+ $class = 'notice notice-info';
85
+ /* translators: %s: search term */
86
+ $message = sprintf( __( 'You\'re using Booster free version. To unlock more features please consider <a target="_blank" href="%s">Upgrade Booster to unlock this feature</a>.', 'woocommerce-jetpack' ), 'https://booster.io/buy-booster/' );
87
+ $booster_icon = '<span class="wcj-booster-logo"></span>';
88
+ ?>
89
+ <style>
90
+ .wcj-booster-logo { width: 19px; height: 19px; display: inline-block; background: url('https://ps.w.org/woocommerce-jetpack/assets/icon-128x128.png?rev=1813426') center/cover; vertical-align: middle; position: relative; top: -1px; margin: 0 6px 0 0; }
91
+ </style>
92
+ <?php
93
+ echo wp_kses_post( '<div class="' . $class . '"><p>' . $booster_icon . $message . '</p></div>' );
94
+ }
95
 
96
+ /**
97
+ * Create_free_version_footer_review_notice.
98
+ *
99
+ * @version 5.5.6
100
+ * @since 5.3.0
101
+ */
102
+ public function create_free_version_footer_review_notice() {
103
+ if ( 'woocommerce-jetpack.php' !== basename( WCJ_PLUGIN_FILE ) ) {
104
+ return;
105
+ }
106
+ $class = 'notice notice-info inline';
107
+ $link = 'https://wordpress.org/support/plugin/woocommerce-jetpack/reviews/?filter=5#new-post';
108
+ $star = '<span class="wcj-review-icon dashicons dashicons-star-filled"></span>';
109
+ $stars_link = '<a href="' . $link . '" target="_blank">' . $star . $star . $star . $star . $star . '</a>';
110
+ $message = sprintf( __( 'Please rate <strong>Booster for WooCommerce</strong> %1$s on <a href="%2$s" target="_blank">WordPress.org</a> to help us spread the word. Thank you from Booster team!', 'woocommerce-jetpack' ), $stars_link, $link );
111
+ ?>
112
+ <style>
113
+ .wcj-review-icon { vertical-align: middle; margin: -6px 0 0 0; }
114
+ </style>
115
+ <?php
116
+ // echo '<div class="' . $class . '"><p>' . $message . '</p></div>';.
117
+ }
118
+ /**
119
+ * Create_pro_version_footer_review_notice.
120
+ *
121
+ * @version 5.5.6
122
+ * @since 5.3.1
123
+ */
124
+ public function create_pro_version_footer_review_notice() {
125
+ $sec_link = wcj_plugin_url();
126
+ ?>
127
+ <div class="circleBox">
128
+ <div class="circle-badge" style="float:right">
129
+ <img src="<?php echo esc_url( $sec_link ); ?>/assets/images/pop_icon.png">
130
+ </div>
131
+ <div class="subCircles">
132
+ <div class="sub-circle">
133
+ <div class="form_label">
134
+ <a href="https://booster.io/submit-idea/" target="_blank">
135
+ <label>Suggest a feature</label>
136
+ <div class="ic_list">
137
+ <img src="<?php echo esc_url( $sec_link ); ?>/assets/images/suggestion-w.png">
138
+ </div>
139
+ </a>
140
+ </div>
141
+ </div>
142
+ <div class="sub-circle">
143
+ <a href="https://wordpress.org/support/plugin/woocommerce-jetpack/#new-topic-0" target="_blank">
144
+ <div class="form_label">
145
+ <label>Booster Free Support (72 business hours response)</label>
146
+ <div class="ic_list"><img src="<?php echo esc_url( $sec_link ); ?>/assets/images/support-3d-w.png"></div>
147
+ </div>
148
+ </a>
149
+ </div>
150
+ <div class="sub-circle">
151
+ <a href="https://booster.io/my-account/booster-contact/" target="_blank">
152
+ <div class="form_label">
153
+ <label>Booster Plus Premium Support (4 hours - 24 hours response)</label>
154
+ <div class="ic_list"><img src="<?php echo esc_url( $sec_link ); ?>/assets/images/support-24-h-w.png"></div>
155
+ </div>
156
+ </a>
157
+ </div>
158
+ </div>
159
+ </div>
160
+ <?php
161
+ if ( 'booster-plus-for-woocommerce.php' !== basename( WCJ_PLUGIN_FILE ) ) {
162
+ return;
163
+ }
164
+ $class = 'notice notice-info inline';
165
+ $link = 'https://wordpress.org/support/plugin/woocommerce-jetpack/reviews/?filter=5#new-post';
166
+ $star = '<span class="wcj-review-icon dashicons dashicons-star-filled"></span>';
167
+ $stars_link = '<a href="' . $link . '" target="_blank">' . $star . $star . $star . $star . $star . '</a>';
168
+ /* translators: %s: search term */
169
+ $message = sprintf( __( 'Please rate <strong>Booster for WooCommerce</strong> %1$s on <a href="%2$s" target="_blank">WordPress.org</a> to help us spread the word. Thank you from Booster team!', 'woocommerce-jetpack' ), $stars_link, $link );
170
+ ?>
171
+ <style>
172
+ .wcj-review-icon { vertical-align: middle; margin: -6px 0 0 0; }
173
+ </style>
174
+ <?php
175
+ echo wp_kses_post( '<div class="' . $class . '"><p>' . $message . '</p></div>' );
176
+ }
177
 
178
+ /**
179
+ * Enqueue_admin_script.
180
+ *
181
+ * @version 5.4.3
182
+ * @since 5.4.2
183
+ */
184
+ public function enqueue_admin_script() {
185
+ wp_enqueue_script( 'wcj-admin-js', trailingslashit( wcj_plugin_url() ) . 'includes/js/wcj-admin.js', array( 'jquery' ), w_c_j()->version, true );
186
+ wp_localize_script( 'wcj-admin-js', 'admin_object', array( 'admin_object' ), false );
187
+ }
 
 
188
 
189
+ /**
190
+ * Output cats
191
+ *
192
+ * @version 5.5.6
193
+ */
194
+ public function output_cats_submenu() {
195
+ global $current_section;
196
+ $current_cat = empty( $_REQUEST['wcj-cat'] ) ? 'dashboard' : sanitize_title( $_REQUEST['wcj-cat'] );
197
+ if ( empty( $this->cats ) ) {
198
+ return;}
199
+ echo '<ul class="wcj-dashboard-header">';
200
+ $array_keys = array_keys( $this->cats );
201
+ foreach ( $this->cats as $id => $label_info ) {
202
+ $dashboard_section = '';
203
+ if ( $id == 'dashboard' ) {
204
+ $dashboard_section = '&section=by_category';
205
+ }
206
+ echo wp_kses_post(
207
+ '<li class="wcj-header-item ' . ( $current_cat == $id ? 'active' : '' ) . '"><a
208
+ href="' . admin_url( 'admin.php?page=wc-settings&tab=' . $this->id . '&wcj-cat=' . sanitize_title( $id ) . '' . $dashboard_section ) . '"
209
+ class="' . ( $current_cat == $id ? 'current' : '' ) . '">' . $label_info['label'] . '</a> ' .
210
+ ( end( $array_keys ) == $id ? '' : '' ) . ' </li>'
211
+ );
212
+ }
213
+ echo '</ul> <br class="clear" />';
214
+ }
215
 
216
+ /**
217
+ * Output sections (modules) sub menu.
218
+ *
219
+ * @version 5.5.6
220
+ * @todo (maybe) for case insensitive sorting: `array_multisort( array_map( 'strtolower', $menu ), $menu );` instead of `asort( $menu );` (see http://php.net/manual/en/function.asort.php)
221
+ */
222
+ public function output_sections_submenu() {
223
+ global $current_section;
224
+ $sections = $this->get_sections();
225
+ $current_cat = empty( $_REQUEST['wcj-cat'] ) ? 'dashboard' : sanitize_title( $_REQUEST['wcj-cat'] );
226
+ if ( 'dashboard' === $current_cat ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
 
228
+ // Counting modules
229
+ $all = 0;
230
+ $active = 0;
231
+ foreach ( $this->module_statuses as $module_status ) {
232
+ if ( isset( $module_status['id'] ) && isset( $module_status['default'] ) ) {
233
+ if ( 'yes' === wcj_get_option( $module_status['id'], $module_status['default'] ) ) {
234
+ $active++;
235
+ } elseif ( wcj_is_module_deprecated( $module_status['id'], true ) ) {
236
+ continue;
237
+ }
238
+ $all++;
239
+ }
240
+ }
241
 
242
+ $sections['by_category'] = '<span><img src="' . wcj_plugin_url() . '/assets/images/home.png"></span>' . __( 'Dashboard', 'woocommerce-jetpack' );
243
+ $sections['all_module'] = '<span><img src="' . wcj_plugin_url() . '/assets/images/multiple 1.png"></span>' . __( 'All Module', 'woocommerce-jetpack' );
244
+ $sections['active'] = '<span><img src="' . wcj_plugin_url() . '/assets/images/t-swich.png"></span>' . __( 'Active Modules', 'woocommerce-jetpack' );
245
+ $sections['manager'] = '<span><img src="' . wcj_plugin_url() . '/assets/images/setting.png"></span>' . __( 'Manage Settings', 'woocommerce-jetpack' );
246
+ if ( ! empty( $this->custom_dashboard_modules ) ) {
247
+ foreach ( $this->custom_dashboard_modules as $custom_dashboard_module_id => $custom_dashboard_module_data ) {
248
+ $sections[ $custom_dashboard_module_id ] = $custom_dashboard_module_data['title'];
249
+ }
250
+ }
251
+ if ( '' == $current_section ) {
252
+ $current_section = 'by_category';
253
+ }
254
+ }
255
+ if ( ! empty( $this->cats[ $current_cat ]['all_cat_ids'] ) ) {
256
+ foreach ( $sections as $id => $label ) {
257
+ if ( ! in_array( $id, $this->cats[ $current_cat ]['all_cat_ids'] ) ) {
258
+ unset( $sections[ $id ] );
259
+ }
260
+ }
261
+ }
262
+ if ( empty( $sections ) || 1 === count( $sections ) ) {
263
+ return;
264
+ }
265
+ foreach ( $this->cats[ $current_cat ]['all_cat_ids'] as $key => $id ) {
266
+ if ( wcj_is_module_deprecated( $id, false, true ) ) {
267
+ unset( $this->cats[ $current_cat ]['all_cat_ids'][ $key ] );
268
+ }
269
+ }
270
+ $menu = array();
271
+ foreach ( $this->cats[ $current_cat ]['all_cat_ids'] as $id ) {
272
+ $menu[ $id ] = $sections[ $id ];
273
+ }
274
+ if ( 'dashboard' !== $current_cat && 'pdf_invoicing' !== $current_cat ) {
275
+ asort( $menu );
276
+ }
277
 
278
+ $menu_links = array();
 
 
 
 
 
 
 
 
279
 
280
+ foreach ( $menu as $id => $label ) {
281
+ $url = admin_url( 'admin.php?page=wc-settings&tab=' . $this->id . '&wcj-cat=' . $current_cat . '&section=' . sanitize_title( $id ) );
282
+ $menu_links[] = '<li class="wcj-sidebar-item ' . ( $current_section == $id ? 'active' : '' ) . '"><a href="' . $url . '" class="' . ( $current_section == $id ? 'current' : '' ) . '">' . $label . '</a></li>';
283
+ }
284
+ echo wp_kses_post( implode( ' ', $menu_links ) . '<br class="clear" />' );
285
+ }
286
+ /**
287
+ * Get_cat_by_section.
288
+ *
289
+ * @param array $section An collection of settings key value pairs.
290
+ */
291
+ public function get_cat_by_section( $section ) {
292
+ foreach ( $this->cats as $id => $label_info ) {
293
+ if ( ! empty( $label_info['all_cat_ids'] ) ) {
294
+ if ( in_array( $section, $label_info['all_cat_ids'] ) ) {
295
+ return $id;
296
+ }
297
+ }
298
+ }
299
+ return '';
300
+ }
301
 
302
+ /**
303
+ * Get sections (modules).
304
+ *
305
+ * @return array
306
+ */
307
+ public function get_sections() {
308
+ return apply_filters( 'wcj_settings_sections', array( '' => __( 'Dashboard', 'woocommerce-jetpack' ) ) );
309
+ }
 
 
310
 
311
+ /**
312
+ * Active.
313
+ *
314
+ * @version 2.8.0
315
+ * @param array $active Check.
316
+ */
317
+ public function active( $active ) {
318
+ return ( 'yes' === $active ) ? 'active' : 'inactive';
319
+ }
320
 
321
+ /**
322
+ * Is_dashboard_section.
323
+ *
324
+ * @version 5.5.6
325
+ * @since 3.0.0
326
+ * @param array $current_section defines the current section.
327
+ */
328
+ public function is_dashboard_section( $current_section ) {
329
+ return in_array( $current_section, array_merge( array( '', 'all_module', 'by_category', 'active', 'manager' ), array_keys( $this->custom_dashboard_modules ) ), true );
330
+ }
331
 
332
+ /**
333
+ * Output the settings.
334
+ *
335
+ * @version 5.5.6
336
+ * @todo (maybe) admin_notices
337
+ */
338
+ public function output() {
339
 
340
+ global $current_section, $wcj_notice;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
341
 
342
+ if ( '' != $wcj_notice ) {
343
+ echo wp_kses_post( '<div id="wcj_message" class="updated"><p><strong>' . $wcj_notice . '</strong></p></div>' );
344
+ }
345
+ if ( $current_section !== 'by_category' ) {
346
+ $is_dashboard = $this->is_dashboard_section( $current_section );
 
 
 
 
 
347
 
348
+ // Deprecated message.
349
+ if ( $replacement_module = wcj_is_module_deprecated( $current_section ) ) {
350
+ echo '<div id="wcj_message" class="error">';
351
+ echo '<p>';
352
+ echo '<strong>';
353
+ echo wp_kses_post(
354
+ sprintf(
355
+ /* translators: %s: search term */
356
+ __( 'Please note that current <em>%1$s</em> module is deprecated and will be removed in future updates. Please use <em>%2$s</em> module instead.', 'woocommerce-jetpack' ),
357
+ w_c_j()->modules[ $current_section ]->short_desc,
358
+ '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $replacement_module['cat'] . '&section=' . $replacement_module['module'] ) . '">' .
359
+ $replacement_module['title'] . '</a>'
360
+ )
361
+ );
362
+ echo wp_kses_post( ' <span style="color:red;">' . __( 'Module will be removed from the module\'s list as soon as you disable it.', 'woocommerce-jetpack' ) . '</span>' );
363
+ echo '</strong>';
364
+ echo '</p>';
365
+ echo '</div>';
366
+ }
 
 
 
 
 
 
 
 
 
 
367
 
368
+ // "Under development" message
369
+ if ( isset( w_c_j()->modules[ $current_section ]->dev ) && true === w_c_j()->modules[ $current_section ]->dev ) {
370
+ echo '<div id="wcj_message" class="error">';
371
+ echo '<p>';
372
+ echo '<strong>';
373
+ echo wp_kses_post( sprintf( __( 'Please note that <em>%s</em> module is currently under development. Until stable module version is released, options can be changed or some options can be moved to paid plugin version.', 'woocommerce-jetpack' ), w_c_j()->modules[ $current_section ]->short_desc ) );
374
+ echo '</strong>';
375
+ echo '</p>';
376
+ echo '</div>';
377
+ }
378
 
379
+ if ( 'yes' === wcj_get_option( 'wcj_debug_tools_enabled', 'no' ) && 'yes' === wcj_get_option( 'wcj_debuging_enabled', 'no' ) ) {
380
+ // Breadcrumbs.
381
+ $breadcrumbs_html = '';
382
+ $breadcrumbs_html .= '<p>';
383
+ $breadcrumbs_html .= '<code>';
384
+ $breadcrumbs_html .= __( 'WooCommerce', 'woocommerce-jetpack' );
385
+ $breadcrumbs_html .= ' > ';
386
+ $breadcrumbs_html .= __( 'Settings', 'woocommerce-jetpack' );
387
+ $breadcrumbs_html .= ' > ';
388
+ $breadcrumbs_html .= __( 'Booster', 'woocommerce-jetpack' );
389
+ $breadcrumbs_html .= ' > ';
390
+ foreach ( $this->cats as $id => $label_info ) {
391
+ if ( $this->get_cat_by_section( $current_section ) === $id ) {
392
+ $breadcrumbs_html .= $label_info['label'];
393
+ break;
394
+ }
395
+ }
396
+ if ( $is_dashboard && isset( $_GET['wcj-cat'] ) && 'dashboard' != $_GET['wcj-cat'] ) {
397
+ $breadcrumbs_html .= $this->cats[ $_GET['wcj-cat'] ]['label'];
398
+ }
399
+ if ( ! $is_dashboard ) {
400
+ $breadcrumbs_html .= ' > ';
401
+ $sections = $this->get_sections();
402
+ $breadcrumbs_html .= $sections[ $current_section ];
403
+ }
404
+ $breadcrumbs_html .= '</code>';
405
+ $breadcrumbs_html .= '</p>';
406
+ echo wp_kses_post( $breadcrumbs_html );
407
+ }
408
 
409
+ $settings = $this->get_settings( $current_section );
 
 
 
 
 
 
410
 
411
+ if ( ! $is_dashboard ) {
412
+ WC_Admin_Settings::output_fields( $settings );
413
+ } else {
414
+ $this->output_dashboard( $current_section );
415
+ }
416
+ }
417
+ }
418
 
419
+ /**
420
+ * Output_dashboard.
421
+ *
422
+ * @version 5.5.6
423
+ * @param array $current_section defines the current section.
424
+ */
425
+ public function output_dashboard( $current_section ) {
426
 
427
+ if ( '' == $current_section ) {
428
+ $current_section = 'by_category';
429
+ }
 
 
 
 
 
430
 
431
+ $the_settings = $this->get_settings();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
432
 
433
+ echo wp_kses_post( '<h3>' . $the_settings[0]['title'] . '</h3>' );
434
+ if ( isset( $this->custom_dashboard_modules[ $current_section ] ) ) {
435
+ echo wp_kses_post( '<p>' . $this->custom_dashboard_modules[ $current_section ]['desc'] . '</p>' );
436
+ } elseif ( 'manager' != $current_section ) {
437
+ echo wp_kses_post( '<p>' . $the_settings[0]['desc'] . '</p>' );
438
+ } else {
439
+ echo wp_kses_post( '<p>' . __( 'This section lets you export, import or reset all Booster\'s modules settings.', 'woocommerce-jetpack' ) . '</p>' );
440
+ }
 
 
 
 
 
 
 
441
 
442
+ if ( 'all_module' === $current_section ) {
443
+ $this->output_dashboard_modules( $the_settings );
444
+ } elseif ( 'by_category' === $current_section ) {
445
+ foreach ( $this->cats as $cat_id => $cat_label_info ) {
446
+ if ( 'dashboard' === $cat_id ) {
447
+ continue;
448
+ }
449
+ if ( isset( $_GET['wcj-cat'] ) && 'dashboard' != $_GET['wcj-cat'] ) {
450
+ if ( $cat_id != $_GET['wcj-cat'] ) {
451
+ continue;
452
+ }
453
+ } else {
454
+ echo wp_kses_post( '<h4>' . $cat_label_info['label'] . '</h4>' );
455
+ }
456
+ $this->output_dashboard_modules( $the_settings, $cat_id );
457
+ }
458
+ } elseif ( 'active' === $current_section ) {
459
+ $this->output_dashboard_modules( $the_settings, 'active_modules_only' );
460
+ } elseif ( 'manager' === $current_section ) {
461
+ $table_data = array(
462
+ array(
463
+ '<button style="width:100px;" class="button-primary" type="submit" name="booster_export_settings">' . __( 'Export', 'woocommerce-jetpack' ) . '</button>',
464
+ '<em>' . __( 'Export all Booster\'s options to a file.', 'woocommerce-jetpack' ) . '</em>',
465
+ ),
466
+ array(
467
+ '<button style="width:100px;" class="button-primary" type="submit" name="booster_import_settings">' . __( 'Import', 'woocommerce-jetpack' ) . '</button>' .
468
+ ' <input type="file" name="booster_import_settings_file">',
469
+ '<em>' . __( 'Import all Booster\'s options from a file.', 'woocommerce-jetpack' ) . '</em>',
470
+ ),
471
+ array(
472
+ '<button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings"' .
473
+ wcj_get_js_confirmation( __( 'This will reset settings to defaults for all Booster modules. Are you sure?', 'woocommerce-jetpack' ) ) . '>' .
474
+ __( 'Reset', 'woocommerce-jetpack' ) . '</button>',
475
+ '<em>' . __( 'Reset all Booster\'s options.', 'woocommerce-jetpack' ) . '</em>',
476
+ ),
477
+ array(
478
+ '<button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings_meta"' .
479
+ wcj_get_js_confirmation( __( 'This will delete all Booster meta. Are you sure?', 'woocommerce-jetpack' ) ) . '>' .
480
+ __( 'Reset meta', 'woocommerce-jetpack' ) . '</button>',
481
+ '<em>' . __( 'Reset all Booster\'s meta.', 'woocommerce-jetpack' ) . '</em>',
482
+ ),
483
+ );
484
+ $manager_settings = $this->get_manager_settings();
485
+ foreach ( $manager_settings as $manager_settings_field ) {
486
+ $table_data[] = array(
487
+ '<label for="' . $manager_settings_field['id'] . '">' .
488
+ '<input name="' . $manager_settings_field['id'] . '" id="' . $manager_settings_field['id'] . '" type="' . $manager_settings_field['type'] . '"' .
489
+ ' class="" value="1" ' . checked( wcj_get_option( $manager_settings_field['id'], $manager_settings_field['default'] ), 'yes', false ) . '>' .
490
+ ' <strong>' . $manager_settings_field['title'] . '</strong>' .
491
+ '</label>',
492
+ '<em>' . $manager_settings_field['desc'] . '</em>',
493
+ );
494
+ }
495
+ echo wp_kses_post(
496
+ wcj_get_table_html(
497
+ $table_data,
498
+ array(
499
+ 'table_class' => 'widefat striped',
500
+ 'table_heading_type' => 'none',
501
+ )
502
+ )
503
+ );
504
+ }
505
 
506
+ if ( isset( $this->custom_dashboard_modules[ $current_section ] ) ) {
507
+ $table_data = array();
508
+ foreach ( $this->custom_dashboard_modules[ $current_section ]['settings'] as $_settings ) {
509
+ $table_data[] = array(
510
+ $_settings['title'],
511
+ '<label class="' . $_settings['id'] . '_label" for="' . $_settings['id'] . '">' .
512
+ '<input name="' . $_settings['id'] .
513
+ '" id="' . $_settings['id'] .
514
+ '" type="' . $_settings['type'] .
515
+ '" class="' . $_settings['class'] .
516
+ '" value="' . wcj_get_option( $_settings['id'], $_settings['default'] ) . '"> <em>' . $_settings['desc'] . '</em></label>',
517
+ );
518
+ }
519
+ echo wp_kses_post(
520
+ wcj_get_table_html(
521
+ $table_data,
522
+ array(
523
+ 'table_class' => 'widefat striped',
524
+ 'table_heading_type' => 'vertical',
525
+ )
526
+ )
527
+ );
528
+ }
529
 
530
+ $plugin_data = get_plugin_data( WCJ_PLUGIN_FILE );
531
+ $plugin_title = ( isset( $plugin_data['Name'] ) ? '[' . $plugin_data['Name'] . '] ' : '' );
532
+ echo wp_kses_post(
533
+ '<p style="text-align:right;color:gray;font-size:x-small;font-style:italic;">' . $plugin_title .
534
+ __( 'Version', 'woocommerce-jetpack' ) . ': ' . wcj_get_option( WCJ_VERSION_OPTION, 'N/A' ) . '</p>'
535
+ );
536
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
537
 
538
+ /**
539
+ * Compare_for_usort.
540
+ *
541
+ * @param string $a this defines title.
542
+ * @param string $b this defines title.
543
+ */
544
+ private function compare_for_usort( $a, $b ) {
545
+ return strcmp( $a['title'], $b['title'] );
546
+ }
 
 
 
 
 
547
 
548
+ /**
549
+ * Output_dashboard_modules.
550
+ *
551
+ * @version 3.3.0
552
+ * @param array $settings this defines title.
553
+ * @param string $cat_id this defines title.
554
+ */
555
+ public function output_dashboard_modules( $settings, $cat_id = '' ) {
556
+ ?>
557
+ <div class="wcj-active-modules">
558
+ <table class="wp-list-table widefat striped plugins">
559
+ <thead>
560
+ <tr>
561
+ <th scope="col" id="cb" class="manage-column column-cb check-column" style=""><label class="screen-reader-text" for="cb-select-all-1"><?php _e( 'Select All', 'woocommerce-jetpack' ); ?></label><input id="cb-select-all-1" type="checkbox" style="margin-top:15px;"></th>
562
+ <th scope="col" id="name" class="manage-column column-name" style="">
563
+ <?php _e( 'Module', 'woocommerce-jetpack' ); ?></th>
564
+ <th scope="col" id="description" class="manage-column column-description" style="">
565
+ <?php _e( 'Description', 'woocommerce-jetpack' ); ?></th>
566
+ </tr>
567
+ </thead>
568
+ <tfoot>
569
+ <tr>
570
+ <th scope="col" class="manage-column column-cb check-column" style=""><label class="screen-reader-text" for="cb-select-all-2"><?php _e( 'Select All', 'woocommerce-jetpack' ); ?></label><input id="cb-select-all-2" type="checkbox" style="margin-top:15px;"></th>
571
+ <th scope="col" class="manage-column column-name" style=""><?php _e( 'Module', 'woocommerce-jetpack' ); ?>
572
+ </th>
573
+ <th scope="col" class="manage-column column-description" style="">
574
+ <?php _e( 'Description', 'woocommerce-jetpack' ); ?></th>
575
+ </tr>
576
+ </tfoot>
577
+ <tbody id="the-list">
578
+ <?php
579
+ $html = '';
580
+ usort( $settings, array( $this, 'compare_for_usort' ) );
581
+ $total_modules = 0;
582
+ foreach ( $settings as $the_feature ) {
583
+ if ( 'checkbox' !== $the_feature['type'] ) {
584
+ continue;
585
+ }
586
+ $section = $the_feature['id'];
587
+ $section = str_replace( 'wcj_', '', $section );
588
+ $section = str_replace( '_enabled', '', $section );
589
+ if ( wcj_is_module_deprecated( $section, false, true ) ) {
590
+ continue;
591
+ }
592
+ if ( '' != $cat_id ) {
593
+ if ( 'active_modules_only' === $cat_id ) {
594
+ if ( 'no' === wcj_get_option( $the_feature['id'], 'no' ) ) {
595
+ continue;
596
+ }
597
+ } elseif ( $cat_id != $this->get_cat_by_section( $section ) ) {
598
+ continue;
599
+ }
600
+ }
601
+ $total_modules++;
602
+ $html .= '<tr id="' . $the_feature['id'] . '" class="' . $this->active( wcj_get_option( $the_feature['id'] ) ) . '">';
603
+ $html .= '<th scope="row" class="check-column">';
604
+ $html .= '<label class="screen-reader-text" for="' . $the_feature['id'] . '">' . $the_feature['desc'] . '</label>';
605
+ $html .= '<input type="checkbox" name="' . $the_feature['id'] . '" value="1" id="' . $the_feature['id'] . '" ' . checked( wcj_get_option( $the_feature['id'] ), 'yes', false ) . '>';
606
+ $html .= '</th>';
607
+ $html .= '<td class="plugin-title"><strong>' . $the_feature['title'] . '</strong>';
608
+ $html .= '<div class="row-actions visible">';
609
+ $html .= '<span class="0"><a href="' . admin_url() . 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $this->get_cat_by_section( $section ) . '&section=' . $section . '">' . __( 'Settings', 'woocommerce' ) . '</a></span>';
610
+ if ( isset( $the_feature['wcj_link'] ) && '' != $the_feature['wcj_link'] ) {
611
+ $html .= ' | <span class="0"><a href="' . $the_feature['wcj_link'] . '?utm_source=module_documentation&utm_medium=dashboard_link&utm_campaign=booster_documentation" target="_blank">' . __( 'Documentation', 'woocommerce' ) . '</a></span>';
612
+ }
613
+ $html .= '</div>';
614
+ $html .= '</td>';
615
+ $html .= '<td class="column-description desc">';
616
+ $html .= '<div class="plugin-description"><p>' . ( ( isset( $the_feature['wcj_desc'] ) ) ? $the_feature['wcj_desc'] : $the_feature['desc_tip'] ) . '</p></div>';
617
+ $html .= '</td>';
618
+ $html .= '</tr>';
619
+ }
620
+ echo wp_kses_post( $html );
621
+ if ( 0 == $total_modules && 'active_modules_only' === $cat_id ) {
622
+ echo wp_kses_post( '<tr><td colspan="3"><em>' . __( 'No active modules found.', 'woocommerce-jetpack' ) . '</em></td></tr>' );
623
+ }
624
+ ?>
625
+ </tbody>
626
+ </table>
627
+ <p style="color:#000;font-size:12px;font-style:italic;">
628
+ <?php echo wp_kses_post( __( 'Total Modules:' ) . ' ' . $total_modules ); ?>
629
+ </p>
630
+ </div>
631
+ <?php
632
+ }
633
 
634
+ /**
635
+ * Save settings.
636
+ *
637
+ * @version 5.3.8
638
+ */
639
+ public function save() {
640
+ global $current_section;
641
+ $settings = $this->get_settings( $current_section );
642
+ WC_Admin_Settings::save_fields( $settings );
643
+ $this->disable_autoload_options_from_section( $settings );
644
+ add_action( 'admin_notices', array( $this, 'booster_message_global' ) );
645
+ do_action( 'woojetpack_after_settings_save', $this->get_sections(), $current_section );
646
+ }
647
 
648
+ /**
649
+ * Disable_autoload_options.
650
+ *
651
+ * @version 5.3.3
652
+ * @since 5.3.3
653
+ *
654
+ * @param array $settings defines the settings.
655
+ */
656
+ public function disable_autoload_options_from_section( $settings ) {
657
+ $fields = wp_list_filter( $settings, array( 'autoload' => false ) );
658
+ $fields = wp_list_filter( $fields, array( 'type' => 'title' ), 'NOT' );
659
+ $fields = wp_list_filter( $fields, array( 'type' => 'sectionend' ), 'NOT' );
660
+ $field_ids = wp_list_pluck( $fields, 'id' );
661
+ $fields_ids_str = '\'' . implode( '\',\'', $field_ids ) . '\'';
662
+ global $wpdb;
663
+ $sql = "
664
+ UPDATE {$wpdb->options} SET autoload = 'no'
665
+ WHERE option_name IN ({$fields_ids_str}) AND autoload != 'no'
666
+ ";
667
+ $wpdb->query( $sql );
668
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
669
 
670
+ /**
671
+ * Booster_message_global.
672
+ *
673
+ * @version 3.6.0
674
+ * @since 3.6.0
675
+ */
676
+ public function booster_message_global() {
677
+ if ( '' != ( $message = apply_filters( 'booster_message', '', 'global' ) ) ) {
678
+ echo wp_kses_post( $message );
679
+ }
680
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
681
 
682
+ /**
683
+ * Get_manager_settings.
684
+ *
685
+ * @version 3.5.0
686
+ * @since 2.6.0
687
+ * @return array
688
+ */
689
+ public function get_manager_settings() {
690
+ return array(
691
+ array(
692
+ 'title' => __( 'Autoload Booster\'s Options', 'woocommerce-jetpack' ),
693
+ 'type' => 'checkbox',
694
+ 'desc' => __( 'Choose if you want Booster\'s options to be autoloaded when calling add_option. After saving this option, you need to Reset all Booster\'s settings. Leave default value (i.e. Enabled) if not sure.', 'woocommerce-jetpack' ),
695
+ 'id' => 'wcj_autoload_options',
696
+ 'default' => 'yes',
697
+ ),
698
+ array(
699
+ 'title' => __( 'Load Modules on Init Hook', 'woocommerce-jetpack' ),
700
+ 'type' => 'checkbox',
701
+ 'desc' => __( 'Choose if you want to load Booster Modules on Init hook.', 'woocommerce-jetpack' ) . ' ' . __( 'It will load the locale appropriately if users change it from the profile page.', 'woocommerce-jetpack' ),
702
+ 'id' => 'wcj_load_modules_on_init',
703
+ 'default' => 'no',
704
+ ),
705
+ array(
706
+ 'title' => __( 'Use List Instead of Comma Separated Text for Products in Settings', 'woocommerce-jetpack' ),
707
+ 'type' => 'checkbox',
708
+ 'desc' => sprintf(
709
+ __( 'Supported modules: %s.', 'woocommerce-jetpack' ),
710
+ implode(
711
+ ', ',
712
+ array(
713
+ __( 'Gateways per Product or Category', 'woocommerce-jetpack' ),
714
+ __( 'Global Discount', 'woocommerce-jetpack' ),
715
+ __( 'Product Info', 'woocommerce-jetpack' ),
716
+ __( 'Product Input Fields', 'woocommerce-jetpack' ),
717
+ __( 'Products XML', 'woocommerce-jetpack' ),
718
+ __( 'Related Products', 'woocommerce-jetpack' ),
719
+ )
720
+ )
721
+ ),
722
+ 'id' => 'wcj_list_for_products',
723
+ 'default' => 'yes',
724
+ ),
725
+ array(
726
+ 'title' => __( 'Use List Instead of Comma Separated Text for Products Categories in Settings', 'woocommerce-jetpack' ),
727
+ 'type' => 'checkbox',
728
+ 'desc' => sprintf(
729
+ __( 'Supported modules: %s.', 'woocommerce-jetpack' ),
730
+ implode(
731
+ ', ',
732
+ array(
733
+ __( 'Product Info', 'woocommerce-jetpack' ),
734
+ )
735
+ )
736
+ ),
737
+ 'id' => 'wcj_list_for_products_cats',
738
+ 'default' => 'yes',
739
+ ),
740
+ array(
741
+ 'title' => __( 'Use List Instead of Comma Separated Text for Products Tags in Settings', 'woocommerce-jetpack' ),
742
+ 'type' => 'checkbox',
743
+ 'desc' => sprintf(
744
+ __( 'Supported modules: %s.', 'woocommerce-jetpack' ),
745
+ implode(
746
+ ', ',
747
+ array(
748
+ __( 'Product Info', 'woocommerce-jetpack' ),
749
+ )
750
+ )
751
+ ),
752
+ 'id' => 'wcj_list_for_products_tags',
753
+ 'default' => 'yes',
754
+ ),
755
+ );
756
+ }
757
+ /**
758
+ * Get settings array
759
+ *
760
+ * @version 3.0.0
761
+ * @return array $current_section defines the current section.
762
+ */
763
+ public function get_settings( $current_section = '' ) {
764
+ if ( ! $this->is_dashboard_section( $current_section ) ) {
765
+ return apply_filters( 'wcj_settings_' . $current_section, array() );
766
+ } elseif ( 'manager' === $current_section ) {
767
+ return $this->get_manager_settings();
768
+ } elseif ( isset( $this->custom_dashboard_modules[ $current_section ] ) ) {
769
+ return $this->custom_dashboard_modules[ $current_section ]['settings'];
770
+ } else {
771
+ $cat_id = ( isset( $_GET['wcj-cat'] ) && '' != $_GET['wcj-cat'] ) ? $_GET['wcj-cat'] : 'dashboard';
772
+ $settings[] = array(
773
+ 'title' => __( 'Booster for WooCommerce', 'woocommerce-jetpack' ) . ' - ' . $this->cats[ $cat_id ]['label'],
774
+ 'type' => 'title',
775
+ 'desc' => $this->cats[ $cat_id ]['desc'],
776
+ 'id' => 'wcj_' . $cat_id . '_options',
777
+ );
778
+ if ( 'dashboard' === $cat_id ) {
779
+ $settings = array_merge( $settings, $this->module_statuses );
780
+ } else {
781
+ $cat_module_statuses = array();
782
+ foreach ( $this->module_statuses as $module_status ) {
783
+ $section = $module_status['id'];
784
+ $section = str_replace( 'wcj_', '', $section );
785
+ $section = str_replace( '_enabled', '', $section );
786
+ if ( $cat_id === $this->get_cat_by_section( $section ) ) {
787
+ $cat_module_statuses[] = $module_status;
788
+ }
789
+ }
790
+ $settings = array_merge( $settings, $cat_module_statuses );
791
+ }
792
+ $settings[] = array(
793
+ 'type' => 'sectionend',
794
+ 'id' => 'wcj_' . $cat_id . '_options',
795
+ 'title' => '', // for usort.
796
+ );
797
+ return $settings;
798
+ }
799
+ }
800
 
801
+ /**
802
+ * Add_module_statuses.
803
+ */
804
+ public function add_module_statuses( $statuses ) {
805
+ $this->module_statuses = $statuses;
806
+ }
807
 
808
+ public function version_details() {
 
809
 
810
+ $file = wcj_plugin_path() . '/version-details.txt';
811
+ if ( file_exists( $file ) ) {
 
 
 
 
 
 
812
 
813
+ $doc = file_get_contents( $file );
814
+ $line = explode( "\n", $doc );
815
+ foreach ( $line as $newline ) {
816
+ echo wp_kses_post( $newline . '<br>' );
817
+ }
818
+ }
819
 
820
+ }
 
 
 
 
 
821
 
822
+ /**
823
+ * Dasboard_menu.
824
+ *
825
+ * @version 5.5.6
826
+ * @return array
827
+ */
828
+ public function dasboard_menu() {
829
+ global $current_section;
830
+ $_section = isset( $_GET['section'] ) ? $_GET['section'] : '';
831
+ $_wcj_cat = isset( $_GET['wcj-cat'] ) ? $_GET['wcj-cat'] : '';
832
+ $_wcj_tab = isset( $_GET['tab'] ) ? $_GET['tab'] : '';
833
+ if ( $_wcj_tab == 'jetpack' && ( $_section == '' || $_section == 'by_category' ) && ( $_wcj_cat == '' || $_wcj_cat == 'dashboard' ) ) {
834
+ ?>
835
+ <style>
836
+ button.button-primary.woocommerce-save-button {
837
+ display: none;
838
+ }
839
+ </style>
840
+ <?php
841
+ }
842
+ ?>
843
+ <div class="wcj-main-container dashboard">
844
+ <div class="wcj-body">
845
+ <section class="wcj-sidebar">
846
+ <div class="wcj-dashboard-logo">
847
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/logo.png'; ?>">
848
+ </div>
849
+ <div class="wcj-nav-sidebar">
850
+ <ul>
851
+ <?php echo wp_kses_post( $this->output_sections_submenu() ); ?>
852
+ <a href="https://booster.io/contact-us/" class="wcj-button" target="_blank"><?php _e( 'Need Help?', 'woocommerce-jetpack' ); ?><span><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/need-help.png'; ?>"></span></a>
853
+ </ul>
854
+ </div>
855
+ </section>
856
+ <section class="wcj-body-container wcj-setting-jetpack">
857
+ <header>
858
+ <?php echo wp_kses_post( $this->output_cats_submenu() ); ?>
859
+ </header>
860
+ <div class="wcj-setting-jetpack-body
861
+ <?php
862
+ if ( $_section === 'pdf_invoicing_extra_columns' ) {
863
+ echo 'wcj_invoice_pdf_dtl';}
864
+ ?>
865
+ " style="
866
+ <?php
867
+ if ( $_section === 'by_category' ) {
868
+ echo 'display:none;';
869
+ }if ( $_wcj_tab == 'jetpack' && $_wcj_cat == '' ) {
870
+ echo 'padding: 0px;';}
871
+ ?>
872
+ ">
873
+ <?php if ( $current_section === 'by_category' ) { ?>
874
+ </div>
875
+ <div class="wcj-body-part">
876
+ <div class="wcj-sub-cnt-top">
877
+ <div class="wcj-sub-cnt-top-left">
878
+ <div class="wcj-tit">
879
+ <h1><?php _e( 'My Account', 'woocommerce-jetpack' ); ?></h1>
880
+ </div>
881
+ </div>
882
+ <div class="wcj-btn-main">
883
+ <a href="https://booster.io/buy-booster/" class="wcj-button" target="_blank"><?php _e( 'Get Booster Plus', 'woocommerce-jetpack' ); ?></a>
884
+ </div>
885
+ </div>
886
+ <div class="wcj-body-sec-part-main">
887
+ <div class="wcj-body-parts wcj-body-left">
888
+ <div class="wcj-info-section wcj-box">
889
+ <div class="wcj-tit">
890
+ <h3><?php _e( 'Getting Started', 'woocommerce-jetpack' ); ?></h3>
891
+ </div>
892
+ <ul class="wcj-dashboard-info-ul">
893
+ <li><a target="_blank" href="https://booster.io/docs/dashboard"><?php _e( 'Dashboard', 'woocommerce-jetpack' ); ?></a></li>
894
+ <li><a target="_blank" href="https://booster.io/docs/how-to-navigate-through-booster-categories-and-modules-smoothly"><?php _e( 'Navigating Categories', 'woocommerce-jetpack' ); ?></a></li>
895
+ <li><a target="_blank" href="https://booster.io/docs/how-to-get-started-with-booster"><?php _e( 'How to get started with booster', 'woocommerce-jetpack' ); ?></a></li>
896
+ </ul>
897
+ </div>
898
+ <div class="wcj-faq-section wcj-box">
899
+ <div class="wcj-tit">
900
+ <h3><?php _e( 'Frequently Asked Questions', 'woocommerce-jetpack' ); ?></h3>
901
+ </div>
902
+ <div class="wcj-faq-body">
903
+ <div class="wcj-faq-sing-box">
904
+ <div class="wcj-accordion">
905
+ <h6><?php _e( 'Do I need to have coding skills to use Booster Plus?', 'woocommerce-jetpack' ); ?></h6>
906
+ <span><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/down-arw.png'; ?>"></span>
907
+ </div>
908
+ <div class="wcj-panel">
909
+ <p><?php _e( 'Absolutely not. You can configure pretty much everything Booster Plus has to offer without any coding knowledge.', 'woocommerce-jetpack' ); ?></p>
910
+ </div>
911
+ </div>
912
+ <div class="wcj-faq-sing-box">
913
+ <div class="wcj-accordion">
914
+ <h6><?php _e( 'Will Booster Plus slow down my website?', 'woocommerce-jetpack' ); ?></h6>
915
+ <span><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/down-arw.png'; ?>"></span>
916
+ </div>
917
+ <div class="wcj-panel">
918
+ <p><?php _e( 'Absolutely not. Booster Plus is carefully built with performance in mind.', 'woocommerce-jetpack' ); ?></p>
919
+ </div>
920
+ </div>
921
+ <div class="wcj-faq-sing-box">
922
+ <div class="wcj-accordion">
923
+ <h6><?php _e( 'Do you offer refunds?', 'woocommerce-jetpack' ); ?></h6>
924
+ <span><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/down-arw.png'; ?>"></span>
925
+ </div>
926
+ <div class="wcj-panel">
927
+ <p><?php _e( 'If you are not completely satisfied with Booster Plus within the fist 30 days, you can request a refund and we will give you 100% of your money back – no questions asked.', 'woocommerce-jetpack' ); ?></p>
928
+ </div>
929
+ </div>
930
+ <div class="wcj-faq-sing-box">
931
+ <div class="wcj-accordion">
932
+ <h6><?php _e( 'Can I use Booster Plus on client sites?', 'woocommerce-jetpack' ); ?></h6>
933
+ <span><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/down-arw.png'; ?>"></span>
934
+ </div>
935
+ <div class="wcj-panel">
936
+ <p><?php _e( 'Yes, you can use Booster Plus on client sites. You can purchase the multiple sites license of Booster Plus.', 'woocommerce-jetpack' ); ?></p>
937
+ </div>
938
+ </div>
939
+ <div class="wcj-faq-sing-box">
940
+ <div class="wcj-accordion">
941
+ <h6><?php _e( 'Do you have an affiliate program?', 'woocommerce-jetpack' ); ?></h6>
942
+ <span><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/down-arw.png'; ?>"></span>
943
+ </div>
944
+ <div class="wcj-panel">
945
+ <p><?php _e( 'Yes, We do have an affiliate program. ', 'woocommerce-jetpack' ); ?><a href="https://booster.io/affiliate-program/" target="_blannk"><?php _e( 'Click here', 'woocommerce-jetpack' ); ?></a><?php _e( ' for the details.', 'woocommerce-jetpack' ); ?></p>
946
+ </div>
947
+ </div>
948
+ <div class="wcj-faq-sing-box">
949
+ <div class="wcj-accordion">
950
+ <h6><?php _e( 'Why should I choose the Booster Plus suite over other individual plugins?', 'woocommerce-jetpack' ); ?></h6>
951
+ <span><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/down-arw.png'; ?>"></span>
952
+ </div>
953
+ <div class="wcj-panel">
954
+ <p><?php _e( "Oh, that's an easy one! Implementing just a few modules from the Booster Plus suite is more cost-effective than using dozens of individual plugins often priced at $15-$30 each. On top of that, stacking your site with a lot of different plugins can make it bloated and slow. What's worse, all those individual plugins don't always play nice together. But Booster Plus is the solution to all that nonsense. The Booster Plus suite features over 100 compatible modules that allow you to add custom features and functionality to your WooCommerce site easily.", 'woocommerce-jetpack' ); ?></p>
955
+ </div>
956
+ </div>
957
+ <div class="wcj-faq-sing-box">
958
+ <div class="wcj-accordion">
959
+ <h6><?php _e( 'What features does Booster Plus have?', 'woocommerce-jetpack' ); ?></h6>
960
+ <span><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/down-arw.png'; ?>"></span>
961
+ </div>
962
+ <div class="wcj-panel">
963
+ <p><?php _e( 'You can see all the features at ', 'woocommerce-jetpack' ); ?><a href="https://booster.io/about/" target="_blank"><?php _e( 'About Booster', 'woocommerce-jetpack' ); ?></a><?php _e( ' page.', 'woocommerce-jetpack' ); ?></p>
964
+ </div>
965
+ </div>
966
+ <div class="wcj-additional-que">
967
+ <h6><?php _e( 'Still have a question?', 'woocommerce-jetpack' ); ?></h6>
968
+ <a href="https://booster.io/contact-us/" class="wcj-button" target="_blank"><?php _e( 'CONTACT BOOSTER SUPPORT', 'woocommerce-jetpack' ); ?></a>
969
+ </div>
970
+ </div>
971
+ </div>
972
+ <div class="wcj-social-connect wcj-box">
973
+ <div class="wcj-tit">
974
+ <h3><?php _e( 'Connect with Booster', 'woocommerce-jetpack' ); ?></h3>
975
+ </div>
976
+ <div class="wcj-socialmedia-connect">
977
+ <div class="wcj-btn-main">
978
+ <a href="https://booster.io/" class="wcj-button" target="_blank"><?php _e( 'BOOSTER WEBSITE', 'woocommerce-jetpack' ); ?></a>
979
+ </div>
980
+ <ul class="wcj-social-icn">
981
+ <li><a href="https://www.youtube.com/channel/UCVQg0c4XIirUI3UnGoX9HVg?sub_confirmation=1"><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/YouTube.png'; ?>"></a></li>
982
+ <li><a href="https://www.facebook.com/booster.for.woocommerce"><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/Facebook.png'; ?>"></a></li>
983
+ <li><a href="https://twitter.com/intent/follow?screen_name=BoosterForWoo"><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/Twitter.png'; ?>"></a></li>
984
+ <li><a href="https://www.linkedin.com/company/booster-for-woocommerce"><img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/Linkedin.png'; ?>"></a></li>
985
+ </ul>
986
+ </div>
987
+ </div>
988
+ </div>
989
+ <div class="wcj-body-parts wcj-body-right">
990
+ <div class="wcj-partitions action-section">
991
+ <div class="wcj-tit">
992
+ <h3><?php _e( 'Actions', 'woocommerce-jetpack' ); ?></h3>
993
+ </div>
994
+ <div class="wcj-action-sub-part">
995
+ <div class="wcj-action-sub-sing-box">
996
+ <div class="wcj-action-single-bx">
997
+ <div class="wcj-action-sub-sing-icon">
998
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/ArrowSquareIn.png'; ?>">
999
+ </div>
1000
+ <div class="wcj-actions-part">
1001
+ <input type="file" name="booster_import_settings_file">
1002
+ <h6><button style="width:100px;" class="button-primary" type="submit" name="booster_import_settings"><?php _e( 'Import', 'woocommerce-jetpack' ); ?></button></h6>
1003
+ <p><?php _e( 'Import Booster options', 'woocommerce-jetpack' ); ?></p>
1004
+ </div>
1005
+ </div>
1006
+ <div class="wcj-action-single-bx">
1007
+ <div class="wcj-action-sub-sing-icon">
1008
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/Export.png'; ?>">
1009
+ </div>
1010
+ <div class="wcj-actions-part">
1011
+ <h6><button style="width:100px;" class="button-primary wcj-export-btn" type="submit" name="booster_export_settings"><?php _e( 'Export', 'woocommerce-jetpack' ); ?></button></h6>
1012
+ <p><?php _e( 'Export Booster options', 'woocommerce-jetpack' ); ?></p>
1013
+ </div>
1014
+ </div>
1015
+ </div>
1016
+ <div class="wcj-action-sub-sing-box">
1017
+ <div class="wcj-action-single-bx">
1018
+ <div class="wcj-action-sub-sing-icon">
1019
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/Repeat.png'; ?>">
1020
+ </div>
1021
+ <div class="wcj-actions-part">
1022
+ <h6><button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings" onclick="return confirm('This will reset settings to defaults for all Booster modules. Are you sure?')"><?php _e( 'Reset', 'woocommerce-jetpack' ); ?></button></h6>
1023
+ <p><?php _e( "Reset all Booster's options", 'woocommerce-jetpack' ); ?></p>
1024
+ </div>
1025
+ </div>
1026
+ <div class="wcj-action-single-bx">
1027
+ <div class="wcj-action-sub-sing-icon">
1028
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/RepeatOnce.png'; ?>">
1029
+ </div>
1030
+ <div class="wcj-actions-part">
1031
+ <h6><button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings_meta" onclick="return confirm('This will delete all Booster meta. Are you sure?')"><?php _e( 'Reset meta', 'woocommerce-jetpack' ); ?></button></h6>
1032
+ <p><?php _e( "Reset all Booster's meta", 'woocommerce-jetpack' ); ?></p>
1033
+ </div>
1034
+ </div>
1035
+ </div>
1036
+ </div>
1037
+ </div>
1038
+ <div class="wcj-partitions documentation-section">
1039
+ <div class="wcj-tit">
1040
+ <h3><?php _e( 'Documentation', 'woocommerce-jetpack' ); ?></h3>
1041
+ </div>
1042
+ <div class="wcj-documentation-dtl">
1043
+ <div class="wcj-documentation-icon">
1044
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/documentation.png'; ?>">
1045
+ </div>
1046
+ <div class="wcj-documentation-sm-rh-dtl">
1047
+ <p><?php _e( 'Here you can find all documentation of Booster', 'woocommerce-jetpack' ); ?></p>
1048
+ <div class="wcj-btn-main">
1049
+ <a href="https://booster.io/docs/" class="wcj-button" target="_blank"><?php _e( 'See Documentation', 'woocommerce-jetpack' ); ?></a>
1050
+ </div>
1051
+ </div>
1052
+ </div>
1053
+ </div>
1054
+ <div class="wcj-partitions updates-section">
1055
+ <div class="wcj-tit">
1056
+ <h3><?php _e( 'Latest updates', 'woocommerce-jetpack' ); ?></h3>
1057
+ </div>
1058
+ <div class="wcj-partitions-sub-dtl">
1059
+ <h6><?php _e( 'Version ', 'woocommerce-jetpack' ); ?><?php echo wp_kses_post( w_c_j()->version ); ?></h6>
1060
+ <ul class="wcj-updates-ul">
1061
+ <li><?php $this->version_details(); ?></li>
1062
+ </ul>
1063
+ <div class="wcj-btn-main">
1064
+ <a href="https://booster.io/changelog/" class="wcj-button" target="_blank"><?php _e( 'SEE MORE', 'woocommerce-jetpack' ); ?></a>
1065
+ </div>
1066
+ </div>
1067
+ </div>
1068
+ </div>
1069
+ </div>
1070
+ </div>
1071
+ </section>
1072
  </div>
1073
  <div class="wcj-footer">
1074
+ <div class="wcj-review-footer">
1075
+ <p><?php _e( 'Please rate ', 'woocommerce-jetpack' ); ?><strong><?php _e( 'Booster for Woocommerce', 'woocommerce-jetpack' ); ?></strong>
1076
+ <span class="wcj-woo-star">
1077
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/star.png'; ?>">
1078
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/star.png'; ?>">
1079
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/star.png'; ?>">
1080
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/star.png'; ?>">
1081
+ <img src="<?php echo esc_url( wcj_plugin_url() ) . '/assets/images/star.png'; ?>">
1082
+ </span>
1083
+ <strong><a href="https://wordpress.org/support/plugin/woocommerce-jetpack/reviews/?rate=5#new-post" target="_blank"><?php _e( 'WordPress.org', 'woocommerce-jetpack' ); ?></a></strong><?php _e( ' to help us spread the word. Thank you from Booster team!', 'woocommerce-jetpack' ); ?>
1084
+ </p>
1085
+ </div>
1086
+ <div class="wcj-review-footer wcj-premium-features-footer">
1087
+ <h6><?php _e( 'Upgrade today to unlock these popular premium features:', 'woocommerce-jetpack' ); ?></h6>
1088
+ <ul>
1089
+ <li><strong><?php _e( '+ PDF Invoices and Packing slips –', 'woocommerce-jetpack' ); ?></strong><?php _e( 'Add ability to create Proforma Invoices, Credit Notes and Packaging slips', 'woocommerce-jetpack' ); ?></li>
1090
+ <li><strong><?php _e( '+ Empty Cart –', 'woocommerce-jetpack' ); ?></strong><?php _e( 'customize empty cart button text, different button positions on cart page', 'woocommerce-jetpack' ); ?></li>
1091
+ <li><strong><?php _e( '+ Cart and checkout –', 'woocommerce-jetpack' ); ?></strong><?php _e( 'add multiple – custom fields, custom info blocks, check out file uploads', 'woocommerce-jetpack' ); ?></li>
1092
+ <li><strong><?php _e( '+ Mini cart –', 'woocommerce-jetpack' ); ?></strong><?php _e( 'More custom information options', 'woocommerce-jetpack' ); ?> </li>
1093
+ <li><strong><?php _e( '+ Prices and currencies –', 'woocommerce-jetpack' ); ?></strong><?php _e( 'add more unlimited number of currencies to WooCommerce', 'woocommerce-jetpack' ); ?> </li>
1094
+ <li><strong><?php _e( '+ Export options –', 'woocommerce-jetpack' ); ?></strong><?php _e( 'more fields enabled', 'woocommerce-jetpack' ); ?> </li>
1095
+ <li><strong><?php _e( '+ Add to cart –', 'woocommerce-jetpack' ); ?></strong><?php _e( 'customize add to cart messages, Button labels - multiple category groups allowed+ +', 'woocommerce-jetpack' ); ?></li>
1096
+ <li><?php _e( '+ More configuration options for payments and shipping', 'woocommerce-jetpack' ); ?></li>
1097
+ </ul>
1098
+ <div class="wcj-btn-main">
1099
+ <a href="https://booster.io/buy-booster/" class="wcj-button" target="_blank"><?php _e( 'Upgrade to Booster Plus', 'woocommerce-jetpack' ); ?></a>
1100
+ </div>
1101
+ </div>
1102
+ </div>
 
1103
  </div>
1104
+ <?php
1105
+ }
1106
+ }
1107
 
1108
+ }
 
 
 
 
1109
 
1110
  endif;
1111
 
includes/admin/class-wcj-settings-custom-fields.php CHANGED
@@ -5,79 +5,86 @@
5
  * @version 5.5.6
6
  * @since 2.8.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Settings_Custom_Fields' ) ) :
 
 
 
 
13
 
14
- class WCJ_Settings_Custom_Fields {
15
-
16
- /**
17
- * Constructor.
18
- *
19
- * @version 3.2.4
20
- * @since 2.8.0
21
- */
22
- function __construct() {
23
- add_action( 'woocommerce_admin_field_wcj_save_settings_button', array( $this, 'output_wcj_save_settings_button' ) );
24
- add_action( 'woocommerce_admin_field_wcj_number_plus_checkbox_start', array( $this, 'output_wcj_number_plus_checkbox_start' ) );
25
- add_action( 'woocommerce_admin_field_wcj_number_plus_checkbox_end', array( $this, 'output_wcj_number_plus_checkbox_end' ) );
26
- add_filter( 'woocommerce_admin_settings_sanitize_option', array( $this, 'format_wcj_number_plus_checkbox_end' ), PHP_INT_MAX, 3 );
27
- add_action( 'woocommerce_admin_field_custom_textarea', array( $this, 'output_custom_textarea' ) );
28
- add_filter( 'woocommerce_admin_settings_sanitize_option', array( $this, 'unclean_custom_textarea' ), PHP_INT_MAX, 3 );
29
- add_action( 'woocommerce_admin_field_custom_number', array( $this, 'output_custom_number' ) );
30
- add_action( 'woocommerce_admin_field_custom_link', array( $this, 'output_custom_link' ) );
31
- add_action( 'woocommerce_admin_field_module_tools', array( $this, 'output_module_tools' ) );
32
- add_filter( 'woocommerce_admin_settings_sanitize_option', array( $this, 'maybe_unclean_field' ), PHP_INT_MAX, 3 );
33
- add_action( 'woocommerce_admin_field_exchange_rate', array( $this, 'output_exchange_rate_settings_button' ) );
34
- }
35
 
36
- /**
37
- * output_exchange_rate_settings_button.
38
- *
39
- * @version 5.2.0
40
- */
41
- function output_exchange_rate_settings_button( $value ) {
 
42
 
43
- $value['type'] = 'number';
44
 
45
- $option_value = wcj_get_option( $value['id'], $value['default'] );
46
 
47
- // Custom attribute handling
48
- $custom_attributes = array();
49
- if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
50
- foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
51
- $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
52
- }
53
- } else {
54
- if (
55
- ! WCJ()->modules['currency_exchange_rates']->is_enabled()
56
- || 'yes' !== wcj_get_option( 'wcj_currency_exchange_rates_point_decimal_separator', 'no' )
57
- ) {
58
- $custom_attributes = array( 'step="' . sprintf( "%.12f", 1 / pow( 10, 12 ) ) . '"', 'min="0"' );
59
  } else {
60
- $custom_attributes = array( 'step="0.00000001"', 'min="0"' );
 
 
 
 
 
 
 
61
  }
62
- }
63
- $custom_attributes_button = array();
64
- if ( ! empty( $value['custom_attributes_button'] ) && is_array( $value['custom_attributes_button'] ) ) {
65
- foreach ( $value['custom_attributes_button'] as $attribute => $attribute_value ) {
66
- $custom_attributes_button[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
67
  }
68
- }
69
- $tip = '';
70
- $description = '';
71
- $exchange_rate_server = wcj_get_currency_exchange_rate_server_name( $value['custom_attributes_button']['currency_from'], $value['custom_attributes_button']['currency_to'] );
72
- $value_title = sprintf( __( 'Grab raw %s rate from %s.', 'woocommerce-jetpack' ), $value['value'], $exchange_rate_server ) .
73
  ' ' . __( 'Doesn\'t apply rounding, offset etc.', 'woocommerce-jetpack' );
74
- ?>
75
  <tr valign="top">
76
  <th scope="row" class="titledesc">
77
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
78
- <?php echo $tip; ?>
79
  </th>
80
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
81
  <input
82
  name="<?php echo esc_attr( $value['id'] ); ?>"
83
  id="<?php echo esc_attr( $value['id'] ); ?>"
@@ -85,7 +92,7 @@ class WCJ_Settings_Custom_Fields {
85
  style="<?php echo esc_attr( $value['css'] ); ?>"
86
  value="<?php echo esc_attr( $option_value ); ?>"
87
  class="<?php echo esc_attr( $value['class'] ); ?>"
88
- <?php echo implode( ' ', $custom_attributes ); ?>
89
  />
90
  <input
91
  name="<?php echo esc_attr( $value['id'] . '_button' ); ?>"
@@ -94,73 +101,84 @@ class WCJ_Settings_Custom_Fields {
94
  value="<?php echo esc_attr( $value['value'] ); ?>"
95
  title="<?php echo esc_attr( $value_title ); ?>"
96
  class="exchage_rate_button"
97
- <?php echo implode( ' ', $custom_attributes_button ); ?>
98
  />
99
  </td>
100
  </tr>
101
- <?php
102
- }
103
 
104
- /**
105
- * maybe_unclean_field.
106
- *
107
- * @version 3.1.3
108
- * @since 3.1.3
109
- */
110
- function maybe_unclean_field( $value, $option, $raw_value ) {
111
- return ( isset( $option['wcj_raw'] ) && $option['wcj_raw'] ? $raw_value : $value );
112
- }
 
 
 
113
 
114
- /**
115
- * output_wcj_save_settings_button.
116
- *
117
- * @version 2.9.0
118
- * @since 2.9.0
119
- */
120
- function output_wcj_save_settings_button( $value ) {
121
- // Output
122
- ?><tr valign="top">
 
 
123
  <th scope="row" class="titledesc"></th>
124
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
125
  <input name="save" class="button-primary woocommerce-save-button" type="submit" value="<?php echo esc_html( $value['title'] ); ?>">
126
  </td>
127
- </tr><?php
128
- }
 
129
 
130
- /**
131
- * format_wcj_number_plus_checkbox_end.
132
- *
133
- * @version 2.8.0
134
- * @since 2.8.0
135
- */
136
- function format_wcj_number_plus_checkbox_end( $value, $option, $raw_value ) {
137
- return ( 'wcj_number_plus_checkbox_end' === $option['type'] ) ? ( '1' === $raw_value || 'yes' === $raw_value ? 'yes' : 'no' ) : $value;
138
- }
 
 
 
139
 
140
- /**
141
- * output_wcj_number_plus_checkbox_start.
142
- *
143
- * @version 2.8.0
144
- * @since 2.8.0
145
- */
146
- function output_wcj_number_plus_checkbox_start( $value ) {
147
- // Custom attribute handling
148
- $custom_attributes = array();
149
- if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
150
- foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
151
- $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
 
 
152
  }
153
- }
154
- // Description handling
155
- $field_description = WC_Admin_Settings::get_field_description( $value );
156
- extract( $field_description );
157
- // Option value
158
- $option_value = WC_Admin_Settings::get_option( $value['id'], $value['default'] );
159
- // Output
160
- ?><tr valign="top">
161
  <th scope="row" class="titledesc">
162
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
163
- <?php echo $tooltip_html; ?>
164
  </th>
165
  <td class="forminp forminp-number-checkbox">
166
  <input
@@ -171,31 +189,35 @@ class WCJ_Settings_Custom_Fields {
171
  value="<?php echo esc_attr( $option_value ); ?>"
172
  class="<?php echo esc_attr( $value['class'] ); ?>"
173
  placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
174
- <?php echo implode( ' ', $custom_attributes ); ?>
175
- /> <?php echo $description . ' ';
176
- }
 
 
177
 
178
- /**
179
- * output_wcj_number_plus_checkbox_end.
180
- *
181
- * @version 2.8.0
182
- * @since 2.8.0
183
- */
184
- function output_wcj_number_plus_checkbox_end( $value ) {
185
- // Custom attribute handling
186
- $custom_attributes = array();
187
- if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
188
- foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
189
- $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
 
 
190
  }
191
- }
192
- // Description handling
193
- $field_description = WC_Admin_Settings::get_field_description( $value );
194
- extract( $field_description );
195
- // Option value
196
- $option_value = WC_Admin_Settings::get_option( $value['id'], $value['default'] );
197
- // Output
198
- ?><label for="<?php echo $value['id'] ?>">
199
  <input
200
  name="<?php echo esc_attr( $value['id'] ); ?>"
201
  id="<?php echo esc_attr( $value['id'] ); ?>"
@@ -203,44 +225,50 @@ class WCJ_Settings_Custom_Fields {
203
  class="<?php echo esc_attr( isset( $value['class'] ) ? $value['class'] : '' ); ?>"
204
  value="1"
205
  <?php checked( $option_value, 'yes' ); ?>
206
- <?php echo implode( ' ', $custom_attributes ); ?>
207
- /> <?php echo $description ?>
208
- </label> <?php echo $tooltip_html; ?>
209
  </td>
210
- </tr><?php
211
- }
 
212
 
213
- /**
214
- * unclean_custom_textarea.
215
- *
216
- * @version 2.5.7
217
- * @since 2.5.7
218
- */
219
- function unclean_custom_textarea( $value, $option, $raw_value ) {
220
- return ( 'custom_textarea' === $option['type'] ) ? $raw_value : $value;
221
- }
 
 
 
222
 
223
- /**
224
- * output_custom_textarea.
225
- *
226
- * @version 2.6.0
227
- * @since 2.2.6
228
- */
229
- function output_custom_textarea( $value ) {
230
- $option_value = wcj_get_option( $value['id'], $value['default'] );
231
- $custom_attributes = ( isset( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) ?
 
232
  $value['custom_attributes'] : array();
233
- $description = ' <p class="description">' . $value['desc'] . '</p>';
234
- $tooltip_html = ( isset( $value['desc_tip'] ) && '' != $value['desc_tip'] ) ?
235
  '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
236
- // Output
237
- ?><tr valign="top">
 
238
  <th scope="row" class="titledesc">
239
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
240
  <?php echo $tooltip_html; ?>
241
  </th>
242
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
243
- <?php echo $description; ?>
244
 
245
  <textarea
246
  name="<?php echo esc_attr( $value['id'] ); ?>"
@@ -248,76 +276,91 @@ class WCJ_Settings_Custom_Fields {
248
  style="<?php echo esc_attr( $value['css'] ); ?>"
249
  class="<?php echo esc_attr( $value['class'] ); ?>"
250
  placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
251
- <?php echo implode( ' ', $custom_attributes ); ?>
252
- ><?php echo esc_textarea( $option_value ); ?></textarea>
253
  </td>
254
- </tr><?php
255
- }
 
256
 
257
- /**
258
- * output_module_tools.
259
- *
260
- * @version 2.7.0
261
- * @since 2.2.3
262
- */
263
- function output_module_tools( $value ) {
264
- ?><tr valign="top">
 
 
265
  <th scope="row" class="titledesc">
266
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
267
- <span class="woocommerce-help-tip" data-tip="<?php echo __( 'To use tools, module must be enabled.', 'woocommerce-jetpack' ); ?>"></span>
268
  </th>
269
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
270
- <?php if ( isset( $_GET['section'] ) ) do_action( 'wcj_module_tools_' . $_GET['section'] ); ?>
 
 
 
271
  </td>
272
- </tr><?php
273
- }
 
274
 
275
- /**
276
- * output_custom_link.
277
- *
278
- * @version 2.7.0
279
- * @since 2.2.8
280
- */
281
- function output_custom_link( $value ) {
282
- $tooltip_html = ( isset( $value['desc_tip'] ) && '' != $value['desc_tip'] ) ?
 
283
  '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
284
- ?><tr valign="top">
 
285
  <th scope="row" class="titledesc">
286
- <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label><?php echo $tooltip_html; ?>
287
  </th>
288
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
289
- <?php echo $value['link']; ?>
290
  </td>
291
- </tr><?php
292
- }
 
293
 
294
- /**
295
- * output_custom_number.
296
- *
297
- * @version 5.5.6
298
- */
299
- function output_custom_number( $value ) {
300
- $type = 'number';
301
- $option_value = get_option( $value['id'], $value['default'] );
302
- $tooltip_html = ( isset( $value['desc_tip'] ) && '' != $value['desc_tip'] ) ?
 
303
  '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
304
- $description = ' <span class="description">' . $value['desc'] . '</span>';
305
- $save_button = apply_filters( 'booster_option', '',
306
- ' <input name="save" class="button-primary" type="submit" value="' . __( 'Save changes', 'woocommerce' ) . '">' );
307
- // Custom attribute handling
308
- $custom_attributes = array();
309
- if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
310
- foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
311
- $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
 
 
 
 
312
  }
313
- }
314
- // Output
315
- ?><tr valign="top">
316
  <th scope="row" class="titledesc">
317
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
318
- <?php echo $tooltip_html; ?>
319
  </th>
320
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
321
  <input
322
  name="<?php echo esc_attr( $value['id'] ); ?>"
323
  id="<?php echo esc_attr( $value['id'] ); ?>"
@@ -326,13 +369,14 @@ class WCJ_Settings_Custom_Fields {
326
  value="<?php echo esc_attr( $option_value ); ?>"
327
  class="<?php echo esc_attr( $value['class'] ); ?>"
328
  placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
329
- <?php echo implode( ' ', $custom_attributes ); ?>
330
- /><?php echo $save_button; ?><?php echo $description; ?>
331
  </td>
332
- </tr><?php
333
- }
 
334
 
335
- }
336
 
337
  endif;
338
 
5
  * @version 5.5.6
6
  * @since 2.8.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/admin
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Settings_Custom_Fields' ) ) :
16
+ /**
17
+ * WCJ_Settings_Custom_Fields.
18
+ */
19
+ class WCJ_Settings_Custom_Fields {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 3.2.4
25
+ * @since 2.8.0
26
+ */
27
+ public function __construct() {
28
+ add_action( 'woocommerce_admin_field_wcj_save_settings_button', array( $this, 'output_wcj_save_settings_button' ) );
29
+ add_action( 'woocommerce_admin_field_wcj_number_plus_checkbox_start', array( $this, 'output_wcj_number_plus_checkbox_start' ) );
30
+ add_action( 'woocommerce_admin_field_wcj_number_plus_checkbox_end', array( $this, 'output_wcj_number_plus_checkbox_end' ) );
31
+ add_filter( 'woocommerce_admin_settings_sanitize_option', array( $this, 'format_wcj_number_plus_checkbox_end' ), PHP_INT_MAX, 3 );
32
+ add_action( 'woocommerce_admin_field_custom_textarea', array( $this, 'output_custom_textarea' ) );
33
+ add_filter( 'woocommerce_admin_settings_sanitize_option', array( $this, 'unclean_custom_textarea' ), PHP_INT_MAX, 3 );
34
+ add_action( 'woocommerce_admin_field_custom_number', array( $this, 'output_custom_number' ) );
35
+ add_action( 'woocommerce_admin_field_custom_link', array( $this, 'output_custom_link' ) );
36
+ add_action( 'woocommerce_admin_field_module_tools', array( $this, 'output_module_tools' ) );
37
+ add_filter( 'woocommerce_admin_settings_sanitize_option', array( $this, 'maybe_unclean_field' ), PHP_INT_MAX, 3 );
38
+ add_action( 'woocommerce_admin_field_exchange_rate', array( $this, 'output_exchange_rate_settings_button' ) );
39
+ }
 
 
40
 
41
+ /**
42
+ * Output_exchange_rate_settings_button.
43
+ *
44
+ * @version 5.2.0
45
+ * @param Array $value Get values.
46
+ */
47
+ public function output_exchange_rate_settings_button( $value ) {
48
 
49
+ $value['type'] = 'number';
50
 
51
+ $option_value = wcj_get_option( $value['id'], $value['default'] );
52
 
53
+ // Custom attribute handling.
54
+ $custom_attributes = array();
55
+ if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
56
+ foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
57
+ $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
58
+ }
 
 
 
 
 
 
59
  } else {
60
+ if (
61
+ ! w_c_j()->modules['currency_exchange_rates']->is_enabled()
62
+ || 'yes' !== wcj_get_option( 'wcj_currency_exchange_rates_point_decimal_separator', 'no' )
63
+ ) {
64
+ $custom_attributes = array( 'step="' . sprintf( '%.12f', 1 / pow( 10, 12 ) ) . '"', 'min="0"' );
65
+ } else {
66
+ $custom_attributes = array( 'step="0.00000001"', 'min="0"' );
67
+ }
68
  }
69
+ $custom_attributes_button = array();
70
+ if ( ! empty( $value['custom_attributes_button'] ) && is_array( $value['custom_attributes_button'] ) ) {
71
+ foreach ( $value['custom_attributes_button'] as $attribute => $attribute_value ) {
72
+ $custom_attributes_button[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
73
+ }
74
  }
75
+ $tip = '';
76
+ $description = '';
77
+ $exchange_rate_server = wcj_get_currency_exchange_rate_server_name( $value['custom_attributes_button']['currency_from'], $value['custom_attributes_button']['currency_to'] );
78
+ /* translators: %s: translation added */
79
+ $value_title = sprintf( __( 'Grab raw %1$s rate from %2$s.', 'woocommerce-jetpack' ), $value['value'], $exchange_rate_server ) .
80
  ' ' . __( 'Doesn\'t apply rounding, offset etc.', 'woocommerce-jetpack' );
81
+ ?>
82
  <tr valign="top">
83
  <th scope="row" class="titledesc">
84
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
85
+ <?php echo wp_kses_post( $tip ); ?>
86
  </th>
87
+ <td class="forminp forminp-<?php echo wp_kses_post( sanitize_title( $value['type'] ) ); ?>">
88
  <input
89
  name="<?php echo esc_attr( $value['id'] ); ?>"
90
  id="<?php echo esc_attr( $value['id'] ); ?>"
92
  style="<?php echo esc_attr( $value['css'] ); ?>"
93
  value="<?php echo esc_attr( $option_value ); ?>"
94
  class="<?php echo esc_attr( $value['class'] ); ?>"
95
+ <?php echo wp_kses_post( implode( ' ', $custom_attributes ) ); ?>
96
  />
97
  <input
98
  name="<?php echo esc_attr( $value['id'] . '_button' ); ?>"
101
  value="<?php echo esc_attr( $value['value'] ); ?>"
102
  title="<?php echo esc_attr( $value_title ); ?>"
103
  class="exchage_rate_button"
104
+ <?php echo wp_kses_post( implode( ' ', $custom_attributes_button ) ); ?>
105
  />
106
  </td>
107
  </tr>
108
+ <?php
109
+ }
110
 
111
+ /**
112
+ * Maybe_unclean_field.
113
+ *
114
+ * @version 3.1.3
115
+ * @since 3.1.3
116
+ * @param Array $value Get values.
117
+ * @param Array $option Get options.
118
+ * @param Array $raw_value Get raw value.
119
+ */
120
+ public function maybe_unclean_field( $value, $option, $raw_value ) {
121
+ return ( isset( $option['wcj_raw'] ) && $option['wcj_raw'] ? $raw_value : $value );
122
+ }
123
 
124
+ /**
125
+ * Output_wcj_save_settings_button.
126
+ *
127
+ * @version 2.9.0
128
+ * @since 2.9.0
129
+ * @param Array $value Get values.
130
+ */
131
+ public function output_wcj_save_settings_button( $value ) {
132
+ // Output.
133
+ ?>
134
+ <tr valign="top">
135
  <th scope="row" class="titledesc"></th>
136
+ <td class="forminp forminp-<?php echo wp_kses_post( sanitize_title( $value['type'] ) ); ?>">
137
  <input name="save" class="button-primary woocommerce-save-button" type="submit" value="<?php echo esc_html( $value['title'] ); ?>">
138
  </td>
139
+ </tr>
140
+ <?php
141
+ }
142
 
143
+ /**
144
+ * Format_wcj_number_plus_checkbox_end.
145
+ *
146
+ * @version 2.8.0
147
+ * @since 2.8.0
148
+ * @param Array $value Get values.
149
+ * @param Array $option Get options.
150
+ * @param Array $raw_value Get raw value.
151
+ */
152
+ public function format_wcj_number_plus_checkbox_end( $value, $option, $raw_value ) {
153
+ return ( 'wcj_number_plus_checkbox_end' === $option['type'] ) ? ( '1' === $raw_value || 'yes' === $raw_value ? 'yes' : 'no' ) : $value;
154
+ }
155
 
156
+ /**
157
+ * Output_wcj_number_plus_checkbox_start.
158
+ *
159
+ * @version 2.8.0
160
+ * @since 2.8.0
161
+ * @param Array $value Get values.
162
+ */
163
+ public function output_wcj_number_plus_checkbox_start( $value ) {
164
+ // Custom attribute handling.
165
+ $custom_attributes = array();
166
+ if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
167
+ foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
168
+ $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
169
+ }
170
  }
171
+ // Description handling.
172
+ $field_description = WC_Admin_Settings::get_field_description( $value );
173
+ extract( $field_description );
174
+ // Option value.
175
+ $option_value = WC_Admin_Settings::get_option( $value['id'], $value['default'] );
176
+ // Output.
177
+ ?>
178
+ <tr valign="top">
179
  <th scope="row" class="titledesc">
180
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
181
+ <?php echo wp_kses_post( $tooltip_html ); ?>
182
  </th>
183
  <td class="forminp forminp-number-checkbox">
184
  <input
189
  value="<?php echo esc_attr( $option_value ); ?>"
190
  class="<?php echo esc_attr( $value['class'] ); ?>"
191
  placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
192
+ <?php echo wp_kses_post( implode( ' ', $custom_attributes ) ); ?>
193
+ />
194
+ <?php
195
+ echo wp_kses_post( $description ) . ' ';
196
+ }
197
 
198
+ /**
199
+ * Output_wcj_number_plus_checkbox_end.
200
+ *
201
+ * @version 2.8.0
202
+ * @since 2.8.0
203
+ * @param Array $value Get values.
204
+ */
205
+ public function output_wcj_number_plus_checkbox_end( $value ) {
206
+ // Custom attribute handling.
207
+ $custom_attributes = array();
208
+ if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
209
+ foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
210
+ $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
211
+ }
212
  }
213
+ // Description handling.
214
+ $field_description = WC_Admin_Settings::get_field_description( $value );
215
+ extract( $field_description );
216
+ // Option value.
217
+ $option_value = WC_Admin_Settings::get_option( $value['id'], $value['default'] );
218
+ // Output.
219
+ ?>
220
+ <label for="<?php echo wp_kses_post( $value['id'] ); ?>">
221
  <input
222
  name="<?php echo esc_attr( $value['id'] ); ?>"
223
  id="<?php echo esc_attr( $value['id'] ); ?>"
225
  class="<?php echo esc_attr( isset( $value['class'] ) ? $value['class'] : '' ); ?>"
226
  value="1"
227
  <?php checked( $option_value, 'yes' ); ?>
228
+ <?php echo wp_kses_post( implode( ' ', $custom_attributes ) ); ?>
229
+ /> <?php echo wp_kses_post( $description ); ?>
230
+ </label> <?php echo wp_kses_post( $tooltip_html ); ?>
231
  </td>
232
+ </tr>
233
+ <?php
234
+ }
235
 
236
+ /**
237
+ * Unclean_custom_textarea.
238
+ *
239
+ * @version 2.5.7
240
+ * @since 2.5.7
241
+ * @param Array $value Get values.
242
+ * @param Array $option Get options.
243
+ * @param Array $raw_value Get raw value.
244
+ */
245
+ public function unclean_custom_textarea( $value, $option, $raw_value ) {
246
+ return ( 'custom_textarea' === $option['type'] ) ? $raw_value : $value;
247
+ }
248
 
249
+ /**
250
+ * Output_custom_textarea.
251
+ *
252
+ * @version 2.6.0
253
+ * @since 2.2.6
254
+ * @param Array $value Get values.
255
+ */
256
+ public function output_custom_textarea( $value ) {
257
+ $option_value = wcj_get_option( $value['id'], $value['default'] );
258
+ $custom_attributes = ( isset( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) ?
259
  $value['custom_attributes'] : array();
260
+ $description = ' <p class="description">' . $value['desc'] . '</p>';
261
+ $tooltip_html = ( isset( $value['desc_tip'] ) && '' !== $value['desc_tip'] ) ?
262
  '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
263
+ // Output.
264
+ ?>
265
+ <tr valign="top">
266
  <th scope="row" class="titledesc">
267
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
268
  <?php echo $tooltip_html; ?>
269
  </th>
270
+ <td class="forminp forminp-<?php echo wp_kses_post( $value['type'] ); ?>">
271
+ <?php echo wp_kses_post( $description ); ?>
272
 
273
  <textarea
274
  name="<?php echo esc_attr( $value['id'] ); ?>"
276
  style="<?php echo esc_attr( $value['css'] ); ?>"
277
  class="<?php echo esc_attr( $value['class'] ); ?>"
278
  placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
279
+ <?php echo wp_kses_post( implode( ' ', $custom_attributes ) ); ?>
280
+ ><?php echo esc_textarea( $option_value ); ?></textarea>
281
  </td>
282
+ </tr>
283
+ <?php
284
+ }
285
 
286
+ /**
287
+ * Output_module_tools.
288
+ *
289
+ * @version 2.7.0
290
+ * @since 2.2.3
291
+ * @param Array $value Get values.
292
+ */
293
+ public function output_module_tools( $value ) {
294
+ ?>
295
+ <tr valign="top">
296
  <th scope="row" class="titledesc">
297
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
298
+ <span class="woocommerce-help-tip" data-tip="<?php echo wp_kses_post( 'To use tools, module must be enabled.', 'woocommerce-jetpack' ); ?>"></span>
299
  </th>
300
+ <td class="forminp forminp-<?php echo wp_kses_post( $value['type'] ); ?>">
301
+ <?php
302
+ if ( isset( $_GET['section'] ) ) {
303
+ do_action( 'wcj_module_tools_' . sanitize_text_field( wp_unslash( $_GET['section'] ) ) );}
304
+ ?>
305
  </td>
306
+ </tr>
307
+ <?php
308
+ }
309
 
310
+ /**
311
+ * Output_custom_link.
312
+ *
313
+ * @version 2.7.0
314
+ * @since 2.2.8
315
+ * @param Array $value Get values.
316
+ */
317
+ public function output_custom_link( $value ) {
318
+ $tooltip_html = ( isset( $value['desc_tip'] ) && '' !== $value['desc_tip'] ) ?
319
  '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
320
+ ?>
321
+ <tr valign="top">
322
  <th scope="row" class="titledesc">
323
+ <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label><?php echo wp_kses_post( $tooltip_html ); ?>
324
  </th>
325
+ <td class="forminp forminp-<?php echo wp_kses_post( $value['type'] ); ?>">
326
+ <?php echo wp_kses_post( $value['link'] ); ?>
327
  </td>
328
+ </tr>
329
+ <?php
330
+ }
331
 
332
+ /**
333
+ * Output_custom_number.
334
+ *
335
+ * @version 5.5.6
336
+ * @param Array $value Get values.
337
+ */
338
+ public function output_custom_number( $value ) {
339
+ $type = 'number';
340
+ $option_value = get_option( $value['id'], $value['default'] );
341
+ $tooltip_html = ( isset( $value['desc_tip'] ) && '' !== $value['desc_tip'] ) ?
342
  '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
343
+ $description = ' <span class="description">' . $value['desc'] . '</span>';
344
+ $save_button = apply_filters(
345
+ 'booster_option',
346
+ '',
347
+ ' <input name="save" class="button-primary" type="submit" value="' . __( 'Save changes', 'woocommerce' ) . '">'
348
+ );
349
+ // Custom attribute handling.
350
+ $custom_attributes = array();
351
+ if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
352
+ foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
353
+ $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
354
+ }
355
  }
356
+ // Output.
357
+ ?>
358
+ <tr valign="top">
359
  <th scope="row" class="titledesc">
360
  <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
361
+ <?php echo wp_kses_post( $tooltip_html ); ?>
362
  </th>
363
+ <td class="forminp forminp-<?php echo wp_kses_post( $value['type'] ); ?>">
364
  <input
365
  name="<?php echo esc_attr( $value['id'] ); ?>"
366
  id="<?php echo esc_attr( $value['id'] ); ?>"
369
  value="<?php echo esc_attr( $option_value ); ?>"
370
  class="<?php echo esc_attr( $value['class'] ); ?>"
371
  placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
372
+ <?php echo wp_kses_post( implode( ' ', $custom_attributes ) ); ?>
373
+ /><?php echo wp_kses_post( $save_button ); ?><?php echo wp_kses_post( $description ); ?>
374
  </td>
375
+ </tr>
376
+ <?php
377
+ }
378
 
379
+ }
380
 
381
  endif;
382
 
includes/admin/class-wcj-settings-manager.php CHANGED
@@ -5,160 +5,169 @@
5
  * @version 3.8.0
6
  * @since 2.9.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Settings_Manager' ) ) :
13
-
14
- class WCJ_Settings_Manager {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 2.9.0
20
- * @since 2.9.0
21
- * @todo add options to import/export selected modules only
22
  */
23
- function __construct() {
24
- add_action( 'wp_loaded', array( $this, 'manage_options' ), PHP_INT_MAX );
25
- }
26
 
27
- /**
28
- * manage_options.
29
- *
30
- * @version 3.4.0
31
- * @since 2.5.2
32
- */
33
- function manage_options() {
34
- if ( is_admin() ) {
35
- if ( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ) {
36
- return;
37
- }
38
- if ( isset( $_POST['booster_import_settings'] ) ) {
39
- $this->manage_options_import();
40
- }
41
- if ( isset( $_POST['booster_export_settings'] ) ) {
42
- $this->manage_options_export();
43
- }
44
- if ( isset( $_POST['booster_reset_settings'] ) ) {
45
- $this->manage_options_reset();
46
- }
47
- if ( isset( $_POST['booster_reset_settings_meta'] ) ) {
48
- $this->manage_options_reset_meta();
 
 
 
 
 
 
 
 
 
 
 
 
49
  }
50
  }
51
- }
52
 
53
- /**
54
- * manage_options_import.
55
- *
56
- * @version 3.8.0
57
- * @since 2.5.2
58
- */
59
- function manage_options_import() {
60
- global $wcj_notice;
61
- if( ! isset( $_FILES['booster_import_settings_file']['tmp_name'] ) || '' == $_FILES['booster_import_settings_file']['tmp_name'] ) {
62
- $wcj_notice .= __( 'Please upload a file to import!', 'woocommerce-jetpack' );
63
- $import_settings = array();
64
- unset( $_POST['booster_import_settings'] );
65
- } else {
66
- $import_counter = 0;
67
- $import_settings = file_get_contents( $_FILES['booster_import_settings_file']['tmp_name'] );
68
- $bom = pack( 'H*','EFBBBF' );
69
- $import_settings = preg_replace( "/^$bom/", '', $import_settings );
70
- $import_settings = explode( PHP_EOL, preg_replace( '~(*BSR_ANYCRLF)\R~', PHP_EOL, $import_settings ) );
71
- if ( ! is_array( $import_settings ) || 2 !== count( $import_settings ) ) {
72
- $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
73
  } else {
74
- $import_header = $import_settings[0];
75
- $required_header = 'Booster for WooCommerce';
76
- if ( $required_header !== substr( $import_header, 0, strlen( $required_header ) ) ) {
 
 
 
77
  $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
78
  } else {
79
- $import_settings = json_decode( $import_settings[1], true );
80
- foreach ( $import_settings as $import_key => $import_setting ) {
81
- if ( strlen( $import_key ) > 4 && 'wcj_' === substr( $import_key, 0, 4 ) ) {
82
- update_option( $import_key, $import_setting );
83
- $import_counter++;
 
 
 
 
 
 
84
  }
 
 
85
  }
86
- $wcj_notice .= sprintf( __( '%d options successfully imported.', 'woocommerce-jetpack' ), $import_counter );
87
  }
88
  }
89
  }
90
- }
91
 
92
- /**
93
- * manage_options_export.
94
- *
95
- * @version 3.8.0
96
- * @since 2.5.2
97
- * @see http://php.net/manual/en/function.header.php
98
- */
99
- function manage_options_export() {
100
- $export_settings = array();
101
- $export_counter = array();
102
- foreach ( WCJ()->modules as $module ) {
103
- $values = $module->get_settings();
104
- foreach ( $values as $value ) {
105
- if ( isset( $value['default'] ) && isset( $value['id'] ) ) {
106
- if ( isset ( $_POST['booster_export_settings'] ) ) {
107
- $export_settings[ $value['id'] ] = wcj_get_option( $value['id'], $value['default'] );
108
- if ( ! isset( $export_counter[ $module->short_desc ] ) ) {
109
- $export_counter[ $module->short_desc ] = 0;
 
 
110
  }
111
- $export_counter[ $module->short_desc ]++;
112
  }
113
  }
114
  }
 
 
 
 
 
 
115
  }
116
- $export_settings = json_encode( $export_settings );
117
- $export_settings = 'Booster for WooCommerce v' . wcj_get_option( WCJ_VERSION_OPTION, 'NA' ) . PHP_EOL . $export_settings;
118
- header( "Content-Type: application/download" );
119
- header( "Content-Disposition: attachment; filename=booster_settings.txt" );
120
- echo $export_settings;
121
- die();
122
- }
123
 
124
- /**
125
- * manage_options_reset_meta.
126
- *
127
- * @version 3.4.0
128
- * @since 3.4.0
129
- * @todo order items meta
130
- * @todo `... LIKE 'wcj_%'`
131
- */
132
- function manage_options_reset_meta() {
133
- global $wpdb, $wcj_notice;
134
- $delete_counter_meta = 0;
135
- $plugin_meta = $wpdb->get_results( "SELECT * FROM $wpdb->postmeta WHERE meta_key LIKE '_wcj_%'" );
136
- foreach( $plugin_meta as $meta ) {
137
- delete_post_meta( $meta->post_id, $meta->meta_key );
138
- $delete_counter_meta++;
 
 
 
139
  }
140
- $wcj_notice .= sprintf( __( '%d meta successfully deleted.', 'woocommerce-jetpack' ), $delete_counter_meta );
141
- }
142
 
143
- /**
144
- * manage_options_reset.
145
- *
146
- * @version 3.4.0
147
- * @since 2.5.2
148
- */
149
- function manage_options_reset() {
150
- global $wpdb, $wcj_notice;
151
- $delete_counter_options = 0;
152
- $plugin_options = $wpdb->get_results( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE 'wcj_%'" );
153
- foreach( $plugin_options as $option ) {
154
- delete_option( $option->option_name );
155
- delete_site_option( $option->option_name );
156
- $delete_counter_options++;
 
 
 
157
  }
158
- $wcj_notice .= sprintf( __( '%d options successfully deleted.', 'woocommerce-jetpack' ), $delete_counter_options );
159
- }
160
 
161
- }
162
 
163
  endif;
164
 
5
  * @version 3.8.0
6
  * @since 2.9.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/admin
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Settings_Manager' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Settings_Manager.
 
 
 
 
18
  */
19
+ class WCJ_Settings_Manager {
 
 
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 2.9.0
25
+ * @since 2.9.0
26
+ * @todo add options to import/export selected modules only
27
+ */
28
+ public function __construct() {
29
+ add_action( 'wp_loaded', array( $this, 'manage_options' ), PHP_INT_MAX );
30
+ }
31
+
32
+ /**
33
+ * Manage_options.
34
+ *
35
+ * @version 3.4.0
36
+ * @since 2.5.2
37
+ */
38
+ public function manage_options() {
39
+ if ( is_admin() ) {
40
+ if ( ! function_exists( 'current_user_can' ) || ! current_user_can( 'manage_options' ) ) {
41
+ return;
42
+ }
43
+ if ( isset( $_POST['booster_import_settings'] ) ) {
44
+ $this->manage_options_import();
45
+ }
46
+ if ( isset( $_POST['booster_export_settings'] ) ) {
47
+ $this->manage_options_export();
48
+ }
49
+ if ( isset( $_POST['booster_reset_settings'] ) ) {
50
+ $this->manage_options_reset();
51
+ }
52
+ if ( isset( $_POST['booster_reset_settings_meta'] ) ) {
53
+ $this->manage_options_reset_meta();
54
+ }
55
  }
56
  }
 
57
 
58
+ /**
59
+ * Manage_options_import.
60
+ *
61
+ * @version 3.8.0
62
+ * @since 2.5.2
63
+ */
64
+ public function manage_options_import() {
65
+ global $wcj_notice;
66
+ if ( ! isset( $_FILES['booster_import_settings_file']['tmp_name'] ) || '' === $_FILES['booster_import_settings_file']['tmp_name'] ) {
67
+ $wcj_notice .= __( 'Please upload a file to import!', 'woocommerce-jetpack' );
68
+ $import_settings = array();
69
+
70
+ unset( $_POST['booster_import_settings'] );
 
 
 
 
 
 
 
71
  } else {
72
+ $import_counter = 0;
73
+ $import_settings = file_get_contents( sanitize_text_field( wp_unslash( $_FILES['booster_import_settings_file']['tmp_name'] ) ) );
74
+ $bom = pack( 'H*', 'EFBBBF' );
75
+ $import_settings = preg_replace( "/^$bom/", '', $import_settings );
76
+ $import_settings = explode( PHP_EOL, preg_replace( '~(*BSR_ANYCRLF)\R~', PHP_EOL, $import_settings ) );
77
+ if ( ! is_array( $import_settings ) || 2 !== count( $import_settings ) ) {
78
  $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
79
  } else {
80
+ $import_header = $import_settings[0];
81
+ $required_header = 'Booster for WooCommerce';
82
+ if ( substr( $import_header, 0, strlen( $required_header ) ) !== $required_header ) {
83
+ $wcj_notice .= __( 'Wrong file format!', 'woocommerce-jetpack' );
84
+ } else {
85
+ $import_settings = json_decode( $import_settings[1], true );
86
+ foreach ( $import_settings as $import_key => $import_setting ) {
87
+ if ( strlen( $import_key ) > 4 && 'wcj_' === substr( $import_key, 0, 4 ) ) {
88
+ update_option( $import_key, $import_setting );
89
+ $import_counter++;
90
+ }
91
  }
92
+ /* translators: %d: translation added */
93
+ $wcj_notice .= sprintf( __( '%d options successfully imported.', 'woocommerce-jetpack' ), $import_counter );
94
  }
 
95
  }
96
  }
97
  }
 
98
 
99
+ /**
100
+ * Manage_options_export.
101
+ *
102
+ * @version 3.8.0
103
+ * @since 2.5.2
104
+ * @see http://php.net/manual/en/function.header.php
105
+ */
106
+ public function manage_options_export() {
107
+ $export_settings = array();
108
+ $export_counter = array();
109
+ foreach ( w_c_j()->modules as $module ) {
110
+ $values = $module->get_settings();
111
+ foreach ( $values as $value ) {
112
+ if ( isset( $value['default'] ) && isset( $value['id'] ) ) {
113
+ if ( isset( $_POST['booster_export_settings'] ) ) {
114
+ $export_settings[ $value['id'] ] = wcj_get_option( $value['id'], $value['default'] );
115
+ if ( ! isset( $export_counter[ $module->short_desc ] ) ) {
116
+ $export_counter[ $module->short_desc ] = 0;
117
+ }
118
+ $export_counter[ $module->short_desc ]++;
119
  }
 
120
  }
121
  }
122
  }
123
+ $export_settings = wp_json_encode( $export_settings );
124
+ $export_settings = 'Booster for WooCommerce v' . wcj_get_option( WCJ_VERSION_OPTION, 'NA' ) . PHP_EOL . $export_settings;
125
+ header( 'Content-Type: application/download' );
126
+ header( 'Content-Disposition: attachment; filename=booster_settings.txt' );
127
+ echo $export_settings;
128
+ die();
129
  }
 
 
 
 
 
 
 
130
 
131
+ /**
132
+ * Manage_options_reset_meta.
133
+ *
134
+ * @version 3.4.0
135
+ * @since 3.4.0
136
+ * @todo order items meta
137
+ * @todo `... LIKE 'wcj_%'`
138
+ */
139
+ public function manage_options_reset_meta() {
140
+ global $wpdb, $wcj_notice;
141
+ $delete_counter_meta = 0;
142
+ $plugin_meta = $wpdb->get_results( "SELECT * FROM $wpdb->postmeta WHERE meta_key LIKE '_wcj_%'" );
143
+ foreach ( $plugin_meta as $meta ) {
144
+ delete_post_meta( $meta->post_id, $meta->meta_key );
145
+ $delete_counter_meta++;
146
+ }
147
+ /* translators: %d: translation added */
148
+ $wcj_notice .= sprintf( __( '%d meta successfully deleted.', 'woocommerce-jetpack' ), $delete_counter_meta );
149
  }
 
 
150
 
151
+ /**
152
+ * Manage_options_reset.
153
+ *
154
+ * @version 3.4.0
155
+ * @since 2.5.2
156
+ */
157
+ public function manage_options_reset() {
158
+ global $wpdb, $wcj_notice;
159
+ $delete_counter_options = 0;
160
+ $plugin_options = $wpdb->get_results( "SELECT option_name FROM $wpdb->options WHERE option_name LIKE 'wcj_%'" );
161
+ foreach ( $plugin_options as $option ) {
162
+ delete_option( $option->option_name );
163
+ delete_site_option( $option->option_name );
164
+ $delete_counter_options++;
165
+ }
166
+ /* translators: %d: translation added */
167
+ $wcj_notice .= sprintf( __( '%d options successfully deleted.', 'woocommerce-jetpack' ), $delete_counter_options );
168
  }
 
 
169
 
170
+ }
171
 
172
  endif;
173
 
includes/admin/class-wcj-tools.php CHANGED
@@ -4,103 +4,119 @@
4
  *
5
  * @version 5.5.9
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Tools' ) ) :
 
 
 
 
12
 
13
- class WCJ_Tools {
14
-
15
- /**
16
- * Constructor.
17
- */
18
- function __construct() {
19
- if ( is_admin() ) {
20
- if ( apply_filters( 'wcj_can_create_admin_interface', true ) ) {
21
- add_action( 'admin_menu', array( $this, 'add_wcj_tools' ), 100 );
22
- add_action( 'admin_enqueue_scripts', array($this,'wcj_new_desing_dashboard_enqueue') );
23
  }
24
  }
25
- }
26
 
27
- /**
28
- * wcj_new_desing_dashboard_enqueue.
29
- *
30
- * @version 5.5.6
31
- * @since 5.5.6
32
- */
33
- function wcj_new_desing_dashboard_enqueue(){
34
- $page = isset( $_GET['page'] ) ? $_GET['page'] : "" ;
35
- if( $page ==='wcj-tools'){
36
- wp_enqueue_style('wcj-admin-wcj-new_desing', wcj_plugin_url() . '/includes/css/admin-style.css');
37
- wp_enqueue_script('wcj-admin-script', wcj_plugin_url() . '/includes/js/admin-script.js', array('jquery'), '5.0.0', true);
38
- //wp_enqueue_script('wcj-admin-dasboard-js', wcj_plugin_url() . '/includes/js/wcj-new_desing.js');
39
- }
40
- }
41
- /**
42
- * add_wcj_tools.
43
- *
44
- * @version 4.8.0
45
- */
46
- function add_wcj_tools() {
47
- if ( apply_filters( 'wcj_can_create_admin_interface', true ) ) {
48
- add_submenu_page(
49
- 'woocommerce',
50
- __( 'Booster for WooCommerce Tools', 'woocommerce-jetpack' ),
51
- __( 'Booster Tools', 'woocommerce-jetpack' ),
52
- ( 'yes' === wcj_get_option( 'wcj_' . 'admin_tools' . '_enabled', 'no' ) && 'yes' === wcj_get_option( 'wcj_admin_tools_show_menus_to_admin_only', 'no' ) ? 'manage_options' : 'manage_woocommerce' ),
53
- 'wcj-tools',
54
- array( $this, 'create_tools_page' )
55
- );
 
56
  }
57
- }
58
 
59
- /**
60
- * create_tools_page.
61
- *
62
- * @version 5.5.9
63
- */
64
- function create_tools_page() {
65
 
66
- // Tabs
67
- $tabs = apply_filters( 'wcj_tools_tabs', array(
68
- array(
69
- 'id' => 'dashboard',
70
- 'title' => __( 'Tools Dashboard', 'woocommerce-jetpack' ),
71
- ),
72
- ) );
73
- $html = '<h2 class="nav-tab-wrapper woo-nav-tab-wrapper wcj_tool_tab_part">';
74
- $active_tab = ( isset( $_GET['tab'] ) ) ? $_GET['tab'] : 'dashboard';
75
- foreach ( $tabs as $tab ) {
76
- $is_active = ( $active_tab === $tab['id'] ) ? 'nav-tab-active' : '';
77
- $html .= '<a href="' . esc_url(add_query_arg( array( 'page' => 'wcj-tools', 'tab' => $tab['id'] ), get_admin_url() . 'admin.php' )) . '" class="nav-tab ' . $is_active . '">' . $tab['title'] . '</a>';
78
- }
79
- $html .= '</h2>';
80
- echo $html;
 
 
 
 
 
 
 
 
 
 
 
81
 
82
- // Content
83
- if ( 'dashboard' === $active_tab ) {
84
- $title = __( 'Booster for WooCommerce Tools - Dashboard', 'woocommerce-jetpack' );
85
- $desc = __( 'This dashboard lets you check statuses and short descriptions of all available Booster for WooCommerce tools. Tools can be enabled through WooCommerce > Settings > Booster. Enabled tools will appear in the tabs menu above.', 'woocommerce-jetpack' );
86
- echo '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
87
- echo '<h3>' . $title . '</h3>';
88
- echo '<p>' . $desc . '</p>';
89
- echo '<table class="widefat striped" style="width:90%;">';
90
- echo '<tr>';
91
- echo '<th style="width:20%;">' . __( 'Tool', 'woocommerce-jetpack' ) . '</th>';
92
- echo '<th style="width:20%;">' . __( 'Module', 'woocommerce-jetpack' ) . '</th>';
93
- echo '<th style="width:50%;">' . __( 'Description', 'woocommerce-jetpack' ) . '</th>';
94
- echo '<th style="width:10%;">' . __( 'Status', 'woocommerce-jetpack' ) . '</th>';
95
- echo '</tr>';
96
- do_action( 'wcj_tools_' . 'dashboard' );
97
- echo '</table>';
98
- echo '</div>';
99
- } else {
100
- do_action( 'wcj_tools_' . $active_tab );
 
101
  }
102
  }
103
- }
104
 
105
  endif;
106
 
4
  *
5
  * @version 5.5.9
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/admin
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Tools' ) ) :
15
+ /**
16
+ * WCJ_Tools.
17
+ */
18
+ class WCJ_Tools {
19
 
20
+ /**
21
+ * Constructor.
22
+ */
23
+ public function __construct() {
24
+ if ( is_admin() ) {
25
+ if ( apply_filters( 'wcj_can_create_admin_interface', true ) ) {
26
+ add_action( 'admin_menu', array( $this, 'add_wcj_tools' ), 100 );
27
+ add_action( 'admin_enqueue_scripts', array( $this, 'wcj_new_desing_dashboard_enqueue' ) );
28
+ }
 
29
  }
30
  }
 
31
 
32
+ /**
33
+ * Wcj_new_desing_dashboard_enqueue.
34
+ *
35
+ * @version 5.5.6
36
+ * @since 5.5.6
37
+ */
38
+ public function wcj_new_desing_dashboard_enqueue() {
39
+ $page = ( isset( $_GET['page'] ) ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';
40
+ if ( 'wcj-tools' === $page ) {
41
+ wp_enqueue_style( 'wcj-admin-wcj-new_desing', wcj_plugin_url() . '/includes/css/admin-style.css', array(), time() );
42
+ wp_enqueue_script( 'wcj-admin-script', wcj_plugin_url() . '/includes/js/admin-script.js', array( 'jquery' ), '5.0.0', true );
43
+
44
+ }
45
+ }
46
+ /**
47
+ * Add_wcj_tools.
48
+ *
49
+ * @version 4.8.0
50
+ */
51
+ public function add_wcj_tools() {
52
+ if ( apply_filters( 'wcj_can_create_admin_interface', true ) ) {
53
+ add_submenu_page(
54
+ 'woocommerce',
55
+ __( 'Booster for WooCommerce Tools', 'woocommerce-jetpack' ),
56
+ __( 'Booster Tools', 'woocommerce-jetpack' ),
57
+ ( 'yes' === wcj_get_option( 'wcj_admin_tools_enabled', 'no' ) && 'yes' === wcj_get_option( 'wcj_admin_tools_show_menus_to_admin_only', 'no' ) ? 'manage_options' : 'manage_woocommerce' ),
58
+ 'wcj-tools',
59
+ array( $this, 'create_tools_page' )
60
+ );
61
+ }
62
  }
 
63
 
64
+ /**
65
+ * Create_tools_page.
66
+ *
67
+ * @version 5.5.9
68
+ */
69
+ public function create_tools_page() {
70
 
71
+ // Tabs.
72
+ $tabs = apply_filters(
73
+ 'wcj_tools_tabs',
74
+ array(
75
+ array(
76
+ 'id' => 'dashboard',
77
+ 'title' => __( 'Tools Dashboard', 'woocommerce-jetpack' ),
78
+ ),
79
+ )
80
+ );
81
+ $html = '<h2 class="nav-tab-wrapper woo-nav-tab-wrapper wcj_tool_tab_part">';
82
+ $active_tab = ( isset( $_GET['tab'] ) ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'dashboard';
83
+ foreach ( $tabs as $tab ) {
84
+ $is_active = ( $active_tab === $tab['id'] ) ? 'nav-tab-active' : '';
85
+ $html .= '<a href="' . esc_url(
86
+ add_query_arg(
87
+ array(
88
+ 'page' => 'wcj-tools',
89
+ 'tab' => $tab['id'],
90
+ ),
91
+ get_admin_url() . 'admin.php'
92
+ )
93
+ ) . '" class="nav-tab ' . $is_active . '">' . $tab['title'] . '</a>';
94
+ }
95
+ $html .= '</h2>';
96
+ echo wp_kses_post( $html );
97
 
98
+ // Content.
99
+ if ( 'dashboard' === $active_tab ) {
100
+ $title = __( 'Booster for WooCommerce Tools - Dashboard', 'woocommerce-jetpack' );
101
+ $desc = __( 'This dashboard lets you check statuses and short descriptions of all available Booster for WooCommerce tools. Tools can be enabled through WooCommerce > Settings > Booster. Enabled tools will appear in the tabs menu above.', 'woocommerce-jetpack' );
102
+ echo '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
103
+ echo '<h3>' . wp_kses_post( $title ) . '</h3>';
104
+ echo '<p>' . wp_kses_post( $desc ) . '</p>';
105
+ echo '<table class="widefat striped" style="width:90%;">';
106
+ echo '<tr>';
107
+ echo '<th style="width:20%;">' . wp_kses_post( 'Tool', 'woocommerce-jetpack' ) . '</th>';
108
+ echo '<th style="width:20%;">' . wp_kses_post( 'Module', 'woocommerce-jetpack' ) . '</th>';
109
+ echo '<th style="width:50%;">' . wp_kses_post( 'Description', 'woocommerce-jetpack' ) . '</th>';
110
+ echo '<th style="width:10%;">' . wp_kses_post( 'Status', 'woocommerce-jetpack' ) . '</th>';
111
+ echo '</tr>';
112
+ do_action( 'wcj_tools_dashboard' );
113
+ echo '</table>';
114
+ echo '</div>';
115
+ } else {
116
+ do_action( 'wcj_tools_' . $active_tab );
117
+ }
118
  }
119
  }
 
120
 
121
  endif;
122
 
includes/admin/class-wcj-welcome.php CHANGED
@@ -1,100 +1,110 @@
1
- <?php
2
- /**
3
- * Booster getting started
4
- *
5
- * @version 5.4.3
6
- * @author Pluggabl LLC.
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
10
-
11
- if ( ! class_exists( 'WCJ_Welcome' ) ) :
12
-
13
- class WCJ_Welcome {
14
- /**
15
- * Constructor.
16
- */
17
- function __construct() {
18
- if ( is_admin() ) {
19
-
20
- if(isset( $_GET['page'] ) && $_GET['page'] == "jetpack-getting-started" ){
21
- add_action('in_admin_header', function () {
22
- remove_all_actions('admin_notices');
23
- remove_all_actions('all_admin_notices');
24
- }, 1);
25
- }
26
-
27
- add_action( 'admin_init', array( $this, 'wcj_redirect_to_getting_started' ), 10 );
28
- add_action( 'admin_menu', array( $this, 'wcj_register_welcome_page' ) );
29
- add_action( 'network_admin_menu', array( $this, 'wcj_register_welcome_page' ) );
30
- add_action( 'admin_head', array( $this, 'wcj_hide_menu' ) );
31
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_script' ) );
32
-
33
- }
34
- }
35
-
36
- /**
37
- * wcj_register_welcome_page
38
- *
39
- * @version 5.4.3
40
- */
41
- public function wcj_register_welcome_page() {
42
- add_dashboard_page(
43
- esc_html__( 'Welcome to Booster', 'woocommerce-jetpack' ),
44
- esc_html__( 'Welcome to Booster', 'woocommerce-jetpack' ),
45
- apply_filters( 'wcj_welcome_screen_filter', 'manage_options' ),
46
- 'jetpack-getting-started',
47
- array( $this, 'wcj_welcome_screen_content' )
48
- );
49
- }
50
-
51
- /**
52
- * wcj_hide_menu
53
- *
54
- * @version 5.4.1
55
- */
56
- public function wcj_hide_menu() {
57
- remove_submenu_page( 'index.php', 'jetpack-getting-started' );
58
- }
59
-
60
- /**
61
- * wcj_redirect_to_getting_started
62
- *
63
- * @version 5.4.1
64
- */
65
- public function wcj_redirect_to_getting_started() {
66
- if ( ! get_transient( '_wcj_activation_redirect' ) || isset( $_GET['wcj-redirect'] ) ) {
67
- return;
68
- }
69
-
70
- delete_transient( '_wcj_activation_redirect' );
71
-
72
- $redirect = admin_url( 'index.php?page=jetpack-getting-started&wcj-redirect=1' );
73
- wp_safe_redirect( $redirect );
74
- exit;
75
- }
76
-
77
- /**
78
- * wcj_welcome_screen_content
79
- *
80
- * @version 5.4.1
81
- */
82
- public function wcj_welcome_screen_content() {
83
- require_once( WCJ_PLUGIN_PATH . '/includes/admin/wcj-welcome-screen-content.php' );
84
- }
85
-
86
- /**
87
- * enqueue_admin_script.
88
- *
89
- * @version 5.4.3
90
- * @since 5.4.3
91
- */
92
- function enqueue_admin_script() {
93
- wp_enqueue_script( 'wcj-admin-js', trailingslashit( wcj_plugin_url() ) . 'includes/js/wcj-admin.js', array( 'jquery' ), WCJ()->version, true );
94
- wp_localize_script( 'wcj-admin-js', 'admin_object' ,array('admin_object'), false );
95
- }
96
- }
97
-
98
- endif;
99
-
100
- return new WCJ_Welcome();
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster getting started
4
+ *
5
+ * @version 5.4.3
6
+ * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/admin
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
+
14
+ if ( ! class_exists( 'WCJ_Welcome' ) ) :
15
+ /**
16
+ * WCJ_Welcome.
17
+ */
18
+ class WCJ_Welcome {
19
+ /**
20
+ * Constructor.
21
+ */
22
+ public function __construct() {
23
+ if ( is_admin() ) {
24
+
25
+ if ( isset( $_GET['page'] ) && 'jetpack-getting-started' === $_GET['page'] ) {
26
+ add_action(
27
+ 'in_admin_header',
28
+ function () {
29
+ remove_all_actions( 'admin_notices' );
30
+ remove_all_actions( 'all_admin_notices' );
31
+ },
32
+ 1
33
+ );
34
+ }
35
+
36
+ add_action( 'admin_init', array( $this, 'wcj_redirect_to_getting_started' ), 10 );
37
+ add_action( 'admin_menu', array( $this, 'wcj_register_welcome_page' ) );
38
+ add_action( 'network_admin_menu', array( $this, 'wcj_register_welcome_page' ) );
39
+ add_action( 'admin_head', array( $this, 'wcj_hide_menu' ) );
40
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_script' ) );
41
+
42
+ }
43
+ }
44
+
45
+ /**
46
+ * Wcj_register_welcome_page.
47
+ *
48
+ * @version 5.4.3
49
+ */
50
+ public function wcj_register_welcome_page() {
51
+ add_dashboard_page(
52
+ esc_html__( 'Welcome to Booster', 'woocommerce-jetpack' ),
53
+ esc_html__( 'Welcome to Booster', 'woocommerce-jetpack' ),
54
+ apply_filters( 'wcj_welcome_screen_filter', 'manage_options' ),
55
+ 'jetpack-getting-started',
56
+ array( $this, 'wcj_welcome_screen_content' )
57
+ );
58
+ }
59
+
60
+ /**
61
+ * Wcj_hide_menu.
62
+ *
63
+ * @version 5.4.1
64
+ */
65
+ public function wcj_hide_menu() {
66
+ remove_submenu_page( 'index.php', 'jetpack-getting-started' );
67
+ }
68
+
69
+ /**
70
+ * Wcj_redirect_to_getting_started.
71
+ *
72
+ * @version 5.4.1
73
+ */
74
+ public function wcj_redirect_to_getting_started() {
75
+
76
+ if ( ! get_transient( '_wcj_activation_redirect' ) || isset( $_GET['wcj-redirect'] ) ) {
77
+ return;
78
+ }
79
+
80
+ delete_transient( '_wcj_activation_redirect' );
81
+
82
+ $redirect = admin_url( 'index.php?page=jetpack-getting-started&wcj-redirect=1' );
83
+ wp_safe_redirect( $redirect );
84
+ exit;
85
+ }
86
+
87
+ /**
88
+ * Wcj_welcome_screen_content.
89
+ *
90
+ * @version 5.4.1
91
+ */
92
+ public function wcj_welcome_screen_content() {
93
+ require_once WCJ_PLUGIN_PATH . '/includes/admin/wcj-welcome-screen-content.php';
94
+ }
95
+
96
+ /**
97
+ * Enqueue_admin_script.
98
+ *
99
+ * @version 5.4.3
100
+ * @since 5.4.3
101
+ */
102
+ public function enqueue_admin_script() {
103
+ wp_enqueue_script( 'wcj-admin-js', trailingslashit( wcj_plugin_url() ) . 'includes/js/wcj-admin.js', array( 'jquery' ), w_c_j()->version, true );
104
+ wp_localize_script( 'wcj-admin-js', 'admin_object', array( 'admin_object' ), false );
105
+ }
106
+ }
107
+
108
+ endif;
109
+
110
+ return new WCJ_Welcome();
includes/admin/wcj-modules-cats.php CHANGED
@@ -6,200 +6,204 @@
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
8
  * @todo (maybe) split "Shipping & Orders", "Cart & Checkout", "Products", "Prices & Currencies" etc.
 
9
  */
10
 
11
- return apply_filters( 'wcj_modules', array(
 
 
12
 
13
- 'dashboard' => array(
14
- 'label' => __( 'Dashboard', 'woocommerce-jetpack' ),
15
- 'desc' => __( 'This dashboard lets you enable/disable any Booster\'s module. Each checkbox comes with short module\'s description. Please visit <a href="https://booster.io" target="_blank">https://booster.io</a> for detailed info on each feature.', 'woocommerce-jetpack' ),
16
- 'all_cat_ids' => array(
17
- 'by_category',
18
- 'all_module',
19
- 'active',
20
- 'manager',
 
21
  ),
22
- ),
23
 
24
- 'prices_and_currencies' => array(
25
- 'label' => __( 'Prices & Currencies', 'woocommerce-jetpack' ),
26
- 'desc' => __( 'Multicurrency, Price Converter, Wholesale Pricing, Name You Price, Price based on User Role and more.', 'woocommerce-jetpack' ),
27
- 'all_cat_ids' => array(
28
- 'price_by_country',
29
- 'multicurrency',
30
- 'multicurrency_base_price',
31
- 'currency_per_product',
32
- 'currency',
33
- 'currency_external_products',
34
- 'bulk_price_converter',
35
- 'wholesale_price',
36
- 'product_open_pricing',
37
- 'offer_price',
38
- 'price_by_user_role',
39
- 'product_price_by_formula',
40
- 'global_discount',
41
- 'currency_exchange_rates',
42
- 'price_formats',
 
43
  ),
44
- ),
45
- 'labels' => array(
46
- 'label' => __( 'Button & Price Labels', 'woocommerce-jetpack' ),
47
- 'desc' => __( 'Add to Cart Labels, Call for Price, Custom Price Labels and more.', 'woocommerce-jetpack' ),
48
- 'all_cat_ids' => array(
49
- 'price_labels',
50
- 'call_for_price',
51
- 'free_price',
52
- 'add_to_cart',
53
- 'more_button_labels',
54
  ),
55
- ),
56
 
57
- 'products' => array(
58
- 'label' => __( 'Products', 'woocommerce-jetpack' ),
59
- 'desc' => __( 'Bookings, Crowdfunding Products, Product Addons and Input Fields, Product Listings, Product Tabs and more.', 'woocommerce-jetpack' ),
60
- 'all_cat_ids' => array(
61
- 'product_listings',
62
- 'tax_display',
63
- 'admin_products_list',
64
- 'products_per_page',
65
- 'product_tabs',
66
- 'product_custom_info',
67
- 'related_products',
68
- 'cross_sells',
69
- 'upsells',
70
- 'sorting',
71
- 'sku',
72
- 'stock',
73
- 'product_input_fields',
74
- 'product_add_to_cart',
75
- 'add_to_cart_button_visibility',
76
- 'purchase_data',
77
- 'product_bookings',
78
- 'crowdfunding',
79
- 'product_addons',
80
- 'product_images',
81
- 'sale_flash',
82
- 'product_by_country',
83
- 'product_by_user_role',
84
- 'product_custom_visibility',
85
- 'product_by_time',
86
- 'product_by_date',
87
- 'product_by_user',
88
- 'products_xml',
89
- 'product_bulk_meta_editor',
90
- 'product_msrp'
 
91
  ),
92
- ),
93
 
94
- 'cart_and_checkout' => array(
95
- 'label' => __( 'Cart & Checkout', 'woocommerce-jetpack' ),
96
- 'desc' => __( 'Cart and Checkout Customization, Empty Cart Button, Mini Cart, Coupons and more.', 'woocommerce-jetpack' ),
97
- 'all_cat_ids' => array(
98
- 'cart',
99
- 'cart_customization',
100
- 'empty_cart',
101
- 'mini_cart',
102
- 'url_coupons',
103
- 'coupon_code_generator',
104
- 'coupon_by_user_role',
105
- 'checkout_core_fields',
106
- 'checkout_custom_fields',
107
- 'checkout_files_upload',
108
- 'checkout_custom_info',
109
- 'checkout_customization',
110
- 'checkout_fees',
111
- 'eu_vat_number',
112
-
 
113
  ),
114
- ),
115
 
116
- 'payment_gateways' => array(
117
- 'label' => __( 'Payment Gateways', 'woocommerce-jetpack' ),
118
- 'desc' => __( 'Custom Payment Gateways, Gateways Currency, Gateways Fees and Discounts and more.', 'woocommerce-jetpack' ),
119
- 'all_cat_ids' => array(
120
- 'payment_gateways',
121
- 'payment_gateways_icons',
122
- 'payment_gateways_fees',
123
- 'payment_gateways_per_category',
124
- 'payment_gateways_currency',
125
- 'payment_gateways_by_currency',
126
- 'payment_gateways_min_max',
127
- 'payment_gateways_by_country',
128
- 'payment_gateways_by_user_role',
129
- 'payment_gateways_by_shipping',
 
130
  ),
131
- ),
132
 
133
- 'shipping_and_orders' => array(
134
- 'label' => __( 'Shipping & Orders', 'woocommerce-jetpack' ),
135
- 'desc' => __( 'Order Custom Statuses, Order Minimum Amount, Order Numbers, Custom Shipping Methods and more.', 'woocommerce-jetpack' ),
136
- 'all_cat_ids' => array(
137
- 'shipping',
138
- 'shipping_options',
139
- 'shipping_icons',
140
- 'shipping_description',
141
- 'shipping_time',
142
- 'left_to_free_shipping',
143
- 'shipping_calculator',
144
- 'shipping_by_user_role',
145
- 'shipping_by_products',
146
- 'shipping_by_cities',
147
- 'shipping_by_time',
148
- 'shipping_by_order_amount',
149
- 'shipping_by_order_qty',
150
- 'address_formats',
151
- 'orders',
152
- 'admin_orders_list',
153
- 'order_min_amount',
154
- 'order_numbers',
155
- 'order_custom_statuses',
156
- 'order_quantities',
157
- 'max_products_per_user',
 
158
  ),
159
- ),
160
 
161
- 'pdf_invoicing' => array(
162
- 'label' => __( 'PDF Invoicing & Packing Slips', 'woocommerce-jetpack' ),
163
- 'desc' => __( 'PDF Documents', 'woocommerce-jetpack' ),
164
- 'all_cat_ids' => array(
165
- 'pdf_invoicing',
166
- 'pdf_invoicing_numbering',
167
- 'pdf_invoicing_templates',
168
- 'pdf_invoicing_header',
169
- 'pdf_invoicing_footer',
170
- 'pdf_invoicing_styling',
171
- 'pdf_invoicing_page',
172
- 'pdf_invoicing_emails',
173
- 'pdf_invoicing_display',
174
- 'pdf_invoicing_advanced',
 
175
  ),
176
- ),
177
 
178
- 'emails_and_misc' => array(
179
- 'label' => __( 'Emails & Misc.', 'woocommerce-jetpack' ),
180
- 'desc' => __( 'Emails, Reports, Export, Admin Tools, General Options and more.', 'woocommerce-jetpack' ),
181
- 'all_cat_ids' => array(
182
- 'general',
183
- 'breadcrumbs',
184
- 'admin_bar',
185
- 'export',
186
- 'my_account',
187
- 'old_slugs',
188
- 'reports',
189
- 'admin_tools',
190
- 'debug_tools',
191
- 'emails',
192
- 'email_options',
193
- 'emails_verification',
194
- 'wpml',
195
- 'custom_css',
196
- 'custom_js',
197
- 'custom_php',
198
- 'track_users',
199
- 'modules_by_user_roles',
200
- 'template_editor',
201
- 'product_info', // deprecated
 
202
  ),
203
- ),
204
 
205
- ) );
 
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
8
  * @todo (maybe) split "Shipping & Orders", "Cart & Checkout", "Products", "Prices & Currencies" etc.
9
+ * @package Booster_For_WooCommerce/admin
10
  */
11
 
12
+ return apply_filters(
13
+ 'wcj_modules',
14
+ array(
15
 
16
+ 'dashboard' => array(
17
+ 'label' => __( 'Dashboard', 'woocommerce-jetpack' ),
18
+ 'desc' => __( 'This dashboard lets you enable/disable any Booster\'s module. Each checkbox comes with short module\'s description. Please visit <a href="https://booster.io" target="_blank">https://booster.io</a> for detailed info on each feature.', 'woocommerce-jetpack' ),
19
+ 'all_cat_ids' => array(
20
+ 'by_category',
21
+ 'all_module',
22
+ 'active',
23
+ 'manager',
24
+ ),
25
  ),
 
26
 
27
+ 'prices_and_currencies' => array(
28
+ 'label' => __( 'Prices & Currencies', 'woocommerce-jetpack' ),
29
+ 'desc' => __( 'Multicurrency, Price Converter, Wholesale Pricing, Name You Price, Price based on User Role and more.', 'woocommerce-jetpack' ),
30
+ 'all_cat_ids' => array(
31
+ 'price_by_country',
32
+ 'multicurrency',
33
+ 'multicurrency_base_price',
34
+ 'currency_per_product',
35
+ 'currency',
36
+ 'currency_external_products',
37
+ 'bulk_price_converter',
38
+ 'wholesale_price',
39
+ 'product_open_pricing',
40
+ 'offer_price',
41
+ 'price_by_user_role',
42
+ 'product_price_by_formula',
43
+ 'global_discount',
44
+ 'currency_exchange_rates',
45
+ 'price_formats',
46
+ ),
47
  ),
48
+ 'labels' => array(
49
+ 'label' => __( 'Button & Price Labels', 'woocommerce-jetpack' ),
50
+ 'desc' => __( 'Add to Cart Labels, Call for Price, Custom Price Labels and more.', 'woocommerce-jetpack' ),
51
+ 'all_cat_ids' => array(
52
+ 'price_labels',
53
+ 'call_for_price',
54
+ 'free_price',
55
+ 'add_to_cart',
56
+ 'more_button_labels',
57
+ ),
58
  ),
 
59
 
60
+ 'products' => array(
61
+ 'label' => __( 'Products', 'woocommerce-jetpack' ),
62
+ 'desc' => __( 'Bookings, Crowdfunding Products, Product Addons and Input Fields, Product Listings, Product Tabs and more.', 'woocommerce-jetpack' ),
63
+ 'all_cat_ids' => array(
64
+ 'product_listings',
65
+ 'tax_display',
66
+ 'admin_products_list',
67
+ 'products_per_page',
68
+ 'product_tabs',
69
+ 'product_custom_info',
70
+ 'related_products',
71
+ 'cross_sells',
72
+ 'upsells',
73
+ 'sorting',
74
+ 'sku',
75
+ 'stock',
76
+ 'product_input_fields',
77
+ 'product_add_to_cart',
78
+ 'add_to_cart_button_visibility',
79
+ 'purchase_data',
80
+ 'product_bookings',
81
+ 'crowdfunding',
82
+ 'product_addons',
83
+ 'product_images',
84
+ 'sale_flash',
85
+ 'product_by_country',
86
+ 'product_by_user_role',
87
+ 'product_custom_visibility',
88
+ 'product_by_time',
89
+ 'product_by_date',
90
+ 'product_by_user',
91
+ 'products_xml',
92
+ 'product_bulk_meta_editor',
93
+ 'product_msrp',
94
+ ),
95
  ),
 
96
 
97
+ 'cart_and_checkout' => array(
98
+ 'label' => __( 'Cart & Checkout', 'woocommerce-jetpack' ),
99
+ 'desc' => __( 'Cart and Checkout Customization, Empty Cart Button, Mini Cart, Coupons and more.', 'woocommerce-jetpack' ),
100
+ 'all_cat_ids' => array(
101
+ 'cart',
102
+ 'cart_customization',
103
+ 'empty_cart',
104
+ 'mini_cart',
105
+ 'url_coupons',
106
+ 'coupon_code_generator',
107
+ 'coupon_by_user_role',
108
+ 'checkout_core_fields',
109
+ 'checkout_custom_fields',
110
+ 'checkout_files_upload',
111
+ 'checkout_custom_info',
112
+ 'checkout_customization',
113
+ 'checkout_fees',
114
+ 'eu_vat_number',
115
+
116
+ ),
117
  ),
 
118
 
119
+ 'payment_gateways' => array(
120
+ 'label' => __( 'Payment Gateways', 'woocommerce-jetpack' ),
121
+ 'desc' => __( 'Custom Payment Gateways, Gateways Currency, Gateways Fees and Discounts and more.', 'woocommerce-jetpack' ),
122
+ 'all_cat_ids' => array(
123
+ 'payment_gateways',
124
+ 'payment_gateways_icons',
125
+ 'payment_gateways_fees',
126
+ 'payment_gateways_per_category',
127
+ 'payment_gateways_currency',
128
+ 'payment_gateways_by_currency',
129
+ 'payment_gateways_min_max',
130
+ 'payment_gateways_by_country',
131
+ 'payment_gateways_by_user_role',
132
+ 'payment_gateways_by_shipping',
133
+ ),
134
  ),
 
135
 
136
+ 'shipping_and_orders' => array(
137
+ 'label' => __( 'Shipping & Orders', 'woocommerce-jetpack' ),
138
+ 'desc' => __( 'Order Custom Statuses, Order Minimum Amount, Order Numbers, Custom Shipping Methods and more.', 'woocommerce-jetpack' ),
139
+ 'all_cat_ids' => array(
140
+ 'shipping',
141
+ 'shipping_options',
142
+ 'shipping_icons',
143
+ 'shipping_description',
144
+ 'shipping_time',
145
+ 'left_to_free_shipping',
146
+ 'shipping_calculator',
147
+ 'shipping_by_user_role',
148
+ 'shipping_by_products',
149
+ 'shipping_by_cities',
150
+ 'shipping_by_time',
151
+ 'shipping_by_order_amount',
152
+ 'shipping_by_order_qty',
153
+ 'address_formats',
154
+ 'orders',
155
+ 'admin_orders_list',
156
+ 'order_min_amount',
157
+ 'order_numbers',
158
+ 'order_custom_statuses',
159
+ 'order_quantities',
160
+ 'max_products_per_user',
161
+ ),
162
  ),
 
163
 
164
+ 'pdf_invoicing' => array(
165
+ 'label' => __( 'PDF Invoicing & Packing Slips', 'woocommerce-jetpack' ),
166
+ 'desc' => __( 'PDF Documents', 'woocommerce-jetpack' ),
167
+ 'all_cat_ids' => array(
168
+ 'pdf_invoicing',
169
+ 'pdf_invoicing_numbering',
170
+ 'pdf_invoicing_templates',
171
+ 'pdf_invoicing_header',
172
+ 'pdf_invoicing_footer',
173
+ 'pdf_invoicing_styling',
174
+ 'pdf_invoicing_page',
175
+ 'pdf_invoicing_emails',
176
+ 'pdf_invoicing_display',
177
+ 'pdf_invoicing_advanced',
178
+ ),
179
  ),
 
180
 
181
+ 'emails_and_misc' => array(
182
+ 'label' => __( 'Emails & Misc.', 'woocommerce-jetpack' ),
183
+ 'desc' => __( 'Emails, Reports, Export, Admin Tools, General Options and more.', 'woocommerce-jetpack' ),
184
+ 'all_cat_ids' => array(
185
+ 'general',
186
+ 'breadcrumbs',
187
+ 'admin_bar',
188
+ 'export',
189
+ 'my_account',
190
+ 'old_slugs',
191
+ 'reports',
192
+ 'admin_tools',
193
+ 'debug_tools',
194
+ 'emails',
195
+ 'email_options',
196
+ 'emails_verification',
197
+ 'wpml',
198
+ 'custom_css',
199
+ 'custom_js',
200
+ 'custom_php',
201
+ 'track_users',
202
+ 'modules_by_user_roles',
203
+ 'template_editor',
204
+ 'product_info', // deprecated.
205
+ ),
206
  ),
 
207
 
208
+ )
209
+ );
includes/admin/wcj-welcome-screen-content.php CHANGED
@@ -1,169 +1,171 @@
1
- <?php
2
-
3
- /**
4
- * Booster for WooCommerce - Welcome Screen Content
5
- *
6
- * @version 5.4.8
7
- * @author Pluggabl LLC.
8
- */
9
- ?>
10
- <div class="wcj-welcome-page">
11
- <div class="wcj-welcome-container">
12
- <div class="wcj-welcome-content-main">
13
- <div class="wcj-welcome-content-logo-main">
14
- <div class="wcj-welcome-content-logo">
15
- </div>
16
- </div>
17
- <div class="wcj-welcome-content-inner">
18
- <h3> <?php esc_html_e('Welcome to booster.', 'woocommerce-jetpack'); ?> </h3>
19
- <p> <?php esc_html_e('Thank you for choosing Booster - Supercharge your WooCommerce site with these awesome powerful features. More than 100 modules. All in one WooCommerce plugin.', 'woocommerce-jetpack'); ?> </p>
20
- <a href="<?php echo admin_url('admin.php?page=wc-settings&tab=jetpack'); ?>" class="wcj-buy-puls-btn"> <?php esc_html_e('Launch Booster Settings', 'woocommerce-jetpack'); ?> </a>
21
- </div>
22
- </div>
23
- <div class="wcj-welcome-content-main wcj-welcome-padding-top-0">
24
- <div class="wcj-welcome-content-inner">
25
- <div class="wcj-buy-puls-btn-main">
26
- <a target="_blank" href="https://booster.io/buy-booster/" class="wcj-buy-puls-btn"> <?php esc_html_e('Upgrade Booster to unlock this feature.', 'woocommerce-jetpack'); ?> </a>
27
- </div>
28
- <div class="wcj-welcome-content-inner wcj-buy-puls-content-row">
29
- <div class="wcj-buy-puls-content-col-4">
30
- <div class="wcj-badge">
31
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/30day-guarantee.png">
32
- <span class="wcj-badge-sp-cn"> <?php esc_html_e('30-Day Risk Free', 'woocommerce-jetpack'); ?> <br> <?php esc_html_e('Money Back Guarantee', 'woocommerce-jetpack'); ?> </span>
33
- </div>
34
- </div>
35
- <div class="wcj-buy-puls-content-col-4">
36
- <div class="wcj-badge">
37
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/wp-logo.svg">
38
- <span class="wcj-badge-sp-cn"><?php esc_html_e('400+ 5-Star', 'woocommerce-jetpack'); ?> <br> <?php esc_html_e('Reviews', 'woocommerce-jetpack'); ?></span>
39
- </div>
40
- </div>
41
- <div class="wcj-buy-puls-content-col-4">
42
- <div class="wcj-badge">
43
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/trust-icon.png">
44
- <span class="wcj-badge-sp-cn"><?php esc_html_e('Trusted by', 'woocommerce-jetpack'); ?> <br> <?php esc_html_e('100,000+', 'woocommerce-jetpack'); ?> <br> <?php esc_html_e('Websites', 'woocommerce-jetpack'); ?></span>
45
- </div>
46
- </div>
47
- </div>
48
- </div>
49
- <div class="wcj-welcome-content-inner wcj-welcome-padding-top-0">
50
- <div class="wcj-buy-puls-head">
51
- <h3> <?php esc_html_e('Tons of Customizations and Zero Coding.', 'woocommerce-jetpack'); ?> </h3>
52
- <p>
53
- <?php esc_html_e('Access more than one hundred easy-to-use modules to quickly add customized functionality to your WooCommerce business', 'woocommerce-jetpack'); ?>
54
- <strong><?php esc_html_e('- Without writing a line of code.', 'woocommerce-jetpack'); ?> </strong>
55
- </p>
56
- </div>
57
- <div class="wcj-welcome-content-inner wcj-buy-puls-content-row">
58
- <div class="wcj-buy-puls-content-col-6 wcj-feature">
59
- <div class="wcj-feature-img">
60
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/feature-pdf.png">
61
- </div>
62
- <div class="wcj-feature-text">
63
- <h4> <?php esc_html_e('PDF Invoicing and Packing Slips', 'woocommerce-jetpack'); ?> </h4>
64
- <p> <?php esc_html_e('Streamline your WooCommerce orders and paperwork, and deliver a seamless customer experience with the PDF Invoicing and Packing Slips module.', 'woocommerce-jetpack'); ?> </p>
65
- </div>
66
- </div>
67
- <div class="wcj-buy-puls-content-col-6 wcj-feature">
68
- <div class="wcj-feature-img">
69
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/feature-add-on.png">
70
- </div>
71
- <div class="wcj-feature-text">
72
- <h4> <?php esc_html_e('Product Addons', 'woocommerce-jetpack'); ?> </h4>
73
- <p> <?php esc_html_e('Create addons for your WooCommerce products like support service or special offers with the Product Addons Module.', 'woocommerce-jetpack'); ?> </p>
74
- </div>
75
- </div>
76
- <div class="wcj-buy-puls-content-col-6 wcj-feature">
77
- <div class="wcj-feature-img">
78
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/feature-input-field.png">
79
- </div>
80
- <div class="wcj-feature-text">
81
- <h4> <?php esc_html_e('Product Input Fields', 'woocommerce-jetpack'); ?> </h4>
82
- <p> <?php esc_html_e('Allow your customers to provide more details about their order with the Product Input Fields module. Super handy when selling customized products.', 'woocommerce-jetpack'); ?> </p>
83
- </div>
84
- </div>
85
- <div class="wcj-buy-puls-content-col-6 wcj-feature">
86
- <div class="wcj-feature-img">
87
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/feature-button-prices.png">
88
- </div>
89
- <div class="wcj-feature-text">
90
- <h4> <?php esc_html_e('Button and Price Labels', 'woocommerce-jetpack'); ?> </h4>
91
- <p> <?php esc_html_e('Add custom buttons and price labels to your products with this popular module. Set automatic price for products with an empty price field.', 'woocommerce-jetpack'); ?> </p>
92
- </div>
93
- </div>
94
- <div class="wcj-buy-puls-content-col-6 wcj-feature">
95
- <div class="wcj-feature-img">
96
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/feature-prices-currency.png">
97
- </div>
98
- <div class="wcj-feature-text">
99
- <h4> <?php esc_html_e('Prices and Currencies', 'woocommerce-jetpack'); ?> </h4>
100
- <p> <?php esc_html_e('Make it easy for customers around the globe to make purchases on your site by displaying their currency with the Prices and Currencies by Country module.', 'woocommerce-jetpack'); ?> </p>
101
- </div>
102
- </div>
103
- <div class="wcj-buy-puls-content-col-6 wcj-feature">
104
- <div class="wcj-feature-img">
105
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/feature-payment-getway.png">
106
- </div>
107
- <div class="wcj-feature-text">
108
- <h4> <?php esc_html_e('Payment Gateways', 'woocommerce-jetpack'); ?> </h4>
109
- <p> <?php esc_html_e('Set up multiple payment gateways based on currency, shipping method, country, or state.', 'woocommerce-jetpack'); ?> </p>
110
- </div>
111
- </div>
112
- <div class="wcj-buy-puls-content-col-6 wcj-feature">
113
- <div class="wcj-feature-img">
114
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/feature-cart-checkout.png">
115
- </div>
116
- <div class="wcj-feature-text">
117
- <h4> <?php esc_html_e('Cart and Checkout', 'woocommerce-jetpack'); ?> </h4>
118
- <p> <?php esc_html_e('Customize the shopping cart and checkout experience. Add coupons, additional fees, custom fields, and buttons with the Cart and Checkout modules.', 'woocommerce-jetpack'); ?> </p>
119
- </div>
120
- </div>
121
- <div class="wcj-buy-puls-content-col-6 wcj-feature">
122
- <div class="wcj-feature-img">
123
- <img src="<?php echo wcj_plugin_url(); ?>/assets/images/feature-emails-addtool.png">
124
- </div>
125
- <div class="wcj-feature-text">
126
- <h4> <?php esc_html_e('Emails & Additional Tools', 'woocommerce-jetpack'); ?> </h4>
127
- <p> <?php esc_html_e('Add custom emails, additional recipients, and verification for increased security. Explore miscellaneous reporting and customization tools for increased functionality.', 'woocommerce-jetpack'); ?> </p>
128
- </div>
129
- </div>
130
- <div class="wcj-buy-puls-btn-main">
131
- <a target="_blank" href="https://booster.io/category/features/" class="wcj-buy-puls-btn"> <?php esc_html_e('See All Features', 'woocommerce-jetpack'); ?> </a>
132
- </div>
133
- </div>
134
- <div id="subscribe-email" class="wcj-welcome-content-inner wcj-welcome-subscribe-email">
135
- <h3> <?php esc_html_e("Don't miss updates from us!", "woocommerce-jetpack"); ?> </h3>
136
- <form method="post" name="subscribe-email-form">
137
- <input class="form-control user_email" type="email" required="true" name="user_email" placeholder="Enter your email">
138
- <input class="subscribe-email-btn" type="button" name="submit_email_to_klaviyo" value="Submit">
139
- </form>
140
- <?php
141
- if (isset($_REQUEST['msg'])) {
142
- $subscribe_message = "";
143
- $subscribe_message_id = $_REQUEST['msg'];
144
- if ($subscribe_message_id == 1) {
145
- $subscribe_message = "Thank you for subscribing your email";
146
- } else if ($subscribe_message_id == 2) {
147
- $subscribe_message = "You have already subscribed your email";
148
- } else if ($subscribe_message_id == 3) {
149
- $subscribe_message = "Something went wrong with your subscription. Please after some time !";
150
- }
151
- echo '<p style="color: #f46c5e;">' . sprintf(__('%s', 'woocommerce-jetpack'), $subscribe_message) . '</p>';
152
- }
153
- ?>
154
- </div>
155
- <div class="wcj-welcome-content-inner wcj-welcome-subscribe-email">
156
- <h3> <?php esc_html_e("Contact Us", "woocommerce-jetpack"); ?> </h3>
157
- <div class="wcj-support">
158
- <p><?php esc_html_e("Booster Plus customers get access to Premium Support and we respond within 24 business hours.", "woocommerce-jetpack"); ?></p>
159
- <a target="_blank" href="https://booster.io/my-account/booster-contact/"><?php esc_html_e("Booster Plus Premium Support", "woocommerce-jetpack"); ?></a>
160
- </div>
161
- <div class="wcj-support">
162
- <p><?php esc_html_e("Free users post on WordPress Plugin Support forum here. We check these threads twice every week Mon and Frid to respond.", "woocommerce-jetpack"); ?></p>
163
- <a target="_blank" href="https://wordpress.org/support/plugin/woocommerce-jetpack/"><?php esc_html_e("Booster Free Plugin Support", "woocommerce-jetpack"); ?></a>
164
- </div>
165
- </div>
166
- </div>
167
- </div>
168
- </div>
169
- </div>
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Welcome Screen Content
4
+ *
5
+ * @version 5.4.8
6
+ * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/admin
8
+ */
9
+
10
+ ?>
11
+ <div class="wcj-welcome-page">
12
+ <div class="wcj-welcome-container">
13
+ <div class="wcj-welcome-content-main">
14
+ <div class="wcj-welcome-content-logo-main">
15
+ <div class="wcj-welcome-content-logo">
16
+ </div>
17
+ </div>
18
+ <div class="wcj-welcome-content-inner">
19
+ <h3> <?php esc_html_e( 'Welcome to booster.', 'woocommerce-jetpack' ); ?> </h3>
20
+ <p> <?php esc_html_e( 'Thank you for choosing Booster - Supercharge your WooCommerce site with these awesome powerful features. More than 100 modules. All in one WooCommerce plugin.', 'woocommerce-jetpack' ); ?> </p>
21
+ <a href="<?php echo wp_kses_post( admin_url( 'admin.php?page=wc-settings&tab=jetpack' ) ); ?>" class="wcj-buy-puls-btn"> <?php esc_html_e( 'Launch Booster Settings', 'woocommerce-jetpack' ); ?> </a>
22
+ </div>
23
+ </div>
24
+ <div class="wcj-welcome-content-main wcj-welcome-padding-top-0">
25
+ <div class="wcj-welcome-content-inner">
26
+ <div class="wcj-buy-puls-btn-main">
27
+ <a target="_blank" href="https://booster.io/buy-booster/" class="wcj-buy-puls-btn"> <?php esc_html_e( 'Upgrade Booster to unlock this feature.', 'woocommerce-jetpack' ); ?> </a>
28
+ </div>
29
+ <div class="wcj-welcome-content-inner wcj-buy-puls-content-row">
30
+ <div class="wcj-buy-puls-content-col-4">
31
+ <div class="wcj-badge">
32
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/30day-guarantee.png">
33
+ <span class="wcj-badge-sp-cn"> <?php esc_html_e( '30-Day Risk Free', 'woocommerce-jetpack' ); ?> <br> <?php esc_html_e( 'Money Back Guarantee', 'woocommerce-jetpack' ); ?> </span>
34
+ </div>
35
+ </div>
36
+ <div class="wcj-buy-puls-content-col-4">
37
+ <div class="wcj-badge">
38
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/wp-logo.svg">
39
+ <span class="wcj-badge-sp-cn"><?php esc_html_e( '400+ 5-Star', 'woocommerce-jetpack' ); ?> <br> <?php esc_html_e( 'Reviews', 'woocommerce-jetpack' ); ?></span>
40
+ </div>
41
+ </div>
42
+ <div class="wcj-buy-puls-content-col-4">
43
+ <div class="wcj-badge">
44
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/trust-icon.png">
45
+ <span class="wcj-badge-sp-cn"><?php esc_html_e( 'Trusted by', 'woocommerce-jetpack' ); ?> <br> <?php esc_html_e( '100,000+', 'woocommerce-jetpack' ); ?> <br> <?php esc_html_e( 'Websites', 'woocommerce-jetpack' ); ?></span>
46
+ </div>
47
+ </div>
48
+ </div>
49
+ </div>
50
+ <div class="wcj-welcome-content-inner wcj-welcome-padding-top-0">
51
+ <div class="wcj-buy-puls-head">
52
+ <h3> <?php esc_html_e( 'Tons of Customizations and Zero Coding.', 'woocommerce-jetpack' ); ?> </h3>
53
+ <p>
54
+ <?php esc_html_e( 'Access more than one hundred easy-to-use modules to quickly add customized functionality to your WooCommerce business', 'woocommerce-jetpack' ); ?>
55
+ <strong><?php esc_html_e( '- Without writing a line of code.', 'woocommerce-jetpack' ); ?> </strong>
56
+ </p>
57
+ </div>
58
+ <div class="wcj-welcome-content-inner wcj-buy-puls-content-row">
59
+ <div class="wcj-buy-puls-content-col-6 wcj-feature">
60
+ <div class="wcj-feature-img">
61
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/feature-pdf.png">
62
+ </div>
63
+ <div class="wcj-feature-text">
64
+ <h4> <?php esc_html_e( 'PDF Invoicing and Packing Slips', 'woocommerce-jetpack' ); ?> </h4>
65
+ <p> <?php esc_html_e( 'Streamline your WooCommerce orders and paperwork, and deliver a seamless customer experience with the PDF Invoicing and Packing Slips module.', 'woocommerce-jetpack' ); ?> </p>
66
+ </div>
67
+ </div>
68
+ <div class="wcj-buy-puls-content-col-6 wcj-feature">
69
+ <div class="wcj-feature-img">
70
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/feature-add-on.png">
71
+ </div>
72
+ <div class="wcj-feature-text">
73
+ <h4> <?php esc_html_e( 'Product Addons', 'woocommerce-jetpack' ); ?> </h4>
74
+ <p> <?php esc_html_e( 'Create addons for your WooCommerce products like support service or special offers with the Product Addons Module.', 'woocommerce-jetpack' ); ?> </p>
75
+ </div>
76
+ </div>
77
+ <div class="wcj-buy-puls-content-col-6 wcj-feature">
78
+ <div class="wcj-feature-img">
79
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/feature-input-field.png">
80
+ </div>
81
+ <div class="wcj-feature-text">
82
+ <h4> <?php esc_html_e( 'Product Input Fields', 'woocommerce-jetpack' ); ?> </h4>
83
+ <p> <?php esc_html_e( 'Allow your customers to provide more details about their order with the Product Input Fields module. Super handy when selling customized products.', 'woocommerce-jetpack' ); ?> </p>
84
+ </div>
85
+ </div>
86
+ <div class="wcj-buy-puls-content-col-6 wcj-feature">
87
+ <div class="wcj-feature-img">
88
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/feature-button-prices.png">
89
+ </div>
90
+ <div class="wcj-feature-text">
91
+ <h4> <?php esc_html_e( 'Button and Price Labels', 'woocommerce-jetpack' ); ?> </h4>
92
+ <p> <?php esc_html_e( 'Add custom buttons and price labels to your products with this popular module. Set automatic price for products with an empty price field.', 'woocommerce-jetpack' ); ?> </p>
93
+ </div>
94
+ </div>
95
+ <div class="wcj-buy-puls-content-col-6 wcj-feature">
96
+ <div class="wcj-feature-img">
97
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/feature-prices-currency.png">
98
+ </div>
99
+ <div class="wcj-feature-text">
100
+ <h4> <?php esc_html_e( 'Prices and Currencies', 'woocommerce-jetpack' ); ?> </h4>
101
+ <p> <?php esc_html_e( 'Make it easy for customers around the globe to make purchases on your site by displaying their currency with the Prices and Currencies by Country module.', 'woocommerce-jetpack' ); ?> </p>
102
+ </div>
103
+ </div>
104
+ <div class="wcj-buy-puls-content-col-6 wcj-feature">
105
+ <div class="wcj-feature-img">
106
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/feature-payment-getway.png">
107
+ </div>
108
+ <div class="wcj-feature-text">
109
+ <h4> <?php esc_html_e( 'Payment Gateways', 'woocommerce-jetpack' ); ?> </h4>
110
+ <p> <?php esc_html_e( 'Set up multiple payment gateways based on currency, shipping method, country, or state.', 'woocommerce-jetpack' ); ?> </p>
111
+ </div>
112
+ </div>
113
+ <div class="wcj-buy-puls-content-col-6 wcj-feature">
114
+ <div class="wcj-feature-img">
115
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/feature-cart-checkout.png">
116
+ </div>
117
+ <div class="wcj-feature-text">
118
+ <h4> <?php esc_html_e( 'Cart and Checkout', 'woocommerce-jetpack' ); ?> </h4>
119
+ <p> <?php esc_html_e( 'Customize the shopping cart and checkout experience. Add coupons, additional fees, custom fields, and buttons with the Cart and Checkout modules.', 'woocommerce-jetpack' ); ?> </p>
120
+ </div>
121
+ </div>
122
+ <div class="wcj-buy-puls-content-col-6 wcj-feature">
123
+ <div class="wcj-feature-img">
124
+ <img src="<?php echo wp_kses_post( wcj_plugin_url() ); ?>/assets/images/feature-emails-addtool.png">
125
+ </div>
126
+ <div class="wcj-feature-text">
127
+ <h4> <?php esc_html_e( 'Emails & Additional Tools', 'woocommerce-jetpack' ); ?> </h4>
128
+ <p> <?php esc_html_e( 'Add custom emails, additional recipients, and verification for increased security. Explore miscellaneous reporting and customization tools for increased functionality.', 'woocommerce-jetpack' ); ?> </p>
129
+ </div>
130
+ </div>
131
+ <div class="wcj-buy-puls-btn-main">
132
+ <a target="_blank" href="https://booster.io/category/features/" class="wcj-buy-puls-btn"> <?php esc_html_e( 'See All Features', 'woocommerce-jetpack' ); ?> </a>
133
+ </div>
134
+ </div>
135
+ <div id="subscribe-email" class="wcj-welcome-content-inner wcj-welcome-subscribe-email">
136
+ <h3> <?php esc_html_e( "Don't miss updates from us!", 'woocommerce-jetpack' ); ?> </h3>
137
+ <form method="post" name="subscribe-email-form">
138
+ <input class="form-control user_email" type="email" required="true" name="user_email" placeholder="Enter your email">
139
+ <input class="subscribe-email-btn" type="button" name="submit_email_to_klaviyo" value="Submit">
140
+ </form>
141
+ <?php
142
+ if ( isset( $_REQUEST['msg'] ) ) {
143
+ $subscribe_message = '';
144
+ $subscribe_message_id = sanitize_text_field( wp_unslash( $_REQUEST['msg'] ) );
145
+ if ( 1 === $subscribe_message_id ) {
146
+ $subscribe_message = 'Thank you for subscribing your email';
147
+ } elseif ( 2 === $subscribe_message_id ) {
148
+ $subscribe_message = 'You have already subscribed your email';
149
+ } elseif ( 3 === $subscribe_message_id ) {
150
+ $subscribe_message = 'Something went wrong with your subscription. Please after some time !';
151
+ }
152
+ /* translators: %s: translation added */
153
+ echo '<p style="color: #f46c5e;">' . wp_kses_post( sprintf( __( '%s', 'woocommerce-jetpack' ), $subscribe_message ) ) . '</p>';
154
+ }
155
+ ?>
156
+ </div>
157
+ <div class="wcj-welcome-content-inner wcj-welcome-subscribe-email">
158
+ <h3> <?php esc_html_e( 'Contact Us', 'woocommerce-jetpack' ); ?> </h3>
159
+ <div class="wcj-support">
160
+ <p><?php esc_html_e( 'Booster Plus customers get access to Premium Support and we respond within 24 business hours.', 'woocommerce-jetpack' ); ?></p>
161
+ <a target="_blank" href="https://booster.io/my-account/booster-contact/"><?php esc_html_e( 'Booster Plus Premium Support', 'woocommerce-jetpack' ); ?></a>
162
+ </div>
163
+ <div class="wcj-support">
164
+ <p><?php esc_html_e( 'Free users post on WordPress Plugin Support forum here. We check these threads twice every week Mon and Frid to respond.', 'woocommerce-jetpack' ); ?></p>
165
+ <a target="_blank" href="https://wordpress.org/support/plugin/woocommerce-jetpack/"><?php esc_html_e( 'Booster Free Plugin Support', 'woocommerce-jetpack' ); ?></a>
166
+ </div>
167
+ </div>
168
+ </div>
169
+ </div>
170
+ </div>
171
+ </div>
includes/background-process/class-wcj-multicurrency-price-updater.php CHANGED
@@ -7,6 +7,7 @@
7
  * @version 4.5.0
8
  * @since 4.5.0
9
  * @author Pluggabl LLC.
 
10
  */
11
 
12
  if ( ! defined( 'ABSPATH' ) ) {
@@ -14,21 +15,32 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  }
15
 
16
  if ( ! class_exists( 'WCJ_Multicurrency_Price_Updater' ) ) :
17
-
 
 
 
 
18
  class WCJ_Multicurrency_Price_Updater extends WP_Background_Process {
19
 
20
  /**
 
 
21
  * @var string
22
  */
23
  protected $action = 'wcj_bkg_process_price_updater';
24
-
 
 
 
 
 
25
  protected function task( $item ) {
26
  $module = 'multicurrency';
27
  if ( wcj_is_module_enabled( $module ) ) {
28
- WCJ()->modules[ $module ]->save_min_max_prices_per_product( $item['id'], $item['currency'] );
29
  }
30
  return false;
31
  }
32
 
33
  }
34
- endif;
7
  * @version 4.5.0
8
  * @since 4.5.0
9
  * @author Pluggabl LLC.
10
+ * @package Booster_For_WooCommerce/includes
11
  */
12
 
13
  if ( ! defined( 'ABSPATH' ) ) {
15
  }
16
 
17
  if ( ! class_exists( 'WCJ_Multicurrency_Price_Updater' ) ) :
18
+ /**
19
+ * WCJ_Multicurrency_Price_Updater
20
+ *
21
+ * @version 4.5.0
22
+ */
23
  class WCJ_Multicurrency_Price_Updater extends WP_Background_Process {
24
 
25
  /**
26
+ * Wcj_bkg_process_price_updater
27
+ *
28
  * @var string
29
  */
30
  protected $action = 'wcj_bkg_process_price_updater';
31
+ /**
32
+ * Task
33
+ *
34
+ * @version 4.5.0
35
+ * @param Array $item Get Items.
36
+ */
37
  protected function task( $item ) {
38
  $module = 'multicurrency';
39
  if ( wcj_is_module_enabled( $module ) ) {
40
+ w_c_j()->modules[ $module ]->save_min_max_prices_per_product( $item['id'], $item['currency'] );
41
  }
42
  return false;
43
  }
44
 
45
  }
46
+ endif;
includes/background-process/class-wcj-price-by-country-updater.php CHANGED
@@ -7,6 +7,7 @@
7
  * @version 5.1.0
8
  * @since 5.1.0
9
  * @author Pluggabl LLC.
 
10
  */
11
 
12
  if ( ! defined( 'ABSPATH' ) ) {
@@ -14,14 +15,25 @@ if ( ! defined( 'ABSPATH' ) ) {
14
  }
15
 
16
  if ( ! class_exists( 'WCJ_Price_By_Country_Updater' ) ) :
17
-
 
 
 
 
18
  class WCJ_Price_By_Country_Updater extends WP_Background_Process {
19
 
20
  /**
 
 
21
  * @var string
22
  */
23
  protected $action = 'wcj_bkg_process_price_by_country_updater';
24
-
 
 
 
 
 
25
  protected function task( $item ) {
26
  $module = 'price_by_country';
27
  if ( wcj_is_module_enabled( $module ) ) {
@@ -31,4 +43,4 @@ if ( ! class_exists( 'WCJ_Price_By_Country_Updater' ) ) :
31
  }
32
 
33
  }
34
- endif;
7
  * @version 5.1.0
8
  * @since 5.1.0
9
  * @author Pluggabl LLC.
10
+ * @package Booster_For_WooCommerce/includes
11
  */
12
 
13
  if ( ! defined( 'ABSPATH' ) ) {
15
  }
16
 
17
  if ( ! class_exists( 'WCJ_Price_By_Country_Updater' ) ) :
18
+ /**
19
+ * WCJ_Price_By_Country_Updater
20
+ *
21
+ * @version 5.1.0
22
+ */
23
  class WCJ_Price_By_Country_Updater extends WP_Background_Process {
24
 
25
  /**
26
+ * Wcj_bkg_process_price_by_country_updater
27
+ *
28
  * @var string
29
  */
30
  protected $action = 'wcj_bkg_process_price_by_country_updater';
31
+ /**
32
+ * Task
33
+ *
34
+ * @version 5.1.0
35
+ * @param Array $item Get Items.
36
+ */
37
  protected function task( $item ) {
38
  $module = 'price_by_country';
39
  if ( wcj_is_module_enabled( $module ) ) {
43
  }
44
 
45
  }
46
+ endif;
includes/class-wcj-add-to-cart-button-visibility.php CHANGED
@@ -5,215 +5,232 @@
5
  * @version 3.9.0
6
  * @since 3.3.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Add_To_Cart_Button_Visibility' ) ) :
13
 
14
- class WCJ_Add_To_Cart_Button_Visibility extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 3.9.0
20
- * @since 3.3.0
21
- * @todo maybe add option to use `woocommerce_before_add_to_cart_form` / `woocommerce_after_add_to_cart_form` instead of `woocommerce_before_add_to_cart_button` / `woocommerce_after_add_to_cart_button`
22
  */
23
- function __construct() {
24
-
25
- $this->id = 'add_to_cart_button_visibility';
26
- $this->short_desc = __( 'Add to Cart Button Visibility', 'woocommerce-jetpack' );
27
- $this->desc = __( 'Enable/disable Add to Cart button globally or on per product basis.', 'woocommerce-jetpack' );
28
- $this->extra_desc = '<em>' . sprintf(
29
- __( 'If you need to enable/disable Add to Cart button for some <strong>user roles</strong> only, we suggest using this module in conjunction with Booster\'s %s module.', 'woocommerce-jetpack' ),
30
- '<a href="' . wcj_get_module_settings_admin_url( 'modules_by_user_roles' ) . '">' .
 
 
 
 
 
 
 
 
 
 
31
  __( 'Modules By User Roles', 'woocommerce-jetpack' ) . '</a>'
32
- ) . '</em>';
33
- $this->link_slug = 'woocommerce-add-to-cart-button-visibility';
34
- parent::__construct();
35
-
36
- if ( $this->is_enabled() ) {
37
- // All products
38
- if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_global_enabled', 'no' ) ) {
39
- // Archives
40
- if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_disable_archives', 'no' ) ) {
41
- if ( 'remove_action' === wcj_get_option( 'wcj_add_to_cart_button_disable_archives_method', 'remove_action' ) ) {
42
- add_action( 'init', array( $this, 'add_to_cart_button_disable_archives' ), PHP_INT_MAX );
43
- add_action( 'woocommerce_after_shop_loop_item', array( $this, 'add_to_cart_button_archives_content' ), 10 );
44
- } else { // 'add_filter'
45
- add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'add_to_cart_button_loop_disable_all_products' ), PHP_INT_MAX, 2 );
 
46
  }
47
- }
48
- // Single Product
49
- if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_disable_single', 'no' ) ) {
50
- if ( 'remove_action' === wcj_get_option( 'wcj_add_to_cart_button_disable_single_method', 'remove_action' ) ) {
51
- add_action( 'init', array( $this, 'add_to_cart_button_disable_single' ), PHP_INT_MAX );
52
- add_action( 'woocommerce_single_product_summary', array( $this, 'add_to_cart_button_single_content' ), 30 );
53
- } else { // 'add_action'
54
- add_action( 'woocommerce_before_add_to_cart_button', 'ob_start', PHP_INT_MAX, 0 );
55
- add_action( 'woocommerce_after_add_to_cart_button', 'ob_end_clean', PHP_INT_MAX, 0 );
56
- add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'add_to_cart_button_single_content' ), PHP_INT_MAX, 0 );
57
  }
58
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
- // Per category
61
- if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_per_category_enabled', 'no' ) ) {
62
- // Single Product
63
- add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'add_to_cart_button_disable_start_per_category' ), PHP_INT_MAX, 0 );
64
- add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'add_to_cart_button_disable_end_per_category' ), PHP_INT_MAX, 0 );
65
- // Archives
66
- add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'add_to_cart_button_loop_disable_per_category' ), PHP_INT_MAX, 2 );
67
- }
68
- // Per product
69
- if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_per_product_enabled', 'no' ) ) {
70
- // Single Product
71
- add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'add_to_cart_button_disable_start' ), PHP_INT_MAX, 0 );
72
- add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'add_to_cart_button_disable_end' ), PHP_INT_MAX, 0 );
73
- // Archives
74
- add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'add_to_cart_button_loop_disable' ), PHP_INT_MAX, 2 );
75
- // Metaboxes
76
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
77
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
78
- }
79
- }
80
 
81
- }
82
 
83
- /**
84
- * add_to_cart_button_loop_disable_all_products.
85
- *
86
- * @version 3.9.0
87
- * @since 3.9.0
88
- */
89
- function add_to_cart_button_loop_disable_all_products( $link, $_product ) {
90
- return do_shortcode( wcj_get_option( 'wcj_add_to_cart_button_archives_content', '' ) );
91
- }
 
 
92
 
93
- /**
94
- * add_to_cart_button_archives_content.
95
- *
96
- * @version 3.4.0
97
- * @since 3.4.0
98
- */
99
- function add_to_cart_button_archives_content() {
100
- if ( '' != ( $content = wcj_get_option( 'wcj_add_to_cart_button_archives_content', '' ) ) ) {
101
- echo do_shortcode( $content );
 
 
102
  }
103
- }
104
 
105
- /**
106
- * add_to_cart_button_single_content.
107
- *
108
- * @version 3.4.0
109
- * @since 3.4.0
110
- */
111
- function add_to_cart_button_single_content() {
112
- if ( '' != ( $content = wcj_get_option( 'wcj_add_to_cart_button_single_content', '' ) ) ) {
113
- echo do_shortcode( $content );
 
 
114
  }
115
- }
116
 
117
- /**
118
- * add_to_cart_button_disable_end_per_category.
119
- *
120
- * @version 3.3.0
121
- * @since 3.3.0
122
- */
123
- function add_to_cart_button_disable_end_per_category() {
124
- $cats_to_hide = wcj_get_option( 'wcj_add_to_cart_button_per_category_disable_single', '' );
125
- if ( ! empty( $cats_to_hide ) && 0 != get_the_ID() && wcj_is_product_term( get_the_ID(), $cats_to_hide, 'product_cat' ) ) {
126
- ob_end_clean();
127
- echo do_shortcode( wcj_get_option( 'wcj_add_to_cart_button_per_category_content_single', '' ) );
 
128
  }
129
- }
130
 
131
- /**
132
- * add_to_cart_button_disable_start_per_category.
133
- *
134
- * @version 3.3.0
135
- * @since 3.3.0
136
- */
137
- function add_to_cart_button_disable_start_per_category() {
138
- $cats_to_hide = wcj_get_option( 'wcj_add_to_cart_button_per_category_disable_single', '' );
139
- if ( ! empty( $cats_to_hide ) && 0 != get_the_ID() && wcj_is_product_term( get_the_ID(), $cats_to_hide, 'product_cat' ) ) {
140
- ob_start();
 
141
  }
142
- }
143
 
144
- /**
145
- * add_to_cart_button_loop_disable_per_category.
146
- *
147
- * @version 3.3.0
148
- * @since 3.3.0
149
- */
150
- function add_to_cart_button_loop_disable_per_category( $link, $_product ) {
151
- $cats_to_hide = wcj_get_option( 'wcj_add_to_cart_button_per_category_disable_loop', '' );
152
- if ( ! empty( $cats_to_hide ) && wcj_is_product_term( wcj_get_product_id_or_variation_parent_id( $_product ), $cats_to_hide, 'product_cat' ) ) {
153
- return do_shortcode( wcj_get_option( 'wcj_add_to_cart_button_per_category_content_loop', '' ) );
 
 
 
 
154
  }
155
- return $link;
156
- }
157
 
158
- /**
159
- * add_to_cart_button_disable_single.
160
- *
161
- * @version 2.6.0
162
- * @since 2.6.0
163
- */
164
- function add_to_cart_button_disable_single() {
165
- remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
166
- }
167
 
168
- /**
169
- * add_to_cart_button_disable_archives.
170
- *
171
- * @version 2.6.0
172
- * @since 2.6.0
173
- */
174
- function add_to_cart_button_disable_archives() {
175
- remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
176
- }
177
 
178
- /**
179
- * add_to_cart_button_loop_disable.
180
- *
181
- * @version 3.3.0
182
- * @since 2.5.2
183
- */
184
- function add_to_cart_button_loop_disable( $link, $_product ) {
185
- if ( 0 != get_the_ID() && 'yes' === get_post_meta( get_the_ID(), '_' . 'wcj_add_to_cart_button_loop_disable', true ) ) {
186
- return do_shortcode( get_post_meta( get_the_ID(), '_' . 'wcj_add_to_cart_button_loop_disable_content', true ) );
 
 
 
 
187
  }
188
- return $link;
189
- }
190
 
191
- /**
192
- * add_to_cart_button_disable_end.
193
- *
194
- * @version 3.3.0
195
- * @since 2.5.2
196
- */
197
- function add_to_cart_button_disable_end() {
198
- if ( 0 != get_the_ID() && 'yes' === get_post_meta( get_the_ID(), '_' . 'wcj_add_to_cart_button_disable', true ) ) {
199
- ob_end_clean();
200
- echo do_shortcode( get_post_meta( get_the_ID(), '_' . 'wcj_add_to_cart_button_disable_content', true ) );
 
201
  }
202
- }
203
 
204
- /**
205
- * add_to_cart_button_disable_start.
206
- *
207
- * @version 2.5.2
208
- * @since 2.5.2
209
- */
210
- function add_to_cart_button_disable_start() {
211
- if ( 0 != get_the_ID() && 'yes' === get_post_meta( get_the_ID(), '_' . 'wcj_add_to_cart_button_disable', true ) ) {
212
- ob_start();
 
213
  }
214
- }
215
 
216
- }
217
 
218
  endif;
219
 
5
  * @version 3.9.0
6
  * @since 3.3.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Add_To_Cart_Button_Visibility' ) ) :
16
 
 
 
17
  /**
18
+ * WCJ_Add_To_Cart_Button_Visibility.
19
  *
20
+ * @version 2.7.0
 
 
21
  */
22
+ class WCJ_Add_To_Cart_Button_Visibility extends WCJ_Module {
23
+
24
+ /**
25
+ * Constructor.
26
+ *
27
+ * @version 3.9.0
28
+ * @since 3.3.0
29
+ * @todo maybe add option to use `woocommerce_before_add_to_cart_form` / `woocommerce_after_add_to_cart_form` instead of `woocommerce_before_add_to_cart_button` / `woocommerce_after_add_to_cart_button`
30
+ */
31
+ public function __construct() {
32
+
33
+ $this->id = 'add_to_cart_button_visibility';
34
+ $this->short_desc = __( 'Add to Cart Button Visibility', 'woocommerce-jetpack' );
35
+ $this->desc = __( 'Enable/disable Add to Cart button globally or on per product basis.', 'woocommerce-jetpack' );
36
+ $this->extra_desc = '<em>' . sprintf(
37
+ /* translators: %s: search term */
38
+ __( 'If you need to enable/disable Add to Cart button for some <strong>user roles</strong> only, we suggest using this module in conjunction with Booster\'s %s module.', 'woocommerce-jetpack' ),
39
+ '<a href="' . wcj_get_module_settings_admin_url( 'modules_by_user_roles' ) . '">' .
40
  __( 'Modules By User Roles', 'woocommerce-jetpack' ) . '</a>'
41
+ ) . '</em>';
42
+ $this->link_slug = 'woocommerce-add-to-cart-button-visibility';
43
+ parent::__construct();
44
+
45
+ if ( $this->is_enabled() ) {
46
+ // All products.
47
+ if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_global_enabled', 'no' ) ) {
48
+ // Archives.
49
+ if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_disable_archives', 'no' ) ) {
50
+ if ( 'remove_action' === wcj_get_option( 'wcj_add_to_cart_button_disable_archives_method', 'remove_action' ) ) {
51
+ add_action( 'init', array( $this, 'add_to_cart_button_disable_archives' ), PHP_INT_MAX );
52
+ add_action( 'woocommerce_after_shop_loop_item', array( $this, 'add_to_cart_button_archives_content' ), 10 );
53
+ } else { // 'add_filter'
54
+ add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'add_to_cart_button_loop_disable_all_products' ), PHP_INT_MAX, 2 );
55
+ }
56
  }
57
+ // Single Product.
58
+ if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_disable_single', 'no' ) ) {
59
+ if ( 'remove_action' === wcj_get_option( 'wcj_add_to_cart_button_disable_single_method', 'remove_action' ) ) {
60
+ add_action( 'init', array( $this, 'add_to_cart_button_disable_single' ), PHP_INT_MAX );
61
+ add_action( 'woocommerce_single_product_summary', array( $this, 'add_to_cart_button_single_content' ), 30 );
62
+ } else { // 'add_action'
63
+ add_action( 'woocommerce_before_add_to_cart_button', 'ob_start', PHP_INT_MAX, 0 );
64
+ add_action( 'woocommerce_after_add_to_cart_button', 'ob_end_clean', PHP_INT_MAX, 0 );
65
+ add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'add_to_cart_button_single_content' ), PHP_INT_MAX, 0 );
66
+ }
67
  }
68
  }
69
+ // Per category.
70
+ if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_per_category_enabled', 'no' ) ) {
71
+ // Single Product.
72
+ add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'add_to_cart_button_disable_start_per_category' ), PHP_INT_MAX, 0 );
73
+ add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'add_to_cart_button_disable_end_per_category' ), PHP_INT_MAX, 0 );
74
+ // Archives.
75
+ add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'add_to_cart_button_loop_disable_per_category' ), PHP_INT_MAX, 2 );
76
+ }
77
+ // Per product.
78
+ if ( 'yes' === wcj_get_option( 'wcj_add_to_cart_button_per_product_enabled', 'no' ) ) {
79
+ // Single Product.
80
+ add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'add_to_cart_button_disable_start' ), PHP_INT_MAX, 0 );
81
+ add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'add_to_cart_button_disable_end' ), PHP_INT_MAX, 0 );
82
+ // Archives.
83
+ add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'add_to_cart_button_loop_disable' ), PHP_INT_MAX, 2 );
84
+ // Metaboxes.
85
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
86
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
87
+ }
88
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
 
90
+ }
91
 
92
+ /**
93
+ * Add_to_cart_button_loop_disable_all_products.
94
+ *
95
+ * @version 3.9.0
96
+ * @since 3.9.0
97
+ * @param string $link defines the link.
98
+ * @param string $_product defines the _product.
99
+ */
100
+ public function add_to_cart_button_loop_disable_all_products( $link, $_product ) {
101
+ return do_shortcode( wcj_get_option( 'wcj_add_to_cart_button_archives_content', '' ) );
102
+ }
103
 
104
+ /**
105
+ * Add_to_cart_button_archives_content.
106
+ *
107
+ * @version 3.4.0
108
+ * @since 3.4.0
109
+ */
110
+ public function add_to_cart_button_archives_content() {
111
+ $content = wcj_get_option( 'wcj_add_to_cart_button_archives_content', '' );
112
+ if ( '' !== ( $content ) ) {
113
+ echo do_shortcode( $content );
114
+ }
115
  }
 
116
 
117
+ /**
118
+ * Add_to_cart_button_single_content.
119
+ *
120
+ * @version 3.4.0
121
+ * @since 3.4.0
122
+ */
123
+ public function add_to_cart_button_single_content() {
124
+ $content = wcj_get_option( 'wcj_add_to_cart_button_single_content', '' );
125
+ if ( '' !== ( $content ) ) {
126
+ echo do_shortcode( $content );
127
+ }
128
  }
 
129
 
130
+ /**
131
+ * Add_to_cart_button_disable_end_per_category.
132
+ *
133
+ * @version 3.3.0
134
+ * @since 3.3.0
135
+ */
136
+ public function add_to_cart_button_disable_end_per_category() {
137
+ $cats_to_hide = wcj_get_option( 'wcj_add_to_cart_button_per_category_disable_single', '' );
138
+ if ( ! empty( $cats_to_hide ) && 0 !== get_the_ID() && wcj_is_product_term( get_the_ID(), $cats_to_hide, 'product_cat' ) ) {
139
+ ob_end_clean();
140
+ echo do_shortcode( wcj_get_option( 'wcj_add_to_cart_button_per_category_content_single', '' ) );
141
+ }
142
  }
 
143
 
144
+ /**
145
+ * Add_to_cart_button_disable_start_per_category.
146
+ *
147
+ * @version 3.3.0
148
+ * @since 3.3.0
149
+ */
150
+ public function add_to_cart_button_disable_start_per_category() {
151
+ $cats_to_hide = wcj_get_option( 'wcj_add_to_cart_button_per_category_disable_single', '' );
152
+ if ( ! empty( $cats_to_hide ) && 0 !== get_the_ID() && wcj_is_product_term( get_the_ID(), $cats_to_hide, 'product_cat' ) ) {
153
+ ob_start();
154
+ }
155
  }
 
156
 
157
+ /**
158
+ * Add_to_cart_button_loop_disable_per_category.
159
+ *
160
+ * @version 3.3.0
161
+ * @since 3.3.0
162
+ * @param string $link defines the link.
163
+ * @param string $_product defines the _product.
164
+ */
165
+ public function add_to_cart_button_loop_disable_per_category( $link, $_product ) {
166
+ $cats_to_hide = wcj_get_option( 'wcj_add_to_cart_button_per_category_disable_loop', '' );
167
+ if ( ! empty( $cats_to_hide ) && wcj_is_product_term( wcj_get_product_id_or_variation_parent_id( $_product ), $cats_to_hide, 'product_cat' ) ) {
168
+ return do_shortcode( wcj_get_option( 'wcj_add_to_cart_button_per_category_content_loop', '' ) );
169
+ }
170
+ return $link;
171
  }
 
 
172
 
173
+ /**
174
+ * Add_to_cart_button_disable_single.
175
+ *
176
+ * @version 2.6.0
177
+ * @since 2.6.0
178
+ */
179
+ public function add_to_cart_button_disable_single() {
180
+ remove_action( 'woocommerce_single_product_summary', 'woocommerce_template_single_add_to_cart', 30 );
181
+ }
182
 
183
+ /**
184
+ * Add_to_cart_button_disable_archives.
185
+ *
186
+ * @version 2.6.0
187
+ * @since 2.6.0
188
+ */
189
+ public function add_to_cart_button_disable_archives() {
190
+ remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
191
+ }
192
 
193
+ /**
194
+ * Add_to_cart_button_loop_disable.
195
+ *
196
+ * @version 3.3.0
197
+ * @since 2.5.2
198
+ * @param string $link defines the link.
199
+ * @param string $_product defines the _product.
200
+ */
201
+ public function add_to_cart_button_loop_disable( $link, $_product ) {
202
+ if ( 0 !== get_the_ID() && 'yes' === get_post_meta( get_the_ID(), '_wcj_add_to_cart_button_loop_disable', true ) ) {
203
+ return do_shortcode( get_post_meta( get_the_ID(), '_wcj_add_to_cart_button_loop_disable_content', true ) );
204
+ }
205
+ return $link;
206
  }
 
 
207
 
208
+ /**
209
+ * Add_to_cart_button_disable_end.
210
+ *
211
+ * @version 3.3.0
212
+ * @since 2.5.2
213
+ */
214
+ public function add_to_cart_button_disable_end() {
215
+ if ( 0 !== get_the_ID() && 'yes' === get_post_meta( get_the_ID(), '_wcj_add_to_cart_button_disable', true ) ) {
216
+ ob_end_clean();
217
+ echo do_shortcode( get_post_meta( get_the_ID(), '_wcj_add_to_cart_button_disable_content', true ) );
218
+ }
219
  }
 
220
 
221
+ /**
222
+ * Add_to_cart_button_disable_start.
223
+ *
224
+ * @version 2.5.2
225
+ * @since 2.5.2
226
+ */
227
+ public function add_to_cart_button_disable_start() {
228
+ if ( 0 !== get_the_ID() && 'yes' === get_post_meta( get_the_ID(), '_wcj_add_to_cart_button_disable', true ) ) {
229
+ ob_start();
230
+ }
231
  }
 
232
 
233
+ }
234
 
235
  endif;
236
 
includes/class-wcj-add-to-cart.php CHANGED
@@ -4,36 +4,44 @@
4
  *
5
  * @version 5.2.0
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Add_To_Cart' ) ) :
12
 
13
- class WCJ_Add_To_Cart extends WCJ_Module {
14
-
15
  /**
16
- * Constructor.
17
  *
18
- * @version 5.2.0
19
  */
20
- function __construct() {
21
-
22
- $this->id = 'add_to_cart';
23
- $this->short_desc = __( 'Add to Cart Button Labels', 'woocommerce-jetpack' );
24
- $this->desc = __( 'Change text for Add to Cart button by product type, by product category or for individual products (1 category group allowed in free version).', 'woocommerce-jetpack' );
25
- $this->desc_pro = __( 'Change text for Add to Cart button by product type, by product category or for individual products.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-add-to-cart-labels';
27
- parent::__construct();
28
-
29
- if ( $this->is_enabled() ) {
30
- include_once( 'add-to-cart/class-wcj-add-to-cart-per-category.php' );
31
- include_once( 'add-to-cart/class-wcj-add-to-cart-per-product.php' );
32
- include_once( 'add-to-cart/class-wcj-add-to-cart-per-product-type.php' );
 
 
 
 
 
 
 
 
33
  }
34
- }
35
 
36
- }
37
 
38
  endif;
39
 
4
  *
5
  * @version 5.2.0
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Add_To_Cart' ) ) :
15
 
 
 
16
  /**
17
+ * WCJ_Add_To_Cart.
18
  *
19
+ * @version 2.7.0
20
  */
21
+ class WCJ_Add_To_Cart extends WCJ_Module {
22
+
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @version 5.2.0
27
+ */
28
+ public function __construct() {
29
+
30
+ $this->id = 'add_to_cart';
31
+ $this->short_desc = __( 'Add to Cart Button Labels', 'woocommerce-jetpack' );
32
+ $this->desc = __( 'Change text for Add to Cart button by product type, by product category or for individual products (1 category group allowed in free version).', 'woocommerce-jetpack' );
33
+ $this->desc_pro = __( 'Change text for Add to Cart button by product type, by product category or for individual products.', 'woocommerce-jetpack' );
34
+ $this->link_slug = 'woocommerce-add-to-cart-labels';
35
+ parent::__construct();
36
+
37
+ if ( $this->is_enabled() ) {
38
+ include_once 'add-to-cart/class-wcj-add-to-cart-per-category.php';
39
+ include_once 'add-to-cart/class-wcj-add-to-cart-per-product.php';
40
+ include_once 'add-to-cart/class-wcj-add-to-cart-per-product-type.php';
41
+ }
42
  }
 
43
 
44
+ }
45
 
46
  endif;
47
 
includes/class-wcj-address-formats.php CHANGED
@@ -5,113 +5,123 @@
5
  * @version 2.8.0
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Address_Formats' ) ) :
13
 
14
- class WCJ_Address_Formats extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
  * @version 2.8.0
20
  */
21
- function __construct() {
 
22
 
23
- $this->id = 'address_formats';
24
- $this->short_desc = __( 'Address Formats', 'woocommerce-jetpack' );
25
- $this->desc = __( 'Set address format in orders on per country basis. Force base country display.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-address-formats';
27
- parent::__construct();
 
 
 
 
 
 
28
 
29
- if ( $this->is_enabled() ) {
30
- add_filter( 'woocommerce_localisation_address_formats', array( $this, 'customize_address_formats' ), PHP_INT_MAX );
31
- add_filter( 'woocommerce_formatted_address_force_country_display', array( $this, 'customize_force_country_display' ), PHP_INT_MAX );
 
32
  }
33
- }
34
 
35
- /**
36
- * customize_force_country_display.
37
- *
38
- * @version 2.7.0
39
- */
40
- function customize_force_country_display( $display ) {
41
- return ( 'yes' === wcj_get_option( 'wcj_address_formats_force_country_display', 'no' ) );
42
- }
 
43
 
44
- /**
45
- * customize_address_formats.
46
- */
47
- function customize_address_formats( $formats ) {
48
- $modified_formats = array();
49
- $default_formats = $this->get_default_address_formats();
50
- foreach ( $default_formats as $country_code => $format ) {
51
- $default_format = isset( $formats[ $country_code ] ) ? $formats[ $country_code ] : $format;
52
- $format = wcj_get_option( 'wcj_address_formats_country_' . $country_code, $default_format );
53
- $modified_formats[ $country_code ] = $format;
 
 
 
 
54
  }
55
- return $modified_formats;
56
- }
57
 
58
- /**
59
- * Get country address formats
60
- *
61
- * @return array
62
- */
63
- function get_default_address_formats() {
64
- // Common formats
65
- $postcode_before_city = "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}";
66
- $default = "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode}\n{country}";
67
- // Define address formats
68
- $formats = array(
69
- 'default' => $default,
70
- 'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
71
- 'AT' => $postcode_before_city,
72
- 'BE' => $postcode_before_city,
73
- 'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
74
- 'CH' => $postcode_before_city,
75
- 'CL' => "{company}\n{name}\n{address_1}\n{address_2}\n{state}\n{postcode} {city}\n{country}",
76
- 'CN' => "{country} {postcode}\n{state}, {city}, {address_2}, {address_1}\n{company}\n{name}",
77
- 'CZ' => $postcode_before_city,
78
- 'DE' => $postcode_before_city,
79
- 'EE' => $postcode_before_city,
80
- 'FI' => $postcode_before_city,
81
- 'DK' => $postcode_before_city,
82
- 'FR' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city_upper}\n{country}",
83
- 'HK' => "{company}\n{first_name} {last_name_upper}\n{address_1}\n{address_2}\n{city_upper}\n{state_upper}\n{country}",
84
- 'HU' => "{name}\n{company}\n{city}\n{address_1}\n{address_2}\n{postcode}\n{country}",
85
- 'IN' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} - {postcode}\n{state}, {country}",
86
- 'IS' => $postcode_before_city,
87
- 'IT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode}\n{city}\n{state_upper}\n{country}",
88
- 'JP' => "{postcode}\n{state}{city}{address_1}\n{address_2}\n{company}\n{last_name} {first_name}\n{country}",
89
- 'TW' => "{company}\n{last_name} {first_name}\n{address_1}\n{address_2}\n{state}, {city} {postcode}\n{country}",
90
- 'LI' => $postcode_before_city,
91
- 'NL' => $postcode_before_city,
92
- 'NZ' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}",
93
- 'NO' => $postcode_before_city,
94
- 'PL' => $postcode_before_city,
95
- 'SK' => $postcode_before_city,
96
- 'SI' => $postcode_before_city,
97
- 'ES' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}",
98
- 'SE' => $postcode_before_city,
99
- 'TR' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city} {state}\n{country}",
100
- 'US' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}, {state_code} {postcode}\n{country}",
101
- 'VN' => "{name}\n{company}\n{address_1}\n{city}\n{country}",
102
- );
103
- $all_countries = wcj_get_countries();
104
- foreach ( $all_countries as $country_code => $country_name ) {
105
- if ( ! isset( $formats[ $country_code ] ) ) {
106
- $formats[ $country_code ] = $default;
 
107
  }
 
 
108
  }
109
- ksort( $formats );
110
- return $formats;
111
  }
112
 
113
- }
114
-
115
  endif;
116
 
117
  return new WCJ_Address_Formats();
5
  * @version 2.8.0
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Address_Formats' ) ) :
16
 
 
 
17
  /**
18
+ * WCJ_Address_Formats.
19
  *
20
  * @version 2.8.0
21
  */
22
+ class WCJ_Address_Formats extends WCJ_Module {
23
+
24
 
25
+ /**
26
+ * Constructor.
27
+ *
28
+ * @version 2.8.0
29
+ */
30
+ public function __construct() {
31
+ $this->id = 'address_formats';
32
+ $this->short_desc = __( 'Address Formats', 'woocommerce-jetpack' );
33
+ $this->desc = __( 'Set address format in orders on per country basis. Force base country display.', 'woocommerce-jetpack' );
34
+ $this->link_slug = 'woocommerce-address-formats';
35
+ parent::__construct();
36
 
37
+ if ( $this->is_enabled() ) {
38
+ add_filter( 'woocommerce_localisation_address_formats', array( $this, 'customize_address_formats' ), PHP_INT_MAX );
39
+ add_filter( 'woocommerce_formatted_address_force_country_display', array( $this, 'customize_force_country_display' ), PHP_INT_MAX );
40
+ }
41
  }
 
42
 
43
+ /**
44
+ * Customize_force_country_display.
45
+ *
46
+ * @param int|bool $display Optional. Whether to use GMT timezone. Default false.
47
+ * @version 2.7.0
48
+ */
49
+ public function customize_force_country_display( $display ) {
50
+ return ( 'yes' === wcj_get_option( 'wcj_address_formats_force_country_display', 'no' ) );
51
+ }
52
 
53
+ /**
54
+ * Customize_address_formats.
55
+ *
56
+ * @param int|bool $formats Optional. Whether to use GMT timezone. Default false.
57
+ */
58
+ public function customize_address_formats( $formats ) {
59
+ $modified_formats = array();
60
+ $default_formats = $this->get_default_address_formats();
61
+ foreach ( $default_formats as $country_code => $format ) {
62
+ $default_format = isset( $formats[ $country_code ] ) ? $formats[ $country_code ] : $format;
63
+ $format = wcj_get_option( 'wcj_address_formats_country_' . $country_code, $default_format );
64
+ $modified_formats[ $country_code ] = $format;
65
+ }
66
+ return $modified_formats;
67
  }
 
 
68
 
69
+ /**
70
+ * Get country address formats.
71
+ *
72
+ * @return array
73
+ */
74
+ public function get_default_address_formats() {
75
+ // Common formats.
76
+ $postcode_before_city = "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city}\n{country}";
77
+ $default = "{name}\n{company}\n{address_1}\n{address_2}\n{city}\n{state}\n{postcode}\n{country}";
78
+ // Define address formats.
79
+ $formats = array(
80
+ 'default' => $default,
81
+ 'AU' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
82
+ 'AT' => $postcode_before_city,
83
+ 'BE' => $postcode_before_city,
84
+ 'CA' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} {state} {postcode}\n{country}",
85
+ 'CH' => $postcode_before_city,
86
+ 'CL' => "{company}\n{name}\n{address_1}\n{address_2}\n{state}\n{postcode} {city}\n{country}",
87
+ 'CN' => "{country} {postcode}\n{state}, {city}, {address_2}, {address_1}\n{company}\n{name}",
88
+ 'CZ' => $postcode_before_city,
89
+ 'DE' => $postcode_before_city,
90
+ 'EE' => $postcode_before_city,
91
+ 'FI' => $postcode_before_city,
92
+ 'DK' => $postcode_before_city,
93
+ 'FR' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode} {city_upper}\n{country}",
94
+ 'HK' => "{company}\n{first_name} {last_name_upper}\n{address_1}\n{address_2}\n{city_upper}\n{state_upper}\n{country}",
95
+ 'HU' => "{name}\n{company}\n{city}\n{address_1}\n{address_2}\n{postcode}\n{country}",
96
+ 'IN' => "{company}\n{name}\n{address_1}\n{address_2}\n{city} - {postcode}\n{state}, {country}",
97
+ 'IS' => $postcode_before_city,
98
+ 'IT' => "{company}\n{name}\n{address_1}\n{address_2}\n{postcode}\n{city}\n{state_upper}\n{country}",
99
+ 'JP' => "{postcode}\n{state}{city}{address_1}\n{address_2}\n{company}\n{last_name} {first_name}\n{country}",
100
+ 'TW' => "{company}\n{last_name} {first_name}\n{address_1}\n{address_2}\n{state}, {city} {postcode}\n{country}",
101
+ 'LI' => $postcode_before_city,
102
+ 'NL' => $postcode_before_city,
103
+ 'NZ' => "{name}\n{company}\n{address_1}\n{address_2}\n{city} {postcode}\n{country}",
104
+ 'NO' => $postcode_before_city,
105
+ 'PL' => $postcode_before_city,
106
+ 'SK' => $postcode_before_city,
107
+ 'SI' => $postcode_before_city,
108
+ 'ES' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city}\n{state}\n{country}",
109
+ 'SE' => $postcode_before_city,
110
+ 'TR' => "{name}\n{company}\n{address_1}\n{address_2}\n{postcode} {city} {state}\n{country}",
111
+ 'US' => "{name}\n{company}\n{address_1}\n{address_2}\n{city}, {state_code} {postcode}\n{country}",
112
+ 'VN' => "{name}\n{company}\n{address_1}\n{city}\n{country}",
113
+ );
114
+ $all_countries = wcj_get_countries();
115
+ foreach ( $all_countries as $country_code => $country_name ) {
116
+ if ( ! isset( $formats[ $country_code ] ) ) {
117
+ $formats[ $country_code ] = $default;
118
+ }
119
  }
120
+ ksort( $formats );
121
+ return $formats;
122
  }
 
 
123
  }
124
 
 
 
125
  endif;
126
 
127
  return new WCJ_Address_Formats();
includes/class-wcj-admin-bar.php CHANGED
@@ -5,650 +5,677 @@
5
  * @version 4.1.0
6
  * @since 2.9.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Admin_Bar' ) ) :
13
 
14
- class WCJ_Admin_Bar extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 4.1.0
20
- * @since 2.9.0
21
- * @todo (maybe) custom user nodes
22
- * @todo (maybe) optional nodes selection
23
- * @todo (maybe) add WooCommerce versions (from / to) to nodes
24
- * @todo (maybe) customizable icons
25
- * @todo (maybe) separate admin bar menu: "Booster Modules", "Booster Tools", "WooCommerce Reports", "WooCommerce Products", "WooCommerce Settings"
26
  */
27
- function __construct() {
28
 
29
- $this->id = 'admin_bar';
30
- $this->short_desc = __( 'Admin Bar', 'woocommerce-jetpack' );
31
- $this->desc = __( 'WooCommerce admin bar.', 'woocommerce-jetpack' );
32
- $this->link_slug = 'woocommerce-admin-bar';
33
- parent::__construct();
 
 
 
 
 
 
 
34
 
35
- if ( $this->is_enabled() ) {
36
- if ( 'yes' === wcj_get_option( 'wcj_admin_bar_wc_enabled', 'yes' ) ) {
37
- add_action( 'admin_bar_menu', array( $this, 'add_woocommerce_admin_bar' ), PHP_INT_MAX );
38
- add_action( 'wp_head', array( $this, 'add_woocommerce_admin_bar_icon_style' ) );
39
- add_action( 'admin_head', array( $this, 'add_woocommerce_admin_bar_icon_style' ) );
40
- }
41
- if ( 'yes' === wcj_get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) || 'yes' === wcj_get_option( 'wcj_admin_bar_booster_active_enabled', 'yes' ) ) {
42
- if ( 'yes' === wcj_get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) ) {
43
- add_action( 'admin_bar_menu', array( $this, 'add_booster_admin_bar' ), PHP_INT_MAX );
 
 
44
  }
45
- if ( 'yes' === wcj_get_option( 'wcj_admin_bar_booster_active_enabled', 'yes' ) ) {
46
- add_action( 'admin_bar_menu', array( $this, 'add_booster_active_admin_bar' ), PHP_INT_MAX );
 
 
 
 
 
 
 
47
  }
48
- add_action( 'wp_head', array( $this, 'add_booster_admin_bar_icon_style' ) );
49
- add_action( 'admin_head', array( $this, 'add_booster_admin_bar_icon_style' ) );
50
  }
 
51
  }
52
- add_action( 'woojetpack_after_settings_save', array( $this, 'reload_page_after_settings_save' ), PHP_INT_MAX, 2 );
53
- }
54
 
55
- /**
56
- * reload_page_after_settings_save.
57
- *
58
- * @version 2.9.0
59
- * @since 2.9.0
60
- * @todo (maybe) somehow add "Your settings have been saved." admin notice
61
- */
62
- function reload_page_after_settings_save( $sections, $current_section ) {
63
- // This function is needed so admin bar menus would appear immediately after module settings are saved (i.e. without additional page refresh)
64
- if ( $this->id === $current_section ) {
65
- wp_safe_redirect( add_query_arg( '', '' ) );
66
- exit;
 
 
 
67
  }
68
- }
69
 
70
- /**
71
- * add_booster_admin_bar_icon_style.
72
- *
73
- * @version 3.1.0
74
- * @since 2.9.0
75
- */
76
- function add_booster_admin_bar_icon_style() {
77
- echo '<style type="text/css"> #wpadminbar #wp-admin-bar-booster .ab-icon:before { content: "\f185"; top: 3px; } </style>';
78
- echo '<style type="text/css"> #wpadminbar #wp-admin-bar-booster-active .ab-icon:before { content: "\f155"; top: 3px; } </style>';
79
- }
80
 
81
- /**
82
- * add_woocommerce_admin_bar_icon_style.
83
- *
84
- * @version 2.9.0
85
- * @since 2.9.0
86
- */
87
- function add_woocommerce_admin_bar_icon_style() {
88
- echo '<style type="text/css"> #wpadminbar #wp-admin-bar-wcj-wc .ab-icon:before { content: "\f174"; top: 3px; } </style>';
89
- }
90
 
91
- /**
92
- * add_woocommerce_admin_bar_nodes.
93
- *
94
- * @version 2.9.0
95
- * @since 2.9.0
96
- */
97
- function add_woocommerce_admin_bar_nodes( $wp_admin_bar, $nodes, $parent_id ) {
98
- foreach ( $nodes as $node_id => $node ) {
99
- $id = ( false !== $parent_id ? $parent_id . '-' . $node_id : $node_id );
100
- $args = array(
101
- 'parent' => $parent_id,
102
- 'id' => $id,
103
- 'title' => $node['title'],
104
- 'href' => $node['href'],
105
- 'meta' => array( 'title' => $node['title'] ),
106
- );
107
- if ( isset( $node['meta'] ) ) {
108
- $args['meta'] = array_merge( $args['meta'], $node['meta'] );
109
- }
110
- $wp_admin_bar->add_node( $args );
111
- if ( isset( $node['nodes'] ) ) {
112
- // Recursion
113
- $this->add_woocommerce_admin_bar_nodes( $wp_admin_bar, $node['nodes'], $id );
 
 
 
 
114
  }
115
  }
116
- }
117
 
118
- /**
119
- * get_nodes_booster_modules.
120
- *
121
- * @version 3.1.0
122
- * @since 2.9.0
123
- * @todo (maybe) dashes instead of underscores
124
- * @todo (maybe) dashboard > alphabetically - list all modules
125
- * @todo (maybe) dashboard > by_category - list all modules
126
- */
127
- function get_nodes_booster_modules() {
128
- $nodes = array();
129
- $cats = include( wcj_plugin_path() . '/includes/admin/' . 'wcj-modules-cats.php' );
130
- $this->active_modules = array();
131
- foreach ( $cats as $id => $label_info ) {
132
- $nodes[ $id ] = array(
133
- 'title' => $label_info['label'],
134
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $id ),
135
- 'meta' => array( 'title' => strip_tags( $label_info['desc'] ) ),
136
- );
137
- if ( 'dashboard' === $id ) {
138
- $nodes[ $id ]['nodes'] = apply_filters( 'wcj_admin_bar_dashboard_nodes', array(
139
- 'alphabetically' => array(
140
- 'title' => __( 'Alphabetically', 'woocommerce-jetpack' ),
141
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=alphabetically' ),
142
- ),
143
- 'by_category' => array(
144
- 'title' => __( 'By Category', 'woocommerce-jetpack' ),
145
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=by_category' ),
146
- ),
147
- 'active' => array(
148
- 'title' => __( 'Active', 'woocommerce-jetpack' ),
149
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=active' ),
150
- ),
151
- 'manager' => array(
152
- 'title' => __( 'Manage Settings', 'woocommerce-jetpack' ),
153
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=manager' ),
154
- ),
155
- ) );
156
- } else {
157
- $cat_nodes = array();
158
- foreach ( $label_info['all_cat_ids'] as $link_id ) {
159
- if ( wcj_is_module_deprecated( $link_id, false, true ) ) {
160
- continue;
161
- }
162
- $cat_nodes[ $link_id ] = array(
163
- 'title' => WCJ()->modules[ $link_id ]->short_desc,
164
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $id . '&section=' . $link_id ),
165
- 'meta' => array( 'title' => WCJ()->modules[ $link_id ]->desc ),
166
- 'nodes' => array(
167
- 'settings' => array(
168
- 'title' => __( 'Settings', 'woocommerce-jetpack' ),
169
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $id . '&section=' . $link_id ),
170
  ),
171
- 'docs' => array(
172
- 'title' => __( 'Documentation', 'woocommerce-jetpack' ),
173
- 'href' => WCJ()->modules[ $link_id ]->link . '?utm_source=module_documentation&utm_medium=admin_bar_link&utm_campaign=booster_documentation',
174
- 'meta' => array( 'target' => '_blank' ),
175
  ),
176
- ),
 
 
 
 
 
 
 
 
177
  );
178
- if ( WCJ()->modules[ $link_id ]->is_enabled() && 'module' === WCJ()->modules[ $link_id ]->type ) {
179
- $this->active_modules[ $link_id ] = $cat_nodes[ $link_id ];
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  }
 
 
181
  }
182
- usort( $cat_nodes, array( $this, 'usort_compare_by_title' ) );
183
- $nodes[ $id ]['nodes'] = $cat_nodes;
184
  }
 
 
 
 
 
185
  }
186
- if ( ! empty( $this->active_modules ) ) {
187
- usort( $this->active_modules, array( $this, 'usort_compare_by_title' ) );
188
- $nodes['dashboard']['nodes']['active']['nodes'] = $this->active_modules;
189
- }
190
- return $nodes;
191
- }
192
 
193
- /**
194
- * usort_compare_by_title.
195
- *
196
- * @version 2.9.1
197
- * @since 2.9.0
198
- */
199
- function usort_compare_by_title( $a, $b ) {
200
- return strcasecmp( $a['title'], $b['title'] );
201
- }
 
 
202
 
203
- /**
204
- * get_nodes_booster_tools.
205
- *
206
- * @version 2.9.0
207
- * @since 2.9.0
208
- */
209
- function get_nodes_booster_tools() {
210
- $nodes = array();
211
- $tools = apply_filters( 'wcj_tools_tabs', array(
212
- array(
213
- 'id' => 'dashboard',
214
- 'title' => __( 'Dashboard', 'woocommerce-jetpack' ),
215
- 'desc' => __( 'This dashboard lets you check statuses and short descriptions of all available Booster for WooCommerce tools. Tools can be enabled through WooCommerce > Settings > Booster.', 'woocommerce-jetpack' ),
216
- ),
217
- ) );
218
- foreach ( $tools as $tool ) {
219
- $nodes[ $tool['id'] ] = array(
220
- 'title' => $tool['title'],
221
- 'href' => admin_url( 'admin.php?page=wcj-tools&tab=' . $tool['id'] ),
222
  );
223
- if ( isset( $tool['desc'] ) ) {
224
- $nodes[ $tool['id'] ]['meta']['title'] = $tool['desc'];
 
 
 
 
 
 
225
  }
 
226
  }
227
- return $nodes;
228
- }
229
-
230
- /**
231
- * add_booster_active_admin_bar.
232
- *
233
- * @version 3.9.0
234
- * @since 3.1.0
235
- */
236
- function add_booster_active_admin_bar( $wp_admin_bar ) {
237
- if ( ! current_user_can( 'manage_woocommerce' ) ) {
238
- return;
239
- }
240
- if ( 'no' === wcj_get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) ) {
241
- $this->get_nodes_booster_modules();
242
- }
243
- $tools = array(
244
- 'tools' => array(
245
- 'title' => __( 'Tools', 'woocommerce-jetpack' ),
246
- 'href' => admin_url( 'admin.php?page=wcj-tools' ),
247
- 'nodes' => $this->get_nodes_booster_tools(),
248
- ),
249
- );
250
- unset( $tools['tools']['nodes']['dashboard'] );
251
- $nodes = array(
252
- 'booster-active' => array(
253
- 'title' => '<span class="ab-icon"></span>' . __( 'Booster: Active', 'woocommerce-jetpack' ),
254
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=active' ),
255
- 'meta' => array(
256
- 'title' => __( 'Booster - Active', 'woocommerce-jetpack' ),
257
- ),
258
- 'nodes' => array_merge( $this->active_modules, $tools ),
259
- ),
260
- );
261
- $this->add_woocommerce_admin_bar_nodes( $wp_admin_bar, $nodes, false );
262
- }
263
 
264
- /**
265
- * add_booster_admin_bar.
266
- *
267
- * @version 3.6.0
268
- * @since 2.9.0
269
- */
270
- function add_booster_admin_bar( $wp_admin_bar ) {
271
- if ( ! current_user_can( 'manage_woocommerce' ) ) {
272
- return;
273
- }
274
- $nodes = array(
275
- 'booster' => array(
276
- 'title' => '<span class="ab-icon"></span>' . __( 'Booster', 'woocommerce-jetpack' ),
277
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack' ),
278
- 'meta' => array(
279
- 'title' => __( 'Booster - Settings', 'woocommerce-jetpack' ),
 
 
 
280
  ),
281
- 'nodes' => array(
282
- 'modules' => array(
283
- 'title' => __( 'Modules', 'woocommerce-jetpack' ),
284
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack' ),
285
- 'nodes' => $this->get_nodes_booster_modules(),
286
- ),
287
- 'tools' => array(
288
- 'title' => __( 'Tools', 'woocommerce-jetpack' ),
289
- 'href' => admin_url( 'admin.php?page=wcj-tools' ),
290
- 'nodes' => $this->get_nodes_booster_tools(),
291
  ),
 
292
  ),
293
- ),
294
- );
295
- $this->add_woocommerce_admin_bar_nodes( $wp_admin_bar, $nodes, false );
296
- }
297
 
298
- /**
299
- * get_nodes_orders_reports.
300
- *
301
- * @version 2.9.0
302
- * @since 2.9.0
303
- */
304
- function get_nodes_orders_reports() {
305
- $nodes = array();
306
- $reports = array(
307
- 'sales_by_date' => __( 'Sales by date', 'woocommerce' ),
308
- 'sales_by_product' => __( 'Sales by product', 'woocommerce' ),
309
- 'sales_by_category' => __( 'Sales by category', 'woocommerce' ),
310
- 'coupon_usage' => __( 'Coupons by date', 'woocommerce' ),
311
- );
312
- foreach ( $reports as $report_id => $report_title ) {
313
- $nodes[ $report_id ] = array(
314
- 'title' => $report_title,
315
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id ),
316
- 'nodes' => array(
317
- '7day' => array(
318
- 'title' => __( 'Last 7 days', 'woocommerce' ),
319
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id . '&range=7day' ),
320
- ),
321
- 'month' => array(
322
- 'title' => __( 'This month', 'woocommerce' ),
323
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id . '&range=month' ),
324
- ),
325
- 'last-month' => array(
326
- 'title' => __( 'Last month', 'woocommerce' ),
327
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id . '&range=last_month' ),
328
  ),
329
- 'year' => array(
330
- 'title' => __( 'Year', 'woocommerce' ),
331
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id . '&range=year' ),
 
 
 
 
 
 
 
 
332
  ),
333
  ),
334
  );
 
335
  }
336
- return $nodes;
337
- }
338
 
339
- /**
340
- * get_nodes_product_taxonomy.
341
- *
342
- * @version 4.1.0
343
- * @since 4.1.0
344
- * @todo [dev] hierarchy
345
- * @todo [dev] count
346
- * @todo [dev] custom taxonomy
347
- */
348
- function get_nodes_product_taxonomy( $taxonomy ) {
349
- $nodes = array();
350
- $terms = get_terms( array(
351
- 'taxonomy' => $taxonomy,
352
- 'orderby' => 'name',
353
- 'order' => 'ASC',
354
- 'hide_empty' => false,
355
- ) );
356
- if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
357
- foreach ( $terms as $term ) {
358
- $nodes[ $term->slug ] = array(
359
- 'title' => $term->name,
360
- 'href' => admin_url( 'edit.php?post_type=product&' . $taxonomy . '=' . $term->slug ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
361
  );
362
  }
 
363
  }
364
- return $nodes;
365
- }
366
 
367
- /**
368
- * add_woocommerce_admin_bar.
369
- *
370
- * @version 4.1.0
371
- * @since 2.9.0
372
- * @todo (maybe) reports > customers > customers > add dates
373
- * @todo (maybe) reports > taxes > taxes_by_code > add dates
374
- * @todo (maybe) reports > taxes > taxes_by_date > add dates
375
- * @todo (maybe) settings > add custom sections (i.e. Booster and other plugins)
376
- * @todo (maybe) extensions > add sections
377
- */
378
- function add_woocommerce_admin_bar( $wp_admin_bar ) {
379
- if ( ! current_user_can( 'manage_woocommerce' ) ) {
380
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
381
  }
382
- $nodes = array(
383
- 'wcj-wc' => array(
384
- 'title' => '<span class="ab-icon"></span>' . __( 'WooCommerce', 'woocommerce' ),
385
- 'href' => admin_url( 'admin.php?page=wc-settings' ),
386
- 'meta' => array(
387
- 'title' => __( 'WooCommerce settings', 'woocommerce' ),
388
- ),
389
- 'nodes' => array(
390
- 'orders' => array(
391
- 'title' => __( 'Orders', 'woocommerce' ),
392
- 'href' => admin_url( 'edit.php?post_type=shop_order' ),
393
- 'nodes' => array(
394
- 'orders' => array(
395
- 'title' => __( 'Orders', 'woocommerce' ),
396
- 'href' => admin_url( 'edit.php?post_type=shop_order' ),
397
- ),
398
- 'add-order' => array(
399
- 'title' => __( 'Add order', 'woocommerce' ),
400
- 'href' => admin_url( 'post-new.php?post_type=shop_order' ),
401
- ),
402
- 'customers' => array(
403
- 'title' => __( 'Customers', 'woocommerce' ),
404
- 'href' => admin_url( 'users.php?role=customer' ),
405
- ),
406
- ),
407
  ),
408
- 'reports' => array(
409
- 'title' => __( 'Reports', 'woocommerce' ),
410
- 'href' => admin_url( 'admin.php?page=wc-reports' ),
411
- 'nodes' => array(
412
- 'orders' => array(
413
- 'title' => __( 'Orders', 'woocommerce' ),
414
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders' ),
415
- 'nodes' => $this->get_nodes_orders_reports(),
416
- ),
417
- 'customers' => array(
418
- 'title' => __( 'Customers', 'woocommerce' ),
419
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=customers' ),
420
- 'nodes' => array(
421
- 'customers' => array(
422
- 'title' => __( 'Customers vs. guests', 'woocommerce' ),
423
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=customers&report=customers' ),
424
- ),
425
- 'customer-list' => array(
426
- 'title' => __( 'Customer list', 'woocommerce' ),
427
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=customers&report=customer_list' ),
428
- ),
429
  ),
430
  ),
431
- 'stock' => array(
432
- 'title' => __( 'Stock', 'woocommerce' ),
433
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=stock' ),
434
- 'nodes' => array(
435
- 'low-in-stock' => array(
436
- 'title' => __( 'Low in stock', 'woocommerce' ),
437
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=stock&report=low_in_stock' ),
438
- ),
439
- 'out-of-stock' => array(
440
- 'title' => __( 'Out of stock', 'woocommerce' ),
441
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=stock&report=out_of_stock' ),
442
- ),
443
- 'most-stocked' => array(
444
- 'title' => __( 'Most Stocked', 'woocommerce' ),
445
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=stock&report=most_stocked' ),
 
 
 
 
 
 
 
446
  ),
447
  ),
448
- ),
449
- 'taxes' => array(
450
- 'title' => __( 'Taxes', 'woocommerce' ),
451
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=taxes' ),
452
- 'nodes' => array(
453
- 'taxes-by-code' => array(
454
- 'title' => __( 'Taxes by code', 'woocommerce' ),
455
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=taxes&report=taxes_by_code' ),
 
 
 
 
 
 
 
 
456
  ),
457
- 'taxes-by-date' => array(
458
- 'title' => __( 'Taxes by date', 'woocommerce' ),
459
- 'href' => admin_url( 'admin.php?page=wc-reports&tab=taxes&report=taxes_by_date' ),
 
 
 
 
 
 
 
 
 
 
460
  ),
461
  ),
462
  ),
463
  ),
464
- ),
465
- 'products' => array(
466
- 'title' => __( 'Products', 'woocommerce' ),
467
- 'href' => admin_url( 'edit.php?post_type=product' ),
468
- 'nodes' => array(
469
- 'products' => array(
470
- 'title' => __( 'Products', 'woocommerce' ),
471
- 'href' => admin_url( 'edit.php?post_type=product' ),
472
- ),
473
- 'add-product' => array(
474
- 'title' => __( 'Add product', 'woocommerce' ),
475
- 'href' => admin_url( 'post-new.php?post_type=product' ),
476
- ),
477
- 'categories' => array(
478
- 'title' => __( 'Categories', 'woocommerce' ),
479
- 'href' => admin_url( 'edit-tags.php?taxonomy=product_cat&post_type=product' ),
480
- 'nodes' => ( 'no' === wcj_get_option( 'wcj_admin_bar_wc_list_cats', 'no' ) ? array() : $this->get_nodes_product_taxonomy( 'product_cat' ) ),
481
- ),
482
- 'tags' => array(
483
- 'title' => __( 'Tags', 'woocommerce' ),
484
- 'href' => admin_url( 'edit-tags.php?taxonomy=product_tag&post_type=product' ),
485
- 'nodes' => ( 'no' === wcj_get_option( 'wcj_admin_bar_wc_list_tags', 'no' ) ? array() : $this->get_nodes_product_taxonomy( 'product_tag' ) ),
486
- ),
487
- 'attributes' => array(
488
- 'title' => __( 'Attributes', 'woocommerce' ),
489
- 'href' => admin_url( 'edit.php?post_type=product&page=product_attributes' ),
490
  ),
491
  ),
492
- ),
493
- 'coupons' => array(
494
- 'title' => __( 'Coupons', 'woocommerce' ),
495
- 'href' => admin_url( 'edit.php?post_type=shop_coupon' ),
496
- 'nodes' => array(
497
- 'coupons' => array(
498
- 'title' => __( 'Coupons', 'woocommerce' ),
499
- 'href' => admin_url( 'edit.php?post_type=shop_coupon' ),
500
- ),
501
- 'add-coupon' => array(
502
- 'title' => __( 'Add coupon', 'woocommerce' ),
503
- 'href' => admin_url( 'post-new.php?post_type=shop_coupon' ),
504
  ),
505
  ),
506
- ),
507
- 'settings' => array(
508
- 'title' => __( 'Settings', 'woocommerce' ),
509
- 'href' => admin_url( 'admin.php?page=wc-settings' ),
510
- 'nodes' => array(
511
- 'general' => array(
512
- 'title' => __( 'General', 'woocommerce' ),
513
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=general' ),
514
- ),
515
- 'products' => array(
516
- 'title' => __( 'Products', 'woocommerce' ),
517
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=products' ),
518
- 'nodes' => array(
519
- 'general' => array(
520
- 'title' => __( 'General', 'woocommerce' ),
521
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=products&section' ),
522
- ),
523
- 'display' => array(
524
- 'title' => __( 'Display', 'woocommerce' ),
525
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=products&section=display' ),
526
- ),
527
- 'inventory' => array(
528
- 'title' => __( 'Inventory', 'woocommerce' ),
529
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=products&section=inventory' ),
530
- ),
531
- 'downloadable' => array(
532
- 'title' => __( 'Downloadable products', 'woocommerce' ),
533
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=products&section=downloadable' ),
534
- ),
535
  ),
536
- ),
537
- 'tax' => array(
538
- 'title' => __( 'Tax', 'woocommerce' ),
539
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=tax' ),
540
- 'nodes' => array(
541
- 'tax-options' => array(
542
- 'title' => __( 'Tax options', 'woocommerce' ),
543
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=tax&section' ),
544
- ),
545
- 'standard-rates' => array(
546
- 'title' => __( 'Standard rates', 'woocommerce' ),
547
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=tax&section=standard' ),
 
 
 
 
 
 
 
 
548
  ),
549
  ),
550
- ),
551
- 'shipping' => array(
552
- 'title' => __( 'Shipping', 'woocommerce' ),
553
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=shipping' ),
554
- 'nodes' => array(
555
- 'shipping-zones' => array(
556
- 'title' => __( 'Shipping zones', 'woocommerce' ),
557
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=shipping&section' ),
558
- ),
559
- 'shipping-options' => array(
560
- 'title' => __( 'Shipping options', 'woocommerce' ),
561
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=shipping&section=options' ),
562
- ),
563
- 'shipping-classes' => array(
564
- 'title' => __( 'Shipping classes', 'woocommerce' ),
565
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=shipping&section=classes' ),
566
  ),
567
  ),
568
- ),
569
- 'checkout' => array(
570
- 'title' => __( 'Checkout', 'woocommerce' ),
571
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout' ),
572
- 'nodes' => array(
573
- 'checkout-options' => array(
574
- 'title' => __( 'Checkout options', 'woocommerce' ),
575
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section' ),
576
- ),
577
- 'bacs' => array(
578
- 'title' => __( 'BACS', 'woocommerce' ),
579
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section=bacs' ),
580
- ),
581
- 'cheque' => array(
582
- 'title' => __( 'Check payments', 'woocommerce' ),
583
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section=cheque' ),
584
- ),
585
- 'cod' => array(
586
- 'title' => __( 'Cash on delivery', 'woocommerce' ),
587
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section=cod' ),
588
- ),
589
- 'paypal' => array(
590
- 'title' => __( 'PayPal', 'woocommerce' ),
591
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section=paypal' ),
592
  ),
593
  ),
594
- ),
595
- 'account' => array(
596
- 'title' => __( 'Account', 'woocommerce' ),
597
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=account' ),
598
- ),
599
- 'email' => array(
600
- 'title' => __( 'Emails', 'woocommerce' ),
601
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=email' ),
602
- ),
603
- 'api' => array(
604
- 'title' => __( 'API', 'woocommerce' ),
605
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=api' ),
606
- 'nodes' => array(
607
- 'settings' => array(
608
- 'title' => __( 'Settings', 'woocommerce' ),
609
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=api&section' ),
610
- ),
611
- 'keys' => array(
612
- 'title' => __( 'Keys/Apps', 'woocommerce' ),
613
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=api&section=keys' ),
 
 
 
 
614
  ),
615
- 'webhooks' => array(
616
- 'title' => __( 'Webhooks', 'woocommerce' ),
617
- 'href' => admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
618
  ),
619
  ),
620
  ),
621
  ),
622
- ),
623
- 'system-status' => array(
624
- 'title' => __( 'System status', 'woocommerce' ),
625
- 'href' => admin_url( 'admin.php?page=wc-status' ),
626
- 'nodes' => array(
627
- 'system-status' => array(
628
- 'title' => __( 'System status', 'woocommerce' ),
629
- 'href' => admin_url( 'admin.php?page=wc-status&tab=status' ),
630
- ),
631
- 'tools' => array(
632
- 'title' => __( 'Tools', 'woocommerce' ),
633
- 'href' => admin_url( 'admin.php?page=wc-status&tab=tools' ),
634
- ),
635
- 'logs' => array(
636
- 'title' => __( 'Logs', 'woocommerce' ),
637
- 'href' => admin_url( 'admin.php?page=wc-status&tab=logs' ),
638
  ),
639
  ),
640
- ),
641
- 'extensions' => array(
642
- 'title' => __( 'Extensions', 'woocommerce' ),
643
- 'href' => admin_url( 'admin.php?page=wc-addons' ),
644
  ),
645
  ),
646
- ),
647
- );
648
- $this->add_woocommerce_admin_bar_nodes( $wp_admin_bar, $nodes, false );
649
- }
650
 
651
- }
652
 
653
  endif;
654
 
5
  * @version 4.1.0
6
  * @since 2.9.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Admin_Bar' ) ) :
16
 
 
 
17
  /**
18
+ * WCJ_Admin_Bar.
19
  *
20
+ * @version 2.7.0
 
 
 
 
 
 
21
  */
22
+ class WCJ_Admin_Bar extends WCJ_Module {
23
 
24
+ /**
25
+ * Constructor.
26
+ *
27
+ * @version 4.1.0
28
+ * @since 2.9.0
29
+ * @todo (maybe) custom user nodes
30
+ * @todo (maybe) optional nodes selection
31
+ * @todo (maybe) add WooCommerce versions (from / to) to nodes
32
+ * @todo (maybe) customizable icons
33
+ * @todo (maybe) separate admin bar menu: "Booster Modules", "Booster Tools", "WooCommerce Reports", "WooCommerce Products", "WooCommerce Settings"
34
+ */
35
+ public function __construct() {
36
 
37
+ $this->id = 'admin_bar';
38
+ $this->short_desc = __( 'Admin Bar', 'woocommerce-jetpack' );
39
+ $this->desc = __( 'WooCommerce admin bar.', 'woocommerce-jetpack' );
40
+ $this->link_slug = 'woocommerce-admin-bar';
41
+ parent::__construct();
42
+
43
+ if ( $this->is_enabled() ) {
44
+ if ( 'yes' === wcj_get_option( 'wcj_admin_bar_wc_enabled', 'yes' ) ) {
45
+ add_action( 'admin_bar_menu', array( $this, 'add_woocommerce_admin_bar' ), PHP_INT_MAX );
46
+ add_action( 'wp_head', array( $this, 'add_woocommerce_admin_bar_icon_style' ) );
47
+ add_action( 'admin_head', array( $this, 'add_woocommerce_admin_bar_icon_style' ) );
48
  }
49
+ if ( 'yes' === wcj_get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) || 'yes' === wcj_get_option( 'wcj_admin_bar_booster_active_enabled', 'yes' ) ) {
50
+ if ( 'yes' === wcj_get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) ) {
51
+ add_action( 'admin_bar_menu', array( $this, 'add_booster_admin_bar' ), PHP_INT_MAX );
52
+ }
53
+ if ( 'yes' === wcj_get_option( 'wcj_admin_bar_booster_active_enabled', 'yes' ) ) {
54
+ add_action( 'admin_bar_menu', array( $this, 'add_booster_active_admin_bar' ), PHP_INT_MAX );
55
+ }
56
+ add_action( 'wp_head', array( $this, 'add_booster_admin_bar_icon_style' ) );
57
+ add_action( 'admin_head', array( $this, 'add_booster_admin_bar_icon_style' ) );
58
  }
 
 
59
  }
60
+ add_action( 'woojetpack_after_settings_save', array( $this, 'reload_page_after_settings_save' ), PHP_INT_MAX, 2 );
61
  }
 
 
62
 
63
+ /**
64
+ * Reload_page_after_settings_save.
65
+ *
66
+ * @version 2.9.0
67
+ * @since 2.9.0
68
+ * @todo (maybe) somehow add "Your settings have been saved." admin notice
69
+ * @param string $sections defines the sections.
70
+ * @param string $current_section defines the current_section.
71
+ */
72
+ public function reload_page_after_settings_save( $sections, $current_section ) {
73
+ // This function is needed so admin bar menus would appear immediately after module settings are saved (i.e. without additional page refresh).
74
+ if ( $this->id === $current_section ) {
75
+ wp_safe_redirect( add_query_arg( '', '' ) );
76
+ exit;
77
+ }
78
  }
 
79
 
80
+ /**
81
+ * Add_booster_admin_bar_icon_style.
82
+ *
83
+ * @version 3.1.0
84
+ * @since 2.9.0
85
+ */
86
+ public function add_booster_admin_bar_icon_style() {
87
+ echo '<style type="text/css"> #wpadminbar #wp-admin-bar-booster .ab-icon:before { content: "\f185"; top: 3px; } </style>';
88
+ echo '<style type="text/css"> #wpadminbar #wp-admin-bar-booster-active .ab-icon:before { content: "\f155"; top: 3px; } </style>';
89
+ }
90
 
91
+ /**
92
+ * Add_woocommerce_admin_bar_icon_style.
93
+ *
94
+ * @version 2.9.0
95
+ * @since 2.9.0
96
+ */
97
+ public function add_woocommerce_admin_bar_icon_style() {
98
+ echo '<style type="text/css"> #wpadminbar #wp-admin-bar-wcj-wc .ab-icon:before { content: "\f174"; top: 3px; } </style>';
99
+ }
100
 
101
+ /**
102
+ * Add_woocommerce_admin_bar_nodes.
103
+ *
104
+ * @version 2.9.0
105
+ * @since 2.9.0
106
+ * @param string $wp_admin_bar defines the wp_admin_bar.
107
+ * @param string $nodes defines the nodes.
108
+ * @param string $parent_id defines the parent_id.
109
+ */
110
+ public function add_woocommerce_admin_bar_nodes( $wp_admin_bar, $nodes, $parent_id ) {
111
+ foreach ( $nodes as $node_id => $node ) {
112
+ $id = ( false !== $parent_id ? $parent_id . '-' . $node_id : $node_id );
113
+ $args = array(
114
+ 'parent' => $parent_id,
115
+ 'id' => $id,
116
+ 'title' => $node['title'],
117
+ 'href' => $node['href'],
118
+ 'meta' => array( 'title' => $node['title'] ),
119
+ );
120
+ if ( isset( $node['meta'] ) ) {
121
+ $args['meta'] = array_merge( $args['meta'], $node['meta'] );
122
+ }
123
+ $wp_admin_bar->add_node( $args );
124
+ if ( isset( $node['nodes'] ) ) {
125
+ // Recursion.
126
+ $this->add_woocommerce_admin_bar_nodes( $wp_admin_bar, $node['nodes'], $id );
127
+ }
128
  }
129
  }
 
130
 
131
+ /**
132
+ * Get_nodes_booster_modules.
133
+ *
134
+ * @version 3.1.0
135
+ * @since 2.9.0
136
+ * @todo (maybe) dashes instead of underscores
137
+ * @todo (maybe) dashboard > alphabetically - list all modules
138
+ * @todo (maybe) dashboard > by_category - list all modules
139
+ */
140
+ public function get_nodes_booster_modules() {
141
+ $nodes = array();
142
+ $cats = include wcj_plugin_path() . '/includes/admin/wcj-modules-cats.php';
143
+ $this->active_modules = array();
144
+ foreach ( $cats as $id => $label_info ) {
145
+ $nodes[ $id ] = array(
146
+ 'title' => $label_info['label'],
147
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $id ),
148
+ 'meta' => array( 'title' => wp_strip_all_tags( $label_info['desc'] ) ),
149
+ );
150
+ if ( 'dashboard' === $id ) {
151
+ $nodes[ $id ]['nodes'] = apply_filters(
152
+ 'wcj_admin_bar_dashboard_nodes',
153
+ array(
154
+ 'alphabetically' => array(
155
+ 'title' => __( 'Alphabetically', 'woocommerce-jetpack' ),
156
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=alphabetically' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  ),
158
+ 'by_category' => array(
159
+ 'title' => __( 'By Category', 'woocommerce-jetpack' ),
160
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=by_category' ),
 
161
  ),
162
+ 'active' => array(
163
+ 'title' => __( 'Active', 'woocommerce-jetpack' ),
164
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=active' ),
165
+ ),
166
+ 'manager' => array(
167
+ 'title' => __( 'Manage Settings', 'woocommerce-jetpack' ),
168
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=manager' ),
169
+ ),
170
+ )
171
  );
172
+ } else {
173
+ $cat_nodes = array();
174
+ foreach ( $label_info['all_cat_ids'] as $link_id ) {
175
+ if ( wcj_is_module_deprecated( $link_id, false, true ) ) {
176
+ continue;
177
+ }
178
+ $cat_nodes[ $link_id ] = array(
179
+ 'title' => w_c_j()->modules[ $link_id ]->short_desc,
180
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $id . '&section=' . $link_id ),
181
+ 'meta' => array( 'title' => w_c_j()->modules[ $link_id ]->desc ),
182
+ 'nodes' => array(
183
+ 'settings' => array(
184
+ 'title' => __( 'Settings', 'woocommerce-jetpack' ),
185
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $id . '&section=' . $link_id ),
186
+ ),
187
+ 'docs' => array(
188
+ 'title' => __( 'Documentation', 'woocommerce-jetpack' ),
189
+ 'href' => w_c_j()->modules[ $link_id ]->link . '?utm_source=module_documentation&utm_medium=admin_bar_link&utm_campaign=booster_documentation',
190
+ 'meta' => array( 'target' => '_blank' ),
191
+ ),
192
+ ),
193
+ );
194
+ if ( w_c_j()->modules[ $link_id ]->is_enabled() && 'module' === w_c_j()->modules[ $link_id ]->type ) {
195
+ $this->active_modules[ $link_id ] = $cat_nodes[ $link_id ];
196
+ }
197
  }
198
+ usort( $cat_nodes, array( $this, 'usort_compare_by_title' ) );
199
+ $nodes[ $id ]['nodes'] = $cat_nodes;
200
  }
 
 
201
  }
202
+ if ( ! empty( $this->active_modules ) ) {
203
+ usort( $this->active_modules, array( $this, 'usort_compare_by_title' ) );
204
+ $nodes['dashboard']['nodes']['active']['nodes'] = $this->active_modules;
205
+ }
206
+ return $nodes;
207
  }
 
 
 
 
 
 
208
 
209
+ /**
210
+ * Usort_compare_by_title.
211
+ *
212
+ * @version 2.9.1
213
+ * @since 2.9.0
214
+ * @param string $a defines the a.
215
+ * @param string $b defines the b.
216
+ */
217
+ public function usort_compare_by_title( $a, $b ) {
218
+ return strcasecmp( $a['title'], $b['title'] );
219
+ }
220
 
221
+ /**
222
+ * Get_nodes_booster_tools.
223
+ *
224
+ * @version 2.9.0
225
+ * @since 2.9.0
226
+ */
227
+ public function get_nodes_booster_tools() {
228
+ $nodes = array();
229
+ $tools = apply_filters(
230
+ 'wcj_tools_tabs',
231
+ array(
232
+ array(
233
+ 'id' => 'dashboard',
234
+ 'title' => __( 'Dashboard', 'woocommerce-jetpack' ),
235
+ 'desc' => __( 'This dashboard lets you check statuses and short descriptions of all available Booster for WooCommerce tools. Tools can be enabled through WooCommerce > Settings > Booster.', 'woocommerce-jetpack' ),
236
+ ),
237
+ )
 
 
238
  );
239
+ foreach ( $tools as $tool ) {
240
+ $nodes[ $tool['id'] ] = array(
241
+ 'title' => $tool['title'],
242
+ 'href' => admin_url( 'admin.php?page=wcj-tools&tab=' . $tool['id'] ),
243
+ );
244
+ if ( isset( $tool['desc'] ) ) {
245
+ $nodes[ $tool['id'] ]['meta']['title'] = $tool['desc'];
246
+ }
247
  }
248
+ return $nodes;
249
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
251
+ /**
252
+ * Add_booster_active_admin_bar.
253
+ *
254
+ * @version 3.9.0
255
+ * @since 3.1.0
256
+ * @param string $wp_admin_bar defines the wp_admin_bar.
257
+ */
258
+ public function add_booster_active_admin_bar( $wp_admin_bar ) {
259
+ if ( ! current_user_can( 'manage_woocommerce' ) ) {
260
+ return;
261
+ }
262
+ if ( 'no' === wcj_get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) ) {
263
+ $this->get_nodes_booster_modules();
264
+ }
265
+ $tools = array(
266
+ 'tools' => array(
267
+ 'title' => __( 'Tools', 'woocommerce-jetpack' ),
268
+ 'href' => admin_url( 'admin.php?page=wcj-tools' ),
269
+ 'nodes' => $this->get_nodes_booster_tools(),
270
  ),
271
+ );
272
+ unset( $tools['tools']['nodes']['dashboard'] );
273
+ $nodes = array(
274
+ 'booster-active' => array(
275
+ 'title' => '<span class="ab-icon"></span>' . __( 'Booster: Active', 'woocommerce-jetpack' ),
276
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=active' ),
277
+ 'meta' => array(
278
+ 'title' => __( 'Booster - Active', 'woocommerce-jetpack' ),
 
 
279
  ),
280
+ 'nodes' => array_merge( $this->active_modules, $tools ),
281
  ),
282
+ );
283
+ $this->add_woocommerce_admin_bar_nodes( $wp_admin_bar, $nodes, false );
284
+ }
 
285
 
286
+ /**
287
+ * Add_booster_admin_bar.
288
+ *
289
+ * @version 3.6.0
290
+ * @since 2.9.0
291
+ * @param string $wp_admin_bar defines the wp_admin_bar.
292
+ */
293
+ public function add_booster_admin_bar( $wp_admin_bar ) {
294
+ if ( ! current_user_can( 'manage_woocommerce' ) ) {
295
+ return;
296
+ }
297
+ $nodes = array(
298
+ 'booster' => array(
299
+ 'title' => '<span class="ab-icon"></span>' . __( 'Booster', 'woocommerce-jetpack' ),
300
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack' ),
301
+ 'meta' => array(
302
+ 'title' => __( 'Booster - Settings', 'woocommerce-jetpack' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
303
  ),
304
+ 'nodes' => array(
305
+ 'modules' => array(
306
+ 'title' => __( 'Modules', 'woocommerce-jetpack' ),
307
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack' ),
308
+ 'nodes' => $this->get_nodes_booster_modules(),
309
+ ),
310
+ 'tools' => array(
311
+ 'title' => __( 'Tools', 'woocommerce-jetpack' ),
312
+ 'href' => admin_url( 'admin.php?page=wcj-tools' ),
313
+ 'nodes' => $this->get_nodes_booster_tools(),
314
+ ),
315
  ),
316
  ),
317
  );
318
+ $this->add_woocommerce_admin_bar_nodes( $wp_admin_bar, $nodes, false );
319
  }
 
 
320
 
321
+ /**
322
+ * Get_nodes_orders_reports.
323
+ *
324
+ * @version 2.9.0
325
+ * @since 2.9.0
326
+ */
327
+ public function get_nodes_orders_reports() {
328
+ $nodes = array();
329
+ $reports = array(
330
+ 'sales_by_date' => __( 'Sales by date', 'woocommerce' ),
331
+ 'sales_by_product' => __( 'Sales by product', 'woocommerce' ),
332
+ 'sales_by_category' => __( 'Sales by category', 'woocommerce' ),
333
+ 'coupon_usage' => __( 'Coupons by date', 'woocommerce' ),
334
+ );
335
+ foreach ( $reports as $report_id => $report_title ) {
336
+ $nodes[ $report_id ] = array(
337
+ 'title' => $report_title,
338
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id ),
339
+ 'nodes' => array(
340
+ '7day' => array(
341
+ 'title' => __( 'Last 7 days', 'woocommerce' ),
342
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id . '&range=7day' ),
343
+ ),
344
+ 'month' => array(
345
+ 'title' => __( 'This month', 'woocommerce' ),
346
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id . '&range=month' ),
347
+ ),
348
+ 'last-month' => array(
349
+ 'title' => __( 'Last month', 'woocommerce' ),
350
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id . '&range=last_month' ),
351
+ ),
352
+ 'year' => array(
353
+ 'title' => __( 'Year', 'woocommerce' ),
354
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders&report=' . $report_id . '&range=year' ),
355
+ ),
356
+ ),
357
  );
358
  }
359
+ return $nodes;
360
  }
 
 
361
 
362
+ /**
363
+ * Get_nodes_product_taxonomy.
364
+ *
365
+ * @version 4.1.0
366
+ * @since 4.1.0
367
+ * @todo [dev] hierarchy
368
+ * @todo [dev] count
369
+ * @todo [dev] custom taxonomy
370
+ * @param string $taxonomy defines the taxonomy.
371
+ */
372
+ public function get_nodes_product_taxonomy( $taxonomy ) {
373
+ $nodes = array();
374
+ $terms = get_terms(
375
+ array(
376
+ 'taxonomy' => $taxonomy,
377
+ 'orderby' => 'name',
378
+ 'order' => 'ASC',
379
+ 'hide_empty' => false,
380
+ )
381
+ );
382
+ if ( ! empty( $terms ) && ! is_wp_error( $terms ) ) {
383
+ foreach ( $terms as $term ) {
384
+ $nodes[ $term->slug ] = array(
385
+ 'title' => $term->name,
386
+ 'href' => admin_url( 'edit.php?post_type=product&' . $taxonomy . '=' . $term->slug ),
387
+ );
388
+ }
389
+ }
390
+ return $nodes;
391
  }
392
+
393
+ /**
394
+ * Add_woocommerce_admin_bar.
395
+ *
396
+ * @version 4.1.0
397
+ * @since 2.9.0
398
+ * @todo (maybe) reports > customers > customers > add dates
399
+ * @todo (maybe) reports > taxes > taxes_by_code > add dates
400
+ * @todo (maybe) reports > taxes > taxes_by_date > add dates
401
+ * @todo (maybe) settings > add custom sections (i.e. Booster and other plugins)
402
+ * @todo (maybe) extensions > add sections
403
+ * @param string $wp_admin_bar defines the wp_admin_bar.
404
+ */
405
+ public function add_woocommerce_admin_bar( $wp_admin_bar ) {
406
+ if ( ! current_user_can( 'manage_woocommerce' ) ) {
407
+ return;
408
+ }
409
+ $nodes = array(
410
+ 'wcj-wc' => array(
411
+ 'title' => '<span class="ab-icon"></span>' . __( 'WooCommerce', 'woocommerce' ),
412
+ 'href' => admin_url( 'admin.php?page=wc-settings' ),
413
+ 'meta' => array(
414
+ 'title' => __( 'WooCommerce settings', 'woocommerce' ),
 
 
415
  ),
416
+ 'nodes' => array(
417
+ 'orders' => array(
418
+ 'title' => __( 'Orders', 'woocommerce' ),
419
+ 'href' => admin_url( 'edit.php?post_type=shop_order' ),
420
+ 'nodes' => array(
421
+ 'orders' => array(
422
+ 'title' => __( 'Orders', 'woocommerce' ),
423
+ 'href' => admin_url( 'edit.php?post_type=shop_order' ),
424
+ ),
425
+ 'add-order' => array(
426
+ 'title' => __( 'Add order', 'woocommerce' ),
427
+ 'href' => admin_url( 'post-new.php?post_type=shop_order' ),
428
+ ),
429
+ 'customers' => array(
430
+ 'title' => __( 'Customers', 'woocommerce' ),
431
+ 'href' => admin_url( 'users.php?role=customer' ),
 
 
 
 
 
432
  ),
433
  ),
434
+ ),
435
+ 'reports' => array(
436
+ 'title' => __( 'Reports', 'woocommerce' ),
437
+ 'href' => admin_url( 'admin.php?page=wc-reports' ),
438
+ 'nodes' => array(
439
+ 'orders' => array(
440
+ 'title' => __( 'Orders', 'woocommerce' ),
441
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=orders' ),
442
+ 'nodes' => $this->get_nodes_orders_reports(),
443
+ ),
444
+ 'customers' => array(
445
+ 'title' => __( 'Customers', 'woocommerce' ),
446
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=customers' ),
447
+ 'nodes' => array(
448
+ 'customers' => array(
449
+ 'title' => __( 'Customers vs. guests', 'woocommerce' ),
450
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=customers&report=customers' ),
451
+ ),
452
+ 'customer-list' => array(
453
+ 'title' => __( 'Customer list', 'woocommerce' ),
454
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=customers&report=customer_list' ),
455
+ ),
456
  ),
457
  ),
458
+ 'stock' => array(
459
+ 'title' => __( 'Stock', 'woocommerce' ),
460
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=stock' ),
461
+ 'nodes' => array(
462
+ 'low-in-stock' => array(
463
+ 'title' => __( 'Low in stock', 'woocommerce' ),
464
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=stock&report=low_in_stock' ),
465
+ ),
466
+ 'out-of-stock' => array(
467
+ 'title' => __( 'Out of stock', 'woocommerce' ),
468
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=stock&report=out_of_stock' ),
469
+ ),
470
+ 'most-stocked' => array(
471
+ 'title' => __( 'Most Stocked', 'woocommerce' ),
472
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=stock&report=most_stocked' ),
473
+ ),
474
  ),
475
+ ),
476
+ 'taxes' => array(
477
+ 'title' => __( 'Taxes', 'woocommerce' ),
478
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=taxes' ),
479
+ 'nodes' => array(
480
+ 'taxes-by-code' => array(
481
+ 'title' => __( 'Taxes by code', 'woocommerce' ),
482
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=taxes&report=taxes_by_code' ),
483
+ ),
484
+ 'taxes-by-date' => array(
485
+ 'title' => __( 'Taxes by date', 'woocommerce' ),
486
+ 'href' => admin_url( 'admin.php?page=wc-reports&tab=taxes&report=taxes_by_date' ),
487
+ ),
488
  ),
489
  ),
490
  ),
491
  ),
492
+ 'products' => array(
493
+ 'title' => __( 'Products', 'woocommerce' ),
494
+ 'href' => admin_url( 'edit.php?post_type=product' ),
495
+ 'nodes' => array(
496
+ 'products' => array(
497
+ 'title' => __( 'Products', 'woocommerce' ),
498
+ 'href' => admin_url( 'edit.php?post_type=product' ),
499
+ ),
500
+ 'add-product' => array(
501
+ 'title' => __( 'Add product', 'woocommerce' ),
502
+ 'href' => admin_url( 'post-new.php?post_type=product' ),
503
+ ),
504
+ 'categories' => array(
505
+ 'title' => __( 'Categories', 'woocommerce' ),
506
+ 'href' => admin_url( 'edit-tags.php?taxonomy=product_cat&post_type=product' ),
507
+ 'nodes' => ( 'no' === wcj_get_option( 'wcj_admin_bar_wc_list_cats', 'no' ) ? array() : $this->get_nodes_product_taxonomy( 'product_cat' ) ),
508
+ ),
509
+ 'tags' => array(
510
+ 'title' => __( 'Tags', 'woocommerce' ),
511
+ 'href' => admin_url( 'edit-tags.php?taxonomy=product_tag&post_type=product' ),
512
+ 'nodes' => ( 'no' === wcj_get_option( 'wcj_admin_bar_wc_list_tags', 'no' ) ? array() : $this->get_nodes_product_taxonomy( 'product_tag' ) ),
513
+ ),
514
+ 'attributes' => array(
515
+ 'title' => __( 'Attributes', 'woocommerce' ),
516
+ 'href' => admin_url( 'edit.php?post_type=product&page=product_attributes' ),
517
+ ),
518
  ),
519
  ),
520
+ 'coupons' => array(
521
+ 'title' => __( 'Coupons', 'woocommerce' ),
522
+ 'href' => admin_url( 'edit.php?post_type=shop_coupon' ),
523
+ 'nodes' => array(
524
+ 'coupons' => array(
525
+ 'title' => __( 'Coupons', 'woocommerce' ),
526
+ 'href' => admin_url( 'edit.php?post_type=shop_coupon' ),
527
+ ),
528
+ 'add-coupon' => array(
529
+ 'title' => __( 'Add coupon', 'woocommerce' ),
530
+ 'href' => admin_url( 'post-new.php?post_type=shop_coupon' ),
531
+ ),
532
  ),
533
  ),
534
+ 'settings' => array(
535
+ 'title' => __( 'Settings', 'woocommerce' ),
536
+ 'href' => admin_url( 'admin.php?page=wc-settings' ),
537
+ 'nodes' => array(
538
+ 'general' => array(
539
+ 'title' => __( 'General', 'woocommerce' ),
540
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=general' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
541
  ),
542
+ 'products' => array(
543
+ 'title' => __( 'Products', 'woocommerce' ),
544
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=products' ),
545
+ 'nodes' => array(
546
+ 'general' => array(
547
+ 'title' => __( 'General', 'woocommerce' ),
548
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=products&section' ),
549
+ ),
550
+ 'display' => array(
551
+ 'title' => __( 'Display', 'woocommerce' ),
552
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=products&section=display' ),
553
+ ),
554
+ 'inventory' => array(
555
+ 'title' => __( 'Inventory', 'woocommerce' ),
556
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=products&section=inventory' ),
557
+ ),
558
+ 'downloadable' => array(
559
+ 'title' => __( 'Downloadable products', 'woocommerce' ),
560
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=products&section=downloadable' ),
561
+ ),
562
  ),
563
  ),
564
+ 'tax' => array(
565
+ 'title' => __( 'Tax', 'woocommerce' ),
566
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=tax' ),
567
+ 'nodes' => array(
568
+ 'tax-options' => array(
569
+ 'title' => __( 'Tax options', 'woocommerce' ),
570
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=tax&section' ),
571
+ ),
572
+ 'standard-rates' => array(
573
+ 'title' => __( 'Standard rates', 'woocommerce' ),
574
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=tax&section=standard' ),
575
+ ),
 
 
 
 
576
  ),
577
  ),
578
+ 'shipping' => array(
579
+ 'title' => __( 'Shipping', 'woocommerce' ),
580
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=shipping' ),
581
+ 'nodes' => array(
582
+ 'shipping-zones' => array(
583
+ 'title' => __( 'Shipping zones', 'woocommerce' ),
584
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=shipping&section' ),
585
+ ),
586
+ 'shipping-options' => array(
587
+ 'title' => __( 'Shipping options', 'woocommerce' ),
588
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=shipping&section=options' ),
589
+ ),
590
+ 'shipping-classes' => array(
591
+ 'title' => __( 'Shipping classes', 'woocommerce' ),
592
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=shipping&section=classes' ),
593
+ ),
 
 
 
 
 
 
 
 
594
  ),
595
  ),
596
+ 'checkout' => array(
597
+ 'title' => __( 'Checkout', 'woocommerce' ),
598
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout' ),
599
+ 'nodes' => array(
600
+ 'checkout-options' => array(
601
+ 'title' => __( 'Checkout options', 'woocommerce' ),
602
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section' ),
603
+ ),
604
+ 'bacs' => array(
605
+ 'title' => __( 'BACS', 'woocommerce' ),
606
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section=bacs' ),
607
+ ),
608
+ 'cheque' => array(
609
+ 'title' => __( 'Check payments', 'woocommerce' ),
610
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section=cheque' ),
611
+ ),
612
+ 'cod' => array(
613
+ 'title' => __( 'Cash on delivery', 'woocommerce' ),
614
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section=cod' ),
615
+ ),
616
+ 'paypal' => array(
617
+ 'title' => __( 'PayPal', 'woocommerce' ),
618
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=checkout&section=paypal' ),
619
+ ),
620
  ),
621
+ ),
622
+ 'account' => array(
623
+ 'title' => __( 'Account', 'woocommerce' ),
624
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=account' ),
625
+ ),
626
+ 'email' => array(
627
+ 'title' => __( 'Emails', 'woocommerce' ),
628
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=email' ),
629
+ ),
630
+ 'api' => array(
631
+ 'title' => __( 'API', 'woocommerce' ),
632
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=api' ),
633
+ 'nodes' => array(
634
+ 'settings' => array(
635
+ 'title' => __( 'Settings', 'woocommerce' ),
636
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=api&section' ),
637
+ ),
638
+ 'keys' => array(
639
+ 'title' => __( 'Keys/Apps', 'woocommerce' ),
640
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=api&section=keys' ),
641
+ ),
642
+ 'webhooks' => array(
643
+ 'title' => __( 'Webhooks', 'woocommerce' ),
644
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=api&section=webhooks' ),
645
+ ),
646
  ),
647
  ),
648
  ),
649
  ),
650
+ 'system-status' => array(
651
+ 'title' => __( 'System status', 'woocommerce' ),
652
+ 'href' => admin_url( 'admin.php?page=wc-status' ),
653
+ 'nodes' => array(
654
+ 'system-status' => array(
655
+ 'title' => __( 'System status', 'woocommerce' ),
656
+ 'href' => admin_url( 'admin.php?page=wc-status&tab=status' ),
657
+ ),
658
+ 'tools' => array(
659
+ 'title' => __( 'Tools', 'woocommerce' ),
660
+ 'href' => admin_url( 'admin.php?page=wc-status&tab=tools' ),
661
+ ),
662
+ 'logs' => array(
663
+ 'title' => __( 'Logs', 'woocommerce' ),
664
+ 'href' => admin_url( 'admin.php?page=wc-status&tab=logs' ),
665
+ ),
666
  ),
667
  ),
668
+ 'extensions' => array(
669
+ 'title' => __( 'Extensions', 'woocommerce' ),
670
+ 'href' => admin_url( 'admin.php?page=wc-addons' ),
671
+ ),
672
  ),
673
  ),
674
+ );
675
+ $this->add_woocommerce_admin_bar_nodes( $wp_admin_bar, $nodes, false );
676
+ }
 
677
 
678
+ }
679
 
680
  endif;
681
 
includes/class-wcj-admin-orders-list.php CHANGED
@@ -5,416 +5,432 @@
5
  * @version 5.5.9
6
  * @since 3.2.4
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Admin_Orders_List' ) ) :
13
 
14
- class WCJ_Admin_Orders_List extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 5.2.0
20
- * @since 3.2.4
21
  */
22
- function __construct() {
23
 
24
- $this->id = 'admin_orders_list';
25
- $this->short_desc = __( 'Admin Orders List', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Customize admin orders list: add custom columns (1 allowed in free version); add multiple status filtering (1 allowed in free version).', 'woocommerce-jetpack' );
27
- $this->desc_pro = __( 'Customize admin orders list: add custom columns; add multiple status filtering.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-admin-orders-list';
29
- parent::__construct();
30
 
31
- if ( $this->is_enabled() ) {
 
 
 
 
 
 
 
 
 
 
 
 
32
 
33
- // Custom columns
34
- if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_custom_columns_enabled', 'no' ) ) {
35
- add_filter( 'manage_edit-shop_order_columns', array( $this, 'add_order_columns' ), PHP_INT_MAX - 1 );
36
- add_action( 'manage_shop_order_posts_custom_column', array( $this, 'render_order_column' ), PHP_INT_MAX );
37
- if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) || 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
38
- // Billing country or Currency filtering
39
- add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );
40
- add_filter( 'parse_query', array( $this, 'parse_query' ) );
41
- }
42
- // Maybe make sortable custom columns
43
- add_filter( 'manage_edit-shop_order_sortable_columns', array( $this, 'shop_order_sortable_columns' ) );
44
- add_action( 'pre_get_posts', array( $this, 'shop_order_pre_get_posts_order_by_column' ) );
45
- }
46
 
47
- // Multiple status
48
- if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_enabled', 'no' ) ) {
49
- if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_not_completed_link', 'no' ) ) {
50
- add_filter( 'views_edit-shop_order', array( $this, 'add_shop_order_multiple_statuses_not_completed_link' ) );
51
- add_action( 'pre_get_posts', array( $this, 'filter_shop_order_multiple_statuses_not_completed_link' ), PHP_INT_MAX, 1 );
52
- }
53
- if ( 'no' != wcj_get_option( 'wcj_order_admin_list_multiple_status_filter', 'no' ) ) {
54
- add_action( 'restrict_manage_posts', array( $this, 'add_shop_order_multiple_statuses' ), PHP_INT_MAX, 2 );
55
- add_action( 'pre_get_posts', array( $this, 'filter_shop_order_multiple_statuses' ), PHP_INT_MAX, 1 );
56
- }
57
- if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_hide_default_statuses_menu', 'no' ) ) {
58
- add_action( 'admin_head', array( $this, 'hide_default_statuses_menu' ), PHP_INT_MAX );
59
  }
60
- if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_admin_menu', 'no' ) ) {
61
- add_action( 'admin_menu', array( $this, 'admin_menu_multiple_status' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  }
63
- }
64
 
65
- // Columns Order
66
- if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_columns_order_enabled', 'no' ) ) {
67
- add_filter( 'manage_edit-shop_order_columns', array( $this, 'rearange_order_columns' ), PHP_INT_MAX - 1 );
 
68
  }
69
-
70
  }
71
- }
72
 
73
- /**
74
- * admin_menu_multiple_status.
75
- *
76
- * @version 3.7.0
77
- * @since 3.7.0
78
- * @todo add presets as links (same as "Not completed" link)
79
- * @todo fix: custom (i.e. presets) menus are not highlighted
80
- */
81
- function admin_menu_multiple_status() {
82
- // Remove "Coupons" menu (to get "Orders" menus on top)
83
- $coupons_menu = remove_submenu_page( 'woocommerce', 'edit.php?post_type=shop_coupon' );
84
- // Maybe remove original "Orders" menu
85
- if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_admin_menu_remove_original', 'no' ) ) {
86
- remove_submenu_page( 'woocommerce', 'edit.php?post_type=shop_order' );
87
- }
88
- // Add presets
89
- $titles = wcj_get_option( 'wcj_order_admin_list_multiple_status_presets_titles', array() );
90
- $statuses = wcj_get_option( 'wcj_order_admin_list_multiple_status_presets_statuses', array() );
91
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_order_admin_list_multiple_status_presets_total_number', 1 ) );
92
- for ( $i = 1; $i <= $total_number; $i++ ) {
93
- if ( ! empty( $titles[ $i ] ) && ! empty( $statuses[ $i ] ) ) {
94
- $menu_slug = 'edit.php?post_type=shop_order';
95
- foreach ( $statuses[ $i ] as $x => $status ) {
96
- $menu_slug .= "&wcj_admin_filter_statuses[{$x}]={$status}";
97
- }
98
- $orders_count_html = '';
99
- if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_admin_menu_counter', 'no' ) ) {
100
- $order_count = 0;
101
  foreach ( $statuses[ $i ] as $x => $status ) {
102
- $order_count += wc_orders_count( substr( $status, 3 ) );
103
  }
104
- $orders_count_html = ' <span class="awaiting-mod update-plugins count-' . esc_attr( $order_count ) . ' wcj-order-count-wrapper"><span class="wcj-order-count">' . number_format_i18n( $order_count ) . '</span></span>'; // WPCS: override ok.
 
 
 
 
 
 
 
 
105
  }
106
- add_submenu_page( 'woocommerce', $titles[ $i ], $titles[ $i ] . $orders_count_html, 'edit_shop_orders', $menu_slug );
107
  }
 
 
108
  }
109
- // Re-add "Coupons" menu
110
- add_submenu_page( 'woocommerce', $coupons_menu[0], $coupons_menu[3], $coupons_menu[1], $coupons_menu[2] );
111
- }
112
 
113
- /**
114
- * shop_order_pre_get_posts_order_by_column.
115
- *
116
- * @version 2.9.0
117
- * @since 2.9.0
118
- * @todo add sortable to "Billing Country" and "Currency Code"
119
- * @todo move custom columns section (probably with reordering and multiple status sections) to new module (e.g. (Admin) Order(s) List) - same with products custom columns
120
- * @todo (maybe) add filtering to custom columns (as it's done for "Billing Country" and "Currency Code")
121
- */
122
- function shop_order_pre_get_posts_order_by_column( $query ) {
123
- if (
124
- $query->is_main_query() &&
125
- ( $orderby = $query->get( 'orderby' ) ) &&
126
- isset( $query->query['post_type'] ) && 'shop_order' === $query->query['post_type'] &&
127
- isset( $query->is_admin ) && 1 == $query->is_admin
128
- ) {
129
- if ( 'wcj_orders_custom_column_' === substr( $orderby, 0, 25 ) ) {
130
- $index = substr( $orderby, 25 );
131
- $query->set( 'orderby', wcj_get_option( 'wcj_orders_list_custom_columns_sortable_' . $index, 'no' ) ); // 'meta_value' or 'meta_value_num'
132
- $query->set( 'meta_key', wcj_get_option( 'wcj_orders_list_custom_columns_sortable_key_' . $index, '' ) );
 
 
 
133
  }
134
  }
135
- }
136
 
137
- /**
138
- * Make columns sortable.
139
- *
140
- * @version 2.9.0
141
- * @since 2.9.0
142
- * @param array $columns
143
- * @return array
144
- */
145
- function shop_order_sortable_columns( $columns ) {
146
- $custom = array();
147
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
148
- for ( $i = 1; $i <= $total_number; $i++ ) {
149
- if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
150
- if ( 'no' != wcj_get_option( 'wcj_orders_list_custom_columns_sortable_' . $i, 'no' ) && '' != wcj_get_option( 'wcj_orders_list_custom_columns_sortable_key_' . $i, '' ) ) {
151
- $custom[ 'wcj_orders_custom_column_' . $i ] = 'wcj_orders_custom_column_' . $i;
 
152
  }
153
  }
 
154
  }
155
- return ( ! empty( $custom ) ? wp_parse_args( $custom, $columns ) : $columns );
156
- }
157
 
158
- /**
159
- * hide_default_statuses_menu.
160
- *
161
- * @version 2.5.7
162
- * @since 2.5.7
163
- */
164
- function hide_default_statuses_menu() {
165
- echo '<style>body.post-type-shop_order ul.subsubsub {display: none !important;}</style>';
166
- }
167
 
168
- /**
169
- * get_orders_default_columns_in_order.
170
- *
171
- * @version 2.5.7
172
- * @since 2.5.7
173
- */
174
- function get_orders_default_columns_in_order() {
175
- $columns = array(
176
- 'cb',
177
- 'order_status',
178
- 'order_title',
179
- 'order_items',
180
- 'billing_address',
181
- 'shipping_address',
182
- 'customer_message',
183
- 'order_notes',
184
- 'order_date',
185
- 'order_total',
186
- 'order_actions',
187
- );
188
- return implode( PHP_EOL, $columns );
189
- }
190
 
191
- /**
192
- * add_shop_order_multiple_statuses_not_completed_link.
193
- *
194
- * @version 5.5.9
195
- * @since 2.5.7
196
- */
197
- function add_shop_order_multiple_statuses_not_completed_link( $views ) {
198
- global $wp_query;
199
- if ( ! wcj_current_user_can( 'edit_others_pages' ) ) {
 
 
 
 
 
 
 
 
 
 
 
200
  return $views;
201
  }
202
- $all_not_completed_statuses = wc_get_order_statuses();
203
- unset( $all_not_completed_statuses['wc-completed'] );
204
- $all_not_completed_statuses = array_keys( $all_not_completed_statuses );
205
- $all_not_completed_statuses_param = urlencode( implode( ',', $all_not_completed_statuses ) );
206
- $class = ( isset( $wp_query->query['post_status'] ) && is_array( $wp_query->query['post_status'] ) && $all_not_completed_statuses === $wp_query->query['post_status'] ) ? 'current' : '';
207
- $query_string = remove_query_arg( array( 'post_status', 'wcj_admin_filter_statuses' ) );
208
- $query_string = esc_url(add_query_arg( 'post_status', $all_not_completed_statuses_param, $query_string ));
209
- $views['wcj_statuses_not_completed'] = '<a href="' . esc_url( $query_string ) . '" class="' . esc_attr( $class ) . '">' . __( 'Not Completed', 'woocommerce-jetpack' ) . '</a>';
210
- return $views;
211
- }
212
 
213
- /**
214
- * filter_shop_order_multiple_statuses_not_completed_link.
215
- *
216
- * @version 3.9.0
217
- * @since 2.5.7
218
- */
219
- function filter_shop_order_multiple_statuses_not_completed_link( $query ) {
220
- if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/edit.php' ) && isset( $_GET['post_type'] ) && 'shop_order' === $_GET['post_type'] ) {
221
- if ( wcj_current_user_can( 'edit_others_pages' ) ) {
222
- if ( isset( $_GET['post_status'] ) && false !== strpos( $_GET['post_status'], ',' ) ) {
223
- $post_statuses = explode( ',', $_GET['post_status'] );
224
- $query->query['post_status'] = $post_statuses;
225
- $query->query_vars['post_status'] = $post_statuses;
 
 
226
  }
227
  }
228
  }
229
- }
230
 
231
- /**
232
- * multiple_shop_order_statuses.
233
- *
234
- * @version 3.7.0
235
- * @since 2.5.7
236
- */
237
- function multiple_shop_order_statuses( $type ) {
238
- $checked_post_statuses = isset( $_GET['wcj_admin_filter_statuses'] ) ? $_GET['wcj_admin_filter_statuses'] : array();
239
- $html = '';
240
- $html .= ( 'checkboxes' === $type ) ?
241
- '<span id="wcj_admin_filter_shop_order_statuses">' :
242
- '<select multiple name="wcj_admin_filter_statuses[]" id="wcj_admin_filter_shop_order_statuses" class="chosen_select">';
243
- $num_posts = wp_count_posts( 'shop_order', 'readable' );
244
- foreach ( array_merge( wc_get_order_statuses(), array( 'trash' => __( 'Trash', 'woocommerce-jetpack' ) ) ) as $status_id => $status_title ) {
245
- $total_number = ( isset( $num_posts->{$status_id} ) ) ? $num_posts->{$status_id} : 0;
246
- if ( $total_number > 0 ) {
247
- $html .= ( 'checkboxes' === $type ) ?
248
- '<input type="checkbox" name="wcj_admin_filter_statuses[]" style="width:16px;height:16px;" value="' . $status_id . '"' .
 
249
  checked( in_array( $status_id, $checked_post_statuses ), true, false ) . '>' . $status_title . ' (' . $total_number . ') ' :
250
- '<option value="' . $status_id . '"' . selected( in_array( $status_id, $checked_post_statuses ), true, false ) . '>' .
251
- $status_title . ' (' . $total_number . ') ' . '</option>';
 
252
  }
 
 
 
 
253
  }
254
- $html .= ( 'checkboxes' === $type ) ?
255
- '</span>' :
256
- '</select>';
257
- return $html;
258
- }
259
 
260
- /**
261
- * add_shop_order_multiple_statuses.
262
- *
263
- * @version 2.5.7
264
- * @since 2.5.7
265
- */
266
- function add_shop_order_multiple_statuses( $post_type, $which ) {
267
- if ( 'shop_order' === $post_type ) {
268
- echo $this->multiple_shop_order_statuses( wcj_get_option( 'wcj_order_admin_list_multiple_status_filter', 'no' ) );
 
 
 
269
  }
270
- }
271
 
272
- /**
273
- * filter_shop_order_multiple_statuses.
274
- *
275
- * @version 3.9.0
276
- * @since 2.5.7
277
- */
278
- function filter_shop_order_multiple_statuses( $query ) {
279
- if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/edit.php' ) && isset( $_GET['post_type'] ) && 'shop_order' === $_GET['post_type'] ) {
280
- if ( wcj_current_user_can( 'edit_others_pages' ) ) {
281
- if ( isset( $_GET['wcj_admin_filter_statuses'] ) ) {
282
- $post_statuses = $_GET['wcj_admin_filter_statuses'];
283
- $query->query['post_status'] = $post_statuses;
284
- $query->query_vars['post_status'] = $post_statuses;
 
 
285
  }
286
  }
287
  }
288
- }
289
 
290
- /**
291
- * Filter the orders in admin based on options.
292
- *
293
- * @version 2.8.0
294
- * @access public
295
- * @param mixed $query
296
- * @return void
297
- */
298
- function parse_query( $query ) {
299
- global $typenow, $wp_query;
300
- if ( $typenow != 'shop_order' ) {
301
- return;
302
- }
303
- if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) && isset( $_GET['country'] ) && 'all' != $_GET['country'] ) {
304
- $query->query_vars['meta_query'][] = array(
305
- 'key' => '_billing_country',
306
- 'value' => $_GET['country'],
307
- );
308
- }
309
- if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) && isset( $_GET['currency'] ) && 'all' != $_GET['currency'] ) {
310
- $query->query_vars['meta_query'][] = array(
311
- 'key' => '_order_currency',
312
- 'value' => $_GET['currency'],
313
- );
 
314
  }
315
- }
316
 
317
- /**
318
- * Filters for post types.
319
- *
320
- * @version 3.9.0
321
- */
322
- function restrict_manage_posts() {
323
- global $typenow, $wp_query;
324
- if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ) ) ) {
325
- if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
326
- $selected_coutry = isset( $_GET['country'] ) ? $_GET['country'] : 'all';
327
- $countries = array_merge( array( 'all' => __( 'All countries', 'woocommerce-jetpack' ) ), wcj_get_countries() );
328
- echo '<select id="country" name="country">';
329
- foreach ( $countries as $code => $name ) {
330
- echo '<option value="' . $code . '" ' . selected( $code, $selected_coutry, false ) . '>' . $name . '</option>';
 
 
331
  }
332
- echo '</select>';
333
- }
334
- if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
335
- $selected_currency = isset( $_GET['currency'] ) ? $_GET['currency'] : 'all';
336
- $currencies = array_merge( array( 'all' => __( 'All currencies', 'woocommerce-jetpack' ) ), wcj_get_woocommerce_currencies_and_symbols() );
337
- echo '<select id="currency" name="currency">';
338
- foreach ( $currencies as $code => $name ) {
339
- echo '<option value="' . $code . '" ' . selected( $code, $selected_currency, false ) . '>' . $name . '</option>';
340
  }
341
- echo '</select>';
342
  }
343
  }
344
- }
345
 
346
- /**
347
- * rearange_order_columns.
348
- *
349
- * @version 2.5.7
350
- * @version 2.5.7
351
- */
352
- function rearange_order_columns( $columns ) {
353
- $reordered_columns = wcj_get_option( 'wcj_order_admin_list_columns_order', $this->get_orders_default_columns_in_order() );
354
- $reordered_columns = explode( PHP_EOL, $reordered_columns );
355
- $reordered_columns_result = array();
356
- if ( ! empty( $reordered_columns ) ) {
357
- foreach ( $reordered_columns as $column_id ) {
358
- $column_id = str_replace( "\n", '', $column_id );
359
- $column_id = str_replace( "\r", '', $column_id );
360
- if ( '' != $column_id && isset( $columns[ $column_id ] ) ) {
361
- $reordered_columns_result[ $column_id ] = $columns[ $column_id ];
362
- unset( $columns[ $column_id ] );
 
 
363
  }
364
  }
 
365
  }
366
- return array_merge( $reordered_columns_result, $columns );
367
- }
368
 
369
- /**
370
- * add_order_columns.
371
- *
372
- * @version 2.8.0
373
- */
374
- function add_order_columns( $columns ) {
375
- if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
376
- $columns['country'] = __( 'Billing Country', 'woocommerce-jetpack' );
377
- }
378
- if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
379
- $columns['currency'] = __( 'Currency Code', 'woocommerce-jetpack' );
380
- }
381
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
382
- for ( $i = 1; $i <= $total_number; $i++ ) {
383
- if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
384
- $columns[ 'wcj_orders_custom_column_' . $i ] = wcj_get_option( 'wcj_orders_list_custom_columns_label_' . $i, '' );
385
  }
386
- }
387
- return $columns;
388
- }
389
-
390
- /**
391
- * Output custom columns for orders
392
- *
393
- * @version 2.8.0
394
- * @param string $column
395
- */
396
- function render_order_column( $column ) {
397
- if ( 'country' === $column && 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
398
- $country_code = do_shortcode( '[wcj_order_checkout_field field_id="billing_country"]' );
399
- echo ( 2 == strlen( $country_code ) )
400
- ? wcj_get_country_flag_by_code( $country_code ) . ' ' . wcj_get_country_name_by_code( $country_code )
401
- : wcj_get_country_name_by_code( $country_code );
402
- } elseif ( 'currency' === $column && 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
403
- echo do_shortcode( '[wcj_order_currency]' );
404
- } else {
405
  $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
406
  for ( $i = 1; $i <= $total_number; $i++ ) {
407
  if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
408
- if ( 'wcj_orders_custom_column_' . $i === $column ) {
409
- echo do_shortcode( wcj_get_option( 'wcj_orders_list_custom_columns_value_' . $i, '' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
  }
411
  }
412
  }
413
  }
414
  }
415
 
416
- }
417
-
418
  endif;
419
 
420
  return new WCJ_Admin_Orders_List();
5
  * @version 5.5.9
6
  * @since 3.2.4
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Admin_Orders_List' ) ) :
16
 
 
 
17
  /**
18
+ * WCJ_Admin_Orders_List.
19
  *
20
+ * @version 2.7.0
 
21
  */
22
+ class WCJ_Admin_Orders_List extends WCJ_Module {
23
 
 
 
 
 
 
 
24
 
25
+ /**
26
+ * Constructor.
27
+ *
28
+ * @version 5.2.0
29
+ * @since 3.2.4
30
+ */
31
+ public function __construct() {
32
+ $this->id = 'admin_orders_list';
33
+ $this->short_desc = __( 'Admin Orders List', 'woocommerce-jetpack' );
34
+ $this->desc = __( 'Customize admin orders list: add custom columns (1 allowed in free version); add multiple status filtering (1 allowed in free version).', 'woocommerce-jetpack' );
35
+ $this->desc_pro = __( 'Customize admin orders list: add custom columns; add multiple status filtering.', 'woocommerce-jetpack' );
36
+ $this->link_slug = 'woocommerce-admin-orders-list';
37
+ parent::__construct();
38
 
39
+ if ( $this->is_enabled() ) {
 
 
 
 
 
 
 
 
 
 
 
 
40
 
41
+ // Custom columns.
42
+ if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_custom_columns_enabled', 'no' ) ) {
43
+ add_filter( 'manage_edit-shop_order_columns', array( $this, 'add_order_columns' ), PHP_INT_MAX - 1 );
44
+ add_action( 'manage_shop_order_posts_custom_column', array( $this, 'render_order_column' ), PHP_INT_MAX );
45
+ if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) || 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
46
+ // Billing country or Currency filtering.
47
+ add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );
48
+ add_filter( 'parse_query', array( $this, 'parse_query' ) );
49
+ }
50
+ // Maybe make sortable custom columns.
51
+ add_filter( 'manage_edit-shop_order_sortable_columns', array( $this, 'shop_order_sortable_columns' ) );
52
+ add_action( 'pre_get_posts', array( $this, 'shop_order_pre_get_posts_order_by_column' ) );
53
  }
54
+
55
+ // Multiple status.
56
+ if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_enabled', 'no' ) ) {
57
+ if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_not_completed_link', 'no' ) ) {
58
+ add_filter( 'views_edit-shop_order', array( $this, 'add_shop_order_multiple_statuses_not_completed_link' ) );
59
+ add_action( 'pre_get_posts', array( $this, 'filter_shop_order_multiple_statuses_not_completed_link' ), PHP_INT_MAX, 1 );
60
+ }
61
+ if ( 'no' !== wcj_get_option( 'wcj_order_admin_list_multiple_status_filter', 'no' ) ) {
62
+ add_action( 'restrict_manage_posts', array( $this, 'add_shop_order_multiple_statuses' ), PHP_INT_MAX, 2 );
63
+ add_action( 'pre_get_posts', array( $this, 'filter_shop_order_multiple_statuses' ), PHP_INT_MAX, 1 );
64
+ }
65
+ if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_hide_default_statuses_menu', 'no' ) ) {
66
+ add_action( 'admin_head', array( $this, 'hide_default_statuses_menu' ), PHP_INT_MAX );
67
+ }
68
+ if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_admin_menu', 'no' ) ) {
69
+ add_action( 'admin_menu', array( $this, 'admin_menu_multiple_status' ) );
70
+ }
71
  }
 
72
 
73
+ // Columns Order.
74
+ if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_columns_order_enabled', 'no' ) ) {
75
+ add_filter( 'manage_edit-shop_order_columns', array( $this, 'rearange_order_columns' ), PHP_INT_MAX - 1 );
76
+ }
77
  }
 
78
  }
 
79
 
80
+ /**
81
+ * Admin_menu_multiple_status.
82
+ *
83
+ * @version 3.7.0
84
+ * @since 3.7.0
85
+ * @todo add presets as links (same as "Not completed" link)
86
+ * @todo fix: custom (i.e. presets) menus are not highlighted
87
+ */
88
+ public function admin_menu_multiple_status() {
89
+ // Remove "Coupons" menu (to get "Orders" menus on top).
90
+ $coupons_menu = remove_submenu_page( 'woocommerce', 'edit.php?post_type=shop_coupon' );
91
+ // Maybe remove original "Orders" menu.
92
+ if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_admin_menu_remove_original', 'no' ) ) {
93
+ remove_submenu_page( 'woocommerce', 'edit.php?post_type=shop_order' );
94
+ }
95
+ // Add presets.
96
+ $titles = wcj_get_option( 'wcj_order_admin_list_multiple_status_presets_titles', array() );
97
+ $statuses = wcj_get_option( 'wcj_order_admin_list_multiple_status_presets_statuses', array() );
98
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_order_admin_list_multiple_status_presets_total_number', 1 ) );
99
+ for ( $i = 1; $i <= $total_number; $i++ ) {
100
+ if ( ! empty( $titles[ $i ] ) && ! empty( $statuses[ $i ] ) ) {
101
+ $menu_slug = 'edit.php?post_type=shop_order';
 
 
 
 
 
 
102
  foreach ( $statuses[ $i ] as $x => $status ) {
103
+ $menu_slug .= "&wcj_admin_filter_statuses[{$x}]={$status}";
104
  }
105
+ $orders_count_html = '';
106
+ if ( 'yes' === wcj_get_option( 'wcj_order_admin_list_multiple_status_admin_menu_counter', 'no' ) ) {
107
+ $order_count = 0;
108
+ foreach ( $statuses[ $i ] as $x => $status ) {
109
+ $order_count += wc_orders_count( substr( $status, 3 ) );
110
+ }
111
+ $orders_count_html = ' <span class="awaiting-mod update-plugins count-' . esc_attr( $order_count ) . ' wcj-order-count-wrapper"><span class="wcj-order-count">' . number_format_i18n( $order_count ) . '</span></span>'; // WPCS: override ok.
112
+ }
113
+ add_submenu_page( 'woocommerce', $titles[ $i ], $titles[ $i ] . $orders_count_html, 'edit_shop_orders', $menu_slug );
114
  }
 
115
  }
116
+ // Re-add "Coupons" menu.
117
+ add_submenu_page( 'woocommerce', $coupons_menu[0], $coupons_menu[3], $coupons_menu[1], $coupons_menu[2] );
118
  }
 
 
 
119
 
120
+ /**
121
+ * Ahop_order_pre_get_posts_order_by_column.
122
+ *
123
+ * @version 2.9.0
124
+ * @since 2.9.0
125
+ * @todo add sortable to "Billing Country" and "Currency Code"
126
+ * @todo move custom columns section (probably with reordering and multiple status sections) to new module (e.g. (Admin) Order(s) List) - same with products custom columns
127
+ * @todo (maybe) add filtering to custom columns (as it's done for "Billing Country" and "Currency Code")
128
+ * @param string $query defines the query.
129
+ */
130
+ public function shop_order_pre_get_posts_order_by_column( $query ) {
131
+ $orderby = $query->get( 'orderby' );
132
+ if (
133
+ $query->is_main_query() &&
134
+ ( $orderby ) &&
135
+ isset( $query->query['post_type'] ) && 'shop_order' === $query->query['post_type'] &&
136
+ isset( $query->is_admin ) && 1 === $query->is_admin
137
+ ) {
138
+ if ( 'wcj_orders_custom_column_' === substr( $orderby, 0, 25 ) ) {
139
+ $index = substr( $orderby, 25 );
140
+ $query->set( 'orderby', wcj_get_option( 'wcj_orders_list_custom_columns_sortable_' . $index, 'no' ) );
141
+ $query->set( 'meta_key', wcj_get_option( 'wcj_orders_list_custom_columns_sortable_key_' . $index, '' ) );
142
+ }
143
  }
144
  }
 
145
 
146
+ /**
147
+ * Make columns sortable.
148
+ *
149
+ * @version 2.9.0
150
+ * @since 2.9.0
151
+ * @param array $columns defines the columns.
152
+ * @return array
153
+ */
154
+ public function shop_order_sortable_columns( $columns ) {
155
+ $custom = array();
156
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
157
+ for ( $i = 1; $i <= $total_number; $i++ ) {
158
+ if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
159
+ if ( 'no' !== wcj_get_option( 'wcj_orders_list_custom_columns_sortable_' . $i, 'no' ) && '' !== wcj_get_option( 'wcj_orders_list_custom_columns_sortable_key_' . $i, '' ) ) {
160
+ $custom[ 'wcj_orders_custom_column_' . $i ] = 'wcj_orders_custom_column_' . $i;
161
+ }
162
  }
163
  }
164
+ return ( ! empty( $custom ) ? wp_parse_args( $custom, $columns ) : $columns );
165
  }
 
 
166
 
167
+ /**
168
+ * Hide_default_statuses_menu.
169
+ *
170
+ * @version 2.5.7
171
+ * @since 2.5.7
172
+ */
173
+ public function hide_default_statuses_menu() {
174
+ echo '<style>body.post-type-shop_order ul.subsubsub {display: none !important;}</style>';
175
+ }
176
 
177
+ /**
178
+ * Get_orders_default_columns_in_order.
179
+ *
180
+ * @version 2.5.7
181
+ * @since 2.5.7
182
+ */
183
+ public function get_orders_default_columns_in_order() {
184
+ $columns = array(
185
+ 'cb',
186
+ 'order_status',
187
+ 'order_title',
188
+ 'order_items',
189
+ 'billing_address',
190
+ 'shipping_address',
191
+ 'customer_message',
192
+ 'order_notes',
193
+ 'order_date',
194
+ 'order_total',
195
+ 'order_actions',
196
+ );
197
+ return implode( PHP_EOL, $columns );
198
+ }
199
 
200
+ /**
201
+ * Add_shop_order_multiple_statuses_not_completed_link.
202
+ *
203
+ * @version 5.5.9
204
+ * @since 2.5.7
205
+ * @param string $views defines the views.
206
+ */
207
+ public function add_shop_order_multiple_statuses_not_completed_link( $views ) {
208
+ global $wp_query;
209
+ if ( ! wcj_current_user_can( 'edit_others_pages' ) ) {
210
+ return $views;
211
+ }
212
+ $all_not_completed_statuses = wc_get_order_statuses();
213
+ unset( $all_not_completed_statuses['wc-completed'] );
214
+ $all_not_completed_statuses = array_keys( $all_not_completed_statuses );
215
+ $all_not_completed_statuses_param = rawurlencode( implode( ',', $all_not_completed_statuses ) );
216
+ $class = ( isset( $wp_query->query['post_status'] ) && is_array( $wp_query->query['post_status'] ) && $all_not_completed_statuses === $wp_query->query['post_status'] ) ? 'current' : '';
217
+ $query_string = esc_url( remove_query_arg( array( 'post_status', 'wcj_admin_filter_statuses' ) ) );
218
+ $query_string = esc_url( add_query_arg( 'post_status', $all_not_completed_statuses_param, $query_string ) );
219
+ $views['wcj_statuses_not_completed'] = '<a href="' . esc_url( $query_string ) . '" class="' . esc_attr( $class ) . '">' . __( 'Not Completed', 'woocommerce-jetpack' ) . '</a>';
220
  return $views;
221
  }
 
 
 
 
 
 
 
 
 
 
222
 
223
+ /**
224
+ * Filter_shop_order_multiple_statuses_not_completed_link.
225
+ *
226
+ * @version 3.9.0
227
+ * @since 2.5.7
228
+ * @param string $query defines the query.
229
+ */
230
+ public function filter_shop_order_multiple_statuses_not_completed_link( $query ) {
231
+ if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/edit.php' ) && isset( $_GET['post_type'] ) && 'shop_order' === $_GET['post_type'] ) {
232
+ if ( wcj_current_user_can( 'edit_others_pages' ) ) {
233
+ if ( isset( $_GET['post_status'] ) && false !== strpos( sanitize_text_field( wp_unslash( $_GET['post_status'] ) ), ',' ) ) {
234
+ $post_statuses = explode( ',', sanitize_text_field( wp_unslash( $_GET['post_status'] ) ) );
235
+ $query->query['post_status'] = $post_statuses;
236
+ $query->query_vars['post_status'] = $post_statuses;
237
+ }
238
  }
239
  }
240
  }
 
241
 
242
+ /**
243
+ * Multiple_shop_order_statuses.
244
+ *
245
+ * @version 3.7.0
246
+ * @since 2.5.7
247
+ * @param string $type defines the type.
248
+ */
249
+ public function multiple_shop_order_statuses( $type ) {
250
+ $checked_post_statuses = isset( $_GET['wcj_admin_filter_statuses'] ) ? $_GET['wcj_admin_filter_statuses'] : array();
251
+ $html = '';
252
+ $html .= ( 'checkboxes' === $type ) ?
253
+ '<span id="wcj_admin_filter_shop_order_statuses">' :
254
+ '<select multiple name="wcj_admin_filter_statuses[]" id="wcj_admin_filter_shop_order_statuses" class="chosen_select">';
255
+ $num_posts = wp_count_posts( 'shop_order', 'readable' );
256
+ foreach ( array_merge( wc_get_order_statuses(), array( 'trash' => __( 'Trash', 'woocommerce-jetpack' ) ) ) as $status_id => $status_title ) {
257
+ $total_number = ( isset( $num_posts->{$status_id} ) ) ? $num_posts->{$status_id} : 0;
258
+ if ( $total_number > 0 ) {
259
+ $html .= ( 'checkboxes' === $type ) ?
260
+ '<input type="checkbox" name="wcj_admin_filter_statuses[]" style="width:16px;height:16px;" value="' . $status_id . '"' .
261
  checked( in_array( $status_id, $checked_post_statuses ), true, false ) . '>' . $status_title . ' (' . $total_number . ') ' :
262
+ '<option value="' . $status_id . '"' . selected( in_array( $status_id, $checked_post_statuses, true ), true, false ) . '>' .
263
+ $status_title . ' (' . $total_number . ') </option>';
264
+ }
265
  }
266
+ $html .= ( 'checkboxes' === $type ) ?
267
+ '</span>' :
268
+ '</select>';
269
+ return $html;
270
  }
 
 
 
 
 
271
 
272
+ /**
273
+ * Add_shop_order_multiple_statuses.
274
+ *
275
+ * @version 2.5.7
276
+ * @since 2.5.7
277
+ * @param string $post_type defines the post_type.
278
+ * @param string $which defines the which.
279
+ */
280
+ public function add_shop_order_multiple_statuses( $post_type, $which ) {
281
+ if ( 'shop_order' === $post_type ) {
282
+ echo wp_kses_post( $this->multiple_shop_order_statuses( wcj_get_option( 'wcj_order_admin_list_multiple_status_filter', 'no' ) ) );
283
+ }
284
  }
 
285
 
286
+ /**
287
+ * Filter_shop_order_multiple_statuses.
288
+ *
289
+ * @version 3.9.0
290
+ * @since 2.5.7
291
+ * @param string $query defines the query.
292
+ */
293
+ public function filter_shop_order_multiple_statuses( $query ) {
294
+ if ( isset( $_SERVER['REQUEST_URI'] ) && ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/edit.php' ) && isset( $_GET['post_type'] ) && 'shop_order' === $_GET['post_type'] ) ) {
295
+ if ( wcj_current_user_can( 'edit_others_pages' ) ) {
296
+ if ( isset( $_GET['wcj_admin_filter_statuses'] ) ) {
297
+ $post_statuses = $_GET['wcj_admin_filter_statuses'];
298
+ $query->query['post_status'] = $post_statuses;
299
+ $query->query_vars['post_status'] = $post_statuses;
300
+ }
301
  }
302
  }
303
  }
 
304
 
305
+ /**
306
+ * Filter the orders in admin based on options.
307
+ *
308
+ * @version 2.8.0
309
+ * @access public
310
+ * @param mixed $query defines the query.
311
+ * @return void
312
+ */
313
+ public function parse_query( $query ) {
314
+ global $typenow, $wp_query;
315
+ if ( 'shop_order' !== $typenow ) {
316
+ return;
317
+ }
318
+ if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) && isset( $_GET['country'] ) && 'all' !== $_GET['country'] ) {
319
+ $query->query_vars['meta_query'][] = array(
320
+ 'key' => '_billing_country',
321
+ 'value' => $_GET['country'],
322
+ );
323
+ }
324
+ if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) && isset( $_GET['currency'] ) && 'all' !== $_GET['currency'] ) {
325
+ $query->query_vars['meta_query'][] = array(
326
+ 'key' => '_order_currency',
327
+ 'value' => $_GET['currency'],
328
+ );
329
+ }
330
  }
 
331
 
332
+ /**
333
+ * Filters for post types.
334
+ *
335
+ * @version 3.9.0
336
+ */
337
+ public function restrict_manage_posts() {
338
+ global $typenow, $wp_query;
339
+ if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ) ) ) {
340
+ if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
341
+ $selected_coutry = isset( $_GET['country'] ) ? sanitize_text_field( wp_unslash( $_GET['country'] ) ) : 'all';
342
+ $countries = array_merge( array( 'all' => __( 'All countries', 'woocommerce-jetpack' ) ), wcj_get_countries() );
343
+ echo '<select id="country" name="country">';
344
+ foreach ( $countries as $code => $name ) {
345
+ echo wp_kses_post( '<option value="' . $code . '" ' . selected( $code, $selected_coutry, false ) . '>' . $name . '</option>' );
346
+ }
347
+ echo '</select>';
348
  }
349
+ if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
350
+ $selected_currency = isset( $_GET['currency'] ) ? $_GET['currency'] : 'all';
351
+ $currencies = array_merge( array( 'all' => __( 'All currencies', 'woocommerce-jetpack' ) ), wcj_get_woocommerce_currencies_and_symbols() );
352
+ echo '<select id="currency" name="currency">';
353
+ foreach ( $currencies as $code => $name ) {
354
+ echo wp_kses_post( '<option value="' . $code . '" ' . selected( $code, $selected_currency, false ) . '>' . $name . '</option>' );
355
+ }
356
+ echo '</select>';
357
  }
 
358
  }
359
  }
 
360
 
361
+ /**
362
+ * Rearange_order_columns.
363
+ *
364
+ * @version 2.5.7
365
+ * @version 2.5.7
366
+ * @param string $columns defines the columns.
367
+ */
368
+ public function rearange_order_columns( $columns ) {
369
+ $reordered_columns = wcj_get_option( 'wcj_order_admin_list_columns_order', $this->get_orders_default_columns_in_order() );
370
+ $reordered_columns = explode( PHP_EOL, $reordered_columns );
371
+ $reordered_columns_result = array();
372
+ if ( ! empty( $reordered_columns ) ) {
373
+ foreach ( $reordered_columns as $column_id ) {
374
+ $column_id = str_replace( "\n", '', $column_id );
375
+ $column_id = str_replace( "\r", '', $column_id );
376
+ if ( '' !== $column_id && isset( $columns[ $column_id ] ) ) {
377
+ $reordered_columns_result[ $column_id ] = $columns[ $column_id ];
378
+ unset( $columns[ $column_id ] );
379
+ }
380
  }
381
  }
382
+ return array_merge( $reordered_columns_result, $columns );
383
  }
 
 
384
 
385
+ /**
386
+ * Add_order_columns.
387
+ *
388
+ * @version 2.8.0
389
+ * @param string $columns defines the columns.
390
+ */
391
+ public function add_order_columns( $columns ) {
392
+ if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
393
+ $columns['country'] = __( 'Billing Country', 'woocommerce-jetpack' );
394
+ }
395
+ if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
396
+ $columns['currency'] = __( 'Currency Code', 'woocommerce-jetpack' );
 
 
 
 
397
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
398
  $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
399
  for ( $i = 1; $i <= $total_number; $i++ ) {
400
  if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
401
+ $columns[ 'wcj_orders_custom_column_' . $i ] = wcj_get_option( 'wcj_orders_list_custom_columns_label_' . $i, '' );
402
+ }
403
+ }
404
+ return $columns;
405
+ }
406
+
407
+ /**
408
+ * Output custom columns for orders
409
+ *
410
+ * @version 2.8.0
411
+ * @param string $column defines the column.
412
+ */
413
+ public function render_order_column( $column ) {
414
+ if ( 'country' === $column && 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
415
+ $country_code = do_shortcode( '[wcj_order_checkout_field field_id="billing_country"]' );
416
+ echo wp_kses_post( ( 2 === strlen( $country_code ) ) )
417
+ ? wp_kses_post( wcj_get_country_flag_by_code( $country_code ) ) . ' ' . wp_kses_post( wcj_get_country_name_by_code( $country_code ) )
418
+ : wp_kses_post( wcj_get_country_name_by_code( $country_code ) );
419
+ } elseif ( 'currency' === $column && 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
420
+ echo do_shortcode( '[wcj_order_currency]' );
421
+ } else {
422
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
423
+ for ( $i = 1; $i <= $total_number; $i++ ) {
424
+ if ( 'yes' === wcj_get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
425
+ if ( 'wcj_orders_custom_column_' . $i === $column ) {
426
+ echo do_shortcode( wcj_get_option( 'wcj_orders_list_custom_columns_value_' . $i, '' ) );
427
+ }
428
  }
429
  }
430
  }
431
  }
432
  }
433
 
 
 
434
  endif;
435
 
436
  return new WCJ_Admin_Orders_List();
includes/class-wcj-admin-products-list.php CHANGED
@@ -5,123 +5,134 @@
5
  * @version 5.2.0
6
  * @since 3.2.4
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Admin_Products_List' ) ) :
13
 
14
- class WCJ_Admin_Products_List extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 5.2.0
20
- * @since 3.2.4
21
  */
22
- function __construct() {
23
 
24
- $this->id = 'admin_products_list';
25
- $this->short_desc = __( 'Admin Products List', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Customize admin products list (1 custom column allowed in free).', 'woocommerce-jetpack' );
27
- $this->desc_pro = __( 'Customize admin products list.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-admin-products-list';
29
- parent::__construct();
 
30
 
31
- if ( $this->is_enabled() ) {
32
- // Admin list - custom columns
33
- if ( 'yes' === wcj_get_option( 'wcj_products_admin_list_custom_columns_enabled', 'no' ) ) {
34
- add_filter( 'manage_edit-product_columns', array( $this, 'add_product_columns' ), PHP_INT_MAX );
35
- add_action( 'manage_product_posts_custom_column', array( $this, 'render_product_column' ), PHP_INT_MAX );
36
- }
37
 
38
- // Admin list - columns order
39
- if ( 'yes' === wcj_get_option( 'wcj_products_admin_list_columns_order_enabled', 'no' ) ) {
40
- add_filter( 'manage_edit-product_columns', array( $this, 'rearange_product_columns' ), PHP_INT_MAX );
 
 
 
 
 
 
 
 
41
  }
42
  }
43
- }
44
 
45
- /**
46
- * rearange_product_columns.
47
- *
48
- * @version 2.9.0
49
- * @since 2.9.0
50
- */
51
- function rearange_product_columns( $columns ) {
52
- $reordered_columns = wcj_get_option( 'wcj_products_admin_list_columns_order', $this->get_products_default_columns_in_order() );
53
- $reordered_columns = explode( PHP_EOL, $reordered_columns );
54
- $reordered_columns_result = array();
55
- if ( ! empty( $reordered_columns ) ) {
56
- foreach ( $reordered_columns as $column_id ) {
57
- $column_id = str_replace( "\n", '', $column_id );
58
- $column_id = str_replace( "\r", '', $column_id );
59
- if ( '' != $column_id && isset( $columns[ $column_id ] ) ) {
60
- $reordered_columns_result[ $column_id ] = $columns[ $column_id ];
61
- unset( $columns[ $column_id ] );
 
 
62
  }
63
  }
 
64
  }
65
- return array_merge( $reordered_columns_result, $columns );
66
- }
67
 
68
- /**
69
- * get_products_default_columns_in_order.
70
- *
71
- * @version 2.9.0
72
- * @since 2.9.0
73
- */
74
- function get_products_default_columns_in_order() {
75
- $columns = array(
76
- 'cb',
77
- 'thumb',
78
- 'name',
79
- 'sku',
80
- 'is_in_stock',
81
- 'price',
82
- 'product_cat',
83
- 'product_tag',
84
- 'featured',
85
- 'product_type',
86
- 'date',
87
- );
88
- return implode( PHP_EOL, $columns );
89
- }
90
 
91
- /**
92
- * add_product_columns.
93
- *
94
- * @version 2.9.0
95
- * @since 2.9.0
96
- */
97
- function add_product_columns( $columns ) {
98
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_products_admin_list_custom_columns_total_number', 1 ) );
99
- for ( $i = 1; $i <= $total_number; $i++ ) {
100
- if ( 'yes' === wcj_get_option( 'wcj_products_admin_list_custom_columns_enabled_' . $i, 'no' ) ) {
101
- $columns[ 'wcj_products_custom_column_' . $i ] = wcj_get_option( 'wcj_products_admin_list_custom_columns_label_' . $i, '' );
 
 
102
  }
 
103
  }
104
- return $columns;
105
- }
106
 
107
- /**
108
- * render_product_column.
109
- *
110
- * @version 2.9.0
111
- * @since 2.9.0
112
- */
113
- function render_product_column( $column ) {
114
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_products_admin_list_custom_columns_total_number', 1 ) );
115
- for ( $i = 1; $i <= $total_number; $i++ ) {
116
- if ( 'yes' === wcj_get_option( 'wcj_products_admin_list_custom_columns_enabled_' . $i, 'no' ) ) {
117
- if ( 'wcj_products_custom_column_' . $i === $column ) {
118
- echo do_shortcode( wcj_get_option( 'wcj_products_admin_list_custom_columns_value_' . $i, '' ) );
 
 
119
  }
120
  }
121
  }
122
- }
123
 
124
- }
125
 
126
  endif;
127
 
5
  * @version 5.2.0
6
  * @since 3.2.4
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Admin_Products_List' ) ) :
16
 
 
 
17
  /**
18
+ * WCJ_Admin_Products_List.
19
  *
20
+ * @version 2.7.0
 
21
  */
22
+ class WCJ_Admin_Products_List extends WCJ_Module {
23
 
24
+ /**
25
+ * Constructor.
26
+ *
27
+ * @version 5.2.0
28
+ * @since 3.2.4
29
+ */
30
+ public function __construct() {
31
 
32
+ $this->id = 'admin_products_list';
33
+ $this->short_desc = __( 'Admin Products List', 'woocommerce-jetpack' );
34
+ $this->desc = __( 'Customize admin products list (1 custom column allowed in free).', 'woocommerce-jetpack' );
35
+ $this->desc_pro = __( 'Customize admin products list.', 'woocommerce-jetpack' );
36
+ $this->link_slug = 'woocommerce-admin-products-list';
37
+ parent::__construct();
38
 
39
+ if ( $this->is_enabled() ) {
40
+ // Admin list - custom columns.
41
+ if ( 'yes' === wcj_get_option( 'wcj_products_admin_list_custom_columns_enabled', 'no' ) ) {
42
+ add_filter( 'manage_edit-product_columns', array( $this, 'add_product_columns' ), PHP_INT_MAX );
43
+ add_action( 'manage_product_posts_custom_column', array( $this, 'render_product_column' ), PHP_INT_MAX );
44
+ }
45
+
46
+ // Admin list - columns order.
47
+ if ( 'yes' === wcj_get_option( 'wcj_products_admin_list_columns_order_enabled', 'no' ) ) {
48
+ add_filter( 'manage_edit-product_columns', array( $this, 'rearange_product_columns' ), PHP_INT_MAX );
49
+ }
50
  }
51
  }
 
52
 
53
+ /**
54
+ * Rearange_product_columns.
55
+ *
56
+ * @version 2.9.0
57
+ * @since 2.9.0
58
+ * @param string $columns defines the columns.
59
+ */
60
+ public function rearange_product_columns( $columns ) {
61
+ $reordered_columns = wcj_get_option( 'wcj_products_admin_list_columns_order', $this->get_products_default_columns_in_order() );
62
+ $reordered_columns = explode( PHP_EOL, $reordered_columns );
63
+ $reordered_columns_result = array();
64
+ if ( ! empty( $reordered_columns ) ) {
65
+ foreach ( $reordered_columns as $column_id ) {
66
+ $column_id = str_replace( "\n", '', $column_id );
67
+ $column_id = str_replace( "\r", '', $column_id );
68
+ if ( '' !== $column_id && isset( $columns[ $column_id ] ) ) {
69
+ $reordered_columns_result[ $column_id ] = $columns[ $column_id ];
70
+ unset( $columns[ $column_id ] );
71
+ }
72
  }
73
  }
74
+ return array_merge( $reordered_columns_result, $columns );
75
  }
 
 
76
 
77
+ /**
78
+ * Get_products_default_columns_in_order.
79
+ *
80
+ * @version 2.9.0
81
+ * @since 2.9.0
82
+ */
83
+ public function get_products_default_columns_in_order() {
84
+ $columns = array(
85
+ 'cb',
86
+ 'thumb',
87
+ 'name',
88
+ 'sku',
89
+ 'is_in_stock',
90
+ 'price',
91
+ 'product_cat',
92
+ 'product_tag',
93
+ 'featured',
94
+ 'product_type',
95
+ 'date',
96
+ );
97
+ return implode( PHP_EOL, $columns );
98
+ }
99
 
100
+ /**
101
+ * Add_product_columns.
102
+ *
103
+ * @version 2.9.0
104
+ * @since 2.9.0
105
+ * @param string $columns defines the columns.
106
+ */
107
+ public function add_product_columns( $columns ) {
108
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_products_admin_list_custom_columns_total_number', 1 ) );
109
+ for ( $i = 1; $i <= $total_number; $i++ ) {
110
+ if ( 'yes' === wcj_get_option( 'wcj_products_admin_list_custom_columns_enabled_' . $i, 'no' ) ) {
111
+ $columns[ 'wcj_products_custom_column_' . $i ] = wcj_get_option( 'wcj_products_admin_list_custom_columns_label_' . $i, '' );
112
+ }
113
  }
114
+ return $columns;
115
  }
 
 
116
 
117
+ /**
118
+ * Render_product_column.
119
+ *
120
+ * @version 2.9.0
121
+ * @since 2.9.0
122
+ * @param string $column defines the column.
123
+ */
124
+ public function render_product_column( $column ) {
125
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_products_admin_list_custom_columns_total_number', 1 ) );
126
+ for ( $i = 1; $i <= $total_number; $i++ ) {
127
+ if ( 'yes' === wcj_get_option( 'wcj_products_admin_list_custom_columns_enabled_' . $i, 'no' ) ) {
128
+ if ( 'wcj_products_custom_column_' . $i === $column ) {
129
+ echo do_shortcode( wcj_get_option( 'wcj_products_admin_list_custom_columns_value_' . $i, '' ) );
130
+ }
131
  }
132
  }
133
  }
 
134
 
135
+ }
136
 
137
  endif;
138
 
includes/class-wcj-admin-tools.php CHANGED
@@ -4,335 +4,368 @@
4
  *
5
  * @version 5.5.6
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Admin_Tools' ) ) :
12
 
13
- class WCJ_Admin_Tools extends WCJ_Module {
14
-
15
  /**
16
- * Constructor.
17
  *
18
- * @version 5.2.0
19
- * @todo [feature] (maybe) add editable (product and order) metas
20
  */
21
- function __construct() {
22
-
23
- $this->id = 'admin_tools';
24
- $this->short_desc = __( 'Admin Tools', 'woocommerce-jetpack' );
25
- $this->desc = __( 'Booster for WooCommerce general back-end tools. Enable interface by user roles (Plus). Custom shop manager editable roles (Plus).', 'woocommerce-jetpack' );
26
- $this->desc_pro = __( 'Booster for WooCommerce general back-end tools.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-booster-admin-tools';
28
- parent::__construct();
29
-
30
- $this->add_tools( array(
31
- 'products_atts' => array(
32
- 'title' => __( 'Products Attributes', 'woocommerce-jetpack' ),
33
- 'desc' => __( 'All Products and All Attributes.', 'woocommerce-jetpack' ),
34
- ),
35
- ) );
36
-
37
- if ( $this->is_enabled() ) {
38
- // Order Meta
39
- if ( 'yes' === wcj_get_option( 'wcj_admin_tools_show_order_meta_enabled', 'no' ) ) {
40
- add_action( 'add_meta_boxes', array( $this, 'add_order_meta_meta_box' ) );
41
- }
42
- // Product Meta
43
- if ( 'yes' === wcj_get_option( 'wcj_admin_tools_show_product_meta_enabled', 'no' ) ) {
44
- add_action( 'add_meta_boxes', array( $this, 'add_product_meta_meta_box' ) );
45
- }
46
- // Variable Product Pricing
47
- if ( 'yes' === wcj_get_option( 'wcj_admin_tools_variable_product_pricing_table_enabled', 'no' ) ) {
48
- add_action( 'admin_head', array( $this, 'make_original_variable_product_pricing_readonly' ) );
49
- add_action( 'add_meta_boxes', array( $this, 'maybe_add_variable_product_pricing_meta_box' ) );
50
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
51
- }
52
- // Product revisions
53
- if ( 'yes' === wcj_get_option( 'wcj_product_revisions_enabled', 'no' ) ) {
54
- add_filter( 'woocommerce_register_post_type_product', array( $this, 'enable_product_revisions' ) );
55
- }
56
- // Admin Notices
57
- if ( 'yes' === wcj_get_option( 'wcj_admin_tools_suppress_connect_notice', 'no' ) ) {
58
- add_filter( 'woocommerce_helper_suppress_connect_notice', '__return_true' );
59
- }
60
- if ( 'yes' === wcj_get_option( 'wcj_admin_tools_suppress_admin_notices', 'no' ) ) {
61
- add_filter( 'woocommerce_helper_suppress_admin_notices', '__return_true' );
62
- }
63
- // JSON product search limit
64
- if ( 0 != wcj_get_option( 'wcj_product_json_search_limit', 0 ) ) {
65
- add_filter( 'woocommerce_json_search_limit', array( $this, 'set_json_search_limit' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
- // Enable interface by user role
68
- add_filter( 'wcj_can_create_admin_interface', array( $this, 'enable_interface_by_user_roles' ) );
69
- // Shop Manager Editable Roles
70
- add_filter( 'woocommerce_shop_manager_editable_roles', array( $this, 'change_shop_manager_editable_roles' ) );
71
  }
72
- }
73
 
74
- /**
75
- * change_shop_manager_editable_roles.
76
- *
77
- * @see wc_modify_editable_roles()
78
- *
79
- * @version 4.9.0
80
- * @since 4.9.0
81
- *
82
- * @param $roles
83
- *
84
- * @return mixed
85
- */
86
- function change_shop_manager_editable_roles( $roles ) {
87
- remove_filter( 'woocommerce_shop_manager_editable_roles', array( $this, 'change_shop_manager_editable_roles' ) );
88
- $roles = wcj_get_option( 'wcj_admin_tools_shop_manager_editable_roles', apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ) );
89
- return $roles;
90
- }
91
-
92
- /**
93
- * enable_interface_by_user_roles.
94
- *
95
- * @version 4.8.0
96
- * @since 4.8.0
97
- *
98
- * @param $allowed
99
- *
100
- * @return bool
101
- */
102
- function enable_interface_by_user_roles( $allowed ) {
103
- if ( empty( $disabled_roles = wcj_get_option( 'wcj_admin_tools_enable_interface_by_role', array() ) ) ) {
104
- return $allowed;
105
  }
106
- $current_user_roles = wcj_get_current_user_all_roles();
107
- if (
108
- ! in_array( 'administrator', $current_user_roles ) &&
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  ! array_intersect( $disabled_roles, $current_user_roles )
110
- ) {
111
- $allowed = false;
 
 
112
  }
113
- return $allowed;
114
- }
115
 
116
- /**
117
- * set_json_search_limit.
118
- *
119
- * @version 4.1.0
120
- * @since 4.1.0
121
- */
122
- function set_json_search_limit( $limit ) {
123
- return wcj_get_option( 'wcj_product_json_search_limit', 0 );
124
- }
 
125
 
126
- /**
127
- * enable_product_revisions.
128
- *
129
- * @version 2.4.0
130
- * @since 2.4.0
131
- */
132
- function enable_product_revisions( $args ) {
133
- $args['supports'][] = 'revisions';
134
- return $args;
135
- }
 
136
 
137
- /**
138
- * make_original_variable_product_pricing_readonly.
139
- *
140
- * @version 3.3.0
141
- * @since 3.3.0
142
- * @todo [fix] this is not really making fields readonly (e.g. field is still editable via keyboard tab button)
143
- */
144
- function make_original_variable_product_pricing_readonly() {
145
- echo '<style>
146
  div.variable_pricing input.wc_input_price {
147
  pointer-events: none;
148
  }
149
  </style>';
150
- }
151
-
152
- /**
153
- * maybe_add_variable_product_pricing_meta_box.
154
- *
155
- * @version 3.3.0
156
- * @since 3.3.0
157
- */
158
- function maybe_add_variable_product_pricing_meta_box() {
159
- if ( ( $_product = wc_get_product() ) && $_product->is_type( 'variable' ) ) {
160
- parent::add_meta_box();
161
  }
162
- }
163
 
164
- /**
165
- * add_product_meta_meta_box.
166
- *
167
- * @version 2.5.8
168
- * @since 2.5.8
169
- */
170
- function add_product_meta_meta_box() {
171
- add_meta_box(
172
- 'wcj-admin-tools-product-meta',
173
- __( 'Product Meta', 'woocommerce-jetpack' ),
174
- array( $this, 'create_meta_meta_box' ),
175
- 'product',
176
- 'normal',
177
- 'low'
178
- );
179
- }
180
 
181
- /**
182
- * add_order_meta_meta_box.
183
- *
184
- * @version 2.5.8
185
- * @since 2.5.8
186
- */
187
- function add_order_meta_meta_box() {
188
- add_meta_box(
189
- 'wcj-admin-tools-order-meta',
190
- __( 'Order Meta', 'woocommerce-jetpack' ),
191
- array( $this, 'create_meta_meta_box' ),
192
- 'shop_order',
193
- 'normal',
194
- 'low'
195
- );
196
- }
197
 
198
- /**
199
- * create_meta_meta_box.
200
- *
201
- * @version 3.2.1
202
- * @since 2.5.8
203
- */
204
- function create_meta_meta_box( $post ) {
205
- $html = '';
206
- $post_id = get_the_ID();
207
- // Meta
208
- $meta = get_post_meta( $post_id );
209
- $table_data = array();
210
- foreach ( $meta as $meta_key => $meta_values ) {
211
- $table_data[] = array( $meta_key, esc_html( print_r( maybe_unserialize( $meta_values[0] ), true ) ) );
 
212
  }
213
- $html .= wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
214
- // Items Meta (for orders only)
215
- if ( 'shop_order' === $post->post_type ) {
216
- $_order = wc_get_order( $post_id );
 
 
 
 
 
 
 
 
 
217
  $table_data = array();
218
- foreach ( $_order->get_items() as $item_key => $item ) {
219
- foreach ( $item['item_meta'] as $item_meta_key => $item_meta_value ) {
220
- $table_data[] = array( $item_key, $item_meta_key, esc_html( print_r( maybe_unserialize( $item_meta_value ), true ) ) );
221
- }
222
  }
223
- if ( ! empty( $table_data ) ) {
224
- $html .= '<h3>' . __( 'Order Items Meta', 'woocommerce-jetpack' ) . '</h3>';
225
- $table_data = array_merge(
226
- array( array( __( 'Item Key', 'woocommerce-jetpack' ), __( 'Item Meta Key', 'woocommerce-jetpack' ), __( 'Item Meta Value', 'woocommerce-jetpack' ) ) ),
227
- $table_data
228
- );
229
- $html .= wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
  }
 
 
231
  }
232
- // Output
233
- echo $html;
234
- }
235
 
236
- /**
237
- * create_products_atts_tool.
238
- *
239
- * @version 2.3.9
240
- * @since 2.3.9
241
- */
242
- function create_products_atts_tool() {
243
- $html = '';
244
- $html .= '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
245
- $html .= $this->get_products_atts();
246
- $html .= '</div>';
247
- echo $html;
248
- }
249
 
250
- /*
251
- * get_products_atts.
252
- *
253
- * @version 4.0.0
254
- * @since 2.3.9
255
- * @todo [dev] rewrite; add module link;
256
- */
257
- function get_products_atts() {
258
-
259
- $total_products = 0;
260
-
261
- $products_attributes = array();
262
- $attributes_names = array();
263
- $attributes_names['wcj_title'] = __( 'Product', 'woocommerce-jetpack' );
264
- $attributes_names['wcj_category'] = __( 'Category', 'woocommerce-jetpack' );
265
-
266
- $offset = 0;
267
- $block_size = 96;
268
- while( true ) {
269
-
270
- $args_products = array(
271
- 'post_type' => 'product',
272
- 'post_status' => 'publish',
273
- 'posts_per_page' => $block_size,
274
- 'orderby' => 'title',
275
- 'order' => 'ASC',
276
- 'offset' => $offset,
277
- );
278
- $loop_products = new WP_Query( $args_products );
279
- if ( ! $loop_products->have_posts() ) break;
280
- while ( $loop_products->have_posts() ) : $loop_products->the_post();
 
 
 
281
 
282
- $total_products++;
283
- $product_id = $loop_products->post->ID;
284
- $the_product = wc_get_product( $product_id );
285
 
286
- $products_attributes[ $product_id ]['wcj_title'] = '<a href="' . get_permalink( $product_id ) . '">' . $the_product->get_title() . '</a>';
287
- $products_attributes[ $product_id ]['wcj_category'] = ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_product->get_categories() : wc_get_product_category_list( $product_id ) );
288
 
289
- foreach ( $the_product->get_attributes() as $attribute ) {
290
- $products_attributes[ $product_id ][ $attribute['name'] ] = $the_product->get_attribute( $attribute['name'] );
291
- if ( ! isset( $attributes_names[ $attribute['name'] ] ) ) {
292
- $attributes_names[ $attribute['name'] ] = wc_attribute_label( $attribute['name'] );
 
293
  }
294
- }
295
 
296
- endwhile;
297
 
298
- $offset += $block_size;
299
 
300
- }
301
 
302
- $table_data = array();
303
- if ( isset( $_GET['wcj_attribute'] ) && '' != $_GET['wcj_attribute'] ) {
304
- $table_data[] = array(
305
- __( 'Product', 'woocommerce-jetpack' ),
306
- __( 'Category', 'woocommerce-jetpack' ),
307
- $_GET['wcj_attribute'],
308
- );
309
- } else {
310
- $header = $attributes_names;
311
- unset( $header['wcj_title'] );
312
- unset( $header['wcj_category'] );
313
- $table_data[] = array_merge( array(
314
- __( 'Product', 'woocommerce-jetpack' ),
315
- __( 'Category', 'woocommerce-jetpack' ),
316
- ), array_keys( $header ) );
317
- }
318
- foreach ( $attributes_names as $attributes_name => $attribute_title ) {
 
 
 
319
 
320
- if ( isset( $_GET['wcj_attribute'] ) && '' != $_GET['wcj_attribute'] ) {
321
- if ( 'wcj_title' != $attributes_name && 'wcj_category' != $attributes_name && $_GET['wcj_attribute'] != $attributes_name ) {
322
- continue;
 
323
  }
324
- }
325
 
326
- foreach ( $products_attributes as $product_id => $product_attributes ) {
327
- $table_data[ $product_id ][ $attributes_name ] = isset( $product_attributes[ $attributes_name ] ) ? $product_attributes[ $attributes_name ] : '';
 
328
  }
 
 
329
  }
330
 
331
- return '<p>' . __( 'Total Products:', 'woocommerce-jetpack' ) . ' ' . $total_products . '</p>' . wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) );
332
  }
333
 
334
- }
335
-
336
  endif;
337
 
338
  return new WCJ_Admin_Tools();
4
  *
5
  * @version 5.5.6
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Admin_Tools' ) ) :
15
 
 
 
16
  /**
17
+ * WCJ_Admin_Tools.
18
  *
19
+ * @version 2.7.0
 
20
  */
21
+ class WCJ_Admin_Tools extends WCJ_Module {
22
+
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @version 5.2.0
27
+ * @todo [feature] (maybe) add editable (product and order) metas
28
+ */
29
+ public function __construct() {
30
+
31
+ $this->id = 'admin_tools';
32
+ $this->short_desc = __( 'Admin Tools', 'woocommerce-jetpack' );
33
+ $this->desc = __( 'Booster for WooCommerce general back-end tools. Enable interface by user roles (Plus). Custom shop manager editable roles (Plus).', 'woocommerce-jetpack' );
34
+ $this->desc_pro = __( 'Booster for WooCommerce general back-end tools.', 'woocommerce-jetpack' );
35
+ $this->link_slug = 'woocommerce-booster-admin-tools';
36
+ parent::__construct();
37
+
38
+ $this->add_tools(
39
+ array(
40
+ 'products_atts' => array(
41
+ 'title' => __( 'Products Attributes', 'woocommerce-jetpack' ),
42
+ 'desc' => __( 'All Products and All Attributes.', 'woocommerce-jetpack' ),
43
+ ),
44
+ )
45
+ );
46
+
47
+ if ( $this->is_enabled() ) {
48
+ // Order Meta.
49
+ if ( 'yes' === wcj_get_option( 'wcj_admin_tools_show_order_meta_enabled', 'no' ) ) {
50
+ add_action( 'add_meta_boxes', array( $this, 'add_order_meta_meta_box' ) );
51
+ }
52
+ // Product Meta.
53
+ if ( 'yes' === wcj_get_option( 'wcj_admin_tools_show_product_meta_enabled', 'no' ) ) {
54
+ add_action( 'add_meta_boxes', array( $this, 'add_product_meta_meta_box' ) );
55
+ }
56
+ // Variable Product Pricing.
57
+ if ( 'yes' === wcj_get_option( 'wcj_admin_tools_variable_product_pricing_table_enabled', 'no' ) ) {
58
+ add_action( 'admin_head', array( $this, 'make_original_variable_product_pricing_readonly' ) );
59
+ add_action( 'add_meta_boxes', array( $this, 'maybe_add_variable_product_pricing_meta_box' ) );
60
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
61
+ }
62
+ // Product revisions.
63
+ if ( 'yes' === wcj_get_option( 'wcj_product_revisions_enabled', 'no' ) ) {
64
+ add_filter( 'woocommerce_register_post_type_product', array( $this, 'enable_product_revisions' ) );
65
+ }
66
+ // Admin Notices.
67
+ if ( 'yes' === wcj_get_option( 'wcj_admin_tools_suppress_connect_notice', 'no' ) ) {
68
+ add_filter( 'woocommerce_helper_suppress_connect_notice', '__return_true' );
69
+ }
70
+ if ( 'yes' === wcj_get_option( 'wcj_admin_tools_suppress_admin_notices', 'no' ) ) {
71
+ add_filter( 'woocommerce_helper_suppress_admin_notices', '__return_true' );
72
+ }
73
+ // JSON product search limit.
74
+ if ( 0 !== wcj_get_option( 'wcj_product_json_search_limit', 0 ) ) {
75
+ add_filter( 'woocommerce_json_search_limit', array( $this, 'set_json_search_limit' ) );
76
+ }
77
+ // Enable interface by user role.
78
+ add_filter( 'wcj_can_create_admin_interface', array( $this, 'enable_interface_by_user_roles' ) );
79
+ // Shop Manager Editable Roles.
80
+ add_filter( 'woocommerce_shop_manager_editable_roles', array( $this, 'change_shop_manager_editable_roles' ) );
81
  }
 
 
 
 
82
  }
 
83
 
84
+ /**
85
+ * Change_shop_manager_editable_roles.
86
+ *
87
+ * @see wc_modify_editable_roles()
88
+ *
89
+ * @version 4.9.0
90
+ * @since 4.9.0
91
+ *
92
+ * @param string $roles defines the roles.
93
+ *
94
+ * @return mixed
95
+ */
96
+ public function change_shop_manager_editable_roles( $roles ) {
97
+ remove_filter( 'woocommerce_shop_manager_editable_roles', array( $this, 'change_shop_manager_editable_roles' ) );
98
+ $roles = wcj_get_option( 'wcj_admin_tools_shop_manager_editable_roles', apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ) );
99
+ return $roles;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
101
+
102
+ /**
103
+ * Enable_interface_by_user_roles.
104
+ *
105
+ * @version 4.8.0
106
+ * @since 4.8.0
107
+ *
108
+ * @param string $allowed defines the allowed.
109
+ *
110
+ * @return bool
111
+ */
112
+ public function enable_interface_by_user_roles( $allowed ) {
113
+ $disabled_roles = wcj_get_option( 'wcj_admin_tools_enable_interface_by_role', array() );
114
+ if ( empty( $disabled_roles ) ) {
115
+ return $allowed;
116
+ }
117
+ $current_user_roles = wcj_get_current_user_all_roles();
118
+ if (
119
+ ! in_array( 'administrator', $current_user_roles, true ) &&
120
  ! array_intersect( $disabled_roles, $current_user_roles )
121
+ ) {
122
+ $allowed = false;
123
+ }
124
+ return $allowed;
125
  }
 
 
126
 
127
+ /**
128
+ * Set_json_search_limit.
129
+ *
130
+ * @version 4.1.0
131
+ * @since 4.1.0
132
+ * @param string $limit defines the limit.
133
+ */
134
+ public function set_json_search_limit( $limit ) {
135
+ return wcj_get_option( 'wcj_product_json_search_limit', 0 );
136
+ }
137
 
138
+ /**
139
+ * Enable_product_revisions.
140
+ *
141
+ * @version 2.4.0
142
+ * @since 2.4.0
143
+ * @param array $args defines the args.
144
+ */
145
+ public function enable_product_revisions( $args ) {
146
+ $args['supports'][] = 'revisions';
147
+ return $args;
148
+ }
149
 
150
+ /**
151
+ * Make_original_variable_product_pricing_readonly.
152
+ *
153
+ * @version 3.3.0
154
+ * @since 3.3.0
155
+ * @todo [fix] this is not really making fields readonly (e.g. field is still editable via keyboard tab button)
156
+ */
157
+ public function make_original_variable_product_pricing_readonly() {
158
+ echo '<style>
159
  div.variable_pricing input.wc_input_price {
160
  pointer-events: none;
161
  }
162
  </style>';
 
 
 
 
 
 
 
 
 
 
 
163
  }
 
164
 
165
+ /**
166
+ * Maybe_add_variable_product_pricing_meta_box.
167
+ *
168
+ * @version 3.3.0
169
+ * @since 3.3.0
170
+ */
171
+ public function maybe_add_variable_product_pricing_meta_box() {
172
+ $_product = wc_get_product();
173
+ if ( $_product && $_product->is_type( 'variable' ) ) {
174
+ parent::add_meta_box();
175
+ }
176
+ }
 
 
 
 
177
 
178
+ /**
179
+ * Add_product_meta_meta_box.
180
+ *
181
+ * @version 2.5.8
182
+ * @since 2.5.8
183
+ */
184
+ public function add_product_meta_meta_box() {
185
+ add_meta_box(
186
+ 'wcj-admin-tools-product-meta',
187
+ __( 'Product Meta', 'woocommerce-jetpack' ),
188
+ array( $this, 'create_meta_meta_box' ),
189
+ 'product',
190
+ 'normal',
191
+ 'low'
192
+ );
193
+ }
194
 
195
+ /**
196
+ * Add_order_meta_meta_box.
197
+ *
198
+ * @version 2.5.8
199
+ * @since 2.5.8
200
+ */
201
+ public function add_order_meta_meta_box() {
202
+ add_meta_box(
203
+ 'wcj-admin-tools-order-meta',
204
+ __( 'Order Meta', 'woocommerce-jetpack' ),
205
+ array( $this, 'create_meta_meta_box' ),
206
+ 'shop_order',
207
+ 'normal',
208
+ 'low'
209
+ );
210
  }
211
+
212
+ /**
213
+ * Create_meta_meta_box.
214
+ *
215
+ * @version 3.2.1
216
+ * @since 2.5.8
217
+ * @param string $post defines the post.
218
+ */
219
+ public function create_meta_meta_box( $post ) {
220
+ $html = '';
221
+ $post_id = get_the_ID();
222
+ // Meta.
223
+ $meta = get_post_meta( $post_id );
224
  $table_data = array();
225
+ foreach ( $meta as $meta_key => $meta_values ) {
226
+ $table_data[] = array( $meta_key, wp_kses_post( maybe_unserialize( $meta_values[0] ), true ) );
 
 
227
  }
228
+ $html .= wcj_get_table_html(
229
+ $table_data,
230
+ array(
231
+ 'table_class' => 'widefat striped',
232
+ 'table_heading_type' => 'vertical',
233
+ )
234
+ );
235
+ // Items Meta (for orders only).
236
+ if ( 'shop_order' === $post->post_type ) {
237
+ $_order = wc_get_order( $post_id );
238
+ $table_data = array();
239
+ foreach ( $_order->get_items() as $item_key => $item ) {
240
+ foreach ( $item['item_meta'] as $item_meta_key => $item_meta_value ) {
241
+ $table_data[] = array( $item_key, $item_meta_key, wp_kses_post( maybe_unserialize( $item_meta_value ), true ) );
242
+ }
243
+ }
244
+ if ( ! empty( $table_data ) ) {
245
+ $html .= '<h3>' . __( 'Order Items Meta', 'woocommerce-jetpack' ) . '</h3>';
246
+ $table_data = array_merge(
247
+ array( array( __( 'Item Key', 'woocommerce-jetpack' ), __( 'Item Meta Key', 'woocommerce-jetpack' ), __( 'Item Meta Value', 'woocommerce-jetpack' ) ) ),
248
+ $table_data
249
+ );
250
+ $html .= wcj_get_table_html(
251
+ $table_data,
252
+ array(
253
+ 'table_class' => 'widefat striped',
254
+ 'table_heading_type' => 'horizontal',
255
+ )
256
+ );
257
+ }
258
  }
259
+ // Output.
260
+ echo $html;
261
  }
 
 
 
262
 
263
+ /**
264
+ * Create_products_atts_tool.
265
+ *
266
+ * @version 2.3.9
267
+ * @since 2.3.9
268
+ */
269
+ public function create_products_atts_tool() {
270
+ $html = '';
271
+ $html .= '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
272
+ $html .= $this->get_products_atts();
273
+ $html .= '</div>';
274
+ echo wp_kses_post( $html );
275
+ }
276
 
277
+ /**
278
+ * Get_products_atts.
279
+ *
280
+ * @version 4.0.0
281
+ * @since 2.3.9
282
+ * @todo [dev] rewrite; add module link;
283
+ */
284
+ public function get_products_atts() {
285
+
286
+ $total_products = 0;
287
+
288
+ $products_attributes = array();
289
+ $attributes_names = array();
290
+ $attributes_names['wcj_title'] = __( 'Product', 'woocommerce-jetpack' );
291
+ $attributes_names['wcj_category'] = __( 'Category', 'woocommerce-jetpack' );
292
+
293
+ $offset = 0;
294
+ $block_size = 96;
295
+ while ( true ) {
296
+
297
+ $args_products = array(
298
+ 'post_type' => 'product',
299
+ 'post_status' => 'publish',
300
+ 'posts_per_page' => $block_size,
301
+ 'orderby' => 'title',
302
+ 'order' => 'ASC',
303
+ 'offset' => $offset,
304
+ );
305
+ $loop_products = new WP_Query( $args_products );
306
+ if ( ! $loop_products->have_posts() ) {
307
+ break;
308
+ }
309
+ while ( $loop_products->have_posts() ) :
310
+ $loop_products->the_post();
311
 
312
+ $total_products++;
313
+ $product_id = $loop_products->post->ID;
314
+ $the_product = wc_get_product( $product_id );
315
 
316
+ $products_attributes[ $product_id ]['wcj_title'] = '<a href="' . get_permalink( $product_id ) . '">' . $the_product->get_title() . '</a>';
317
+ $products_attributes[ $product_id ]['wcj_category'] = ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_product->get_categories() : wc_get_product_category_list( $product_id ) );
318
 
319
+ foreach ( $the_product->get_attributes() as $attribute ) {
320
+ $products_attributes[ $product_id ][ $attribute['name'] ] = $the_product->get_attribute( $attribute['name'] );
321
+ if ( ! isset( $attributes_names[ $attribute['name'] ] ) ) {
322
+ $attributes_names[ $attribute['name'] ] = wc_attribute_label( $attribute['name'] );
323
+ }
324
  }
 
325
 
326
+ endwhile;
327
 
328
+ $offset += $block_size;
329
 
330
+ }
331
 
332
+ $table_data = array();
333
+ if ( isset( $_GET['wcj_attribute'] ) && '' !== $_GET['wcj_attribute'] ) {
334
+ $table_data[] = array(
335
+ __( 'Product', 'woocommerce-jetpack' ),
336
+ __( 'Category', 'woocommerce-jetpack' ),
337
+ sanitize_text_field( wp_unslash( $_GET['wcj_attribute'] ) ),
338
+ );
339
+ } else {
340
+ $header = $attributes_names;
341
+ unset( $header['wcj_title'] );
342
+ unset( $header['wcj_category'] );
343
+ $table_data[] = array_merge(
344
+ array(
345
+ __( 'Product', 'woocommerce-jetpack' ),
346
+ __( 'Category', 'woocommerce-jetpack' ),
347
+ ),
348
+ array_keys( $header )
349
+ );
350
+ }
351
+ foreach ( $attributes_names as $attributes_name => $attribute_title ) {
352
 
353
+ if ( isset( $_GET['wcj_attribute'] ) && '' !== $_GET['wcj_attribute'] ) {
354
+ if ( 'wcj_title' !== $attributes_name && 'wcj_category' !== $attributes_name && $_GET['wcj_attribute'] !== $attributes_name ) {
355
+ continue;
356
+ }
357
  }
 
358
 
359
+ foreach ( $products_attributes as $product_id => $product_attributes ) {
360
+ $table_data[ $product_id ][ $attributes_name ] = isset( $product_attributes[ $attributes_name ] ) ? $product_attributes[ $attributes_name ] : '';
361
+ }
362
  }
363
+
364
+ return '<p>' . __( 'Total Products:', 'woocommerce-jetpack' ) . ' ' . $total_products . '</p>' . wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) );
365
  }
366
 
 
367
  }
368
 
 
 
369
  endif;
370
 
371
  return new WCJ_Admin_Tools();
includes/class-wcj-breadcrumbs.php CHANGED
@@ -5,88 +5,97 @@
5
  * @version 5.2.0
6
  * @since 2.9.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Breadcrumbs' ) ) :
13
 
14
- class WCJ_Breadcrumbs extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 5.2.0
20
- * @since 2.9.0
21
- * @todo recheck filter: `woocommerce_get_breadcrumb`
22
- * @todo recheck filter: `woocommerce_structured_data_breadcrumblist`; action: `woocommerce_breadcrumb`;
23
- * @todo recheck filter: `woocommerce_breadcrumb_defaults`; action: `woocommerce_breadcrumb`
24
  */
25
- function __construct() {
26
 
27
- $this->id = 'breadcrumbs';
28
- $this->short_desc = __( 'Breadcrumbs', 'woocommerce-jetpack' );
29
- $this->desc = __( 'Customize WooCommerce breadcrumbs. Hide breadcrumbs (Plus).', 'woocommerce-jetpack' );
30
- $this->desc_pro = __( 'Customize WooCommerce breadcrumbs.', 'woocommerce-jetpack' );
31
- $this->link_slug = 'woocommerce-breadcrumbs';
32
- parent::__construct();
 
 
 
 
33
 
34
- if ( $this->is_enabled() ) {
35
- // Hide Breadcrumbs
36
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_breadcrumbs_hide', 'no' ) ) ) {
37
- add_filter( 'woocommerce_get_breadcrumb', '__return_false', PHP_INT_MAX );
38
- add_action( 'wp_head', array( $this, 'hide_breadcrumbs_with_css' ) );
39
- add_action( 'wp_loaded', array( $this, 'hide_breadcrumbs_by_removing_action' ), PHP_INT_MAX );
40
- }
41
- // Home URL
42
- if ( 'yes' === wcj_get_option( 'wcj_breadcrumbs_change_home_url_enabled', 'no' ) ) {
43
- add_filter( 'woocommerce_breadcrumb_home_url', array( $this, 'change_home_url' ), PHP_INT_MAX );
 
 
 
 
 
 
 
 
44
  }
45
  }
46
- }
47
 
48
- /**
49
- * change_home_url.
50
- *
51
- * @version 2.9.0
52
- * @since 2.9.0
53
- */
54
- function change_home_url( $_url ) {
55
- return wcj_get_option( 'wcj_breadcrumbs_home_url', home_url() );
56
- }
 
57
 
58
- /**
59
- * hide_breadcrumbs_with_css.
60
- *
61
- * @version 3.2.2
62
- * @since 2.9.0
63
- * @todo (maybe) option to add custom identifiers
64
- * @todo (maybe) add more identifiers
65
- */
66
- function hide_breadcrumbs_with_css() {
67
- $identifiers = array(
68
- '.woocommerce-breadcrumb',
69
- '.woo-breadcrumbs',
70
- '.breadcrumbs',
71
- '.breadcrumb',
72
- '#breadcrumbs',
73
- '.breadcrumbs-wrapper',
74
- );
75
- echo '<style>' . implode( ', ', $identifiers ) . ' { display: none !important; }' . '</style>';
76
- }
77
 
78
- /**
79
- * hide_breadcrumbs_by_removing_action.
80
- *
81
- * @version 2.9.0
82
- * @since 2.9.0
83
- * @see `add_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0 );`
84
- */
85
- function hide_breadcrumbs_by_removing_action() {
86
- remove_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20 );
87
- }
88
 
89
- }
90
 
91
  endif;
92
 
5
  * @version 5.2.0
6
  * @since 2.9.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Breadcrumbs' ) ) :
16
 
 
 
17
  /**
18
+ * WCJ_Breadcrumbs.
19
  *
20
+ * @version 2.7.0
 
 
 
 
21
  */
22
+ class WCJ_Breadcrumbs extends WCJ_Module {
23
 
24
+ /**
25
+ * Constructor.
26
+ *
27
+ * @version 5.2.0
28
+ * @since 2.9.0
29
+ * @todo recheck filter: `woocommerce_get_breadcrumb`
30
+ * @todo recheck filter: `woocommerce_structured_data_breadcrumblist`; action: `woocommerce_breadcrumb`;
31
+ * @todo recheck filter: `woocommerce_breadcrumb_defaults`; action: `woocommerce_breadcrumb`
32
+ */
33
+ public function __construct() {
34
 
35
+ $this->id = 'breadcrumbs';
36
+ $this->short_desc = __( 'Breadcrumbs', 'woocommerce-jetpack' );
37
+ $this->desc = __( 'Customize WooCommerce breadcrumbs. Hide breadcrumbs (Plus).', 'woocommerce-jetpack' );
38
+ $this->desc_pro = __( 'Customize WooCommerce breadcrumbs.', 'woocommerce-jetpack' );
39
+ $this->link_slug = 'woocommerce-breadcrumbs';
40
+ parent::__construct();
41
+
42
+ if ( $this->is_enabled() ) {
43
+ // Hide Breadcrumbs.
44
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_breadcrumbs_hide', 'no' ) ) ) {
45
+ add_filter( 'woocommerce_get_breadcrumb', '__return_false', PHP_INT_MAX );
46
+ add_action( 'wp_head', array( $this, 'hide_breadcrumbs_with_css' ) );
47
+ add_action( 'wp_loaded', array( $this, 'hide_breadcrumbs_by_removing_action' ), PHP_INT_MAX );
48
+ }
49
+ // Home URL.
50
+ if ( 'yes' === wcj_get_option( 'wcj_breadcrumbs_change_home_url_enabled', 'no' ) ) {
51
+ add_filter( 'woocommerce_breadcrumb_home_url', array( $this, 'change_home_url' ), PHP_INT_MAX );
52
+ }
53
  }
54
  }
 
55
 
56
+ /**
57
+ * Change_home_url.
58
+ *
59
+ * @version 2.9.0
60
+ * @since 2.9.0
61
+ * @param string $_url defines the url.
62
+ */
63
+ public function change_home_url( $_url ) {
64
+ return wcj_get_option( 'wcj_breadcrumbs_home_url', home_url() );
65
+ }
66
 
67
+ /**
68
+ * Hide_breadcrumbs_with_css.
69
+ *
70
+ * @version 3.2.2
71
+ * @since 2.9.0
72
+ * @todo (maybe) option to add custom identifiers
73
+ * @todo (maybe) add more identifiers
74
+ */
75
+ public function hide_breadcrumbs_with_css() {
76
+ $identifiers = array(
77
+ '.woocommerce-breadcrumb',
78
+ '.woo-breadcrumbs',
79
+ '.breadcrumbs',
80
+ '.breadcrumb',
81
+ '#breadcrumbs',
82
+ '.breadcrumbs-wrapper',
83
+ );
84
+ echo '<style>' . esc_html( implode( ', ', $identifiers ) ) . ' { display: none !important; }</style>';
85
+ }
86
 
87
+ /**
88
+ * Hide_breadcrumbs_by_removing_action.
89
+ *
90
+ * @version 2.9.0
91
+ * @since 2.9.0
92
+ * @see `add_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0 );`
93
+ */
94
+ public function hide_breadcrumbs_by_removing_action() {
95
+ remove_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20 );
96
+ }
97
 
98
+ }
99
 
100
  endif;
101
 
includes/class-wcj-call-for-price.php CHANGED
@@ -4,171 +4,195 @@
4
  *
5
  * @version 5.2.0
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Call_For_Price' ) ) :
12
 
13
- class WCJ_Call_For_Price extends WCJ_module {
14
-
15
  /**
16
- * Constructor.
17
  *
18
- * @version 5.2.0
19
- * @todo add "per product type" labels
20
- * @todo add "per product" labels
21
  */
22
- function __construct() {
23
-
24
- $this->id = 'call_for_price';
25
- $this->short_desc = __( 'Call for Price', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Create any custom price label for all products with empty price (Plus).', 'woocommerce-jetpack' );
27
- $this->desc_pro = __( 'Create any custom price label for all products with empty price.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-call-for-price';
29
- parent::__construct();
30
-
31
- if ( $this->is_enabled() ) {
32
- add_filter( 'woocommerce_get_variation_prices_hash', array( $this, 'get_variation_prices_hash' ), PHP_INT_MAX, 3 );
33
- add_action( 'init', array( $this, 'add_empty_price_hooks' ), PHP_INT_MAX );
34
- add_filter( 'woocommerce_sale_flash', array( $this, 'hide_sales_flash' ), PHP_INT_MAX, 3 );
35
- add_action( 'admin_head', array( $this, 'hide_variation_price_required_placeholder' ), PHP_INT_MAX );
36
- add_filter( 'woocommerce_variation_is_visible', array( $this, 'make_variation_visible_with_empty_price' ), PHP_INT_MAX, 4 );
37
- add_action( 'wp_head', array( $this, 'hide_disabled_variation_add_to_cart_button' ) );
38
- if ( 'yes' === wcj_get_option( 'wcj_call_for_price_make_all_empty', 'no' ) ) {
39
- add_filter( WCJ_PRODUCT_GET_PRICE_FILTER, array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
40
- add_filter( 'woocommerce_variation_prices_price', array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
41
- if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
42
- add_filter( 'woocommerce_product_variation_get_price', array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
 
 
 
 
 
 
 
 
 
 
43
  }
44
  }
45
  }
46
- }
47
 
48
- /**
49
- * get_variation_prices_hash.
50
- *
51
- * @version 3.2.4
52
- * @since 3.2.4
53
- * @todo not sure if this is really needed
54
- */
55
- function get_variation_prices_hash( $price_hash, $_product, $display ) {
56
- $price_hash['wcj_call_for_price'] = array(
57
- get_option( 'wcj_call_for_price_make_all_empty', 'no' ),
58
- );
59
- return $price_hash;
60
- }
 
 
 
61
 
62
- /**
63
- * make_variation_visible_with_empty_price.
64
- *
65
- * @version 3.2.4
66
- * @since 3.2.4
67
- * @return bool
68
- */
69
- function make_variation_visible_with_empty_price( $visible, $_variation_id, $_id, $_product ) {
70
- if ( '' === $_product->get_price() ) {
71
- $visible = true;
72
- // Published == enabled checkbox
73
- if ( get_post_status( $_variation_id ) != 'publish' ) {
74
- $visible = false;
 
 
 
 
 
 
 
75
  }
 
76
  }
77
- return $visible;
78
- }
79
 
80
- /**
81
- * hide_disabled_variation_add_to_cart_button.
82
- *
83
- * @version 3.2.4
84
- * @since 3.2.4
85
- */
86
- function hide_disabled_variation_add_to_cart_button() {
87
- echo '<style>div.woocommerce-variation-add-to-cart-disabled { display: none ! important; }</style>';
88
- }
89
 
90
- /**
91
- * hide_variation_price_required_placeholder.
92
- *
93
- * @version 3.2.4
94
- * @since 3.2.4
95
- */
96
- function hide_variation_price_required_placeholder() {
97
- echo '<style>
98
- div.variable_pricing input.wc_input_price::-webkit-input-placeholder { /* WebKit browsers */
99
- color: transparent;
100
- }
101
- div.variable_pricing input.wc_input_price:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
102
- color: transparent;
103
- }
104
- div.variable_pricing input.wc_input_price::-moz-placeholder { /* Mozilla Firefox 19+ */
105
- color: transparent;
106
- }
107
- div.variable_pricing input.wc_input_price:-ms-input-placeholder { /* Internet Explorer 10+ */
108
- color: transparent;
109
- }
110
- </style>';
111
- }
112
 
113
- /**
114
- * make_empty_price.
115
- *
116
- * @version 3.2.4
117
- * @since 2.5.7
118
- */
119
- function make_empty_price( $price, $_product ) {
120
- return '';
121
- }
 
 
122
 
123
- /**
124
- * add_empty_price_hooks.
125
- *
126
- * @version 3.2.4
127
- */
128
- function add_empty_price_hooks() {
129
- add_filter( 'woocommerce_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
130
- add_filter( 'woocommerce_variable_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
131
- add_filter( 'woocommerce_grouped_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
132
- add_filter( 'woocommerce_variation_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 ); // Only in < WC3
133
- }
134
 
135
- /**
136
- * Hide "sales" icon for empty price products.
137
- *
138
- * @version 3.2.4
139
- * @todo recheck if we really need this
140
- */
141
- function hide_sales_flash( $onsale_html, $post, $product ) {
142
- if ( 'yes' === wcj_get_option( 'wcj_call_for_price_hide_sale_sign', 'yes' ) && '' === $product->get_price() ) {
143
- return '';
 
 
 
 
 
144
  }
145
- return $onsale_html;
146
- }
147
 
148
- /**
149
- * On empty price filter - return the label.
150
- *
151
- * @version 3.2.4
152
- * @todo `is_page()`
153
- */
154
- function on_empty_price( $price, $_product ) {
155
- if ( '' !== wcj_get_option( 'wcj_call_for_price_text_variation' ) && $_product->is_type( 'variation' ) ) {
156
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text_variation' ) ) );
157
- } elseif ( '' !== wcj_get_option( 'wcj_call_for_price_text' ) && is_single( get_the_ID() ) ) {
158
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text' ) ) );
159
- } elseif ( '' !== wcj_get_option( 'wcj_call_for_price_text_on_related' ) && is_single() && ! is_single( get_the_ID() ) ) {
160
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text_on_related' ) ) );
161
- } elseif ( '' !== wcj_get_option( 'wcj_call_for_price_text_on_archive' ) && is_archive() ) {
162
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text_on_archive' ) ) );
163
- } elseif ( '' !== wcj_get_option( 'wcj_call_for_price_text_on_home' ) && is_front_page() ) {
164
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text_on_home' ) ) );
165
- } else {
166
- return $price;
 
 
 
167
  }
168
- }
169
 
170
- }
171
 
172
- endif;
173
 
174
- return new WCJ_Call_For_Price();
4
  *
5
  * @version 5.2.0
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Call_For_Price' ) ) :
15
 
 
 
16
  /**
17
+ * WCJ_Call_For_Price.
18
  *
19
+ * @version 2.7.0
 
 
20
  */
21
+ class WCJ_Call_For_Price extends WCJ_module {
22
+
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @version 5.2.0
27
+ * @todo add "per product type" labels
28
+ * @todo add "per product" labels
29
+ */
30
+ public function __construct() {
31
+
32
+ $this->id = 'call_for_price';
33
+ $this->short_desc = __( 'Call for Price', 'woocommerce-jetpack' );
34
+ $this->desc = __( 'Create any custom price label for all products with empty price (Plus).', 'woocommerce-jetpack' );
35
+ $this->desc_pro = __( 'Create any custom price label for all products with empty price.', 'woocommerce-jetpack' );
36
+ $this->link_slug = 'woocommerce-call-for-price';
37
+ parent::__construct();
38
+
39
+ if ( $this->is_enabled() ) {
40
+ add_filter( 'woocommerce_get_variation_prices_hash', array( $this, 'get_variation_prices_hash' ), PHP_INT_MAX, 3 );
41
+ add_action( 'init', array( $this, 'add_empty_price_hooks' ), PHP_INT_MAX );
42
+ add_filter( 'woocommerce_sale_flash', array( $this, 'hide_sales_flash' ), PHP_INT_MAX, 3 );
43
+ add_action( 'admin_head', array( $this, 'hide_variation_price_required_placeholder' ), PHP_INT_MAX );
44
+ add_filter( 'woocommerce_variation_is_visible', array( $this, 'make_variation_visible_with_empty_price' ), PHP_INT_MAX, 4 );
45
+ add_action( 'wp_head', array( $this, 'hide_disabled_variation_add_to_cart_button' ) );
46
+ if ( 'yes' === wcj_get_option( 'wcj_call_for_price_make_all_empty', 'no' ) ) {
47
+ add_filter( WCJ_PRODUCT_GET_PRICE_FILTER, array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
48
+ add_filter( 'woocommerce_variation_prices_price', array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
49
+ if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
50
+ add_filter( 'woocommerce_product_variation_get_price', array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
51
+ }
52
  }
53
  }
54
  }
 
55
 
56
+ /**
57
+ * Get_variation_prices_hash.
58
+ *
59
+ * @version 3.2.4
60
+ * @since 3.2.4
61
+ * @todo not sure if this is really needed
62
+ * @param array $price_hash defines the price hash.
63
+ * @param string $_product defines the product.
64
+ * @param string $display defines the display.
65
+ */
66
+ public function get_variation_prices_hash( $price_hash, $_product, $display ) {
67
+ $price_hash['wcj_call_for_price'] = array(
68
+ get_option( 'wcj_call_for_price_make_all_empty', 'no' ),
69
+ );
70
+ return $price_hash;
71
+ }
72
 
73
+ /**
74
+ * Make_variation_visible_with_empty_price.
75
+ *
76
+ * @version 3.2.4
77
+ * @since 3.2.4
78
+ *
79
+ * @param bool $visible defines the visible.
80
+ * @param string $_variation_id defines the _variation_id.
81
+ * @param string $_id defines the _id.
82
+ * @param string $_product defines the _product.
83
+ *
84
+ * @return bool
85
+ */
86
+ public function make_variation_visible_with_empty_price( $visible, $_variation_id, $_id, $_product ) {
87
+ if ( '' === $_product->get_price() ) {
88
+ $visible = true;
89
+ // Published == enabled checkbox.
90
+ if ( get_post_status( $_variation_id ) !== 'publish' ) {
91
+ $visible = false;
92
+ }
93
  }
94
+ return $visible;
95
  }
 
 
96
 
97
+ /**
98
+ * Hide_disabled_variation_add_to_cart_button.
99
+ *
100
+ * @version 3.2.4
101
+ * @since 3.2.4
102
+ */
103
+ public function hide_disabled_variation_add_to_cart_button() {
104
+ echo '<style>div.woocommerce-variation-add-to-cart-disabled { display: none ! important; }</style>';
105
+ }
106
 
107
+ /**
108
+ * Hide_variation_price_required_placeholder.
109
+ *
110
+ * @version 3.2.4
111
+ * @since 3.2.4
112
+ */
113
+ public function hide_variation_price_required_placeholder() {
114
+ echo '<style>
115
+ div.variable_pricing input.wc_input_price::-webkit-input-placeholder { /* WebKit browsers */
116
+ color: transparent;
117
+ }
118
+ div.variable_pricing input.wc_input_price:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
119
+ color: transparent;
120
+ }
121
+ div.variable_pricing input.wc_input_price::-moz-placeholder { /* Mozilla Firefox 19+ */
122
+ color: transparent;
123
+ }
124
+ div.variable_pricing input.wc_input_price:-ms-input-placeholder { /* Internet Explorer 10+ */
125
+ color: transparent;
126
+ }
127
+ </style>';
128
+ }
129
 
130
+ /**
131
+ * Make_empty_price.
132
+ *
133
+ * @version 3.2.4
134
+ * @since 2.5.7
135
+ * @param int $price defines the price.
136
+ * @param string $_product defines the _product.
137
+ */
138
+ public function make_empty_price( $price, $_product ) {
139
+ return '';
140
+ }
141
 
142
+ /**
143
+ * Add_empty_price_hooks.
144
+ *
145
+ * @version 3.2.4
146
+ */
147
+ public function add_empty_price_hooks() {
148
+ add_filter( 'woocommerce_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
149
+ add_filter( 'woocommerce_variable_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
150
+ add_filter( 'woocommerce_grouped_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
151
+ add_filter( 'woocommerce_variation_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 ); // Only in < WC3.
152
+ }
153
 
154
+ /**
155
+ * Hide "sales" icon for empty price products.
156
+ *
157
+ * @version 3.2.4
158
+ * @todo recheck if we really need this
159
+ * @param string $onsale_html defines the onsale_html.
160
+ * @param string $post defines the post.
161
+ * @param string $product defines the product.
162
+ */
163
+ public function hide_sales_flash( $onsale_html, $post, $product ) {
164
+ if ( 'yes' === wcj_get_option( 'wcj_call_for_price_hide_sale_sign', 'yes' ) && '' === $product->get_price() ) {
165
+ return '';
166
+ }
167
+ return $onsale_html;
168
  }
 
 
169
 
170
+ /**
171
+ * On empty price filter - return the label.
172
+ *
173
+ * @version 3.2.4
174
+ * @todo `is_page()`
175
+ * @param int $price defines the price.
176
+ * @param string $_product defines the _product.
177
+ */
178
+ public function on_empty_price( $price, $_product ) {
179
+ if ( '' !== wcj_get_option( 'wcj_call_for_price_text_variation' ) && $_product->is_type( 'variation' ) ) {
180
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text_variation' ) ) );
181
+ } elseif ( '' !== wcj_get_option( 'wcj_call_for_price_text' ) && is_single( get_the_ID() ) ) {
182
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text' ) ) );
183
+ } elseif ( '' !== wcj_get_option( 'wcj_call_for_price_text_on_related' ) && is_single() && ! is_single( get_the_ID() ) ) {
184
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text_on_related' ) ) );
185
+ } elseif ( '' !== wcj_get_option( 'wcj_call_for_price_text_on_archive' ) && is_archive() ) {
186
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text_on_archive' ) ) );
187
+ } elseif ( '' !== wcj_get_option( 'wcj_call_for_price_text_on_home' ) && is_front_page() ) {
188
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', wcj_get_option( 'wcj_call_for_price_text_on_home' ) ) );
189
+ } else {
190
+ return $price;
191
+ }
192
  }
 
193
 
194
+ }
195
 
196
+ endif;
197
 
198
+ return new WCJ_Call_For_Price();
includes/class-wcj-cart-customization.php CHANGED
@@ -5,114 +5,134 @@
5
  * @version 3.1.0
6
  * @since 2.7.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Cart_Customization' ) ) :
13
 
14
- class WCJ_Cart_Customization extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 3.1.0
20
- * @since 2.7.0
21
  */
22
- function __construct() {
23
 
24
- $this->id = 'cart_customization';
25
- $this->short_desc = __( 'Cart Customization', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Customize WooCommerce cart - hide coupon field; item remove link; change empty cart "Return to shop" button text.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-cart-customization';
28
- parent::__construct();
 
 
29
 
30
- if ( $this->is_enabled() ) {
31
- // Hide coupon
32
- if ( 'yes' === wcj_get_option( 'wcj_cart_hide_coupon', 'no' ) ) {
33
- add_filter( 'woocommerce_coupons_enabled', array( $this, 'hide_coupon_field_on_cart' ), PHP_INT_MAX );
34
- }
35
- // Hide item remove link
36
- if ( 'yes' === wcj_get_option( 'wcj_cart_hide_item_remove_link', 'no' ) ) {
37
- add_filter( 'woocommerce_cart_item_remove_link', '__return_empty_string', PHP_INT_MAX );
38
- }
39
- // Customize "Return to shop" button text
40
- if ( 'yes' === wcj_get_option( 'wcj_cart_customization_return_to_shop_button_enabled', 'no' ) ) {
41
- if ( 'js' === wcj_get_option( 'wcj_cart_customization_return_to_shop_button_text_method', 'js' ) ) {
42
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
43
- } else { // 'template'
44
- add_filter( 'wc_get_template', array( $this, 'replace_empty_cart_template' ), PHP_INT_MAX, 5 );
45
- add_filter( 'wcj_return_to_shop_text', array( $this, 'change_empty_cart_button_text' ), PHP_INT_MAX );
 
 
 
 
 
 
 
 
 
 
 
46
  }
47
- }
48
- // Customize "Return to shop" button link
49
- if ( 'yes' === wcj_get_option( 'wcj_cart_customization_return_to_shop_button_link_enabled', 'no' ) ) {
50
- add_action( 'woocommerce_return_to_shop_redirect', array( $this, 'change_empty_cart_return_to_shop_link' ) );
51
  }
52
  }
53
- }
54
 
55
- /**
56
- * change_empty_cart_button_text.
57
- *
58
- * @version 3.1.0
59
- * @since 3.1.0
60
- */
61
- function change_empty_cart_button_text( $text ) {
62
- return wcj_get_option( 'wcj_cart_customization_return_to_shop_button_text', __( 'Return to shop', 'woocommerce' ) );
63
- }
 
64
 
65
- /**
66
- * replace_empty_cart_template.
67
- *
68
- * @version 3.1.0
69
- * @since 3.1.0
70
- * @todo [dev] fix folder structure in `/templates`
71
- */
72
- function replace_empty_cart_template( $located, $template_name, $args, $template_path, $default_path ) {
73
- if ( 'cart/cart-empty.php' == $template_name ) {
74
- $located = untrailingslashit( realpath( plugin_dir_path( __FILE__ ) . '/..' ) ) . '/includes/templates/cart-empty.php';
 
 
 
 
 
 
 
75
  }
76
- return $located;
77
- }
78
 
79
- /**
80
- * change_empty_cart_return_to_shop_link.
81
- *
82
- * @version 3.0.1
83
- * @since 3.0.1
84
- * @todo [dev] (maybe) check if link is not empty
85
- */
86
- function change_empty_cart_return_to_shop_link( $link ) {
87
- return ( is_cart() ? wcj_get_option( 'wcj_cart_customization_return_to_shop_button_link', '' ) : $link );
88
- }
 
89
 
90
- /**
91
- * enqueue_scripts.
92
- *
93
- * @version 2.8.0
94
- * @since 2.8.0
95
- * @todo [dev] maybe check `is_cart()`
96
- */
97
- function enqueue_scripts() {
98
- wp_enqueue_script( 'wcj-cart-customization', wcj_plugin_url() . '/includes/js/wcj-cart-customization.js', array( 'jquery' ), WCJ()->version, false );
99
- wp_localize_script( 'wcj-cart-customization', 'wcj_cart_customization', array(
100
- 'return_to_shop_button_text' => wcj_get_option( 'wcj_cart_customization_return_to_shop_button_text', __( 'Return to shop', 'woocommerce' ) ),
101
- ) );
102
- }
 
 
 
 
103
 
104
- /**
105
- * hide_coupon_field_on_cart.
106
- *
107
- * @version 2.6.0
108
- * @since 2.6.0
109
- */
110
- function hide_coupon_field_on_cart( $enabled ) {
111
- return ( is_cart() ) ? false : $enabled;
112
- }
 
113
 
114
- }
115
 
116
- endif;
117
 
118
- return new WCJ_Cart_Customization();
5
  * @version 3.1.0
6
  * @since 2.7.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes.
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Cart_Customization' ) ) :
16
 
 
 
17
  /**
18
+ * WCJ_Cart_Customization.
19
  *
20
+ * @version 2.7.0
 
21
  */
22
+ class WCJ_Cart_Customization extends WCJ_Module {
23
 
24
+ /**
25
+ * Constructor.
26
+ *
27
+ * @version 3.1.0
28
+ * @since 2.7.0
29
+ */
30
+ public function __construct() {
31
 
32
+ $this->id = 'cart_customization';
33
+ $this->short_desc = __( 'Cart Customization', 'woocommerce-jetpack' );
34
+ $this->desc = __( 'Customize WooCommerce cart - hide coupon field; item remove link; change empty cart "Return to shop" button text.', 'woocommerce-jetpack' );
35
+ $this->link_slug = 'woocommerce-cart-customization';
36
+ parent::__construct();
37
+
38
+ if ( $this->is_enabled() ) {
39
+ // Hide coupon.
40
+ if ( 'yes' === wcj_get_option( 'wcj_cart_hide_coupon', 'no' ) ) {
41
+ add_filter( 'woocommerce_coupons_enabled', array( $this, 'hide_coupon_field_on_cart' ), PHP_INT_MAX );
42
+ }
43
+ // Hide item remove link.
44
+ if ( 'yes' === wcj_get_option( 'wcj_cart_hide_item_remove_link', 'no' ) ) {
45
+ add_filter( 'woocommerce_cart_item_remove_link', '__return_empty_string', PHP_INT_MAX );
46
+ }
47
+ // Customize "Return to shop" button text.
48
+ if ( 'yes' === wcj_get_option( 'wcj_cart_customization_return_to_shop_button_enabled', 'no' ) ) {
49
+ if ( 'js' === wcj_get_option( 'wcj_cart_customization_return_to_shop_button_text_method', 'js' ) ) {
50
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
51
+ } else { // 'template'
52
+ add_filter( 'wc_get_template', array( $this, 'replace_empty_cart_template' ), PHP_INT_MAX, 5 );
53
+ add_filter( 'wcj_return_to_shop_text', array( $this, 'change_empty_cart_button_text' ), PHP_INT_MAX );
54
+ }
55
+ }
56
+ // Customize "Return to shop" button link.
57
+ if ( 'yes' === wcj_get_option( 'wcj_cart_customization_return_to_shop_button_link_enabled', 'no' ) ) {
58
+ add_action( 'woocommerce_return_to_shop_redirect', array( $this, 'change_empty_cart_return_to_shop_link' ) );
59
  }
 
 
 
 
60
  }
61
  }
 
62
 
63
+ /**
64
+ * Change_empty_cart_button_text.
65
+ *
66
+ * @version 3.1.0
67
+ * @since 3.1.0
68
+ * @param string $text defines the text.
69
+ */
70
+ public function change_empty_cart_button_text( $text ) {
71
+ return wcj_get_option( 'wcj_cart_customization_return_to_shop_button_text', __( 'Return to shop', 'woocommerce' ) );
72
+ }
73
 
74
+ /**
75
+ * Replace_empty_cart_template.
76
+ *
77
+ * @version 3.1.0
78
+ * @since 3.1.0
79
+ * @todo [dev] fix folder structure in `/templates`
80
+ * @param string $located defines the located.
81
+ * @param string $template_name defines the template_name.
82
+ * @param array $args defines the args.
83
+ * @param string $template_path defines the template_path.
84
+ * @param string $default_path defines the default_path.
85
+ */
86
+ public function replace_empty_cart_template( $located, $template_name, $args, $template_path, $default_path ) {
87
+ if ( 'cart/cart-empty.php' === $template_name ) {
88
+ $located = untrailingslashit( realpath( plugin_dir_path( __FILE__ ) . '/..' ) ) . '/includes/templates/cart-empty.php';
89
+ }
90
+ return $located;
91
  }
 
 
92
 
93
+ /**
94
+ * Change_empty_cart_return_to_shop_link.
95
+ *
96
+ * @version 3.0.1
97
+ * @since 3.0.1
98
+ * @todo [dev] (maybe) check if link is not empty
99
+ * @param string $link defines the link.
100
+ */
101
+ public function change_empty_cart_return_to_shop_link( $link ) {
102
+ return ( is_cart() ? wcj_get_option( 'wcj_cart_customization_return_to_shop_button_link', '' ) : $link );
103
+ }
104
 
105
+ /**
106
+ * Enqueue_scripts.
107
+ *
108
+ * @version 2.8.0
109
+ * @since 2.8.0
110
+ * @todo [dev] maybe check `is_cart()`
111
+ */
112
+ public function enqueue_scripts() {
113
+ wp_enqueue_script( 'wcj-cart-customization', wcj_plugin_url() . '/includes/js/wcj-cart-customization.js', array( 'jquery' ), w_c_j()->version, false );
114
+ wp_localize_script(
115
+ 'wcj-cart-customization',
116
+ 'wcj_cart_customization',
117
+ array(
118
+ 'return_to_shop_button_text' => wcj_get_option( 'wcj_cart_customization_return_to_shop_button_text', __( 'Return to shop', 'woocommerce' ) ),
119
+ )
120
+ );
121
+ }
122
 
123
+ /**
124
+ * Hide_coupon_field_on_cart.
125
+ *
126
+ * @version 2.6.0
127
+ * @since 2.6.0
128
+ * @param string $enabled defines the enabled.
129
+ */
130
+ public function hide_coupon_field_on_cart( $enabled ) {
131
+ return ( is_cart() ) ? false : $enabled;
132
+ }
133
 
134
+ }
135
 
136
+ endif;
137
 
138
+ return new WCJ_Cart_Customization();
includes/class-wcj-cart.php CHANGED
@@ -4,84 +4,97 @@
4
  *
5
  * @version 5.2.0
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Cart' ) ) :
12
 
13
- class WCJ_Cart extends WCJ_Module {
14
-
15
  /**
16
- * Constructor.
17
  *
18
- * @version 5.2.0
19
  */
20
- function __construct() {
21
 
22
- $this->id = 'cart';
23
- $this->short_desc = __( 'Cart Custom Info', 'woocommerce-jetpack' );
24
- $this->desc = __( 'Add custom info to the cart page (1 cart block allowed in free version).', 'woocommerce-jetpack' );
25
- $this->desc_pro = __( 'Add custom info to the cart page.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-cart-custom-info';
27
- parent::__construct();
28
 
29
- if ( $this->is_enabled() ) {
30
- // Cart items table custom info
31
- add_filter( 'woocommerce_cart_item_name', array( $this, 'add_custom_info_to_cart_item_name' ), PHP_INT_MAX, 3 );
32
- // Cart custom info
33
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_cart_custom_info_total_number', 1 ) );
34
- for ( $i = 1; $i <= $total_number; $i++) {
35
- add_action(
36
- get_option( 'wcj_cart_custom_info_hook_' . $i, 'woocommerce_after_cart_totals' ),
37
- array( $this, 'add_cart_custom_info' ),
38
- get_option( 'wcj_cart_custom_info_priority_' . $i, 10 )
39
- );
 
 
 
 
 
 
 
 
40
  }
41
  }
42
- }
43
 
44
- /**
45
- * add_custom_info_to_cart_item_name.
46
- *
47
- * @version 3.7.0
48
- * @since 2.3.9
49
- * @todo (maybe) `wc_setup_product_data( $post );`
50
- */
51
- function add_custom_info_to_cart_item_name( $product_title, $cart_item, $cart_item_key ) {
52
- $custom_content = wcj_get_option( 'wcj_cart_custom_info_item' );
53
- if ( '' != $custom_content ) {
54
- global $post;
55
- $product_id = ( ! empty( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : $cart_item['product_id'] );
56
- $post = get_post( $product_id );
57
- setup_postdata( $post );
58
- $product_title .= do_shortcode( $custom_content );
59
- wp_reset_postdata();
 
 
 
 
 
60
  }
61
- return $product_title;
62
- }
63
 
64
- /**
65
- * add_cart_custom_info.
66
- *
67
- * @version 2.4.6
68
- */
69
- function add_cart_custom_info() {
70
- $current_filter = current_filter();
71
- $current_filter_priority = wcj_current_filter_priority();
72
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_cart_custom_info_total_number', 1 ) );
73
- for ( $i = 1; $i <= $total_number; $i++ ) {
74
- if (
75
- '' != wcj_get_option( 'wcj_cart_custom_info_content_' . $i ) &&
76
- $current_filter === wcj_get_option( 'wcj_cart_custom_info_hook_' . $i, 'woocommerce_after_cart_totals' ) &&
77
- $current_filter_priority == wcj_get_option( 'wcj_cart_custom_info_priority_' . $i, 10 )
78
- ) {
79
- echo do_shortcode( wcj_get_option( 'wcj_cart_custom_info_content_' . $i ) );
 
 
 
80
  }
81
  }
82
- }
83
 
84
- }
85
 
86
  endif;
87
 
4
  *
5
  * @version 5.2.0
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes.
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Cart' ) ) :
15
 
 
 
16
  /**
17
+ * WCJ_Cart.
18
  *
19
+ * @version 2.7.0
20
  */
21
+ class WCJ_Cart extends WCJ_Module {
22
 
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @version 5.2.0
27
+ */
28
+ public function __construct() {
29
 
30
+ $this->id = 'cart';
31
+ $this->short_desc = __( 'Cart Custom Info', 'woocommerce-jetpack' );
32
+ $this->desc = __( 'Add custom info to the cart page (1 cart block allowed in free version).', 'woocommerce-jetpack' );
33
+ $this->desc_pro = __( 'Add custom info to the cart page.', 'woocommerce-jetpack' );
34
+ $this->link_slug = 'woocommerce-cart-custom-info';
35
+ parent::__construct();
36
+
37
+ if ( $this->is_enabled() ) {
38
+ // Cart items table custom info.
39
+ add_filter( 'woocommerce_cart_item_name', array( $this, 'add_custom_info_to_cart_item_name' ), PHP_INT_MAX, 3 );
40
+ // Cart custom info.
41
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_cart_custom_info_total_number', 1 ) );
42
+ for ( $i = 1; $i <= $total_number; $i++ ) {
43
+ add_action(
44
+ get_option( 'wcj_cart_custom_info_hook_' . $i, 'woocommerce_after_cart_totals' ),
45
+ array( $this, 'add_cart_custom_info' ),
46
+ get_option( 'wcj_cart_custom_info_priority_' . $i, 10 )
47
+ );
48
+ }
49
  }
50
  }
 
51
 
52
+ /**
53
+ * Add_custom_info_to_cart_item_name.
54
+ *
55
+ * @version 3.7.0
56
+ * @since 2.3.9
57
+ * @todo (maybe) `wc_setup_product_data( $post );`
58
+ * @param string $product_title defines the product_title.
59
+ * @param string $cart_item defines the cart_item.
60
+ * @param string $cart_item_key defines the product_title.
61
+ */
62
+ public function add_custom_info_to_cart_item_name( $product_title, $cart_item, $cart_item_key ) {
63
+ $custom_content = wcj_get_option( 'wcj_cart_custom_info_item' );
64
+ if ( '' !== $custom_content ) {
65
+ global $post;
66
+ $product_id = ( ! empty( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : $cart_item['product_id'] );
67
+ $posts = get_post( $product_id );
68
+ setup_postdata( $posts );
69
+ $product_title .= do_shortcode( $custom_content );
70
+ wp_reset_postdata();
71
+ }
72
+ return $product_title;
73
  }
 
 
74
 
75
+ /**
76
+ * Add_cart_custom_info.
77
+ *
78
+ * @version 2.4.6
79
+ */
80
+ public function add_cart_custom_info() {
81
+ $current_filter = current_filter();
82
+ $current_filter_priority = wcj_current_filter_priority();
83
+ settype( $current_filter_priority, 'string' );
84
+
85
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_cart_custom_info_total_number', 1 ) );
86
+ for ( $i = 1; $i <= $total_number; $i++ ) {
87
+ if (
88
+ '' !== wcj_get_option( 'wcj_cart_custom_info_content_' . $i ) &&
89
+ wcj_get_option( 'wcj_cart_custom_info_hook_' . $i, 'woocommerce_after_cart_totals' ) === $current_filter &&
90
+ wcj_get_option( 'wcj_cart_custom_info_priority_' . $i, 10 ) === $current_filter_priority
91
+ ) {
92
+ echo do_shortcode( wcj_get_option( 'wcj_cart_custom_info_content_' . $i ) );
93
+ }
94
  }
95
  }
 
96
 
97
+ }
98
 
99
  endif;
100
 
includes/class-wcj-checkout-core-fields.php CHANGED
@@ -4,277 +4,309 @@
4
  *
5
  * @version 5.3.7
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Checkout_Core_Fields' ) ) :
12
 
13
- class WCJ_Checkout_Core_Fields extends WCJ_Module {
14
-
15
  /**
16
- * Constructor.
17
  *
18
- * @version 5.4.0
19
- * @see https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
20
- * @todo (maybe) default overrides should be `disable`
21
  */
22
- function __construct() {
23
 
24
- $this->id = 'checkout_core_fields';
25
- $this->short_desc = __( 'Checkout Core Fields', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Customize core checkout fields. Disable/enable fields, set required, change labels and/or placeholders; Setup fields by category (Plus)', 'woocommerce-jetpack' );
27
- $this->desc_pro = __( 'Customize core checkout fields. Disable/enable fields, set required, change labels and/or placeholders etc.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-checkout-core-fields';
29
- parent::__construct();
 
 
30
 
31
- $this->woocommerce_core_checkout_fields = array(
32
- 'billing_country',
33
- 'billing_first_name',
34
- 'billing_last_name',
35
- 'billing_company',
36
- 'billing_address_1',
37
- 'billing_address_2',
38
- 'billing_city',
39
- 'billing_state',
40
- 'billing_postcode',
41
- 'billing_email',
42
- 'billing_phone',
43
- 'shipping_country',
44
- 'shipping_first_name',
45
- 'shipping_last_name',
46
- 'shipping_company',
47
- 'shipping_address_1',
48
- 'shipping_address_2',
49
- 'shipping_city',
50
- 'shipping_state',
51
- 'shipping_postcode',
52
- 'account_username',
53
- 'account_password',
54
- 'account_password-2',
55
- 'order_comments',
56
- );
57
 
58
- if ( $this->is_enabled() ) {
59
- add_filter( 'woocommerce_checkout_fields' , array( $this, 'custom_override_checkout_fields' ), PHP_INT_MAX );
60
- add_action('woocommerce_checkout_fields', array($this, 'enqueue_scripts'), PHP_INT_MAX);
61
- if ( 'disable' != ( $this->country_locale_override = wcj_get_option( 'wcj_checkout_core_fields_override_country_locale_fields', 'billing' ) ) ) {
62
- add_filter( 'woocommerce_get_country_locale', array( $this, 'custom_override_country_locale_fields' ), PHP_INT_MAX );
63
- }
64
- if ( 'disable' != ( $this->default_address_override = wcj_get_option( 'wcj_checkout_core_fields_override_default_address_fields', 'billing' ) ) ) {
65
- add_filter( 'woocommerce_default_address_fields', array( $this, 'custom_override_default_address_fields' ), PHP_INT_MAX );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  }
67
  }
68
- }
69
 
70
- /**
71
- * maybe_override_fields.
72
- *
73
- * @version 3.6.0
74
- * @since 3.1.0
75
- * @todo (maybe) add option to choose `$options_to_override`
76
- * @todo (maybe) add to `$options_to_override`: enabled; class;
77
- */
78
- function maybe_override_fields( $fields, $override_with_section ) {
79
- $options_to_override = array(
80
- 'label' => array(
81
- 'default' => '',
82
- ),
83
- 'placeholder' => array(
84
- 'default' => '',
85
- ),
86
- 'description' => array(
87
- 'default' => '',
88
- ),
89
- 'priority' => array(
90
- 'default' => 0,
91
- ),
92
- 'required' => array(
93
- 'default' => 'default',
94
- 'option_id' => 'is_required',
95
- 'values' => array(
96
- 'yes' => true,
97
- 'no' => false,
 
 
 
98
  ),
99
- ),
100
- );
101
- foreach ( $fields as $field_key => $field_values ) {
102
- $field = $override_with_section . '_' . $field_key;
103
- foreach ( $options_to_override as $option => $option_data ) {
104
- $default_value = $option_data['default'];
105
- $option_id = ( isset( $option_data['option_id'] ) ? $option_data['option_id'] : $option );
106
- $option_id = 'wcj_checkout_fields_' . $field . '_' . $option_id;
107
- if ( $default_value != ( $value = wcj_get_option( $option_id, $default_value ) ) ) {
108
- $value = ( isset( $option_data['values'][ $value ] ) ? $option_data['values'][ $value ] : $value );
109
- $fields[ $field_key ][ $option ] = $value;
 
110
  }
111
  }
 
112
  }
113
- return $fields;
114
- }
115
 
116
- /**
117
- * custom_override_country_locale_fields.
118
- *
119
- * @version 3.1.0
120
- * @since 3.1.0
121
- */
122
- function custom_override_country_locale_fields( $fields ) {
123
- foreach ( $fields as $country => $country_fields ) {
124
- $fields[ $country ] = $this->maybe_override_fields( $country_fields, $this->country_locale_override );
 
 
 
125
  }
126
- return $fields;
127
- }
128
 
129
- /**
130
- * custom_override_default_address_fields.
131
- *
132
- * @version 3.1.0
133
- * @since 2.3.8
134
- */
135
- function custom_override_default_address_fields( $fields ) {
136
- return $this->maybe_override_fields( $fields, $this->default_address_override );
137
- }
 
138
 
139
- /**
140
- * custom_override_checkout_fields.
141
- *
142
- * @version 5.3.7
143
- * @todo add "per products", "per products tags"
144
- * @todo (maybe) fix - priority seems to not affect tab order (same in Checkout Custom Fields module)
145
- * @todo (maybe) enable if was not enabled by default, i.e. `! isset( $checkout_fields[ $section ][ $field ] )`
146
- */
147
- function custom_override_checkout_fields( $checkout_fields ) {
148
- foreach ( $this->woocommerce_core_checkout_fields as $field ) {
149
- $field_parts = explode( '_', $field, 2 );
150
- $section = ( ! empty( $field_parts ) && is_array( $field_parts ) ? $field_parts[0] : '' ); // billing or shipping
151
- // enabled
152
- if ( 'no' === ( $is_enabled = wcj_get_option( 'wcj_checkout_fields_' . $field . '_' . 'is_enabled', 'default' ) ) ) {
153
- if ( isset( $checkout_fields[ $section ][ $field ] ) ) {
154
- unset( $checkout_fields[ $section ][ $field ] ); // e.g. unset( $checkout_fields['billing']['billing_country'] );
155
- continue;
156
- }
157
- }
158
- // enabled - per products categories
159
- if ( ! $this->is_visible( array(
160
- 'include_products' => '',
161
- 'exclude_products' => '',
162
- 'include_categories' => apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_fields_' . $field . '_' . 'cats_incl', '' ) ),
163
- 'exclude_categories' => apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_fields_' . $field . '_' . 'cats_excl', '' ) ),
164
- 'include_tags' => '',
165
- 'exclude_tags' => '',
166
- ), wcj_get_option( 'wcj_checkout_core_fields_checking_relation', 'all' ) )
167
- ) {
168
- unset( $checkout_fields[ $section ][ $field ] );
169
- continue;
170
- }
171
- if ( isset( $checkout_fields[ $section ][ $field ] ) ) {
172
- // required
173
- if ( 'default' != ( $is_required = wcj_get_option( 'wcj_checkout_fields_' . $field . '_' . 'is_required', 'default' ) ) ) {
174
- $checkout_fields[ $section ][ $field ]['required'] = ( 'yes' === $is_required );
175
- }
176
- // label
177
- if ( '' != ( $label = wcj_get_option( 'wcj_checkout_fields_' . $field . '_' . 'label', '' ) ) ) {
178
- $checkout_fields[ $section ][ $field ]['label'] = $label;
179
- }
180
- // placeholder
181
- if ( '' != ( $placeholder = wcj_get_option( 'wcj_checkout_fields_' . $field . '_' . 'placeholder', '' ) ) ) {
182
- $checkout_fields[ $section ][ $field ]['placeholder'] = $placeholder;
183
- }
184
- // description
185
- if ( '' != ( $description = wcj_get_option( 'wcj_checkout_fields_' . $field . '_' . 'description', '' ) ) ) {
186
- $checkout_fields[ $section ][ $field ]['description'] = $description;
187
  }
188
- // class
189
- if ( 'default' != ( $class = wcj_get_option( 'wcj_checkout_fields_' . $field . '_' . 'class', 'default' ) ) ) {
190
- $checkout_fields[ $section ][ $field ]['class'] = array( $class );
 
 
 
 
 
 
 
 
 
 
 
 
191
  }
192
- // priority
193
- if ( 0 != ( $priority = apply_filters( 'booster_option', 0, wcj_get_option( 'wcj_checkout_fields_' . $field . '_' . 'priority', 0 ) ) ) ) {
194
- $checkout_fields[ $section ][ $field ]['priority'] = $priority;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
195
  }
196
  }
197
- }
198
- if ( 'yes' === wcj_get_option( 'wcj_checkout_core_fields_force_sort_by_priority', 'no' ) ) {
199
- $field_sets = array( 'billing', 'shipping', 'account', 'order' );
200
- foreach ( $field_sets as $field_set ) {
201
- if ( isset( $checkout_fields[ $field_set ] ) ) {
202
- uasort( $checkout_fields[ $field_set ], array( $this, 'sort_by_priority' ) );
203
  }
204
  }
 
 
205
  }
206
- wcj_session_set("wcj_checkout_fields", $checkout_fields);
207
- return $checkout_fields;
208
- }
209
 
210
- /**
211
- * is_visible.
212
- *
213
- * @version 4.9.0
214
- * @since 3.4.0
215
- * @todo (maybe) save `$this->cart_product_ids` array (instead of calling `WC()->cart->get_cart()` for each field)
216
- *
217
- * @param $args
218
- * @param string $relation
219
- *
220
- * @return bool
221
- */
222
- function is_visible( $args, $relation = 'and' ) {
223
- $relation = strtolower( $relation );
224
- $all_empty = true;
225
- foreach ( $args as $arg ) {
226
- if ( ! empty( $arg ) ) {
227
- $all_empty = false;
228
- // At least one arg is filled - checking products in cart
229
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
230
- if ( 'and' === $relation ) {
231
- if ( ! wcj_is_enabled_for_product( $values['product_id'], $args ) ) {
232
- return false;
233
- }
234
- } elseif ( 'or' === $relation ) {
235
- if ( wcj_is_enabled_for_product( $values['product_id'], $args ) ) {
236
- return true;
 
237
  }
238
  }
 
239
  }
240
- break;
241
  }
 
 
 
 
242
  }
243
- if ( $all_empty ) {
244
- return true;
245
- }
246
- return 'and' === $relation ? true : false;
247
- }
248
 
249
- /**
250
- * sort_by_priority.
251
- *
252
- * @version 3.4.0
253
- * @since 3.4.0
254
- */
255
- function sort_by_priority( $a, $b ) {
256
- $a = ( isset( $a['priority'] ) ? $a['priority'] : 0 );
257
- $b = ( isset( $b['priority'] ) ? $b['priority'] : 0 );
258
- if ( $a == $b ) {
259
- return 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  }
261
- return ( $a < $b ) ? -1 : 1;
262
- }
263
- /**
264
- * enqueue_scripts.
265
- *
266
- * @version 5.3.7
267
- */
268
- function enqueue_scripts($checkout_fields)
269
- {
270
- wp_enqueue_script('wcj-checkout-core-fields', wcj_plugin_url() . '/includes/js/wcj-checkout-core-fields.js', array(), wcj()->version, false);
271
- wp_localize_script('wcj-checkout-core-fields', 'wcj_checkout_core_fields', array(
272
- 'checkout_fields' => wcj_session_get("wcj_checkout_fields")
273
- ));
274
- return $checkout_fields;
275
- }
276
 
277
- }
278
 
279
  endif;
280
 
4
  *
5
  * @version 5.3.7
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Checkout_Core_Fields' ) ) :
15
 
 
 
16
  /**
17
+ * WCJ_Checkout_Core_Fields.
18
  *
19
+ * @version 2.7.0
 
 
20
  */
21
+ class WCJ_Checkout_Core_Fields extends WCJ_Module {
22
 
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @version 5.4.0
27
+ * @see https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
28
+ * @todo (maybe) default overrides should be `disable`
29
+ */
30
+ public function __construct() {
31
 
32
+ $this->id = 'checkout_core_fields';
33
+ $this->short_desc = __( 'Checkout Core Fields', 'woocommerce-jetpack' );
34
+ $this->desc = __( 'Customize core checkout fields. Disable/enable fields, set required, change labels and/or placeholders; Setup fields by category (Plus)', 'woocommerce-jetpack' );
35
+ $this->desc_pro = __( 'Customize core checkout fields. Disable/enable fields, set required, change labels and/or placeholders etc.', 'woocommerce-jetpack' );
36
+ $this->link_slug = 'woocommerce-checkout-core-fields';
37
+ parent::__construct();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
+ $this->woocommerce_core_checkout_fields = array(
40
+ 'billing_country',
41
+ 'billing_first_name',
42
+ 'billing_last_name',
43
+ 'billing_company',
44
+ 'billing_address_1',
45
+ 'billing_address_2',
46
+ 'billing_city',
47
+ 'billing_state',
48
+ 'billing_postcode',
49
+ 'billing_email',
50
+ 'billing_phone',
51
+ 'shipping_country',
52
+ 'shipping_first_name',
53
+ 'shipping_last_name',
54
+ 'shipping_company',
55
+ 'shipping_address_1',
56
+ 'shipping_address_2',
57
+ 'shipping_city',
58
+ 'shipping_state',
59
+ 'shipping_postcode',
60
+ 'account_username',
61
+ 'account_password',
62
+ 'account_password-2',
63
+ 'order_comments',
64
+ );
65
+
66
+ if ( $this->is_enabled() ) {
67
+ add_filter( 'woocommerce_checkout_fields', array( $this, 'custom_override_checkout_fields' ), PHP_INT_MAX );
68
+ add_action( 'woocommerce_checkout_fields', array( $this, 'enqueue_scripts' ), PHP_INT_MAX );
69
+ $this->country_locale_override = wcj_get_option( 'wcj_checkout_core_fields_override_country_locale_fields', 'billing' );
70
+ if ( 'disable' !== ( $this->country_locale_override ) ) {
71
+ add_filter( 'woocommerce_get_country_locale', array( $this, 'custom_override_country_locale_fields' ), PHP_INT_MAX );
72
+ }
73
+ $this->default_address_override = wcj_get_option( 'wcj_checkout_core_fields_override_default_address_fields', 'billing' );
74
+ if ( 'disable' !== ( $this->default_address_override ) ) {
75
+ add_filter( 'woocommerce_default_address_fields', array( $this, 'custom_override_default_address_fields' ), PHP_INT_MAX );
76
+ }
77
  }
78
  }
 
79
 
80
+ /**
81
+ * Maybe_override_fields.
82
+ *
83
+ * @version 3.6.0
84
+ * @since 3.1.0
85
+ * @todo (maybe) add option to choose `$options_to_override`
86
+ * @todo (maybe) add to `$options_to_override`: enabled; class;
87
+ * @param string $fields defines the fields.
88
+ * @param string $override_with_section defines the override_with_section.
89
+ */
90
+ public function maybe_override_fields( $fields, $override_with_section ) {
91
+ $options_to_override = array(
92
+ 'label' => array(
93
+ 'default' => '',
94
+ ),
95
+ 'placeholder' => array(
96
+ 'default' => '',
97
+ ),
98
+ 'description' => array(
99
+ 'default' => '',
100
+ ),
101
+ 'priority' => array(
102
+ 'default' => 0,
103
+ ),
104
+ 'required' => array(
105
+ 'default' => 'default',
106
+ 'option_id' => 'is_required',
107
+ 'values' => array(
108
+ 'yes' => true,
109
+ 'no' => false,
110
+ ),
111
  ),
112
+ );
113
+ foreach ( $fields as $field_key => $field_values ) {
114
+ $field = $override_with_section . '_' . $field_key;
115
+ foreach ( $options_to_override as $option => $option_data ) {
116
+ $default_value = $option_data['default'];
117
+ $option_id = ( isset( $option_data['option_id'] ) ? $option_data['option_id'] : $option );
118
+ $option_id = 'wcj_checkout_fields_' . $field . '_' . $option_id;
119
+ $value = wcj_get_option( $option_id, $default_value );
120
+ if ( $default_value !== $value ) {
121
+ $value = ( isset( $option_data['values'][ $value ] ) ? $option_data['values'][ $value ] : $value );
122
+ $fields[ $field_key ][ $option ] = $value;
123
+ }
124
  }
125
  }
126
+ return $fields;
127
  }
 
 
128
 
129
+ /**
130
+ * Custom_override_country_locale_fields.
131
+ *
132
+ * @version 3.1.0
133
+ * @since 3.1.0
134
+ * @param string $fields defines the fields.
135
+ */
136
+ public function custom_override_country_locale_fields( $fields ) {
137
+ foreach ( $fields as $country => $country_fields ) {
138
+ $fields[ $country ] = $this->maybe_override_fields( $country_fields, $this->country_locale_override );
139
+ }
140
+ return $fields;
141
  }
 
 
142
 
143
+ /**
144
+ * Custom_override_default_address_fields.
145
+ *
146
+ * @version 3.1.0
147
+ * @since 2.3.8
148
+ * @param string $fields defines the fields.
149
+ */
150
+ public function custom_override_default_address_fields( $fields ) {
151
+ return $this->maybe_override_fields( $fields, $this->default_address_override );
152
+ }
153
 
154
+ /**
155
+ * Custom_override_checkout_fields.
156
+ *
157
+ * @version 5.3.7
158
+ * @todo add "per products", "per products tags"
159
+ * @todo (maybe) fix - priority seems to not affect tab order (same in Checkout Custom Fields module)
160
+ * @todo (maybe) enable if was not enabled by default, i.e. `! isset( $checkout_fields[ $section ][ $field ] )`
161
+ * @param string $checkout_fields defines the checkout_fields.
162
+ */
163
+ public function custom_override_checkout_fields( $checkout_fields ) {
164
+ foreach ( $this->woocommerce_core_checkout_fields as $field ) {
165
+ $field_parts = explode( '_', $field, 2 );
166
+ $section = ( ! empty( $field_parts ) && is_array( $field_parts ) ? $field_parts[0] : '' ); // billing or shipping
167
+ // enabled.
168
+ $is_enabled = wcj_get_option( 'wcj_checkout_fields_' . $field . '_is_enabled', 'default' );
169
+ if ( 'no' === ( $is_enabled ) ) {
170
+ if ( isset( $checkout_fields[ $section ][ $field ] ) ) {
171
+ unset( $checkout_fields[ $section ][ $field ] );
172
+ continue;
173
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
174
  }
175
+ // enabled - per products categories.
176
+ if ( ! $this->is_visible(
177
+ array(
178
+ 'include_products' => '',
179
+ 'exclude_products' => '',
180
+ 'include_categories' => apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_fields_' . $field . '_cats_incl', '' ) ),
181
+ 'exclude_categories' => apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_fields_' . $field . '_cats_excl', '' ) ),
182
+ 'include_tags' => '',
183
+ 'exclude_tags' => '',
184
+ ),
185
+ wcj_get_option( 'wcj_checkout_core_fields_checking_relation', 'all' )
186
+ )
187
+ ) {
188
+ unset( $checkout_fields[ $section ][ $field ] );
189
+ continue;
190
  }
191
+ if ( isset( $checkout_fields[ $section ][ $field ] ) ) {
192
+ // required.
193
+ $is_required = wcj_get_option( 'wcj_checkout_fields_' . $field . '_is_required', 'default' );
194
+ if ( 'default' !== ( $is_required ) ) {
195
+ $checkout_fields[ $section ][ $field ]['required'] = ( 'yes' === $is_required );
196
+ }
197
+ // label.
198
+ $label = wcj_get_option( 'wcj_checkout_fields_' . $field . '_label', '' );
199
+ if ( '' !== ( $label ) ) {
200
+ $checkout_fields[ $section ][ $field ]['label'] = $label;
201
+ }
202
+ // placeholder.
203
+ $placeholder = wcj_get_option( 'wcj_checkout_fields_' . $field . '_placeholder', '' );
204
+ if ( '' !== ( $placeholder ) ) {
205
+ $checkout_fields[ $section ][ $field ]['placeholder'] = $placeholder;
206
+ }
207
+ // description.
208
+ $description = wcj_get_option( 'wcj_checkout_fields_' . $field . '_description', '' );
209
+ if ( '' !== ( $description ) ) {
210
+ $checkout_fields[ $section ][ $field ]['description'] = $description;
211
+ }
212
+ // class.
213
+ $class = wcj_get_option( 'wcj_checkout_fields_' . $field . '_class', 'default' );
214
+ if ( 'default' !== ( $class ) ) {
215
+ $checkout_fields[ $section ][ $field ]['class'] = array( $class );
216
+ }
217
+ // priority.
218
+ $priority = apply_filters( 'booster_option', 0, wcj_get_option( 'wcj_checkout_fields_' . $field . '_priority', 0 ) );
219
+ if ( 0 !== ( $priority ) ) {
220
+ $checkout_fields[ $section ][ $field ]['priority'] = $priority;
221
+ }
222
  }
223
  }
224
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_core_fields_force_sort_by_priority', 'no' ) ) {
225
+ $field_sets = array( 'billing', 'shipping', 'account', 'order' );
226
+ foreach ( $field_sets as $field_set ) {
227
+ if ( isset( $checkout_fields[ $field_set ] ) ) {
228
+ uasort( $checkout_fields[ $field_set ], array( $this, 'sort_by_priority' ) );
229
+ }
230
  }
231
  }
232
+ wcj_session_set( 'wcj_checkout_fields', $checkout_fields );
233
+ return $checkout_fields;
234
  }
 
 
 
235
 
236
+ /**
237
+ * Is_visible.
238
+ *
239
+ * @version 4.9.0
240
+ * @since 3.4.0
241
+ * @todo (maybe) save `$this->cart_product_ids` array (instead of calling `WC()->cart->get_cart()` for each field)
242
+ *
243
+ * @param array $args defines the arguments.
244
+ * @param string $relation defines the relation.
245
+ *
246
+ * @return bool
247
+ */
248
+ public function is_visible( $args, $relation = 'and' ) {
249
+ $relation = strtolower( $relation );
250
+ $all_empty = true;
251
+ foreach ( $args as $arg ) {
252
+ if ( ! empty( $arg ) ) {
253
+ $all_empty = false;
254
+ // At least one arg is filled - checking products in cart.
255
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
256
+ if ( 'and' === $relation ) {
257
+ if ( ! wcj_is_enabled_for_product( $values['product_id'], $args ) ) {
258
+ return false;
259
+ }
260
+ } elseif ( 'or' === $relation ) {
261
+ if ( wcj_is_enabled_for_product( $values['product_id'], $args ) ) {
262
+ return true;
263
+ }
264
  }
265
  }
266
+ break;
267
  }
 
268
  }
269
+ if ( $all_empty ) {
270
+ return true;
271
+ }
272
+ return 'and' === $relation ? true : false;
273
  }
 
 
 
 
 
274
 
275
+ /**
276
+ * Sort_by_priority.
277
+ *
278
+ * @version 3.4.0
279
+ * @since 3.4.0
280
+ * @param string $a defines the a.
281
+ * @param string $b defines the b.
282
+ */
283
+ public function sort_by_priority( $a, $b ) {
284
+ $a = ( isset( $a['priority'] ) ? $a['priority'] : 0 );
285
+ $b = ( isset( $b['priority'] ) ? $b['priority'] : 0 );
286
+ if ( $a === $b ) {
287
+ return 0;
288
+ }
289
+ return ( $a < $b ) ? -1 : 1;
290
+ }
291
+ /**
292
+ * Enqueue_scripts.
293
+ *
294
+ * @version 5.3.7
295
+ * @param string $checkout_fields defines the checkout_fields.
296
+ */
297
+ public function enqueue_scripts( $checkout_fields ) {
298
+ wp_enqueue_script( 'wcj-checkout-core-fields', wcj_plugin_url() . '/includes/js/wcj-checkout-core-fields.js', array(), w_c_j()->version, false );
299
+ wp_localize_script(
300
+ 'wcj-checkout-core-fields',
301
+ 'wcj_checkout_core_fields',
302
+ array(
303
+ 'checkout_fields' => wcj_session_get( 'wcj_checkout_fields' ),
304
+ )
305
+ );
306
+ return $checkout_fields;
307
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
308
 
309
+ }
310
 
311
  endif;
312
 
includes/class-wcj-checkout-custom-fields.php CHANGED
@@ -4,383 +4,422 @@
4
  *
5
  * @version 5.5.6
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Checkout_Custom_Fields' ) ) :
12
 
13
- class WCJ_Checkout_Custom_Fields extends WCJ_Module {
14
-
15
  /**
16
- * Constructor.
17
  *
18
- * @version 5.4.0
19
- * @todo (maybe) check if `'wcj_checkout_custom_field_customer_meta_fields_' . $i` option should affect `add_default_checkout_custom_fields`
20
  */
21
- function __construct() {
22
-
23
- $this->id = 'checkout_custom_fields';
24
- $this->short_desc = __( 'Checkout Custom Fields', 'woocommerce-jetpack' );
25
- $this->desc = __( 'Add custom fields to the checkout page (1 field allowed in free version).', 'woocommerce-jetpack' );
26
- $this->desc_pro = __( 'Add custom fields to the checkout page.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-checkout-custom-fields';
28
- $this->extra_desc = sprintf( __( 'After setting Checkout Custom Fields, you can use below shortcode with meta_key to display the Product Input Fields value: %s', 'woocommerce-jetpack' ),
29
- '<ol>' .
30
- '<li>' . sprintf( __( '<strong>Shortcodes:</strong> %s', 'woocommerce-jetpack' ),
31
- '<code>[wcj_order_checkout_field meta_key = "billing_wcj_checkout_field_&lt;field_id&gt;"]</code><br>field_id is the key of your Checkout Custom Fields, You will find key from Option Custom Field' ) .
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  '</li>' .
33
- '<li>' . sprintf( __( '<strong>PHP code:</strong> by using %s function,<br> e.g.: %s', 'woocommerce-jetpack' ),
 
 
34
  '<code>do_shortcode()</code>',
35
- '<code>echo&nbsp;do_shortcode(&nbsp;\'[wcj_order_checkout_field meta_key = "billing_wcj_checkout_field_1]\'&nbsp;);</code>' ) .
 
36
  '</li>' .
37
- '</ol>' );
 
38
 
39
- parent::__construct();
40
 
41
- if ( $this->is_enabled() ) {
42
- add_filter( 'woocommerce_checkout_fields', array( $this, 'add_custom_checkout_fields' ), PHP_INT_MAX );
43
- add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_custom_billing_fields_to_admin_order_display' ), PHP_INT_MAX );
44
- add_filter( 'woocommerce_admin_shipping_fields', array( $this, 'add_custom_shipping_fields_to_admin_order_display' ), PHP_INT_MAX );
45
- add_action( 'woocommerce_admin_order_data_after_shipping_address', array( $this, 'add_custom_order_and_account_fields_to_admin_order_display' ), PHP_INT_MAX );
46
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_fields_add_to_order_received', 'yes' ) ) {
47
- add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_custom_fields_to_view_order_and_thankyou_pages' ), PHP_INT_MAX );
48
- }
49
- add_action( 'woocommerce_email_after_order_table', array( $this, 'add_custom_fields_to_emails' ), PHP_INT_MAX, 2 );
50
- add_filter( 'woo_ce_order_fields', array( $this, 'add_custom_fields_to_store_exporter' ) );
51
- add_filter( 'woo_ce_order', array( $this, 'add_custom_fields_to_store_exporter_order' ), PHP_INT_MAX, 2 );
52
- add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'update_custom_checkout_fields_order_meta' ) );
53
- add_filter( 'woocommerce_form_field_' . 'text', array( $this, 'woocommerce_form_field_type_number' ), PHP_INT_MAX, 4 );
54
- add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_checkout_custom_fields_customer_meta_fields' ) );
55
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
56
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
57
- $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
58
- $the_key = 'wcj_checkout_field_' . $i;
59
- $the_name = $the_section . '_' . $the_key;
60
- add_filter( 'default_checkout_' . $the_name, array( $this, 'add_default_checkout_custom_fields' ), PHP_INT_MAX, 2 );
61
  }
62
- }
63
- // select2 script
64
- add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
- // Update checkout fields from admin edit order
67
- add_action( 'save_post_shop_order', array( $this, 'update_custom_checkout_fields_order_meta' ) );
68
 
69
- // Update checkout fields from admin on a subscription order
70
- add_action( 'save_post_shop_subscription', array( $this, 'update_custom_checkout_fields_order_meta' ) );
 
71
  }
72
- }
73
 
74
- /**
75
- * maybe_enqueue_scripts.
76
- *
77
- * @version 3.6.0
78
- * @since 3.2.0
79
- */
80
- function maybe_enqueue_scripts( $fields ) {
81
- if ( is_checkout() ) {
82
- $select2_fields = array();
83
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
84
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i, 'no' ) ) {
85
- if ( 'select' === wcj_get_option( 'wcj_checkout_custom_field_type_' . $i, 'text' ) ) {
86
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_select_select2_' . $i, 'no' ) ) {
87
- $select2_fields[] = array(
88
- 'field_id' => wcj_get_option( 'wcj_checkout_custom_field_section_' . $i, 'billing' ) . '_' . 'wcj_checkout_field_' . $i,
89
- 'minimumInputLength' => wcj_get_option( 'wcj_checkout_custom_field_select_select2_min_input_length' . $i, 0 ),
90
- 'maximumInputLength' => wcj_get_option( 'wcj_checkout_custom_field_select_select2_max_input_length' . $i, 0 ),
91
- );
 
 
92
  }
93
  }
94
  }
95
- }
96
- if ( ! empty( $select2_fields ) ) {
97
- wp_enqueue_script(
98
- 'wcj-checkout-custom-fields',
99
- wcj_plugin_url() . '/includes/js/wcj-checkout-custom-fields.js',
100
- array( 'jquery' ),
101
- WCJ()->version,
102
- true
103
- );
104
- wp_localize_script(
105
- 'wcj-checkout-custom-fields',
106
- 'wcj_checkout_custom_fields',
107
- array(
108
- 'select2_fields' => $select2_fields,
109
- )
110
- );
111
  }
112
  }
113
- }
114
 
115
- /**
116
- * add_checkout_custom_fields_customer_meta_fields.
117
- *
118
- * @version 3.2.4
119
- * @since 2.4.5
120
- */
121
- function add_checkout_custom_fields_customer_meta_fields( $fields ) {
122
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
123
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
124
- if ( 'no' === wcj_get_option( 'wcj_checkout_custom_field_customer_meta_fields_' . $i, 'yes' ) ) {
125
- continue;
 
 
 
 
 
 
 
 
 
126
  }
127
- $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
128
- $the_key = 'wcj_checkout_field_' . $i;
129
- $the_name = $the_section . '_' . $the_key;
130
- $fields[ $the_section ]['fields'][ $the_name ] = array(
131
- 'label' => wcj_get_option( 'wcj_checkout_custom_field_label_' . $i ),
132
- 'description' => '',
133
- );
134
  }
 
135
  }
136
- return $fields;
137
- }
138
 
139
- /**
140
- * add_default_checkout_custom_fields.
141
- *
142
- * @version 2.4.5
143
- * @since 2.4.5
144
- */
145
- function add_default_checkout_custom_fields( $default_value, $field_key ) {
146
- if ( is_user_logged_in() ) {
147
- $current_user = wp_get_current_user();
148
- if ( $meta = get_user_meta( $current_user->ID, $field_key, true ) ) {
149
- return $meta;
 
 
 
 
150
  }
 
151
  }
152
- return $default_value;
153
- }
154
 
155
- /**
156
- * woocommerce_form_field_type_number.
157
- *
158
- * @version 2.3.0
159
- * @since 2.3.0
160
- */
161
- function woocommerce_form_field_type_number( $field, $key, $args, $value ) {
162
- if ( isset( $args['custom_attributes']['display'] ) && 'number' === $args['custom_attributes']['display'] ) {
163
- $field = str_replace( '<input type="text" ', '<input type="number" ', $field );
 
 
 
 
 
 
164
  }
165
- return $field;
166
- }
167
 
168
- /**
169
- * add_custom_fields_to_store_exporter_order.
170
- *
171
- * @version 2.3.0
172
- * @since 2.2.7
173
- */
174
- function add_custom_fields_to_store_exporter_order( $order, $order_id ) {
175
- $post_meta = get_post_meta( $order_id );
176
- foreach( $post_meta as $key => $values ) {
177
- if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
178
- if ( false !== strpos( $key, '_label_' ) ) {
179
- continue;
 
 
 
 
180
  }
181
- $order->$key = isset( $values[0]['value'] ) ? $values[0]['value'] : $values[0];
182
  }
183
- }
184
 
185
- return $order;
186
- }
187
 
188
- /**
189
- * add_custom_fields_to_store_exporter.
190
- */
191
- function add_custom_fields_to_store_exporter( $fields ) {
192
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
193
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
194
- $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
195
- $the_key = 'wcj_checkout_field_' . $i;
196
- $fields[] = array(
197
- 'name' => $the_section . '_' . $the_key,
198
- 'label' => wcj_get_option( 'wcj_checkout_custom_field_label_' . $i ),
199
- );
 
 
 
200
  }
 
201
  }
202
- return $fields;
203
- }
204
 
205
- /**
206
- * update_custom_checkout_fields_order_meta.
207
- *
208
- * @version 5.4.3
209
- */
210
- function update_custom_checkout_fields_order_meta( $order_id ) {
211
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
212
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
213
- if ( 'woocommerce_checkout_update_order_meta' === current_filter() && ! $this->is_visible( $i ) ) {
214
- continue;
215
- }
216
- $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
217
- $the_type = wcj_get_option( 'wcj_checkout_custom_field_type_' . $i );
218
- $option_name = $the_section . '_' . 'wcj_checkout_field_' . $i;
219
- $option_name_label = $the_section . '_' . 'wcj_checkout_field_label_' . $i;
220
- $option_name_type = $the_section . '_' . 'wcj_checkout_field_type_' . $i;
221
- $post_value = isset( $_POST[ $option_name ] ) ? $_POST[ $option_name ] : ( isset( $_POST[ '_' . $option_name ] ) ? $_POST[ '_' . $option_name ] : get_post_meta( $order_id, '_' . $option_name, true ) );
222
- if ( ! empty( $post_value ) || 'checkbox' === $the_type ) {
223
- update_post_meta( $order_id, '_' . $option_name_type, $the_type );
224
- update_post_meta( $order_id, '_' . $option_name_label, wcj_get_option( 'wcj_checkout_custom_field_label_' . $i ) );
225
- if ( 'checkbox' === $the_type ) {
226
- $the_value = ! empty( $post_value ) ? 1 : 0;
227
- update_post_meta( $order_id, '_' . $option_name, $the_value );
228
- $option_name_checkbox_value = $the_section . '_' . 'wcj_checkout_field_checkbox_value_' . $i;
229
- $checkbox_value = ( 1 == $the_value ) ?
 
 
230
  get_option( 'wcj_checkout_custom_field_checkbox_yes_' . $i ) :
231
  get_option( 'wcj_checkout_custom_field_checkbox_no_' . $i );
232
- update_post_meta( $order_id, '_' . $option_name_checkbox_value, $checkbox_value );
233
- } elseif ( 'radio' === $the_type || 'select' === $the_type ) {
234
- update_post_meta( $order_id, '_' . $option_name, wc_clean( urldecode( $post_value ) ) );
235
- $option_name_values = $the_section . '_' . 'wcj_checkout_field_select_options_' . $i;
236
- $the_values = wcj_get_option( 'wcj_checkout_custom_field_select_options_' . $i );
237
- update_post_meta( $order_id, '_' . $option_name_values, $the_values );
238
- } elseif ( 'textarea' === $the_type && 'no' === wcj_get_option( 'wcj_checkout_custom_fields_textarea_clean', 'yes' ) ) {
239
- update_post_meta( $order_id, '_' . $option_name, urldecode( $post_value ) );
240
- } else {
241
- update_post_meta( $order_id, '_' . $option_name, wc_clean( urldecode( $post_value ) ) );
 
242
  }
243
  }
244
  }
245
  }
246
- }
247
 
248
- /**
249
- * add_custom_fields_to_emails.
250
- *
251
- * @version 3.2.2
252
- */
253
- function add_custom_fields_to_emails( $order, $sent_to_admin ) {
254
- if (
255
- ( $sent_to_admin && 'yes' === wcj_get_option( 'wcj_checkout_custom_fields_email_all_to_admin' ) ) ||
 
 
256
  ( ! $sent_to_admin && 'yes' === wcj_get_option( 'wcj_checkout_custom_fields_email_all_to_customer' ) )
257
- ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
258
  $templates = array(
259
- 'before' => wcj_get_option( 'wcj_checkout_custom_fields_emails_template_before', '' ),
260
- 'field' => wcj_get_option( 'wcj_checkout_custom_fields_emails_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
261
- 'after' => wcj_get_option( 'wcj_checkout_custom_fields_emails_template_after', '' ),
262
  );
263
  $this->add_custom_fields_to_order_display( $order, '', $templates );
264
  }
265
- }
266
-
267
- /**
268
- * add_custom_fields_to_view_order_and_thankyou_pages.
269
- *
270
- * @version 3.2.2
271
- * @since 3.2.2
272
- */
273
- function add_custom_fields_to_view_order_and_thankyou_pages( $order ) {
274
- $templates = array(
275
- 'before' => wcj_get_option( 'wcj_checkout_custom_fields_order_received_template_before', '' ),
276
- 'field' => wcj_get_option( 'wcj_checkout_custom_fields_order_received_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
277
- 'after' => wcj_get_option( 'wcj_checkout_custom_fields_order_received_template_after', '' ),
278
- );
279
- $this->add_custom_fields_to_order_display( $order, '', $templates );
280
- }
281
 
282
- /**
283
- * add_custom_fields_to_order_display.
284
- *
285
- * @version 5.4.7
286
- * @since 2.3.0
287
- * @todo convert from before version 2.3.0
288
- */
289
- function add_custom_fields_to_order_display( $order, string $section =null, $templates ) {
290
- $post_meta = get_post_meta( wcj_get_order_id( $order ) );
291
- $final_output = '';
292
- foreach( $post_meta as $key => $values ) {
293
- if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
294
- // Checking section (if set)
295
- if ( '' != $section ) {
296
- $the_section = strtok( $key, '_' );
297
- if ( $section !== $the_section ) {
298
- continue;
 
 
 
 
299
  }
300
- }
301
- // Skipping unnecessary meta
302
- if (
303
  false !== strpos( $key, '_label_' ) ||
304
  false !== strpos( $key, '_type_' ) ||
305
  false !== strpos( $key, '_checkbox_value_' ) ||
306
  false !== strpos( $key, '_select_options_' )
307
- ) {
308
- continue;
309
- }
310
- // Field label
311
- $label = '';
312
- $the_label_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_label_', $key );
313
- if ( isset( $post_meta[ $the_label_key ][0] ) ) {
314
- $label = $post_meta[ $the_label_key ][0];
315
- } elseif ( is_array( $values[0] ) && isset( $values[0]['label'] ) ) {
316
- $label = $values[0]['label'];
317
- }
318
- // Field value
319
- $value = '';
320
- $_value = ( is_array( $values[0] ) && isset( $values[0]['value'] ) ? $values[0]['value'] : $values[0] );
321
- $type_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_type_', $key );
322
- if ( isset( $post_meta[ $type_key ][0] ) && 'checkbox' === $post_meta[ $type_key ][0] ) {
323
- $checkbox_value_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_checkbox_value_', $key );
324
- $value = ( isset( $post_meta[ $checkbox_value_key ][0] ) ? $post_meta[ $checkbox_value_key ][0] : $_value );
325
- } elseif ( isset( $post_meta[ $type_key ][0] ) && ( 'radio' === $post_meta[ $type_key ][0] || 'select' === $post_meta[ $type_key ][0] ) ) {
326
- $select_values_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_select_options_', $key );
327
- $select_values = ( isset( $post_meta[ $select_values_key ][0] ) ) ? $post_meta[ $select_values_key ][0] : '';
328
- if ( ! empty( $select_values ) ) {
329
- $select_values_prepared = wcj_get_select_options( $select_values );
330
- $value = ( isset( $select_values_prepared[ $_value ] ) ? $select_values_prepared[ $_value ] : $_value );
 
 
 
 
 
331
  } else {
332
  $value = $_value;
333
  }
334
- } elseif ( isset( $post_meta[ $type_key ][0] ) && 'textarea' === $post_meta[ $type_key ][0] && 'yes' === wcj_get_option( 'wcj_checkout_custom_fields_textarea_replace_line_breaks', 'no' ) ) {
335
- $value = str_replace( PHP_EOL, '<br>', $_value );
336
- } else {
337
- $value = $_value;
338
- }
339
- // Adding field to final output
340
- if ( '' != $value ) {
341
- if($value != 'No'){
342
- $replaced_values = array(
343
- '%label%' => $label,
344
- '%value%' => $value,
345
- );
346
- $final_output .= str_replace( array_keys( $replaced_values ), $replaced_values, $templates['field'] );
347
- }
348
-
349
- }
350
- else if ('' == $value) {
351
- $templates = array(
352
  'before' => '',
353
  'field' => '',
354
  'after' => '',
355
  );
356
  $final_output .= str_replace( array_keys( $templates ), $templates, $templates['field'] );
357
- }
 
 
 
 
 
358
  }
359
  }
360
- // Outputting
361
- if ( '' != $final_output ) {
362
- echo $templates['before'] . $final_output . $templates['after'];
363
- }
364
- }
365
 
366
- /**
367
- * add_woocommerce_admin_fields.
368
- *
369
- * @version 5.5.6
370
- * @todo converting from before version 2.3.0: section?
371
- * @todo add alternative way of displaying fields (e.g. new meta box), so we have more control over displaying fields' values (e.g. line breaks)
372
- */
373
- function add_woocommerce_admin_fields( $fields, $section ) {
374
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
375
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
376
- $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
377
- if ( $section != $the_section ) {
378
- continue;
379
- }
380
- $the_type = wcj_get_option( 'wcj_checkout_custom_field_type_' . $i );
381
- if ('textarea'=== $the_type ) { ?>
 
 
382
  <script type="text/javascript">
383
-
384
  jQuery(document).ready(function($){
385
  $("input.textarea").each(function () {
386
  var $txtarea = $("<textarea />");
@@ -392,299 +431,310 @@ class WCJ_Checkout_Custom_Fields extends WCJ_Module {
392
  });
393
  });
394
  </script>
395
- <?php }
396
-
397
- if ( 'select' === $the_type ) {
398
- $the_class = 'first';
399
- $options = wcj_get_select_options( wcj_get_option( 'wcj_checkout_custom_field_select_options_' . $i ) );
400
- }
401
- elseif ('textarea'=== $the_type ) {
402
- $the_class = 'first textarea';
403
- }
404
- elseif ( 'radio' === $the_type ) {
405
- $the_options = get_post_meta( get_the_ID(), '_' . $section . '_' . 'wcj_checkout_field_select_options_' . $i, true );
406
- if ( ! empty( $the_options ) ) {
407
- $the_type = 'select';
408
  $the_class = 'first';
409
- $options = wcj_get_select_options( $the_options );
410
- } else {
411
- $the_options = wcj_get_select_options( wcj_get_option( 'wcj_checkout_custom_field_select_options_' . $i ) );
 
 
412
  if ( ! empty( $the_options ) ) {
413
  $the_type = 'select';
414
  $the_class = 'first';
415
- $options = $the_options;
416
  } else {
417
- $the_type = 'text';
418
- $the_class = 'short';
 
 
 
 
 
 
 
419
  }
 
 
 
 
 
 
 
420
  }
421
- } elseif ( 'country' === $the_type ) {
422
- $the_type = 'select';
423
- $the_class = 'js_field-country select short';
424
- $options = WC()->countries->get_allowed_countries();
425
- } else {
426
- $the_type = 'text';
427
- $the_class = 'short';
428
- }
429
- $the_key = 'wcj_checkout_field_' . $i;
430
- $the_key_label = 'wcj_checkout_field_label_' . $i;
431
- $the_meta = get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key, true );
432
- if ( is_array( $the_meta ) ) {
433
- // Converting from before version 2.3.0
434
- if ( isset( $the_meta['value'] ) ) {
435
- update_post_meta( get_the_ID(), '_' . $section . '_' . $the_key, $the_meta['value'] );
436
- }
437
- if ( isset( $the_meta['label'] ) ) {
438
- update_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, $the_meta['label'] );
439
- }
440
- }
441
- if ( ! isset( $_POST[ '_' . $section . '_' . $the_key ] ) ) {
442
- $fields[ $the_key ] = array(
443
- 'type' => $the_type,
444
- 'label' => ( '' != get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, true ) ) ?
445
- get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, true ) :
446
- get_option( 'wcj_checkout_custom_field_label_' . $i ),
447
- 'show' => true,
448
- 'class' => $the_class,
449
- 'wrapper_class' => 'form-field-wide',
450
- );
451
- if ( ! empty( $the_meta ) && ! is_array( $the_meta ) ) {
452
- $fields[ $the_key ]['value'] = $the_meta;
453
  }
454
- if ( isset( $options ) ) {
455
- add_filter( "woocommerce_order_get__{$section}_{$the_key}", function ( $name ) use ( $options ) {
456
- if ( isset( $options[ $name ] ) ) {
457
- return $options[ $name ];
458
- }
459
- return $name;
460
- } );
461
- $fields[ $the_key ]['options'] = $options;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
462
  }
463
  }
464
  }
 
465
  }
466
- return $fields;
467
- }
468
-
469
- /**
470
- * add_custom_billing_fields_to_admin_order_display.
471
- */
472
- function add_custom_billing_fields_to_admin_order_display( $fields ) {
473
- return $this->add_woocommerce_admin_fields( $fields, 'billing' );
474
- }
475
 
476
- /**
477
- * add_custom_shipping_fields_to_admin_order_display.
478
- */
479
- function add_custom_shipping_fields_to_admin_order_display( $fields ) {
480
- return $this->add_woocommerce_admin_fields( $fields, 'shipping' );
481
- }
482
-
483
- /**
484
- * add_custom_order_and_account_fields_to_admin_order_display
485
- *
486
- * @version 3.2.2
487
- */
488
- function add_custom_order_and_account_fields_to_admin_order_display( $order ) {
489
- $templates = array(
490
- 'before' => '<div class="clear"></div><p>',
491
- 'field' => '<strong>%label%: </strong>%value%<br>',
492
- 'after' => '</p>',
493
- );
494
- $this->add_custom_fields_to_order_display( $order, 'order', $templates );
495
- $this->add_custom_fields_to_order_display( $order, 'account', $templates );
496
- }
497
 
498
- /**
499
- * is_visible.
500
- *
501
- * @version 4.2.0
502
- * @since 2.6.0
503
- * @todo add "user roles to include/exclude"
504
- */
505
- function is_visible( $i ) {
506
 
507
- if ( apply_filters( 'wcj_checkout_custom_field_always_visible_on_empty_cart', false ) && WC()->cart->is_empty() ) {
508
- // Added for "One Page Checkout" plugin compatibility.
509
- return true;
 
 
 
 
 
 
 
 
 
 
 
510
  }
511
 
512
- // Checking categories
513
- $categories_ex = wcj_get_option( 'wcj_checkout_custom_field_categories_ex_' . $i );
514
- if ( ! empty( $categories_ex ) ) {
515
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
516
- $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
517
- if ( empty( $product_categories ) ) {
518
- continue;
519
- }
520
- foreach( $product_categories as $product_category ) {
521
- if ( in_array( $product_category->term_id, $categories_ex ) ) {
522
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
523
  }
524
  }
525
  }
526
- }
527
- $categories_in = wcj_get_option( 'wcj_checkout_custom_field_categories_in_' . $i );
528
- if ( ! empty( $categories_in ) ) {
529
- $categories_in_cart = array();
530
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
531
- $product_categories = wp_get_post_terms( $values['product_id'], 'product_cat', array( "fields" => "ids" ) );
532
- $categories_in_cart = array_merge( $product_categories, $categories_in_cart );
533
- }
534
- if ( count( array_intersect( $categories_in, $categories_in_cart ) ) == 0 ) {
535
- return false;
536
- }
537
- }
538
-
539
- // Checking products
540
- $products_ex = wcj_get_option( 'wcj_checkout_custom_field_products_ex_' . $i );
541
- if ( ! empty( $products_ex ) ) {
542
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
543
- if ( in_array( $values['product_id'], $products_ex ) ) {
544
  return false;
545
  }
546
  }
547
- }
548
- $products_in = wcj_get_option( 'wcj_checkout_custom_field_products_in_' . $i );
549
- if ( ! empty( $products_in ) ) {
550
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
551
- if ( in_array( $values['product_id'], $products_in ) ) {
552
- return true;
 
 
553
  }
554
  }
555
- return false;
556
- }
557
-
558
- // Checking min/max cart amount
559
- $cart_total = false;
560
- if ( ( $min_cart_amount = wcj_get_option( 'wcj_checkout_custom_field_min_cart_amount_' . $i, 0 ) ) > 0 ) {
561
- WC()->cart->calculate_totals();
562
- $cart_total = WC()->cart->total;
563
- if ( $cart_total < $min_cart_amount ) {
564
  return false;
565
  }
566
- }
567
- if ( ( $max_cart_amount = wcj_get_option( 'wcj_checkout_custom_field_max_cart_amount_' . $i, 0 ) ) > 0 ) {
568
- if ( false === $cart_total ) {
 
 
569
  WC()->cart->calculate_totals();
570
  $cart_total = WC()->cart->total;
 
 
 
571
  }
572
- if ( $cart_total > $max_cart_amount ) {
573
- return false;
 
 
 
 
 
 
 
574
  }
575
- }
576
 
577
- // All passed
578
- return apply_filters( 'wcj_checkout_custom_field_visible', true, $i );
579
- }
580
 
581
- /**
582
- * add_custom_checkout_fields.
583
- *
584
- * @version 5.5.0
585
- * @todo (maybe) fix - priority seems to not affect tab order (same in Checkout Core Fields module)
586
- * @todo (dev) (maybe) add `do_shortcode` for e.g. `description` etc.
587
- */
588
- function add_custom_checkout_fields( $fields ) {
 
589
 
590
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
591
 
592
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
593
 
594
- if ( ! $this->is_visible( $i ) ) {
595
- continue;
596
- }
597
 
598
- $the_type = wcj_get_option( 'wcj_checkout_custom_field_type_' . $i );
599
- $custom_attributes = array();
600
- if ( 'datepicker' === $the_type || 'weekpicker' === $the_type || 'timepicker' === $the_type || 'number' === $the_type ) {
601
- if ( 'datepicker' === $the_type || 'weekpicker' === $the_type ) {
602
- $datepicker_format_option = wcj_get_option( 'wcj_checkout_custom_field_datepicker_format_' . $i, '' );
603
- $datepicker_format = ( '' == $datepicker_format_option ) ? wcj_get_option( 'date_format' ) : $datepicker_format_option;
604
- $datepicker_format = wcj_date_format_php_to_js( $datepicker_format );
605
- $custom_attributes['dateformat'] = $datepicker_format;
606
- $custom_attributes['mindate'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_mindate_' . $i, -365 );
607
- if ( 0 == $custom_attributes['mindate'] ) {
608
- $custom_attributes['mindate'] = 'zero';
609
- $custom_attributes['currentday_time_limit'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_current_day_time_limit_' . $i, 0 );
610
- $current_datetime = current_datetime();
611
- $time_limit_datetime = new \DateTime(null, $current_datetime->getTimezone());
612
- $time_limit_datetime->setTimestamp($current_datetime->getTimestamp());
613
- if ( ! empty( $custom_attributes['currentday_time_limit'] ) ) {
614
- $time = explode( ':', $custom_attributes['currentday_time_limit'] );
615
- $time_limit_datetime->setTime( $time[0], $time[1] );
 
 
 
 
616
  }
617
- if ( $time_limit_datetime < $current_datetime ) {
618
- $custom_attributes['mindate'] = 1;
 
619
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
620
  }
621
- $custom_attributes['maxdate'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_maxdate_' . $i, 365 );
622
- if ( 0 == $custom_attributes['maxdate'] ) {
623
- $custom_attributes['maxdate'] = 'zero';
624
- }
625
- $custom_attributes['firstday'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_firstday_' . $i, 0 );
626
- if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_datepicker_changeyear_' . $i, 'yes' ) ) {
627
- $custom_attributes['changeyear'] = 1;
628
- $custom_attributes['yearrange'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_yearrange_' . $i, 'c-10:c+10' );
629
- }
630
- $custom_attributes['display'] = ( 'datepicker' === $the_type ) ? 'date' : 'week';
631
- //Blocked Dates
632
- $blocked_dates_format = wcj_get_option( 'wcj_checkout_custom_field_datepicker_blockeddates_format_' . $i, 'mm-dd' );
633
- $custom_attributes['data-blocked_dates_format']=$blocked_dates_format;
634
- $blocked_dates_textarea = wcj_get_option( 'wcj_checkout_custom_field_datepicker_blockeddates_' . $i, '' );
635
- $custom_attributes['data-blocked_dates'] = implode( ' ', array_map( 'trim', explode( PHP_EOL, $blocked_dates_textarea ) ) );
636
- } elseif ( 'timepicker' === $the_type ) {
637
- $custom_attributes['timeformat'] = wcj_get_option( 'wcj_checkout_custom_field_timepicker_format_' . $i, 'hh:mm p' );
638
- $custom_attributes['interval'] = wcj_get_option( 'wcj_checkout_custom_field_timepicker_interval_' . $i, 15 );
639
- $custom_attributes['display'] = 'time';
640
- } else { // 'number'
641
- $custom_attributes['display'] = $the_type;
642
  }
643
- $the_type = 'text';
644
- }
645
- $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
646
- $the_key = 'wcj_checkout_field_' . $i;
647
-
648
- $the_field = array(
649
- 'type' => $the_type,
650
- 'label' => wcj_get_option( 'wcj_checkout_custom_field_label_' . $i ),
651
- 'placeholder' => wcj_get_option( 'wcj_checkout_custom_field_placeholder_' . $i ),
652
- 'required' => ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_required_' . $i ) ),
653
- 'custom_attributes' => $custom_attributes,
654
- 'clear' => ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_clear_' . $i ) ),
655
- 'class' => array( wcj_get_option( 'wcj_checkout_custom_field_class_' . $i ) ),
656
- 'priority' => wcj_get_option( 'wcj_checkout_custom_field_priority_' . $i, '' ),
657
- 'description' => wcj_get_option( 'wcj_checkout_custom_field_description_' . $i, '' ),
658
- );
659
 
660
- if ( 'select' === $the_type || 'radio' === $the_type ) {
661
- $select_options_raw = wcj_get_option( 'wcj_checkout_custom_field_select_options_' . $i );
662
- $select_options = wcj_get_select_options( $select_options_raw,false );
663
- if ( 'select' === $the_type ) {
664
- $placeholder = wcj_get_option( 'wcj_checkout_custom_field_placeholder_' . $i );
665
- if ( '' != $placeholder ) {
666
- $select_options = array_replace( array( '' => $placeholder ), $select_options );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
667
  }
668
  }
669
- $the_field['options'] = $select_options;
670
- if ( ! empty( $select_options ) ) {
671
- reset( $select_options );
672
- $the_field['default'] = key( $select_options );
673
  }
674
- }
675
 
676
- if ( 'checkbox' === $the_type ) {
677
- $the_field['default'] = ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_checkbox_default_' . $i ) ) ? 1 : 0;
678
  }
679
-
680
- $fields[ $the_section ][ $the_section . '_' . $the_key ] = $the_field;
681
  }
 
682
  }
683
- return $fields;
684
- }
685
 
686
- }
687
 
688
  endif;
689
 
690
- return new WCJ_Checkout_Custom_Fields();
4
  *
5
  * @version 5.5.6
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit;
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Checkout_Custom_Fields' ) ) :
15
 
 
 
16
  /**
17
+ * WCJ_Checkout_Custom_Fields.
18
  *
19
+ * @version 2.7.0
 
20
  */
21
+ class WCJ_Checkout_Custom_Fields extends WCJ_Module {
22
+
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @version 5.4.0
27
+ * @todo (maybe) check if `'wcj_checkout_custom_field_customer_meta_fields_' . $i` option should affect `add_default_checkout_custom_fields`
28
+ */
29
+ public function __construct() {
30
+
31
+ $this->id = 'checkout_custom_fields';
32
+ $this->short_desc = __( 'Checkout Custom Fields', 'woocommerce-jetpack' );
33
+ $this->desc = __( 'Add custom fields to the checkout page (1 field allowed in free version).', 'woocommerce-jetpack' );
34
+ $this->desc_pro = __( 'Add custom fields to the checkout page.', 'woocommerce-jetpack' );
35
+ $this->link_slug = 'woocommerce-checkout-custom-fields';
36
+ $this->extra_desc = sprintf(
37
+ /* translators: %s: search term */
38
+ __( 'After setting Checkout Custom Fields, you can use below shortcode with meta_key to display the Product Input Fields value: %s', 'woocommerce-jetpack' ),
39
+ '<ol>' .
40
+ '<li>' . sprintf(
41
+ /* translators: %s: search term */
42
+ __( '<strong>Shortcodes:</strong> %s', 'woocommerce-jetpack' ),
43
+ '<code>[wcj_order_checkout_field meta_key = "billing_wcj_checkout_field_&lt;field_id&gt;"]</code><br>field_id is the key of your Checkout Custom Fields, You will find key from Option Custom Field'
44
+ ) .
45
  '</li>' .
46
+ '<li>' . sprintf(
47
+ /* translators: %s: search term */
48
+ __( '<strong>PHP code:</strong> by using %1$s function,<br> e.g.: %2$s', 'woocommerce-jetpack' ),
49
  '<code>do_shortcode()</code>',
50
+ '<code>echo&nbsp;do_shortcode(&nbsp;\'[wcj_order_checkout_field meta_key = "billing_wcj_checkout_field_1]\'&nbsp;);</code>'
51
+ ) .
52
  '</li>' .
53
+ '</ol>'
54
+ );
55
 
56
+ $this->wcj_checkout_custom_fields_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_fields_total_number', 1 ) );
57
 
58
+ parent::__construct();
59
+
60
+ if ( $this->is_enabled() ) {
61
+ add_filter( 'woocommerce_checkout_fields', array( $this, 'add_custom_checkout_fields' ), PHP_INT_MAX );
62
+ add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_custom_billing_fields_to_admin_order_display' ), PHP_INT_MAX );
63
+ add_filter( 'woocommerce_admin_shipping_fields', array( $this, 'add_custom_shipping_fields_to_admin_order_display' ), PHP_INT_MAX );
64
+ add_action( 'woocommerce_admin_order_data_after_shipping_address', array( $this, 'add_custom_order_and_account_fields_to_admin_order_display' ), PHP_INT_MAX );
65
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_fields_add_to_order_received', 'yes' ) ) {
66
+ add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_custom_fields_to_view_order_and_thankyou_pages' ), PHP_INT_MAX );
 
 
 
 
 
 
 
 
 
 
 
67
  }
68
+ add_action( 'woocommerce_email_after_order_table', array( $this, 'add_custom_fields_to_emails' ), PHP_INT_MAX, 2 );
69
+ add_filter( 'woo_ce_order_fields', array( $this, 'add_custom_fields_to_store_exporter' ) );
70
+ add_filter( 'woo_ce_order', array( $this, 'add_custom_fields_to_store_exporter_order' ), PHP_INT_MAX, 2 );
71
+ add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'update_custom_checkout_fields_order_meta' ) );
72
+ add_filter( 'woocommerce_form_field_text', array( $this, 'woocommerce_form_field_type_number' ), PHP_INT_MAX, 4 );
73
+ add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_checkout_custom_fields_customer_meta_fields' ) );
74
+ for ( $i = 1; $i <= $this->wcj_checkout_custom_fields_total_number; $i++ ) {
75
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
76
+ $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
77
+ $the_key = 'wcj_checkout_field_' . $i;
78
+ $the_name = $the_section . '_' . $the_key;
79
+ add_filter( 'default_checkout_' . $the_name, array( $this, 'add_default_checkout_custom_fields' ), PHP_INT_MAX, 2 );
80
+ }
81
+ }
82
+ // Select2 script.
83
+ add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ) );
84
 
85
+ // Update checkout fields from admin edit order.
86
+ add_action( 'save_post_shop_order', array( $this, 'update_custom_checkout_fields_order_meta' ) );
87
 
88
+ // Update checkout fields from admin on a subscription order.
89
+ add_action( 'save_post_shop_subscription', array( $this, 'update_custom_checkout_fields_order_meta' ) );
90
+ }
91
  }
 
92
 
93
+ /**
94
+ * Maybe_enqueue_scripts.
95
+ *
96
+ * @version 3.6.0
97
+ * @since 3.2.0
98
+ * @param string $fields defines the fields.
99
+ */
100
+ public function maybe_enqueue_scripts( $fields ) {
101
+ if ( is_checkout() ) {
102
+ $select2_fields = array();
103
+ for ( $i = 1; $i <= $this->wcj_checkout_custom_fields_total_number; $i++ ) {
104
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i, 'no' ) ) {
105
+ if ( 'select' === wcj_get_option( 'wcj_checkout_custom_field_type_' . $i, 'text' ) ) {
106
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_select_select2_' . $i, 'no' ) ) {
107
+ $select2_fields[] = array(
108
+ 'field_id' => wcj_get_option( 'wcj_checkout_custom_field_section_' . $i, 'billing' ) . '_wcj_checkout_field_' . $i,
109
+ 'minimumInputLength' => wcj_get_option( 'wcj_checkout_custom_field_select_select2_min_input_length' . $i, 0 ),
110
+ 'maximumInputLength' => wcj_get_option( 'wcj_checkout_custom_field_select_select2_max_input_length' . $i, 0 ),
111
+ );
112
+ }
113
  }
114
  }
115
  }
116
+ if ( ! empty( $select2_fields ) ) {
117
+ wp_enqueue_script(
118
+ 'wcj-checkout-custom-fields',
119
+ wcj_plugin_url() . '/includes/js/wcj-checkout-custom-fields.js',
120
+ array( 'jquery' ),
121
+ w_c_j()->version,
122
+ true
123
+ );
124
+ wp_localize_script(
125
+ 'wcj-checkout-custom-fields',
126
+ 'wcj_checkout_custom_fields',
127
+ array(
128
+ 'select2_fields' => $select2_fields,
129
+ )
130
+ );
131
+ }
132
  }
133
  }
 
134
 
135
+ /**
136
+ * Add_checkout_custom_fields_customer_meta_fields.
137
+ *
138
+ * @version 3.2.4
139
+ * @since 2.4.5
140
+ * @param string $fields defines the fields.
141
+ */
142
+ public function add_checkout_custom_fields_customer_meta_fields( $fields ) {
143
+ for ( $i = 1; $i <= $this->wcj_checkout_custom_fields_total_number; $i++ ) {
144
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
145
+ if ( 'no' === wcj_get_option( 'wcj_checkout_custom_field_customer_meta_fields_' . $i, 'yes' ) ) {
146
+ continue;
147
+ }
148
+ $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
149
+ $the_key = 'wcj_checkout_field_' . $i;
150
+ $the_name = $the_section . '_' . $the_key;
151
+ $fields[ $the_section ]['fields'][ $the_name ] = array(
152
+ 'label' => wcj_get_option( 'wcj_checkout_custom_field_label_' . $i ),
153
+ 'description' => '',
154
+ );
155
  }
 
 
 
 
 
 
 
156
  }
157
+ return $fields;
158
  }
 
 
159
 
160
+ /**
161
+ * Add_default_checkout_custom_fields.
162
+ *
163
+ * @version 2.4.5
164
+ * @since 2.4.5
165
+ * @param string $default_value defines the default_value.
166
+ * @param string $field_key defines the field_key.
167
+ */
168
+ public function add_default_checkout_custom_fields( $default_value, $field_key ) {
169
+ if ( is_user_logged_in() ) {
170
+ $current_user = wp_get_current_user();
171
+ $meta = get_user_meta( $current_user->ID, $field_key, true );
172
+ if ( $meta ) {
173
+ return $meta;
174
+ }
175
  }
176
+ return $default_value;
177
  }
 
 
178
 
179
+ /**
180
+ * Woocommerce_form_field_type_number.
181
+ *
182
+ * @version 2.3.0
183
+ * @since 2.3.0
184
+ * @param string $field defines the field.
185
+ * @param string $key defines the key.
186
+ * @param array $args defines the args.
187
+ * @param string $value defines the value.
188
+ */
189
+ public function woocommerce_form_field_type_number( $field, $key, $args, $value ) {
190
+ if ( isset( $args['custom_attributes']['display'] ) && 'number' === $args['custom_attributes']['display'] ) {
191
+ $field = str_replace( '<input type="text" ', '<input type="number" ', $field );
192
+ }
193
+ return $field;
194
  }
 
 
195
 
196
+ /**
197
+ * Add_custom_fields_to_store_exporter_order.
198
+ *
199
+ * @version 2.3.0
200
+ * @since 2.2.7
201
+ * @param string $order defines the order.
202
+ * @param string $order_id defines the order_id.
203
+ */
204
+ public function add_custom_fields_to_store_exporter_order( $order, $order_id ) {
205
+ $post_meta = get_post_meta( $order_id );
206
+ foreach ( $post_meta as $key => $values ) {
207
+ if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
208
+ if ( false !== strpos( $key, '_label_' ) ) {
209
+ continue;
210
+ }
211
+ $order->$key = isset( $values[0]['value'] ) ? $values[0]['value'] : $values[0];
212
  }
 
213
  }
 
214
 
215
+ return $order;
216
+ }
217
 
218
+ /**
219
+ * Add_custom_fields_to_store_exporter.
220
+ *
221
+ * @param string $fields defines the fields.
222
+ */
223
+ public function add_custom_fields_to_store_exporter( $fields ) {
224
+ for ( $i = 1; $i <= $this->wcj_checkout_custom_fields_total_number; $i++ ) {
225
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
226
+ $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
227
+ $the_key = 'wcj_checkout_field_' . $i;
228
+ $fields[] = array(
229
+ 'name' => $the_section . '_' . $the_key,
230
+ 'label' => wcj_get_option( 'wcj_checkout_custom_field_label_' . $i ),
231
+ );
232
+ }
233
  }
234
+ return $fields;
235
  }
 
 
236
 
237
+ /**
238
+ * Update_custom_checkout_fields_order_meta.
239
+ *
240
+ * @version 5.4.3
241
+ *
242
+ * @param string $order_id defines the order_id.
243
+ */
244
+ public function update_custom_checkout_fields_order_meta( $order_id ) {
245
+ for ( $i = 1; $i <= $this->wcj_checkout_custom_fields_total_number; $i++ ) {
246
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
247
+ if ( 'woocommerce_checkout_update_order_meta' === current_filter() && ! $this->is_visible( $i ) ) {
248
+ continue;
249
+ }
250
+ $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
251
+ $the_type = wcj_get_option( 'wcj_checkout_custom_field_type_' . $i );
252
+ $option_name = $the_section . '_wcj_checkout_field_' . $i;
253
+ $option_name_label = $the_section . '_wcj_checkout_field_label_' . $i;
254
+ $option_name_type = $the_section . '_wcj_checkout_field_type_' . $i;
255
+ $post_value = ( isset( $_POST[ $option_name ] ) ? ( sanitize_text_field( wp_unslash( $_POST[ $option_name ] ) ) ) : ! empty( $_POST[ '_' . $option_name ] ) ) ? sanitize_text_field( wp_unslash( $_POST[ '_' . $option_name ] ) ) : get_post_meta( $order_id, '_' . $option_name, true );
256
+ if ( ! empty( $post_value ) || 'checkbox' === $the_type ) {
257
+ update_post_meta( $order_id, '_' . $option_name_type, $the_type );
258
+ update_post_meta( $order_id, '_' . $option_name_label, wcj_get_option( 'wcj_checkout_custom_field_label_' . $i ) );
259
+ if ( 'checkbox' === $the_type ) {
260
+ $the_value = ! empty( $post_value ) ? 1 : 0;
261
+ update_post_meta( $order_id, '_' . $option_name, $the_value );
262
+ $option_name_checkbox_value = $the_section . '_wcj_checkout_field_checkbox_value_' . $i;
263
+ $checkbox_value = ( 1 === $the_value ) ?
264
  get_option( 'wcj_checkout_custom_field_checkbox_yes_' . $i ) :
265
  get_option( 'wcj_checkout_custom_field_checkbox_no_' . $i );
266
+ update_post_meta( $order_id, '_' . $option_name_checkbox_value, $checkbox_value );
267
+ } elseif ( 'radio' === $the_type || 'select' === $the_type ) {
268
+ update_post_meta( $order_id, '_' . $option_name, wc_clean( urldecode( $post_value ) ) );
269
+ $option_name_values = $the_section . '_wcj_checkout_field_select_options_' . $i;
270
+ $the_values = wcj_get_option( 'wcj_checkout_custom_field_select_options_' . $i );
271
+ update_post_meta( $order_id, '_' . $option_name_values, $the_values );
272
+ } elseif ( 'textarea' === $the_type && 'no' === wcj_get_option( 'wcj_checkout_custom_fields_textarea_clean', 'yes' ) ) {
273
+ update_post_meta( $order_id, '_' . $option_name, urldecode( $post_value ) );
274
+ } else {
275
+ update_post_meta( $order_id, '_' . $option_name, wc_clean( urldecode( $post_value ) ) );
276
+ }
277
  }
278
  }
279
  }
280
  }
 
281
 
282
+ /**
283
+ * Add_custom_fields_to_emails.
284
+ *
285
+ * @version 3.2.2
286
+ * @param string $order defines the order.
287
+ * @param string $sent_to_admin defines the sent_to_admin.
288
+ */
289
+ public function add_custom_fields_to_emails( $order, $sent_to_admin ) {
290
+ if (
291
+ ( $sent_to_admin && 'yes' === wcj_get_option( 'wcj_checkout_custom_fields_email_all_to_admin' ) ) ||
292
  ( ! $sent_to_admin && 'yes' === wcj_get_option( 'wcj_checkout_custom_fields_email_all_to_customer' ) )
293
+ ) {
294
+ $templates = array(
295
+ 'before' => wcj_get_option( 'wcj_checkout_custom_fields_emails_template_before', '' ),
296
+ 'field' => wcj_get_option( 'wcj_checkout_custom_fields_emails_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
297
+ 'after' => wcj_get_option( 'wcj_checkout_custom_fields_emails_template_after', '' ),
298
+ );
299
+ $this->add_custom_fields_to_order_display( $order, '', $templates );
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Add_custom_fields_to_view_order_and_thankyou_pages.
305
+ *
306
+ * @version 3.2.2
307
+ * @since 3.2.2
308
+ * @param string $order defines the order.
309
+ */
310
+ public function add_custom_fields_to_view_order_and_thankyou_pages( $order ) {
311
  $templates = array(
312
+ 'before' => wcj_get_option( 'wcj_checkout_custom_fields_order_received_template_before', '' ),
313
+ 'field' => wcj_get_option( 'wcj_checkout_custom_fields_order_received_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
314
+ 'after' => wcj_get_option( 'wcj_checkout_custom_fields_order_received_template_after', '' ),
315
  );
316
  $this->add_custom_fields_to_order_display( $order, '', $templates );
317
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
 
319
+ /**
320
+ * Add_custom_fields_to_order_display.
321
+ *
322
+ * @version 5.4.7
323
+ * @since 2.3.0
324
+ * @todo convert from before version 2.3.0
325
+ * @param string $order defines the order.
326
+ * @param string $section defines the section.
327
+ * @param string $templates defines the templates.
328
+ */
329
+ public function add_custom_fields_to_order_display( $order, string $section = null, $templates ) {
330
+ $post_meta = get_post_meta( wcj_get_order_id( $order ) );
331
+ $final_output = '';
332
+ foreach ( $post_meta as $key => $values ) {
333
+ if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
334
+ // Checking section (if set).
335
+ if ( '' !== $section ) {
336
+ $the_section = strtok( $key, '_' );
337
+ if ( $section !== $the_section ) {
338
+ continue;
339
+ }
340
  }
341
+ // Skipping unnecessary meta.
342
+ if (
 
343
  false !== strpos( $key, '_label_' ) ||
344
  false !== strpos( $key, '_type_' ) ||
345
  false !== strpos( $key, '_checkbox_value_' ) ||
346
  false !== strpos( $key, '_select_options_' )
347
+ ) {
348
+ continue;
349
+ }
350
+ // Field label.
351
+ $label = '';
352
+ $the_label_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_label_', $key );
353
+ if ( isset( $post_meta[ $the_label_key ][0] ) ) {
354
+ $label = $post_meta[ $the_label_key ][0];
355
+ } elseif ( is_array( $values[0] ) && isset( $values[0]['label'] ) ) {
356
+ $label = $values[0]['label'];
357
+ }
358
+ // Field value.
359
+ $value = '';
360
+ $_value = ( is_array( $values[0] ) && isset( $values[0]['value'] ) ? $values[0]['value'] : $values[0] );
361
+ $type_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_type_', $key );
362
+ if ( isset( $post_meta[ $type_key ][0] ) && 'checkbox' === $post_meta[ $type_key ][0] ) {
363
+ $checkbox_value_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_checkbox_value_', $key );
364
+ $value = ( sanitize_text_field( wp_unslash( $post_meta[ $checkbox_value_key ][0] ) ) ? $post_meta[ $checkbox_value_key ][0] : $_value );
365
+ } elseif ( isset( $post_meta[ $type_key ][0] ) && ( 'radio' === $post_meta[ $type_key ][0] || 'select' === $post_meta[ $type_key ][0] ) ) {
366
+ $select_values_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_select_options_', $key );
367
+ $select_values = ( sanitize_text_field( wp_unslash( $post_meta[ $select_values_key ][0] ) ) ) ? $post_meta[ $select_values_key ][0] : '';
368
+ if ( ! empty( $select_values ) ) {
369
+ $select_values_prepared = wcj_get_select_options( $select_values );
370
+ $value = ( sanitize_text_field( wp_unslash( $select_values_prepared[ $_value ] ) ) ? $select_values_prepared[ $_value ] : $_value );
371
+ } else {
372
+ $value = $_value;
373
+ }
374
+ } elseif ( isset( $post_meta[ $type_key ][0] ) && 'textarea' === $post_meta[ $type_key ][0] && 'yes' === wcj_get_option( 'wcj_checkout_custom_fields_textarea_replace_line_breaks', 'no' ) ) {
375
+ $value = str_replace( PHP_EOL, '<br>', $_value );
376
  } else {
377
  $value = $_value;
378
  }
379
+ // Adding field to final output.
380
+ if ( '' !== $value ) {
381
+ if ( 'No' !== $value ) {
382
+ $replaced_values = array(
383
+ '%label%' => $label,
384
+ '%value%' => $value,
385
+ );
386
+ $final_output .= str_replace( array_keys( $replaced_values ), $replaced_values, $templates['field'] );
387
+ }
388
+ } elseif ( '' === $value ) {
389
+ $templates = array(
 
 
 
 
 
 
 
390
  'before' => '',
391
  'field' => '',
392
  'after' => '',
393
  );
394
  $final_output .= str_replace( array_keys( $templates ), $templates, $templates['field'] );
395
+ }
396
+ }
397
+ }
398
+ // Outputting.
399
+ if ( '' !== $final_output ) {
400
+ echo wp_kses_post( $templates['before'] . $final_output . $templates['after'] );
401
  }
402
  }
 
 
 
 
 
403
 
404
+ /**
405
+ * Add_woocommerce_admin_fields.
406
+ *
407
+ * @version 5.5.6
408
+ * @todo converting from before version 2.3.0: section?
409
+ * @todo add alternative way of displaying fields (e.g. new meta box), so we have more control over displaying fields' values (e.g. line breaks)
410
+ * @param string $fields defines the fields.
411
+ * @param string $section defines the section.
412
+ */
413
+ public function add_woocommerce_admin_fields( $fields, $section ) {
414
+ for ( $i = 1; $i <= $this->wcj_checkout_custom_fields_total_number; $i++ ) {
415
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
416
+ $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
417
+ if ( $section !== $the_section ) {
418
+ continue;
419
+ }
420
+ $the_type = wcj_get_option( 'wcj_checkout_custom_field_type_' . $i );
421
+ if ( 'textarea' === $the_type ) { ?>
422
  <script type="text/javascript">
 
423
  jQuery(document).ready(function($){
424
  $("input.textarea").each(function () {
425
  var $txtarea = $("<textarea />");
431
  });
432
  });
433
  </script>
434
+ <?php
435
+ }
436
+
437
+ if ( 'select' === $the_type ) {
 
 
 
 
 
 
 
 
 
438
  $the_class = 'first';
439
+ $options = wcj_get_select_options( wcj_get_option( 'wcj_checkout_custom_field_select_options_' . $i ) );
440
+ } elseif ( 'textarea' === $the_type ) {
441
+ $the_class = 'first textarea';
442
+ } elseif ( 'radio' === $the_type ) {
443
+ $the_options = get_post_meta( get_the_ID(), '_' . $section . '_wcj_checkout_field_select_options_' . $i, true );
444
  if ( ! empty( $the_options ) ) {
445
  $the_type = 'select';
446
  $the_class = 'first';
447
+ $options = wcj_get_select_options( $the_options );
448
  } else {
449
+ $the_options = wcj_get_select_options( wcj_get_option( 'wcj_checkout_custom_field_select_options_' . $i ) );
450
+ if ( ! empty( $the_options ) ) {
451
+ $the_type = 'select';
452
+ $the_class = 'first';
453
+ $options = $the_options;
454
+ } else {
455
+ $the_type = 'text';
456
+ $the_class = 'short';
457
+ }
458
  }
459
+ } elseif ( 'country' === $the_type ) {
460
+ $the_type = 'select';
461
+ $the_class = 'js_field-country select short';
462
+ $options = WC()->countries->get_allowed_countries();
463
+ } else {
464
+ $the_type = 'text';
465
+ $the_class = 'short';
466
  }
467
+ $the_key = 'wcj_checkout_field_' . $i;
468
+ $the_key_label = 'wcj_checkout_field_label_' . $i;
469
+ $the_meta = get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key, true );
470
+ if ( is_array( $the_meta ) ) {
471
+ // Converting from before version 2.3.0.
472
+ if ( isset( $the_meta['value'] ) ) {
473
+ update_post_meta( get_the_ID(), '_' . $section . '_' . $the_key, $the_meta['value'] );
474
+ }
475
+ if ( isset( $the_meta['label'] ) ) {
476
+ update_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, $the_meta['label'] );
477
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
478
  }
479
+ if ( ! isset( $_POST[ '_' . $section . '_' . $the_key ] ) ) {
480
+ $fields[ $the_key ] = array(
481
+ 'type' => $the_type,
482
+ 'label' => ( '' !== get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, true ) ) ?
483
+ get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, true ) :
484
+ get_option( 'wcj_checkout_custom_field_label_' . $i ),
485
+ 'show' => true,
486
+ 'class' => $the_class,
487
+ 'wrapper_class' => 'form-field-wide',
488
+ );
489
+ if ( ! empty( $the_meta ) && ! is_array( $the_meta ) ) {
490
+ $fields[ $the_key ]['value'] = $the_meta;
491
+ }
492
+ if ( isset( $options ) ) {
493
+ add_filter(
494
+ "woocommerce_order_get__{$section}_{$the_key}",
495
+ function ( $name ) use ( $options ) {
496
+ if ( isset( $options[ $name ] ) ) {
497
+ return $options[ $name ];
498
+ }
499
+ return $name;
500
+ }
501
+ );
502
+ $fields[ $the_key ]['options'] = $options;
503
+ }
504
  }
505
  }
506
  }
507
+ return $fields;
508
  }
 
 
 
 
 
 
 
 
 
509
 
510
+ /**
511
+ * Add_custom_billing_fields_to_admin_order_display.
512
+ *
513
+ * @param array $fields defines the fields.
514
+ */
515
+ public function add_custom_billing_fields_to_admin_order_display( $fields ) {
516
+ return $this->add_woocommerce_admin_fields( $fields, 'billing' );
517
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
518
 
519
+ /**
520
+ * Add_custom_shipping_fields_to_admin_order_display.
521
+ *
522
+ * @param array $fields defines the fields.
523
+ */
524
+ public function add_custom_shipping_fields_to_admin_order_display( $fields ) {
525
+ return $this->add_woocommerce_admin_fields( $fields, 'shipping' );
526
+ }
527
 
528
+ /**
529
+ * Add_custom_order_and_account_fields_to_admin_order_display
530
+ *
531
+ * @version 3.2.2
532
+ * @param string $order defines the order.
533
+ */
534
+ public function add_custom_order_and_account_fields_to_admin_order_display( $order ) {
535
+ $templates = array(
536
+ 'before' => '<div class="clear"></div><p>',
537
+ 'field' => '<strong>%label%: </strong>%value%<br>',
538
+ 'after' => '</p>',
539
+ );
540
+ $this->add_custom_fields_to_order_display( $order, 'order', $templates );
541
+ $this->add_custom_fields_to_order_display( $order, 'account', $templates );
542
  }
543
 
544
+ /**
545
+ * Is_visible.
546
+ *
547
+ * @version 4.2.0
548
+ * @since 2.6.0
549
+ * @todo add "user roles to include/exclude"
550
+ * @param string $i defines the i.
551
+ */
552
+ public function is_visible( $i ) {
553
+
554
+ if ( apply_filters( 'wcj_checkout_custom_field_always_visible_on_empty_cart', false ) && WC()->cart->is_empty() ) {
555
+ // Added for "One Page Checkout" plugin compatibility.
556
+ return true;
557
+ }
558
+
559
+ // Checking categories.
560
+ $categories_ex = wcj_get_option( 'wcj_checkout_custom_field_categories_ex_' . $i );
561
+ if ( ! empty( $categories_ex ) ) {
562
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
563
+ $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
564
+ if ( empty( $product_categories ) ) {
565
+ continue;
566
+ }
567
+ foreach ( $product_categories as $product_category ) {
568
+ if ( in_array( $product_category->term_id, $categories_ex, true ) ) {
569
+ return false;
570
+ }
571
  }
572
  }
573
  }
574
+ $categories_in = wcj_get_option( 'wcj_checkout_custom_field_categories_in_' . $i );
575
+ if ( ! empty( $categories_in ) ) {
576
+ $categories_in_cart = array();
577
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
578
+ $product_categories = wp_get_post_terms( $values['product_id'], 'product_cat', array( 'fields' => 'ids' ) );
579
+ $categories_in_cart = array_merge( $product_categories, $categories_in_cart );
580
+ }
581
+ if ( count( array_intersect( $categories_in, $categories_in_cart ) ) === 0 ) {
 
 
 
 
 
 
 
 
 
 
582
  return false;
583
  }
584
  }
585
+
586
+ // Checking products.
587
+ $products_ex = wcj_get_option( 'wcj_checkout_custom_field_products_ex_' . $i );
588
+ if ( ! empty( $products_ex ) ) {
589
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
590
+ if ( in_array( $values['product_id'], $products_ex ) ) {
591
+ return false;
592
+ }
593
  }
594
  }
595
+ $products_in = wcj_get_option( 'wcj_checkout_custom_field_products_in_' . $i );
596
+ if ( ! empty( $products_in ) ) {
597
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
598
+ if ( in_array( $values['product_id'], $products_in ) ) {
599
+ return true;
600
+ }
601
+ }
 
 
602
  return false;
603
  }
604
+
605
+ // Checking min/max cart amount.
606
+ $cart_total = false;
607
+ $min_cart_amount = wcj_get_option( 'wcj_checkout_custom_field_min_cart_amount_' . $i, 0 );
608
+ if ( ( $min_cart_amount ) > 0 ) {
609
  WC()->cart->calculate_totals();
610
  $cart_total = WC()->cart->total;
611
+ if ( $cart_total < $min_cart_amount ) {
612
+ return false;
613
+ }
614
  }
615
+ $max_cart_amount = wcj_get_option( 'wcj_checkout_custom_field_max_cart_amount_' . $i, 0 );
616
+ if ( ( $max_cart_amount ) > 0 ) {
617
+ if ( false === $cart_total ) {
618
+ WC()->cart->calculate_totals();
619
+ $cart_total = WC()->cart->total;
620
+ }
621
+ if ( $cart_total > $max_cart_amount ) {
622
+ return false;
623
+ }
624
  }
 
625
 
626
+ // All passed.
627
+ return apply_filters( 'wcj_checkout_custom_field_visible', true, $i );
628
+ }
629
 
630
+ /**
631
+ * Add_custom_checkout_fields.
632
+ *
633
+ * @version 5.5.0
634
+ * @todo (maybe) fix - priority seems to not affect tab order (same in Checkout Core Fields module)
635
+ * @todo (dev) (maybe) add `do_shortcode` for e.g. `description` etc.
636
+ * @param array $fields defines the fields.
637
+ */
638
+ public function add_custom_checkout_fields( $fields ) {
639
 
640
+ for ( $i = 1; $i <= $this->wcj_checkout_custom_fields_total_number; $i++ ) {
641
 
642
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
643
 
644
+ if ( ! $this->is_visible( $i ) ) {
645
+ continue;
646
+ }
647
 
648
+ $the_type = wcj_get_option( 'wcj_checkout_custom_field_type_' . $i );
649
+ $custom_attributes = array();
650
+ if ( 'datepicker' === $the_type || 'weekpicker' === $the_type || 'timepicker' === $the_type || 'number' === $the_type ) {
651
+ if ( 'datepicker' === $the_type || 'weekpicker' === $the_type ) {
652
+ $datepicker_format_option = wcj_get_option( 'wcj_checkout_custom_field_datepicker_format_' . $i, '' );
653
+ $datepicker_format = ( '' === $datepicker_format_option ) ? wcj_get_option( 'date_format' ) : $datepicker_format_option;
654
+ $datepicker_format = wcj_date_format_php_to_js( $datepicker_format );
655
+ $custom_attributes['dateformat'] = $datepicker_format;
656
+ $custom_attributes['mindate'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_mindate_' . $i, -365 );
657
+ if ( 0 === $custom_attributes['mindate'] ) {
658
+ $custom_attributes['mindate'] = 'zero';
659
+ $custom_attributes['currentday_time_limit'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_current_day_time_limit_' . $i, 0 );
660
+ $current_datetime = current_datetime();
661
+ $time_limit_datetime = new \DateTime( null, $current_datetime->getTimezone() );
662
+ $time_limit_datetime->setTimestamp( $current_datetime->getTimestamp() );
663
+ if ( ! empty( $custom_attributes['currentday_time_limit'] ) ) {
664
+ $time = explode( ':', $custom_attributes['currentday_time_limit'] );
665
+ $time_limit_datetime->setTime( $time[0], $time[1] );
666
+ }
667
+ if ( $time_limit_datetime < $current_datetime ) {
668
+ $custom_attributes['mindate'] = 1;
669
+ }
670
  }
671
+ $custom_attributes['maxdate'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_maxdate_' . $i, 365 );
672
+ if ( 0 === $custom_attributes['maxdate'] ) {
673
+ $custom_attributes['maxdate'] = 'zero';
674
  }
675
+ $custom_attributes['firstday'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_firstday_' . $i, 0 );
676
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_datepicker_changeyear_' . $i, 'yes' ) ) {
677
+ $custom_attributes['changeyear'] = 1;
678
+ $custom_attributes['yearrange'] = wcj_get_option( 'wcj_checkout_custom_field_datepicker_yearrange_' . $i, 'c-10:c+10' );
679
+ }
680
+ $custom_attributes['display'] = ( 'datepicker' === $the_type ) ? 'date' : 'week';
681
+ // Blocked Dates.
682
+ $blocked_dates_format = wcj_get_option( 'wcj_checkout_custom_field_datepicker_blockeddates_format_' . $i, 'mm-dd' );
683
+ $custom_attributes['data-blocked_dates_format'] = $blocked_dates_format;
684
+ $blocked_dates_textarea = wcj_get_option( 'wcj_checkout_custom_field_datepicker_blockeddates_' . $i, '' );
685
+ $custom_attributes['data-blocked_dates'] = implode( ' ', array_map( 'trim', explode( PHP_EOL, $blocked_dates_textarea ) ) );
686
+ } elseif ( 'timepicker' === $the_type ) {
687
+ $custom_attributes['timeformat'] = wcj_get_option( 'wcj_checkout_custom_field_timepicker_format_' . $i, 'hh:mm p' );
688
+ $custom_attributes['interval'] = wcj_get_option( 'wcj_checkout_custom_field_timepicker_interval_' . $i, 15 );
689
+ $custom_attributes['display'] = 'time';
690
+ } else { // 'number'
691
+ $custom_attributes['display'] = $the_type;
692
  }
693
+ $the_type = 'text';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
694
  }
695
+ $the_section = wcj_get_option( 'wcj_checkout_custom_field_section_' . $i );
696
+ $the_key = 'wcj_checkout_field_' . $i;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
697
 
698
+ $the_field = array(
699
+ 'type' => $the_type,
700
+ 'label' => wcj_get_option( 'wcj_checkout_custom_field_label_' . $i ),
701
+ 'placeholder' => wcj_get_option( 'wcj_checkout_custom_field_placeholder_' . $i ),
702
+ 'required' => ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_required_' . $i ) ),
703
+ 'custom_attributes' => $custom_attributes,
704
+ 'clear' => ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_clear_' . $i ) ),
705
+ 'class' => array( wcj_get_option( 'wcj_checkout_custom_field_class_' . $i ) ),
706
+ 'priority' => wcj_get_option( 'wcj_checkout_custom_field_priority_' . $i, '' ),
707
+ 'description' => wcj_get_option( 'wcj_checkout_custom_field_description_' . $i, '' ),
708
+ );
709
+
710
+ if ( 'select' === $the_type || 'radio' === $the_type ) {
711
+ $select_options_raw = wcj_get_option( 'wcj_checkout_custom_field_select_options_' . $i );
712
+ $select_options = wcj_get_select_options( $select_options_raw, false );
713
+ if ( 'select' === $the_type ) {
714
+ $placeholder = wcj_get_option( 'wcj_checkout_custom_field_placeholder_' . $i );
715
+ if ( '' !== $placeholder ) {
716
+ $select_options = array_replace( array( '' => $placeholder ), $select_options );
717
+ }
718
+ }
719
+ $the_field['options'] = $select_options;
720
+ if ( ! empty( $select_options ) ) {
721
+ reset( $select_options );
722
+ $the_field['default'] = key( $select_options );
723
  }
724
  }
725
+
726
+ if ( 'checkbox' === $the_type ) {
727
+ $the_field['default'] = ( 'yes' === wcj_get_option( 'wcj_checkout_custom_field_checkbox_default_' . $i ) ) ? 1 : 0;
 
728
  }
 
729
 
730
+ $fields[ $the_section ][ $the_section . '_' . $the_key ] = $the_field;
 
731
  }
 
 
732
  }
733
+ return $fields;
734
  }
 
 
735
 
736
+ }
737
 
738
  endif;
739
 
740
+ return new WCJ_Checkout_Custom_Fields();
includes/class-wcj-checkout-custom-info.php CHANGED
@@ -5,61 +5,70 @@
5
  * @version 5.2.0
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
-
 
12
  if ( ! class_exists( 'WCJ_Checkout_Custom_Info' ) ) :
13
-
14
- class WCJ_Checkout_Custom_Info extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 5.2.0
20
  */
21
- function __construct() {
22
 
23
- $this->id = 'checkout_custom_info';
24
- $this->short_desc = __( 'Checkout Custom Info', 'woocommerce-jetpack' );
25
- $this->desc = __( 'Add custom info to the checkout page (1 block allowed in free version).', 'woocommerce-jetpack' );
26
- $this->desc_pro = __( 'Add custom info to the checkout page.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-checkout-custom-info';
28
- parent::__construct();
29
 
30
- if ( $this->is_enabled() ) {
31
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_info_total_number', 1 ) ); $i++) {
32
- add_action(
33
- get_option( 'wcj_checkout_custom_info_hook_' . $i, 'woocommerce_checkout_after_order_review' ),
34
- array( $this, 'add_checkout_custom_info' ),
35
- get_option( 'wcj_checkout_custom_info_priority_' . $i, 10 )
36
- );
 
 
 
 
 
 
 
 
 
 
37
  }
38
  }
39
- }
40
 
41
- /**
42
- * add_checkout_custom_info.
43
- *
44
- * @version 2.4.7
45
- */
46
- function add_checkout_custom_info() {
47
- $current_filter = current_filter();
48
- $current_filter_priority = wcj_current_filter_priority();
49
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_info_total_number', 1 ) );
50
- for ( $i = 1; $i <= $total_number; $i++ ) {
51
- if (
52
- '' != wcj_get_option( 'wcj_checkout_custom_info_content_' . $i ) &&
53
- $current_filter === wcj_get_option( 'wcj_checkout_custom_info_hook_' . $i ) &&
54
- $current_filter_priority == wcj_get_option( 'wcj_checkout_custom_info_priority_' . $i, 10 )
55
- ) {
56
- echo do_shortcode( wcj_get_option( 'wcj_checkout_custom_info_content_' . $i ) );
 
 
57
  }
58
  }
59
- }
60
 
61
- }
62
 
63
- endif;
64
 
65
- return new WCJ_Checkout_Custom_Info();
5
  * @version 5.2.0
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
  if ( ! class_exists( 'WCJ_Checkout_Custom_Info' ) ) :
 
 
 
15
  /**
16
+ * WCJ_Checkout_Custom_Info.
17
  *
18
+ * @version 2.7.0
19
  */
20
+ class WCJ_Checkout_Custom_Info extends WCJ_Module {
21
 
22
+ /**
23
+ * Constructor.
24
+ *
25
+ * @version 5.2.0
26
+ */
27
+ public function __construct() {
28
 
29
+ $this->id = 'checkout_custom_info';
30
+ $this->short_desc = __( 'Checkout Custom Info', 'woocommerce-jetpack' );
31
+ $this->desc = __( 'Add custom info to the checkout page (1 block allowed in free version).', 'woocommerce-jetpack' );
32
+ $this->desc_pro = __( 'Add custom info to the checkout page.', 'woocommerce-jetpack' );
33
+ $this->link_slug = 'woocommerce-checkout-custom-info';
34
+ parent::__construct();
35
+ $this->wcj_checkout_custom_info_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_custom_info_total_number', 1 ) );
36
+
37
+ if ( $this->is_enabled() ) {
38
+
39
+ for ( $i = 1; $i <= $this->wcj_checkout_custom_info_total_number; $i++ ) {
40
+ add_action(
41
+ get_option( 'wcj_checkout_custom_info_hook_' . $i, 'woocommerce_checkout_after_order_review' ),
42
+ array( $this, 'add_checkout_custom_info' ),
43
+ get_option( 'wcj_checkout_custom_info_priority_' . $i, 10 )
44
+ );
45
+ }
46
  }
47
  }
 
48
 
49
+ /**
50
+ * Add_checkout_custom_info.
51
+ *
52
+ * @version 2.4.7
53
+ */
54
+ public function add_checkout_custom_info() {
55
+ $current_filter = current_filter();
56
+ $current_filter_priority = wcj_current_filter_priority();
57
+ settype( $current_filter_priority, 'string' );
58
+ $total_number = $this->wcj_checkout_custom_info_total_number;
59
+ for ( $i = 1; $i <= $total_number; $i++ ) {
60
+ if (
61
+ '' !== wcj_get_option( 'wcj_checkout_custom_info_content_' . $i ) &&
62
+ wcj_get_option( 'wcj_checkout_custom_info_hook_' . $i ) === $current_filter &&
63
+ wcj_get_option( 'wcj_checkout_custom_info_priority_' . $i, 10 ) === $current_filter_priority
64
+ ) {
65
+ echo do_shortcode( wcj_get_option( 'wcj_checkout_custom_info_content_' . $i ) );
66
+ }
67
  }
68
  }
 
69
 
70
+ }
71
 
72
+ endif;
73
 
74
+ return new WCJ_Checkout_Custom_Info();
includes/class-wcj-checkout-customization.php CHANGED
@@ -5,97 +5,105 @@
5
  * @version 5.2.0
6
  * @since 2.7.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Checkout_Customization' ) ) :
13
-
14
- class WCJ_Checkout_Customization extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 5.2.0
20
- * @since 2.7.0
21
  */
22
- function __construct() {
23
 
24
- $this->id = 'checkout_customization';
25
- $this->short_desc = __( 'Checkout Customization', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Customize WooCommerce checkout - restrict countries by customer\'s IP (Plus); hide "Order Again" button; disable selected fields on checkout for logged users and more (Custom fields available in Plus).', 'woocommerce-jetpack' );
27
- $this->desc_pro = __( 'Customize WooCommerce checkout - restrict countries by customer\'s IP; hide "Order Again" button; disable selected fields on checkout for logged users and more.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-checkout-customization';
29
- parent::__construct();
 
30
 
31
- if ( $this->is_enabled() ) {
32
- // "Create an account?" Checkbox
33
- if ( 'default' != ( $create_account_default = wcj_get_option( 'wcj_checkout_create_account_default_checked', 'default' ) ) ) {
34
- if ( 'checked' === $create_account_default ) {
35
- add_filter( 'woocommerce_create_account_default_checked', '__return_true' );
36
- } elseif ( 'not_checked' === $create_account_default ) {
37
- add_filter( 'woocommerce_create_account_default_checked', '__return_false' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  }
39
- }
40
- // Hide "Order Again" button
41
- if ( 'yes' === wcj_get_option( 'wcj_checkout_hide_order_again', 'no' ) ) {
42
- add_action( 'init', array( $this, 'checkout_hide_order_again' ), PHP_INT_MAX );
43
- }
44
- // Disable Fields on Checkout for Logged Users
45
- add_filter( 'woocommerce_checkout_fields' , array( $this, 'maybe_disable_fields' ), PHP_INT_MAX );
46
- $checkout_fields_types = array(
47
- 'country',
48
- 'state',
49
- 'textarea',
50
- 'checkbox',
51
- 'password',
52
- 'text',
53
- 'email',
54
- 'tel',
55
- 'number',
56
- 'select',
57
- 'radio',
58
- );
59
- foreach ( $checkout_fields_types as $checkout_fields_type ) {
60
- add_filter( 'woocommerce_form_field_' . $checkout_fields_type, array( $this, 'maybe_add_description' ), PHP_INT_MAX, 4 );
61
- }
62
- // Custom "order received" message text
63
- if ( 'yes' === wcj_get_option( 'wcj_checkout_customization_order_received_message_enabled', 'no' ) ) {
64
- add_filter( 'woocommerce_thankyou_order_received_text', array( $this, 'customize_order_received_message' ), PHP_INT_MAX, 2 );
65
- }
66
- // Custom checkout login message
67
- if ( 'yes' === wcj_get_option( 'wcj_checkout_customization_checkout_login_message_enabled', 'no' ) ) {
68
- add_filter( 'woocommerce_checkout_login_message', array( $this, 'checkout_login_message' ), PHP_INT_MAX );
69
- }
70
- // Restrict countries by customer's IP
71
- if ( 'yes' === wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_billing', 'no' ) ) {
72
- add_filter( 'woocommerce_countries_allowed_countries', array( $this, 'restrict_countries_by_customer_ip' ), PHP_INT_MAX );
73
- }
74
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_shipping', 'no' ) ) ) {
75
- add_filter( 'woocommerce_countries_shipping_countries', array( $this, 'restrict_countries_by_customer_ip' ), PHP_INT_MAX );
76
- }
77
- // Recalculate Checkout
78
- if ( 'yes' === wcj_get_option( 'wcj_checkout_recalculate_checkout_update_enable', 'no' ) ) {
79
- add_action( 'wp_footer', array( $this, 'recalculate_checkout' ), 50 );
80
- }
81
- // Update Checkout
82
- if ( 'yes' === wcj_get_option( 'wcj_checkout_force_checkout_update_enable', 'no' ) ) {
83
- add_action( 'wp_footer', array( $this, 'update_checkout' ), 50 );
84
  }
85
  }
86
- }
87
 
88
- /**
89
- * Updates checkout.
90
- *
91
- * @version 4.1.0
92
- * @since 4.1.0
93
- */
94
- function update_checkout() {
95
- if ( ! is_checkout() ) {
96
- return;
97
- }
98
- ?>
99
  <script type="text/javascript">
100
  jQuery(function ($) {
101
  var selector = <?php echo wp_json_encode( wcj_get_option( 'wcj_checkout_force_checkout_update_fields', '' ) ); ?>;
@@ -104,20 +112,20 @@ class WCJ_Checkout_Customization extends WCJ_Module {
104
  });
105
  });
106
  </script>
107
- <?php
108
- }
109
-
110
- /**
111
- * Recalculates checkout.
112
- *
113
- * @version 4.1.0
114
- * @since 4.1.0
115
- */
116
- function recalculate_checkout() {
117
- if ( ! is_checkout() ) {
118
- return;
119
  }
120
- ?>
 
 
 
 
 
 
 
 
 
 
 
121
  <script type="text/javascript">
122
  jQuery(function ($) {
123
  var old_values = [];
@@ -132,177 +140,193 @@ class WCJ_Checkout_Customization extends WCJ_Module {
132
  });
133
  });
134
  </script>
135
- <?php
136
- }
137
 
138
- /**
139
- * Checks if conditions are valid in order for the country restriction to work.
140
- *
141
- * @version 4.6.0
142
- * @since 4.6.0
143
- *
144
- * @return bool
145
- */
146
- function are_conditions_valid() {
147
- $valid = false;
148
- $conditions = wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_conditions', array() );
149
- foreach ( $conditions as $key => $condition ) {
150
- $function = $condition;
151
- $valid = $function();
152
- if ( $valid ) {
153
- break;
 
154
  }
 
155
  }
156
- return $valid;
157
- }
158
 
159
- /**
160
- * restrict_countries_by_customer_ip.
161
- *
162
- * @version 4.6.0
163
- * @since 3.4.0
164
- * @todo (maybe) handle case when `wcj_get_country_by_ip()` returns empty string
165
- * @todo (maybe) for shipping countries - filter `woocommerce_ship_to_countries` option
166
- */
167
- function restrict_countries_by_customer_ip( $countries ) {
168
- if (
 
169
  ( 'yes' === wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_ignore_admin', 'no' ) && is_admin() ) ||
170
  ( ! empty( wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_conditions', array() ) ) && ! $this->are_conditions_valid() )
171
- ) {
172
- return $countries;
173
- }
174
- $user_country = wcj_get_country_by_ip();
175
 
176
- // Get country from 'billing_country' user meta
177
- if (
 
 
178
  'yes' === wcj_get_option( 'wcj_checkout_restrict_countries_by_user_billing_country', 'no' ) &&
179
- 0 != ( $user_id = get_current_user_id() )
180
- ) {
181
- $user_country = ! empty( $user_billing_country = get_user_meta( $user_id, 'billing_country', true ) ) ? $user_billing_country : wcj_get_country_by_ip();
182
- }
183
 
184
- // Get country from a manual order ID created by YITH Request a Quote plugin
185
- if ( 'yes' === wcj_get_option( 'wcj_checkout_restrict_countries_based_on_yith_raq', 'no' ) && class_exists( 'YITH_Request_Quote' ) ) {
186
- $yith_order_id = WC()->session->get( 'order_awaiting_payment' );
187
- if ( ! empty( $yith_order_id ) ) {
188
- $user_country = ! empty( $order_billing_country = get_post_meta( $yith_order_id, '_billing_country', true ) ) ? $order_billing_country : wcj_get_country_by_ip();
 
 
189
  }
 
190
  }
191
- return array( $user_country => wcj_get_country_name_by_code( $user_country ) );
192
- }
193
-
194
- /**
195
- * checkout_login_message.
196
- *
197
- * @version 3.3.0
198
- * @since 3.3.0
199
- */
200
- function checkout_login_message( $message ) {
201
- return wcj_get_option( 'wcj_checkout_customization_checkout_login_message', __( 'Returning customer?', 'woocommerce' ) );
202
- }
203
 
204
- /**
205
- * customize_order_received_message.
206
- *
207
- * @version 3.1.0
208
- * @since 3.1.0
209
- */
210
- function customize_order_received_message( $message, $_order ) {
211
- if ( null != $_order ) {
212
- global $post;
213
- $post = get_post( wcj_get_order_id( $_order ) );
214
- setup_postdata( $post );
215
- }
216
- $message = do_shortcode( wcj_get_option( 'wcj_checkout_customization_order_received_message', __( 'Thank you. Your order has been received.', 'woocommerce' ) ) );
217
- if ( null != $_order ) {
218
- wp_reset_postdata();
219
  }
220
- return $message;
221
- }
222
 
223
- /**
224
- * maybe_add_description.
225
- *
226
- * @version 3.8.0
227
- * @since 2.9.0
228
- */
229
- function maybe_add_description( $field, $key, $args, $value ) {
230
- if ( is_user_logged_in() ) {
231
- $fields_to_disable = wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged', array() );
232
- if ( empty( $fields_to_disable ) ) {
233
- $fields_to_disable = array();
 
 
 
 
 
 
234
  }
235
- $fields_to_disable_custom_r = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_r', '' ) ) ) );
236
- $fields_to_disable_custom_d = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_d', '' ) ) ) );
237
- $fields_to_disable = array_merge( $fields_to_disable, $fields_to_disable_custom_r, $fields_to_disable_custom_d );
238
- if ( ! empty( $fields_to_disable ) ) {
239
- if ( in_array( $key, $fields_to_disable ) ) {
240
- $desc = wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_message',
241
- '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>' );
242
- if ( '' != $desc ) {
243
- $field = str_replace( '__WCJ_TEMPORARY_VALUE_TO_REPLACE__', $desc, $field );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
  }
245
  }
246
  }
 
247
  }
248
- return $field;
249
- }
250
 
251
- /**
252
- * maybe_disable_fields.
253
- *
254
- * @version 3.8.0
255
- * @since 2.9.0
256
- * @see woocommerce_form_field
257
- * @todo (maybe) add single option (probably checkbox) to disable all fields
258
- * @todo (maybe) on `'billing_country', 'shipping_country'` change to simple `select` (i.e. probably remove `wc-enhanced-select` class)
259
- */
260
- function maybe_disable_fields( $checkout_fields ) {
261
- if ( is_user_logged_in() ) {
262
- $fields_to_disable = wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged', array() );
263
- if ( empty( $fields_to_disable ) ) {
264
- $fields_to_disable = array();
265
- }
266
- $fields_to_disable_custom_r = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_r', '' ) ) ) );
267
- $fields_to_disable_custom_d = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_d', '' ) ) ) );
268
- $fields_to_disable = array_merge( $fields_to_disable, $fields_to_disable_custom_r, $fields_to_disable_custom_d );
269
- $disable_type_fields = array_merge( array( 'billing_country', 'shipping_country' ), $fields_to_disable_custom_d );
270
- $do_add_desc_placeholder = ( '' != wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_message',
271
- '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>' ) );
272
- if ( ! empty( $fields_to_disable ) ) {
273
- foreach ( $fields_to_disable as $field_to_disable ) {
274
- $section = explode( '_', $field_to_disable );
275
- $section = $section[0];
276
- if ( isset( $checkout_fields[ $section ][ $field_to_disable ] ) ) {
277
- if ( ! isset( $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] ) ) {
278
- $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] = array();
279
- }
280
- $custom_attributes = ( in_array( $field_to_disable, $disable_type_fields ) ? array( 'disabled' => 'disabled' ) : array( 'readonly' => 'readonly' ) );
281
- $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] = array_merge(
282
- $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'],
283
- $custom_attributes
284
- );
285
- if ( $do_add_desc_placeholder ) {
286
- $checkout_fields[ $section ][ $field_to_disable ]['description'] = '__WCJ_TEMPORARY_VALUE_TO_REPLACE__';
 
 
 
 
287
  }
288
  }
289
  }
290
  }
 
291
  }
292
- return $checkout_fields;
293
- }
294
 
295
- /**
296
- * checkout_hide_order_again.
297
- *
298
- * @version 2.6.0
299
- * @since 2.6.0
300
- */
301
- function checkout_hide_order_again() {
302
- remove_action( 'woocommerce_order_details_after_order_table', 'woocommerce_order_again_button' );
303
- }
304
 
305
- }
306
 
307
  endif;
308
 
5
  * @version 5.2.0
6
  * @since 2.7.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Checkout_Customization' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Checkout_Customization.
18
  *
19
+ * @version 2.7.0
 
20
  */
21
+ class WCJ_Checkout_Customization extends WCJ_Module {
22
 
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @version 5.2.0
27
+ * @since 2.7.0
28
+ */
29
+ public function __construct() {
30
 
31
+ $this->id = 'checkout_customization';
32
+ $this->short_desc = __( 'Checkout Customization', 'woocommerce-jetpack' );
33
+ $this->desc = __( 'Customize WooCommerce checkout - restrict countries by customer\'s IP (Plus); hide "Order Again" button; disable selected fields on checkout for logged users and more (Custom fields available in Plus).', 'woocommerce-jetpack' );
34
+ $this->desc_pro = __( 'Customize WooCommerce checkout - restrict countries by customer\'s IP; hide "Order Again" button; disable selected fields on checkout for logged users and more.', 'woocommerce-jetpack' );
35
+ $this->link_slug = 'woocommerce-checkout-customization';
36
+ parent::__construct();
37
+
38
+ if ( $this->is_enabled() ) {
39
+ // "Create an account?" Checkbox.
40
+ $create_account_default = wcj_get_option( 'wcj_checkout_create_account_default_checked', 'default' );
41
+ if ( 'default' !== ( $create_account_default ) ) {
42
+ if ( 'checked' === $create_account_default ) {
43
+ add_filter( 'woocommerce_create_account_default_checked', '__return_true' );
44
+ } elseif ( 'not_checked' === $create_account_default ) {
45
+ add_filter( 'woocommerce_create_account_default_checked', '__return_false' );
46
+ }
47
+ }
48
+ // Hide "Order Again" button.
49
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_hide_order_again', 'no' ) ) {
50
+ add_action( 'init', array( $this, 'checkout_hide_order_again' ), PHP_INT_MAX );
51
+ }
52
+ // Disable Fields on Checkout for Logged Users.
53
+ add_filter( 'woocommerce_checkout_fields', array( $this, 'maybe_disable_fields' ), PHP_INT_MAX );
54
+ $checkout_fields_types = array(
55
+ 'country',
56
+ 'state',
57
+ 'textarea',
58
+ 'checkbox',
59
+ 'password',
60
+ 'text',
61
+ 'email',
62
+ 'tel',
63
+ 'number',
64
+ 'select',
65
+ 'radio',
66
+ );
67
+ foreach ( $checkout_fields_types as $checkout_fields_type ) {
68
+ add_filter( 'woocommerce_form_field_' . $checkout_fields_type, array( $this, 'maybe_add_description' ), PHP_INT_MAX, 4 );
69
+ }
70
+ // Custom "order received" message text.
71
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_customization_order_received_message_enabled', 'no' ) ) {
72
+ add_filter( 'woocommerce_thankyou_order_received_text', array( $this, 'customize_order_received_message' ), PHP_INT_MAX, 2 );
73
+ }
74
+ // Custom checkout login message.
75
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_customization_checkout_login_message_enabled', 'no' ) ) {
76
+ add_filter( 'woocommerce_checkout_login_message', array( $this, 'checkout_login_message' ), PHP_INT_MAX );
77
+ }
78
+ // Restrict countries by customer's IP.
79
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_billing', 'no' ) ) {
80
+ add_filter( 'woocommerce_countries_allowed_countries', array( $this, 'restrict_countries_by_customer_ip' ), PHP_INT_MAX );
81
+ }
82
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_shipping', 'no' ) ) ) {
83
+ add_filter( 'woocommerce_countries_shipping_countries', array( $this, 'restrict_countries_by_customer_ip' ), PHP_INT_MAX );
84
+ }
85
+ // Recalculate Checkout.
86
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_recalculate_checkout_update_enable', 'no' ) ) {
87
+ add_action( 'wp_footer', array( $this, 'recalculate_checkout' ), 50 );
88
+ }
89
+ // Update Checkout.
90
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_force_checkout_update_enable', 'no' ) ) {
91
+ add_action( 'wp_footer', array( $this, 'update_checkout' ), 50 );
92
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  }
94
  }
 
95
 
96
+ /**
97
+ * Updates checkout.
98
+ *
99
+ * @version 4.1.0
100
+ * @since 4.1.0
101
+ */
102
+ public function update_checkout() {
103
+ if ( ! is_checkout() ) {
104
+ return;
105
+ }
106
+ ?>
107
  <script type="text/javascript">
108
  jQuery(function ($) {
109
  var selector = <?php echo wp_json_encode( wcj_get_option( 'wcj_checkout_force_checkout_update_fields', '' ) ); ?>;
112
  });
113
  });
114
  </script>
115
+ <?php
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
+
118
+ /**
119
+ * Recalculates checkout.
120
+ *
121
+ * @version 4.1.0
122
+ * @since 4.1.0
123
+ */
124
+ public function recalculate_checkout() {
125
+ if ( ! is_checkout() ) {
126
+ return;
127
+ }
128
+ ?>
129
  <script type="text/javascript">
130
  jQuery(function ($) {
131
  var old_values = [];
140
  });
141
  });
142
  </script>
143
+ <?php
144
+ }
145
 
146
+ /**
147
+ * Checks if conditions are valid in order for the country restriction to work.
148
+ *
149
+ * @version 4.6.0
150
+ * @since 4.6.0
151
+ *
152
+ * @return bool
153
+ */
154
+ public function are_conditions_valid() {
155
+ $valid = false;
156
+ $conditions = wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_conditions', array() );
157
+ foreach ( $conditions as $key => $condition ) {
158
+ $function = $condition;
159
+ $valid = $function();
160
+ if ( $valid ) {
161
+ break;
162
+ }
163
  }
164
+ return $valid;
165
  }
 
 
166
 
167
+ /**
168
+ * Restrict_countries_by_customer_ip.
169
+ *
170
+ * @version 4.6.0
171
+ * @since 3.4.0
172
+ * @todo (maybe) handle case when `wcj_get_country_by_ip()` returns empty string
173
+ * @todo (maybe) for shipping countries - filter `woocommerce_ship_to_countries` option
174
+ * @param string $countries defines the countries.
175
+ */
176
+ public function restrict_countries_by_customer_ip( $countries ) {
177
+ if (
178
  ( 'yes' === wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_ignore_admin', 'no' ) && is_admin() ) ||
179
  ( ! empty( wcj_get_option( 'wcj_checkout_restrict_countries_by_customer_ip_conditions', array() ) ) && ! $this->are_conditions_valid() )
180
+ ) {
181
+ return $countries;
182
+ }
183
+ $user_country = wcj_get_country_by_ip();
184
 
185
+ // Get country from 'billing_country' user meta.
186
+ $user_id = get_current_user_id();
187
+ $user_billing_country = get_user_meta( $user_id, 'billing_country', true );
188
+ if (
189
  'yes' === wcj_get_option( 'wcj_checkout_restrict_countries_by_user_billing_country', 'no' ) &&
190
+ 0 !== ( $user_id )
191
+ ) {
192
+ $user_country = ! empty( $user_billing_country ) ? $user_billing_country : wcj_get_country_by_ip();
193
+ }
194
 
195
+ // Get country from a manual order ID created by YITH Request a Quote plugin.
196
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_restrict_countries_based_on_yith_raq', 'no' ) && class_exists( 'YITH_Request_Quote' ) ) {
197
+ $yith_order_id = WC()->session->get( 'order_awaiting_payment' );
198
+ if ( ! empty( $yith_order_id ) ) {
199
+ $order_billing_country = get_post_meta( $yith_order_id, '_billing_country', true );
200
+ $user_country = ! empty( $order_billing_country ) ? $order_billing_country : wcj_get_country_by_ip();
201
+ }
202
  }
203
+ return array( $user_country => wcj_get_country_name_by_code( $user_country ) );
204
  }
 
 
 
 
 
 
 
 
 
 
 
 
205
 
206
+ /**
207
+ * Checkout_login_message.
208
+ *
209
+ * @version 3.3.0
210
+ * @since 3.3.0
211
+ * @param string $message defines the message.
212
+ */
213
+ public function checkout_login_message( $message ) {
214
+ return wcj_get_option( 'wcj_checkout_customization_checkout_login_message', __( 'Returning customer?', 'woocommerce' ) );
 
 
 
 
 
 
215
  }
 
 
216
 
217
+ /**
218
+ * Customize_order_received_message.
219
+ *
220
+ * @version 3.1.0
221
+ * @since 3.1.0
222
+ * @param string $message defines the message.
223
+ * @param int | string $_order defines the _order.
224
+ */
225
+ public function customize_order_received_message( $message, $_order ) {
226
+ if ( null !== $_order ) {
227
+ global $post;
228
+ $posts = get_post( wcj_get_order_id( $_order ) );
229
+ setup_postdata( $posts );
230
+ }
231
+ $message = do_shortcode( wcj_get_option( 'wcj_checkout_customization_order_received_message', __( 'Thank you. Your order has been received.', 'woocommerce' ) ) );
232
+ if ( null !== $_order ) {
233
+ wp_reset_postdata();
234
  }
235
+ return $message;
236
+ }
237
+
238
+ /**
239
+ * Maybe_add_description.
240
+ *
241
+ * @version 3.8.0
242
+ * @since 2.9.0
243
+ * @param string $field defines the field.
244
+ * @param string | int $key defines the key.
245
+ * @param string $args defines the args.
246
+ * @param string | int $value defines the value.
247
+ */
248
+ public function maybe_add_description( $field, $key, $args, $value ) {
249
+ if ( is_user_logged_in() ) {
250
+ $fields_to_disable = wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged', array() );
251
+ if ( empty( $fields_to_disable ) ) {
252
+ $fields_to_disable = array();
253
+ }
254
+ $fields_to_disable_custom_r = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_r', '' ) ) ) );
255
+ $fields_to_disable_custom_d = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_d', '' ) ) ) );
256
+ $fields_to_disable = array_merge( $fields_to_disable, $fields_to_disable_custom_r, $fields_to_disable_custom_d );
257
+ if ( ! empty( $fields_to_disable ) ) {
258
+ if ( in_array( $key, $fields_to_disable ) ) {
259
+ $desc = wcj_get_option(
260
+ 'wcj_checkout_customization_disable_fields_for_logged_message',
261
+ '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>'
262
+ );
263
+ if ( '' !== $desc ) {
264
+ $field = str_replace( '__WCJ_TEMPORARY_VALUE_TO_REPLACE__', $desc, $field );
265
+ }
266
  }
267
  }
268
  }
269
+ return $field;
270
  }
 
 
271
 
272
+ /**
273
+ * Maybe_disable_fields.
274
+ *
275
+ * @version 3.8.0
276
+ * @since 2.9.0
277
+ * @see woocommerce_form_field
278
+ * @todo (maybe) add single option (probably checkbox) to disable all fields
279
+ * @todo (maybe) on `'billing_country', 'shipping_country'` change to simple `select` (i.e. probably remove `wc-enhanced-select` class)
280
+ * @param array $checkout_fields defines the checkout_fields.
281
+ */
282
+ public function maybe_disable_fields( $checkout_fields ) {
283
+ if ( is_user_logged_in() ) {
284
+ $fields_to_disable = wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged', array() );
285
+ if ( empty( $fields_to_disable ) ) {
286
+ $fields_to_disable = array();
287
+ }
288
+ $fields_to_disable_custom_r = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_r', '' ) ) ) );
289
+ $fields_to_disable_custom_d = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', wcj_get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_d', '' ) ) ) );
290
+ $fields_to_disable = array_merge( $fields_to_disable, $fields_to_disable_custom_r, $fields_to_disable_custom_d );
291
+ $disable_type_fields = array_merge( array( 'billing_country', 'shipping_country' ), $fields_to_disable_custom_d );
292
+ $do_add_desc_placeholder = ( '' !== wcj_get_option(
293
+ 'wcj_checkout_customization_disable_fields_for_logged_message',
294
+ '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>'
295
+ ) );
296
+ if ( ! empty( $fields_to_disable ) ) {
297
+ foreach ( $fields_to_disable as $field_to_disable ) {
298
+ $section = explode( '_', $field_to_disable );
299
+ $section = $section[0];
300
+ if ( isset( $checkout_fields[ $section ][ $field_to_disable ] ) ) {
301
+ if ( ! isset( $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] ) ) {
302
+ $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] = array();
303
+ }
304
+ $custom_attributes = ( in_array( $field_to_disable, $disable_type_fields ) ? array( 'disabled' => 'disabled' ) : array( 'readonly' => 'readonly' ) );
305
+ $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] = array_merge(
306
+ $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'],
307
+ $custom_attributes
308
+ );
309
+ if ( $do_add_desc_placeholder ) {
310
+ $checkout_fields[ $section ][ $field_to_disable ]['description'] = '__WCJ_TEMPORARY_VALUE_TO_REPLACE__';
311
+ }
312
  }
313
  }
314
  }
315
  }
316
+ return $checkout_fields;
317
  }
 
 
318
 
319
+ /**
320
+ * Checkout_hide_order_again.
321
+ *
322
+ * @version 2.6.0
323
+ * @since 2.6.0
324
+ */
325
+ public function checkout_hide_order_again() {
326
+ remove_action( 'woocommerce_order_details_after_order_table', 'woocommerce_order_again_button' );
327
+ }
328
 
329
+ }
330
 
331
  endif;
332
 
includes/class-wcj-checkout-fees.php CHANGED
@@ -5,276 +5,293 @@
5
  * @version 5.2.0
6
  * @since 3.7.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Checkout_Fees' ) ) :
13
-
14
- class WCJ_Checkout_Fees extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 5.2.0
20
- * @since 3.7.0
21
- * @todo (maybe) rename module to "Cart & Checkout Fees"
22
  */
23
- function __construct() {
24
 
25
- $this->id = 'checkout_fees';
26
- $this->short_desc = __( 'Checkout Fees', 'woocommerce-jetpack' );
27
- $this->desc = __( 'Add fees to WooCommerce cart & checkout (1 fee allowed in free version).', 'woocommerce-jetpack' );
28
- $this->desc_pro = __( 'Add fees to WooCommerce cart & checkout.', 'woocommerce-jetpack' );
29
- $this->link_slug = 'woocommerce-checkout-fees';
30
- parent::__construct();
 
 
31
 
32
- if ( $this->is_enabled() ) {
33
- // Core function
34
- add_action( 'woocommerce_cart_calculate_fees', array( $this, 'add_fees' ), PHP_INT_MAX );
35
- // Checkout fields
36
- $this->checkout_fields = wcj_get_option( 'wcj_checkout_fees_data_checkout_fields', array() );
37
- $this->checkout_fields = array_filter( $this->checkout_fields );
38
- if ( ! empty( $this->checkout_fields ) ) {
39
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
 
 
 
 
 
 
 
 
40
  }
41
  }
42
- }
43
 
44
- /**
45
- * enqueue_scripts.
46
- *
47
- * @version 3.8.0
48
- * @since 3.8.0
49
- */
50
- function enqueue_scripts() {
51
- if ( is_checkout() ) {
52
- wp_enqueue_script( 'wcj-checkout-fees', wcj_plugin_url() . '/includes/js/wcj-checkout-fees.js', array( 'jquery' ), WCJ()->version, true );
53
- wp_localize_script( 'wcj-checkout-fees', 'wcj_checkout_fees', array(
54
- 'checkout_fields' => 'input[name="' . implode( '"], input[name="', $this->checkout_fields ) . '"]',
55
- ) );
 
 
 
 
 
56
  }
57
- }
58
 
59
- /**
60
- * Validate fee without considering overlapping.
61
- *
62
- * @version 4.6.1
63
- * @since 4.5.0
64
- *
65
- * @param $fee_id
66
- * @param WC_Cart $cart
67
- *
68
- * @return bool
69
- */
70
- function is_fee_valid( $fee_id, \WC_Cart $cart ) {
71
- $fees = $this->get_fees();
72
- $enabled = wcj_get_option( 'wcj_checkout_fees_data_enabled', array() );
73
- $values = wcj_get_option( 'wcj_checkout_fees_data_values', array() );
74
 
75
- // Check if is active and empty value
76
- if (
 
77
  ( isset( $enabled[ $fee_id ] ) && 'no' === $enabled[ $fee_id ] ) ||
78
- ( 0 == ( $value = ( isset( $values[ $fee_id ] ) ? $values[ $fee_id ] : 0 ) ) )
79
- ) {
80
- return false;
81
- }
82
 
83
- // Check cart quantity
84
- if (
85
  $cart->get_cart_contents_count() < $fees[ $fee_id ]['cart_min'] ||
86
  ( $fees[ $fee_id ]['cart_max'] > 0 && $cart->get_cart_contents_count() > $fees[ $fee_id ]['cart_max'] )
87
- ) {
88
- return false;
89
- }
90
 
91
- // Check cart total
92
- if (
93
  $cart->get_cart_contents_total() < $fees[ $fee_id ]['cart_min_total'] ||
94
  ( ! empty( $fees[ $fee_id ]['cart_max_total'] ) && $fees[ $fee_id ]['cart_max_total'] > 0 && $cart->get_cart_contents_total() > $fees[ $fee_id ]['cart_max_total'] )
95
- ) {
96
- return false;
97
- }
98
 
99
- // Check checkout fields
100
- if ( ! empty( $this->checkout_fields[ $fee_id ] ) ) {
101
- if ( isset( $post_data ) || isset( $_REQUEST['post_data'] ) ) {
102
- if ( ! isset( $post_data ) ) {
103
- $post_data = array();
104
- parse_str( $_REQUEST['post_data'], $post_data );
105
- }
106
- if ( empty( $post_data[ $this->checkout_fields[ $fee_id ] ] ) ) {
 
 
 
107
  return false;
108
  }
109
- } elseif ( empty( $_REQUEST[ $this->checkout_fields[ $fee_id ] ] ) ) {
110
- return false;
111
  }
 
112
  }
113
- return true;
114
- }
115
 
116
- /**
117
- * @version 4.5.0
118
- * @since 4.5.0
119
- *
120
- * @param $valid_fees
121
- *
122
- * @return array
123
- */
124
- function get_overlapped_fees( $valid_fees ) {
125
- $fees = $this->get_fees();
126
- $overlapped = array();
127
- foreach ( $valid_fees as $fee_id ) {
128
- if ( ! in_array( $fee_id, $overlapped ) ) {
129
- $overlapped = array_unique( array_merge( $overlapped, $fees[ $fee_id ]['overlap'] ) );
 
 
 
130
  }
 
131
  }
132
- return $overlapped;
133
- }
134
 
135
- /**
136
- * Get Fees.
137
- *
138
- * @version 4.6.1
139
- * @since 4.5.0
140
- *
141
- * @param bool $only_enabled
142
- * @param bool $adjust_priority
143
- *
144
- * @return array
145
- */
146
- function get_fees( $only_enabled = true, $adjust_priority = true ) {
147
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_fees_total_number', 1 ) );
148
- $titles = wcj_get_option( 'wcj_checkout_fees_data_titles', array() );
149
- $types = wcj_get_option( 'wcj_checkout_fees_data_types', array() );
150
- $values = wcj_get_option( 'wcj_checkout_fees_data_values', array() );
151
- $cart_min = wcj_get_option( 'wcj_checkout_fees_cart_min_amount', array() );
152
- $cart_min_total = wcj_get_option( 'wcj_checkout_fees_cart_min_total_amount', array() );
153
- $cart_max = wcj_get_option( 'wcj_checkout_fees_cart_max_amount', array() );
154
- $cart_max_total = wcj_get_option( 'wcj_checkout_fees_cart_max_total_amount', array() );
155
- $taxable = wcj_get_option( 'wcj_checkout_fees_data_taxable', array() );
156
- $checkout_fields = wcj_get_option( 'wcj_checkout_fees_data_values', array() );
157
- $enabled = wcj_get_option( 'wcj_checkout_fees_data_enabled', array() );
158
- $overlap_opt = wcj_get_option( 'wcj_checkout_fees_overlap', array() );
159
- $priorities = wcj_get_option( 'wcj_checkout_fees_priority', array() );
160
 
161
- $fees = array();
162
- for ( $i = 1; $i <= $total_number; $i ++ ) {
163
- if ( ! isset( $priorities[ $i ] ) || empty( $priorities[ $i ] ) ) {
164
- $priorities[ $i ] = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
165
  }
166
- $enabled = isset( $enabled[ $i ] ) ? $enabled[ $i ] : 'yes';
167
- if ( $only_enabled && "no" === $enabled ) {
168
- continue;
 
 
 
 
169
  }
170
- $fees[ $i ] = array(
171
- 'enabled' => $enabled,
172
- 'cart_min' => isset( $cart_min[ $i ] ) ? $cart_min[ $i ] : 1,
173
- 'cart_min_total' => isset( $cart_min_total[ $i ] ) ? $cart_min_total[ $i ] : 0,
174
- 'cart_max' => isset( $cart_max[ $i ] ) ? $cart_max[ $i ] : 0,
175
- 'cart_max_total' => isset( $cart_max_total[ $i ] ) ? $cart_max_total[ $i ] : '',
176
- 'title' => isset( $titles[ $i ] ) ? $titles[ $i ] : '',
177
- 'type' => isset( $types[ $i ] ) ? $types[ $i ] : 'fixed',
178
- 'value' => isset( $values[ $i ] ) ? $values[ $i ] : 0,
179
- 'priority' => isset( $priorities[ $i ] ) ? ( $priorities[ $i ] ) : 0,
180
- 'taxable' => isset( $taxable[ $i ] ) ? $taxable[ $i ] : 'yes',
181
- 'checkout_field' => isset( $checkout_fields[ $i ] ) ? $checkout_fields[ $i ] : '',
182
- 'overlap' => isset( $overlap_opt[ $i ] ) ? $overlap_opt[ $i ] : array(),
183
- );
184
  }
185
- if ( $adjust_priority ) {
186
- uksort( $fees, function ( $a, $b ) use ( $fees, $priorities ) {
187
- return $priorities[ $a ] < $priorities[ $b ];
188
- } );
189
- }
190
- return $fees;
191
- }
192
 
193
- /**
194
- * Get valid fees.
195
- *
196
- * @version 4.5.0
197
- * @since 4.5.0
198
- *
199
- * @param $cart
200
- * @param bool $ignore_overlapped
201
- *
202
- * @return array
203
- */
204
- function get_valid_fees( $cart, $ignore_overlapped = true ) {
205
- $titles = wcj_get_option( 'wcj_checkout_fees_data_titles', array() );
206
- $types = wcj_get_option( 'wcj_checkout_fees_data_types', array() );
207
- $values = wcj_get_option( 'wcj_checkout_fees_data_values', array() );
208
- $taxable = wcj_get_option( 'wcj_checkout_fees_data_taxable', array() );
209
 
210
- //$total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_fees_total_number', 1 ) );
211
- $fees = $this->get_fees();
212
 
213
- $fees_to_add = array();
214
- $valid_fees = array();
215
 
216
- // Get Valid fees
217
- foreach ( $fees as $fee_id => $fee_title ) {
218
- if ( ! $this->is_fee_valid( $fee_id, $cart ) ) {
219
- continue;
 
 
220
  }
221
- $valid_fees[] = $fee_id;
222
- }
223
-
224
- // Ignore overlapped
225
- if ( $ignore_overlapped ) {
226
- $overlapped_fees = $this->get_overlapped_fees( $valid_fees );
227
- $valid_fees = array_diff( $valid_fees, $overlapped_fees );
228
- }
229
 
230
- foreach ( $valid_fees as $fee_id ) {
231
- // Adding the fee
232
- $title = ( isset( $titles[ $fee_id ] ) ? $titles[ $fee_id ] : __( 'Fee', 'woocommerce-jetpack' ) . ' #' . $fee_id );
233
- $value = isset( $values[ $fee_id ] ) ? $values[ $fee_id ] : 0;
234
- if ( isset( $types[ $fee_id ] ) && 'percent' === $types[ $fee_id ] ) {
235
- $value = $cart->get_cart_contents_total() * $value / 100;
236
  }
237
- $fees_to_add[ $fee_id ] = array(
238
- 'name' => $title,
239
- 'amount' => $value,
240
- 'taxable' => ( isset( $taxable[ $fee_id ] ) ? ( 'yes' === $taxable[ $fee_id ] ) : true ),
241
- 'tax_class' => 'standard',
242
- );
243
- }
244
 
245
- return $fees_to_add;
246
- }
 
 
 
 
 
 
 
 
 
 
 
 
247
 
248
- /**
249
- * add_fees.
250
- *
251
- * @version 4.5.0
252
- * @since 3.7.0
253
- * @todo fees with same title
254
- * @todo options: `tax_class`
255
- * @todo options: `cart total` (for percent) - include/exclude shipping etc. - https://docs.woocommerce.com/wc-apidocs/class-WC_Cart.html
256
- * @todo options: `rounding` (for percent)
257
- * @todo options: `min/max cart amount`
258
- * @todo options: `products, cats, tags to include/exclude`
259
- * @todo options: `countries to include/exclude`
260
- * @todo options: `user roles to include/exclude`
261
- * @todo see https://wcbooster.zendesk.com/agent/tickets/446
262
- */
263
- function add_fees( $cart ) {
264
- if ( ! wcj_is_frontend() ) {
265
- return;
266
  }
267
 
268
- $fees_to_add = $this->get_valid_fees( $cart );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
 
270
- if ( ! empty( $fees_to_add ) ) {
271
- foreach ( $fees_to_add as $fee_to_add ) {
272
- $cart->add_fee( $fee_to_add['name'], $fee_to_add['amount'], $fee_to_add['taxable'], $fee_to_add['tax_class'] );
 
273
  }
274
  }
275
- }
276
 
277
- }
278
 
279
  endif;
280
 
5
  * @version 5.2.0
6
  * @since 3.7.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Checkout_Fees' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Checkout_Customization.
18
  *
19
+ * @version 2.7.0
 
 
20
  */
21
+ class WCJ_Checkout_Fees extends WCJ_Module {
22
 
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @version 5.2.0
27
+ * @since 3.7.0
28
+ * @todo (maybe) rename module to "Cart & Checkout Fees"
29
+ */
30
+ public function __construct() {
31
 
32
+ $this->id = 'checkout_fees';
33
+ $this->short_desc = __( 'Checkout Fees', 'woocommerce-jetpack' );
34
+ $this->desc = __( 'Add fees to WooCommerce cart & checkout (1 fee allowed in free version).', 'woocommerce-jetpack' );
35
+ $this->desc_pro = __( 'Add fees to WooCommerce cart & checkout.', 'woocommerce-jetpack' );
36
+ $this->link_slug = 'woocommerce-checkout-fees';
37
+ parent::__construct();
38
+
39
+ if ( $this->is_enabled() ) {
40
+ // Core function.
41
+ add_action( 'woocommerce_cart_calculate_fees', array( $this, 'add_fees' ), PHP_INT_MAX );
42
+ // Checkout fields.
43
+ $this->checkout_fields = wcj_get_option( 'wcj_checkout_fees_data_checkout_fields', array() );
44
+ $this->checkout_fields = array_filter( $this->checkout_fields );
45
+ if ( ! empty( $this->checkout_fields ) ) {
46
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
47
+ }
48
  }
49
  }
 
50
 
51
+ /**
52
+ * Enqueue_scripts.
53
+ *
54
+ * @version 3.8.0
55
+ * @since 3.8.0
56
+ */
57
+ public function enqueue_scripts() {
58
+ if ( is_checkout() ) {
59
+ wp_enqueue_script( 'wcj-checkout-fees', wcj_plugin_url() . '/includes/js/wcj-checkout-fees.js', array( 'jquery' ), w_c_j()->version, true );
60
+ wp_localize_script(
61
+ 'wcj-checkout-fees',
62
+ 'wcj_checkout_fees',
63
+ array(
64
+ 'checkout_fields' => 'input[name="' . implode( '"], input[name="', $this->checkout_fields ) . '"]',
65
+ )
66
+ );
67
+ }
68
  }
 
69
 
70
+ /**
71
+ * Validate fee without considering overlapping.
72
+ *
73
+ * @version 4.6.1
74
+ * @since 4.5.0
75
+ *
76
+ * @param int $fee_id defines the fee_id.
77
+ * @param array | string WC_Cart $cart defines the cart.
78
+ *
79
+ * @return bool
80
+ */
81
+ public function is_fee_valid( $fee_id, \WC_Cart $cart ) {
82
+ $fees = $this->get_fees();
83
+ $enabled = wcj_get_option( 'wcj_checkout_fees_data_enabled', array() );
84
+ $values = wcj_get_option( 'wcj_checkout_fees_data_values', array() );
85
 
86
+ // Check if is active and empty value.
87
+ $value = ( isset( $values[ $fee_id ] ) ? $values[ $fee_id ] : 0 );
88
+ if (
89
  ( isset( $enabled[ $fee_id ] ) && 'no' === $enabled[ $fee_id ] ) ||
90
+ ( 0 === ( $value ) )
91
+ ) {
92
+ return false;
93
+ }
94
 
95
+ // Check cart quantity.
96
+ if (
97
  $cart->get_cart_contents_count() < $fees[ $fee_id ]['cart_min'] ||
98
  ( $fees[ $fee_id ]['cart_max'] > 0 && $cart->get_cart_contents_count() > $fees[ $fee_id ]['cart_max'] )
99
+ ) {
100
+ return false;
101
+ }
102
 
103
+ // Check cart total.
104
+ if (
105
  $cart->get_cart_contents_total() < $fees[ $fee_id ]['cart_min_total'] ||
106
  ( ! empty( $fees[ $fee_id ]['cart_max_total'] ) && $fees[ $fee_id ]['cart_max_total'] > 0 && $cart->get_cart_contents_total() > $fees[ $fee_id ]['cart_max_total'] )
107
+ ) {
108
+ return false;
109
+ }
110
 
111
+ // Check checkout fields.
112
+ if ( ! empty( $this->checkout_fields[ $fee_id ] ) ) {
113
+ if ( isset( $post_data ) || isset( $_REQUEST['post_data'] ) ) {
114
+ if ( ! isset( $post_data ) ) {
115
+ $post_data = array();
116
+ parse_str( $_REQUEST['post_data'], $post_data );
117
+ }
118
+ if ( empty( $post_data[ $this->checkout_fields[ $fee_id ] ] ) ) {
119
+ return false;
120
+ }
121
+ } elseif ( empty( $_REQUEST[ $this->checkout_fields[ $fee_id ] ] ) ) {
122
  return false;
123
  }
 
 
124
  }
125
+ return true;
126
  }
 
 
127
 
128
+ /**
129
+ * Get_overlapped_fees.
130
+ *
131
+ * @version 4.5.0
132
+ * @since 4.5.0
133
+ *
134
+ * @param int | string $valid_fees defines the valid_fees.
135
+ *
136
+ * @return array
137
+ */
138
+ public function get_overlapped_fees( $valid_fees ) {
139
+ $fees = $this->get_fees();
140
+ $overlapped = array();
141
+ foreach ( $valid_fees as $fee_id ) {
142
+ if ( ! in_array( $fee_id, $overlapped, true ) ) {
143
+ $overlapped = array_unique( array_merge( $overlapped, $fees[ $fee_id ]['overlap'] ) );
144
+ }
145
  }
146
+ return $overlapped;
147
  }
 
 
148
 
149
+ /**
150
+ * Get Fees.
151
+ *
152
+ * @version 4.6.1
153
+ * @since 4.5.0
154
+ *
155
+ * @param bool $only_enabled check enalbed.
156
+ * @param bool $adjust_priority check adjust_priority.
157
+ *
158
+ * @return array
159
+ */
160
+ public function get_fees( $only_enabled = true, $adjust_priority = true ) {
161
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_fees_total_number', 1 ) );
162
+ $titles = wcj_get_option( 'wcj_checkout_fees_data_titles', array() );
163
+ $types = wcj_get_option( 'wcj_checkout_fees_data_types', array() );
164
+ $values = wcj_get_option( 'wcj_checkout_fees_data_values', array() );
165
+ $cart_min = wcj_get_option( 'wcj_checkout_fees_cart_min_amount', array() );
166
+ $cart_min_total = wcj_get_option( 'wcj_checkout_fees_cart_min_total_amount', array() );
167
+ $cart_max = wcj_get_option( 'wcj_checkout_fees_cart_max_amount', array() );
168
+ $cart_max_total = wcj_get_option( 'wcj_checkout_fees_cart_max_total_amount', array() );
169
+ $taxable = wcj_get_option( 'wcj_checkout_fees_data_taxable', array() );
170
+ $checkout_fields = wcj_get_option( 'wcj_checkout_fees_data_values', array() );
171
+ $enabled = wcj_get_option( 'wcj_checkout_fees_data_enabled', array() );
172
+ $overlap_opt = wcj_get_option( 'wcj_checkout_fees_overlap', array() );
173
+ $priorities = wcj_get_option( 'wcj_checkout_fees_priority', array() );
174
 
175
+ $fees = array();
176
+ for ( $i = 1; $i <= $total_number; $i ++ ) {
177
+ if ( ! isset( $priorities[ $i ] ) || empty( $priorities[ $i ] ) ) {
178
+ $priorities[ $i ] = 0;
179
+ }
180
+ $enabled = isset( $enabled[ $i ] ) ? $enabled[ $i ] : 'yes';
181
+ if ( $only_enabled && 'no' === $enabled ) {
182
+ continue;
183
+ }
184
+ $fees[ $i ] = array(
185
+ 'enabled' => $enabled,
186
+ 'cart_min' => isset( $cart_min[ $i ] ) ? $cart_min[ $i ] : 1,
187
+ 'cart_min_total' => isset( $cart_min_total[ $i ] ) ? $cart_min_total[ $i ] : 0,
188
+ 'cart_max' => isset( $cart_max[ $i ] ) ? $cart_max[ $i ] : 0,
189
+ 'cart_max_total' => isset( $cart_max_total[ $i ] ) ? $cart_max_total[ $i ] : '',
190
+ 'title' => isset( $titles[ $i ] ) ? $titles[ $i ] : '',
191
+ 'type' => isset( $types[ $i ] ) ? $types[ $i ] : 'fixed',
192
+ 'value' => isset( $values[ $i ] ) ? $values[ $i ] : 0,
193
+ 'priority' => isset( $priorities[ $i ] ) ? ( $priorities[ $i ] ) : 0,
194
+ 'taxable' => isset( $taxable[ $i ] ) ? $taxable[ $i ] : 'yes',
195
+ 'checkout_field' => isset( $checkout_fields[ $i ] ) ? $checkout_fields[ $i ] : '',
196
+ 'overlap' => isset( $overlap_opt[ $i ] ) ? $overlap_opt[ $i ] : array(),
197
+ );
198
  }
199
+ if ( $adjust_priority ) {
200
+ uksort(
201
+ $fees,
202
+ function ( $a, $b ) use ( $fees, $priorities ) {
203
+ return $priorities[ $a ] < $priorities[ $b ];
204
+ }
205
+ );
206
  }
207
+ return $fees;
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  }
 
 
 
 
 
 
 
209
 
210
+ /**
211
+ * Get valid fees.
212
+ *
213
+ * @version 4.5.0
214
+ * @since 4.5.0
215
+ *
216
+ * @param string | array $cart define cart details.
217
+ * @param bool $ignore_overlapped define ignore_overlapped.
218
+ *
219
+ * @return array
220
+ */
221
+ public function get_valid_fees( $cart, $ignore_overlapped = true ) {
222
+ $titles = wcj_get_option( 'wcj_checkout_fees_data_titles', array() );
223
+ $types = wcj_get_option( 'wcj_checkout_fees_data_types', array() );
224
+ $values = wcj_get_option( 'wcj_checkout_fees_data_values', array() );
225
+ $taxable = wcj_get_option( 'wcj_checkout_fees_data_taxable', array() );
226
 
227
+ $fees = $this->get_fees();
 
228
 
229
+ $fees_to_add = array();
230
+ $valid_fees = array();
231
 
232
+ // Get Valid fees.
233
+ foreach ( $fees as $fee_id => $fee_title ) {
234
+ if ( ! $this->is_fee_valid( $fee_id, $cart ) ) {
235
+ continue;
236
+ }
237
+ $valid_fees[] = $fee_id;
238
  }
 
 
 
 
 
 
 
 
239
 
240
+ // Ignore overlapped.
241
+ if ( $ignore_overlapped ) {
242
+ $overlapped_fees = $this->get_overlapped_fees( $valid_fees );
243
+ $valid_fees = array_diff( $valid_fees, $overlapped_fees );
 
 
244
  }
 
 
 
 
 
 
 
245
 
246
+ foreach ( $valid_fees as $fee_id ) {
247
+ // Adding the fee.
248
+ $title = ( isset( $titles[ $fee_id ] ) ? $titles[ $fee_id ] : __( 'Fee', 'woocommerce-jetpack' ) . ' #' . $fee_id );
249
+ $value = isset( $values[ $fee_id ] ) ? $values[ $fee_id ] : 0;
250
+ if ( isset( $types[ $fee_id ] ) && 'percent' === $types[ $fee_id ] ) {
251
+ $value = $cart->get_cart_contents_total() * $value / 100;
252
+ }
253
+ $fees_to_add[ $fee_id ] = array(
254
+ 'name' => $title,
255
+ 'amount' => $value,
256
+ 'taxable' => ( isset( $taxable[ $fee_id ] ) ? ( 'yes' === $taxable[ $fee_id ] ) : true ),
257
+ 'tax_class' => 'standard',
258
+ );
259
+ }
260
 
261
+ return $fees_to_add;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  }
263
 
264
+ /**
265
+ * Add_fees.
266
+ *
267
+ * @version 4.5.0
268
+ * @since 3.7.0
269
+ * @todo fees with same title
270
+ * @todo options: `tax_class`
271
+ * @todo options: `cart total` (for percent) - include/exclude shipping etc. - https://docs.woocommerce.com/wc-apidocs/class-WC_Cart.html
272
+ * @todo options: `rounding` (for percent)
273
+ * @todo options: `min/max cart amount`
274
+ * @todo options: `products, cats, tags to include/exclude`
275
+ * @todo options: `countries to include/exclude`
276
+ * @todo options: `user roles to include/exclude`
277
+ * @todo see https://wcbooster.zendesk.com/agent/tickets/446
278
+ * @param string | array $cart defines the cart.
279
+ */
280
+ public function add_fees( $cart ) {
281
+ if ( ! wcj_is_frontend() ) {
282
+ return;
283
+ }
284
+
285
+ $fees_to_add = $this->get_valid_fees( $cart );
286
 
287
+ if ( ! empty( $fees_to_add ) ) {
288
+ foreach ( $fees_to_add as $fee_to_add ) {
289
+ $cart->add_fee( $fee_to_add['name'], $fee_to_add['amount'], $fee_to_add['taxable'], $fee_to_add['tax_class'] );
290
+ }
291
  }
292
  }
 
293
 
294
+ }
295
 
296
  endif;
297
 
includes/class-wcj-checkout-files-upload.php CHANGED
@@ -5,825 +5,992 @@
5
  * @version 5.5.9
6
  * @since 2.4.5
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Checkout_Files_Upload' ) ) :
13
-
14
- class WCJ_Checkout_Files_Upload extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
  *
19
- * @version 5.2.0
20
- * @since 2.4.5
21
- * @todo styling options
22
  */
23
- function __construct() {
24
-
25
- $this->id = 'checkout_files_upload';
26
- $this->short_desc = __( 'Checkout Files Upload', 'woocommerce-jetpack' );
27
- $this->desc = __( 'Let customers upload files on (or after) the checkout (1 file allowed in free version).', 'woocommerce-jetpack' );
28
- $this->desc_pro = __( 'Let customers upload files on (or after) the checkout.', 'woocommerce-jetpack' );
29
- $this->link_slug = 'woocommerce-checkout-files-upload';
30
- parent::__construct();
31
-
32
- if ( $this->is_enabled() ) {
33
- $this->init_settings();
34
- add_action( 'add_meta_boxes', array( $this, 'add_file_admin_order_meta_box' ) );
35
- add_action( 'init', array( $this, 'process_checkout_files_upload' ) );
36
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_remove_on_empty_cart', 'no' ) ) {
37
- add_action( 'woocommerce_cart_item_removed', array( $this, 'remove_files_on_empty_cart' ), PHP_INT_MAX, 2 );
38
- }
39
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
40
- for ( $i = 1; $i <= $total_number; $i++ ) {
41
- if ( 'disable' != ( $the_hook = wcj_get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' ) ) ) {
42
- add_action( $the_hook, array( $this, 'add_files_upload_form_to_checkout_frontend' ), wcj_get_option( 'wcj_checkout_files_upload_hook_priority_' . $i, 10 ) );
43
- }
44
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_thankyou_' . $i, 'no' ) ) {
45
- add_action( 'woocommerce_thankyou', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
 
46
  }
47
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_myaccount_' . $i, 'no' ) ) {
48
- add_action( 'woocommerce_view_order', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
 
 
 
 
 
 
 
 
 
 
49
  }
 
 
 
 
 
50
  }
51
- add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_files_to_order' ), PHP_INT_MAX, 2 );
52
- add_action( 'woocommerce_after_checkout_validation', array( $this, 'validate_on_checkout' ) );
53
- add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
54
- add_action( 'woocommerce_email_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
55
- add_filter( 'woocommerce_email_attachments', array( $this, 'add_files_to_email_attachments' ), PHP_INT_MAX, 3 );
56
  }
57
- }
58
 
59
- /**
60
- * init_settings.
61
- *
62
- * @version 3.9.0
63
- * @since 3.8.0
64
- * @todo (dev) (maybe) init settings on demand only
65
- */
66
- function init_settings() {
67
- $this->templates_settings = wcj_get_option( 'wcj_checkout_files_upload_templates', array() );
68
- $this->templates_settings = wp_parse_args( $this->templates_settings, array(
69
- 'order_before' => '',
70
- 'order_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
71
- 'order_after' => '',
72
- 'order_image_style' => 'width:64px;',
73
- 'email_before' => '',
74
- 'email_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
75
- 'email_after' => '',
76
- ) );
77
- $this->additional_admin_emails_settings = wcj_get_option( 'wcj_checkout_files_upload_additional_admin_emails', array() );
78
- $this->additional_admin_emails_settings = wp_parse_args( $this->additional_admin_emails_settings, array(
79
- 'actions' => array(),
80
- 'do_attach' => 'yes',
81
- ) );
82
- $this->checkout_files_upload_notice_type = wcj_get_option( 'wcj_checkout_files_upload_notice_type', 'wc_add_notice' );
83
- }
84
-
85
- /**
86
- * add_files_to_email_attachments.
87
- *
88
- * @version 2.7.0
89
- * @since 2.5.5
90
- */
91
- function add_files_to_email_attachments( $attachments, $status, $order ) {
92
- if (
93
- ( 'new_order' === $status && 'yes' === wcj_get_option( 'wcj_checkout_files_upload_attach_to_admin_new_order', 'yes' ) ) ||
 
 
 
 
 
 
 
 
 
 
 
94
  ( 'customer_processing_order' === $status && 'yes' === wcj_get_option( 'wcj_checkout_files_upload_attach_to_customer_processing_order', 'yes' ) )
95
- ) {
96
- $total_files = get_post_meta( wcj_get_order_id( $order ), '_' . 'wcj_checkout_files_total_files', true );
97
- for ( $i = 1; $i <= $total_files; $i++ ) {
98
- $attachments[] = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( wcj_get_order_id( $order ), '_' . 'wcj_checkout_files_upload_' . $i, true );
99
- }
100
- }
101
- return $attachments;
102
- }
103
-
104
- /**
105
- * add_files_to_order_display.
106
- *
107
- * @version 5.5.9
108
- * @since 2.4.7
109
- * @todo (maybe) somehow add `%image%` to emails also
110
- */
111
- function add_files_to_order_display( $order ) {
112
- $order_id = wcj_get_order_id( $order );
113
- $html = '';
114
- $total_files = get_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', true );
115
- $do_add_img = false;
116
- if ( 'woocommerce_email_after_order_table' === current_filter() ) {
117
- $template_before = $this->templates_settings['email_before'];
118
- $template_after = $this->templates_settings['email_after'];
119
- $template = $this->templates_settings['email_item'];
120
- } else {
121
- $template_before = $this->templates_settings['order_before'];
122
- $template_after = $this->templates_settings['order_after'];
123
- $template = $this->templates_settings['order_item'];
124
- $do_add_img = ( false !== strpos( $template, '%image%' ) );
125
- if ( $do_add_img ) {
126
- $img_style = $this->templates_settings['order_image_style'];
127
  }
128
- }
129
- for ( $i = 1; $i <= $total_files; $i++ ) {
130
- $real_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
131
- if ( '' != $real_file_name ) {
132
- $img = '';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
133
  if ( $do_add_img ) {
134
- $order_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
135
- if ( @is_array( getimagesize( $order_file_name ) ) ) {
136
- $link = esc_url(add_query_arg( array( 'wcj_download_checkout_file' => $i, '_wpnonce' => wp_create_nonce( 'wcj_download_checkout_file' ), 'wcj_download_checkout_file_order_id' => $order_id ) ));
137
- $img = '<img style="' . $img_style . '" src="' . esc_url($link). '"> ';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  }
 
 
 
 
 
 
 
139
  }
140
- $html .= wcj_handle_replacements( array(
141
- '%file_name%' => $real_file_name,
142
- '%image%' => $img,
143
- ), $template );
144
  }
145
  }
146
- if ( '' != $html ) {
147
- echo $template_before . $html . $template_after;
148
- }
149
- }
150
 
151
- /**
152
- * add_notice.
153
- *
154
- * @version 3.9.0
155
- * @since 3.9.0
156
- */
157
- function add_notice( $message, $notice_type = 'success' ) {
158
- if ( 'wc_add_notice' === $this->checkout_files_upload_notice_type ) {
159
- wc_add_notice( $message, $notice_type );
160
- } elseif ( 'wc_print_notice' === $this->checkout_files_upload_notice_type ) {
161
- wc_print_notice( $message, $notice_type );
 
 
 
162
  }
163
- }
164
 
165
- /**
166
- * validate_on_checkout.
167
- *
168
- * @version 3.9.0
169
- * @since 2.4.5
170
- */
171
- function validate_on_checkout( $posted ) {
172
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
173
- for ( $i = 1; $i <= $total_number; $i++ ) {
174
- if (
 
175
  'yes' === wcj_get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) &&
176
  $this->is_visible( $i ) &&
177
  'disable' != wcj_get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' )
178
- ) {
179
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_required_' . $i, 'no' ) && null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
180
- // Is required
181
- $this->add_notice( wcj_get_option( 'wcj_checkout_files_upload_notice_required_' . $i, __( 'File is required!', 'woocommerce-jetpack' ) ), 'error' );
182
- }
183
- if ( null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
184
- continue;
185
- }
186
- $file_name = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
187
- $file_name = $file_name['name'];
188
- $file_type = '.' . pathinfo( $file_name, PATHINFO_EXTENSION );
189
- if ( '' != ( $file_accept = wcj_get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) ) ) {
190
- // Validate file type
191
- $file_accept = explode( ',', $file_accept );
192
- if ( is_array( $file_accept ) && ! empty( $file_accept ) ) {
193
- if ( ! in_array( $file_type, $file_accept ) ) {
194
- $this->add_notice( sprintf( wcj_get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
195
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $file_name ), 'error' );
 
 
 
 
 
 
 
 
 
 
 
196
  }
197
  }
198
- }
199
- if ( $this->is_extension_blocked( $file_type ) ) {
200
- $this->add_notice( sprintf( wcj_get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
201
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $file_name ), 'error' );
 
 
 
 
 
 
 
 
 
202
  }
203
  }
204
  }
205
- }
206
 
207
- /**
208
- * add_file_admin_order_meta_box.
209
- *
210
- * @version 2.4.5
211
- * @since 2.4.5
212
- */
213
- function add_file_admin_order_meta_box() {
214
- $screen = 'shop_order';
215
- $context = 'side';
216
- $priority = 'high';
217
- add_meta_box(
218
- 'wc-jetpack-' . $this->id,
219
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Uploaded Files', 'woocommerce-jetpack' ),
220
- array( $this, 'create_file_admin_order_meta_box' ),
221
- $screen,
222
- $context,
223
- $priority
224
- );
225
- }
226
 
227
- /**
228
- * create_file_admin_order_meta_box.
229
- *
230
- * @version 5.5.9
231
- * @since 2.4.5
232
- */
233
- function create_file_admin_order_meta_box() {
234
- $order_id = get_the_ID();
235
- $html = '';
236
- $total_files = get_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', true );
237
- $files_exists = false;
238
- for ( $i = 1; $i <= $total_files; $i++ ) {
239
- $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
240
- $real_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
241
- if ( '' != $order_file_name ) {
242
- $files_exists = true;
243
- $html .= '<p><a href="' . esc_url(add_query_arg(
244
- array(
245
- 'wcj_download_checkout_file_admin' => $order_file_name,
246
- 'wcj_checkout_file_number' => $i,
247
- ) ) ) . '">' . $real_file_name . '</a></p>';
 
 
248
  }
249
- }
250
- if ( ! $files_exists ) {
251
- $html .= '<p><em>' . __( 'No files uploaded.', 'woocommerce-jetpack' ) . '</em></p>';
252
- } else {
253
- $html .= '<p><a style="color:#a00;" href="' . esc_url(add_query_arg( 'wcj_download_checkout_file_admin_delete_all', $order_id )) . '"' . wcj_get_js_confirmation() . '>' .
254
  __( 'Delete all files', 'woocommerce-jetpack' ) . '</a></p>';
255
- }
256
- echo $html;
257
- }
258
-
259
- /**
260
- * is_extension_blocked.
261
- *
262
- * @version 3.2.3
263
- * @since 3.2.3
264
- */
265
- function is_extension_blocked( $ext ) {
266
- if ( 'no' === wcj_get_option( 'wcj_checkout_files_upload_block_files_enabled', 'yes' ) ) {
267
- return false;
268
- }
269
- $ext = strtolower( $ext );
270
- if ( strlen( $ext ) > 0 && '.' === $ext[0] ) {
271
- $ext = substr( $ext, 1 );
272
- }
273
- $blocked_file_exts = wcj_get_option( 'wcj_checkout_files_upload_block_files_exts',
274
- 'bat|exe|cmd|sh|php|php0|php1|php2|php3|php4|php5|php6|php7|php8|php9|ph|ph0|ph1|ph2|ph3|ph4|ph5|ph6|ph7|ph8|ph9|pl|cgi|386|dll|com|torrent|js|app|jar|pif|vb|vbscript|wsf|asp|cer|csr|jsp|drv|sys|ade|adp|bas|chm|cpl|crt|csh|fxp|hlp|hta|inf|ins|isp|jse|htaccess|htpasswd|ksh|lnk|mdb|mde|mdt|mdw|msc|msi|msp|mst|ops|pcd|prg|reg|scr|sct|shb|shs|url|vbe|vbs|wsc|wsf|wsh|html|htm'
275
- );
276
- $blocked_file_exts = explode( '|', $blocked_file_exts );
277
- return in_array( $ext, $blocked_file_exts );
278
- }
279
-
280
- /**
281
- * add_files_to_order.
282
- *
283
- * @version 3.4.0
284
- * @since 2.4.5
285
- */
286
- function add_files_to_order( $order_id, $posted ) {
287
- $upload_dir = wcj_get_wcj_uploads_dir( 'checkout_files_upload' );
288
- if ( ! file_exists( $upload_dir ) ) {
289
- mkdir( $upload_dir, 0755, true );
290
- }
291
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
292
- for ( $i = 1; $i <= $total_number; $i++ ) {
293
- if ( null !== wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
294
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
295
- $file_name = $session_data['name'];
296
- $ext = pathinfo( $file_name, PATHINFO_EXTENSION );
297
- $download_file_name = $order_id . '_' . $i . '.' . $ext;
298
- $file_path = $upload_dir . '/' . $download_file_name;
299
- $tmp_file_name = $session_data['tmp_name'];
300
- $file_data = file_get_contents( $tmp_file_name );
301
- if ( ! $this->is_extension_blocked( $ext ) ) { // should already be validated earlier, but just in case...
302
- file_put_contents( $file_path, $file_data );
303
- }
304
- unlink( $tmp_file_name );
305
- wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
306
- update_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, $download_file_name );
307
- update_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, $file_name );
308
  }
309
- }
310
- update_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', $total_number );
311
- }
312
-
313
- /**
314
- * remove_files_on_empty_cart.
315
- *
316
- * @version 3.9.0
317
- * @since 3.6.0
318
- */
319
- function remove_files_on_empty_cart( $cart_item_key, $cart ) {
320
- if ( $cart->is_empty() ) {
321
- wcj_session_maybe_start();
322
- $any_files_removed = false;
323
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) ); $i++ ) {
324
- if ( null != ( $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) ) {
325
- $any_files_removed = true;
326
- if ( isset( $session_data['tmp_name'] ) ) {
327
- unlink( $session_data['tmp_name'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
328
  }
 
329
  wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
 
 
330
  }
331
  }
332
- if ( $any_files_removed && 'yes' === wcj_get_option( 'wcj_checkout_files_upload_remove_on_empty_cart_add_notice', 'no' ) ) {
333
- $this->add_notice( wcj_get_option( 'wcj_checkout_files_upload_notice_remove_on_empty_cart', __( 'Files were successfully removed.', 'woocommerce-jetpack' ) ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
334
  }
335
  }
336
- }
337
-
338
- /**
339
- * get_order_full_file_name.
340
- *
341
- * @version 3.8.0
342
- * @since 3.8.0
343
- * @todo use where needed
344
- */
345
- function get_order_full_file_name( $order_id, $file_num ) {
346
- return wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $file_num, true );
347
- }
348
 
349
- /**
350
- * process_checkout_files_upload.
351
- *
352
- * @version 3.9.0
353
- * @since 2.4.5
354
- * @todo add option for admin to delete files one by one (i.e. not all at once)
355
- * @todo `$this->additional_admin_emails_settings` - more customization options, e.g.: admin email, subject, content, from
356
- */
357
- function process_checkout_files_upload() {
358
- wcj_session_maybe_start();
359
- $admin_email = wcj_get_option( 'admin_email' );
360
- $admin_email_subject = __( 'Booster for WooCommerce: Checkout Files Upload: %action%', 'woocommerce-jetpack' );
361
- $admin_email_content = __( 'Order ID: %order_id%; File name: %file_name%', 'woocommerce-jetpack' );
362
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
363
- // Remove file
364
- for ( $i = 1; $i <= $total_number; $i++ ) {
365
- if ( isset( $_POST[ 'wcj_remove_checkout_file_' . $i ] ) ) {
366
- if ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ) {
367
- $order_id = $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ];
368
- $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
369
- if ( '' != $order_file_name ) {
370
- $file_path = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
371
- unlink( $file_path );
372
- $file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
373
- $this->add_notice( sprintf( wcj_get_option( 'wcj_checkout_files_upload_notice_success_remove_' . $i,
374
- __( 'File "%s" was successfully removed.', 'woocommerce-jetpack' ) ), $file_name ) );
375
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i );
376
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i );
377
- if ( in_array( 'remove_file', $this->additional_admin_emails_settings['actions'] ) ) {
378
- wp_mail(
379
- $admin_email,
380
- wcj_handle_replacements( array(
381
- '%action%' => __( 'File Removed', 'woocommerce-jetpack' ),
382
- ), $admin_email_subject ),
383
- wcj_handle_replacements( array(
384
- '%order_id%' => $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ],
385
- '%file_name%' => $file_name,
386
- ), $admin_email_content )
 
 
 
 
 
 
 
 
 
387
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
388
  }
389
- do_action( 'wcj_checkout_files_upload', 'remove_file', $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ], $file_name );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  }
391
- } else {
392
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
393
- $file_name = $session_data['name'];
394
- unlink( $session_data['tmp_name'] );
395
- wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
396
- $this->add_notice( sprintf( wcj_get_option( 'wcj_checkout_files_upload_notice_success_remove_' . $i,
397
- __( 'File "%s" was successfully removed.', 'woocommerce-jetpack' ) ), $file_name ) );
398
- do_action( 'wcj_checkout_files_upload', 'remove_file', false, $file_name );
399
  }
400
  }
401
- }
402
- // Upload file
403
- for ( $i = 1; $i <= $total_number; $i++ ) {
404
- if ( isset( $_POST[ 'wcj_upload_checkout_file_' . $i ] ) ) {
405
- $file_name = 'wcj_checkout_files_upload_' . $i;
406
- if ( isset( $_FILES[ $file_name ] ) && '' != $_FILES[ $file_name ]['tmp_name'] ) {
407
- // Validate
408
- $is_valid = true;
409
- $real_file_name = $_FILES[ $file_name ]['name'];
410
- $file_type = '.' . pathinfo( $real_file_name, PATHINFO_EXTENSION );
411
- if ( '' != ( $file_accept = wcj_get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) ) ) {
412
- // Validate file type
413
- $file_accept = explode( ',', $file_accept );
414
- if ( is_array( $file_accept ) && ! empty( $file_accept ) ) {
415
- if ( ! in_array( $file_type, $file_accept ) ) {
416
- $this->add_notice( sprintf( wcj_get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
417
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $real_file_name ), 'error' );
418
- $is_valid = false;
 
 
 
 
 
 
 
 
 
 
419
  }
420
  }
421
- }
422
- if ( $this->is_extension_blocked( $file_type ) ) {
423
- $this->add_notice( sprintf( wcj_get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
424
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $real_file_name ), 'error' );
425
- $is_valid = false;
426
- }
427
- if ( $is_valid ) {
428
- // To session
429
- $tmp_dest_file = tempnam( sys_get_temp_dir(), 'wcj' );
430
- move_uploaded_file( $_FILES[ $file_name ]['tmp_name'], $tmp_dest_file );
431
- $session_data = $_FILES[ $file_name ];
432
- $session_data['tmp_name'] = $tmp_dest_file;
433
- wcj_session_set( $file_name, $session_data );
434
- $this->add_notice( sprintf( wcj_get_option( 'wcj_checkout_files_upload_notice_success_upload_' . $i,
435
- __( 'File "%s" was successfully uploaded.', 'woocommerce-jetpack' ) ), $_FILES[ $file_name ]['name'] ) );
436
- // To order
437
- if ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ) {
438
- $this->add_files_to_order( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ], null );
439
- if ( in_array( 'upload_file', $this->additional_admin_emails_settings['actions'] ) ) {
440
- $attachments = ( 'no' === $this->additional_admin_emails_settings['do_attach'] ?
441
- array() : array( $this->get_order_full_file_name( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ], $i ) ) );
442
- wp_mail(
443
- $admin_email,
444
- wcj_handle_replacements( array(
445
- '%action%' => __( 'File Uploaded', 'woocommerce-jetpack' ),
446
- ), $admin_email_subject ),
447
- wcj_handle_replacements( array(
448
- '%order_id%' => $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ],
449
- '%file_name%' => $_FILES[ $file_name ]['name'],
450
- ), $admin_email_content ),
451
- '',
452
- $attachments
453
- );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
454
  }
 
 
 
 
 
 
 
455
  }
456
- // Action
457
- do_action( 'wcj_checkout_files_upload', 'upload_file',
458
- ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ? $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] : false ),
459
- $_FILES[ $file_name ]['name'] );
 
 
 
 
460
  }
461
- } else {
462
- $this->add_notice( wcj_get_option( 'wcj_checkout_files_upload_notice_upload_no_file_' . $i,
463
- __( 'Please select file to upload!', 'woocommerce-jetpack' ) ), 'notice' );
464
  }
465
  }
466
- }
467
- // Admin file download
468
- if ( isset( $_GET['wcj_download_checkout_file_admin'] ) ) {
469
- $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $_GET['wcj_download_checkout_file_admin'];
470
- $file_name = get_post_meta( $_GET['post'], '_' . 'wcj_checkout_files_upload_real_name_' . $_GET['wcj_checkout_file_number'], true );
471
- if ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) {
472
- header( "Expires: 0" );
473
- header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
474
- header( "Cache-Control: private", false );
475
- header( 'Content-disposition: attachment; filename=' . $file_name );
476
- header( "Content-Transfer-Encoding: binary" );
477
- header( "Content-Length: ". filesize( $tmp_file_name ) );
478
- readfile( $tmp_file_name );
479
- exit();
480
  }
481
- }
482
- // Admin all files delete
483
- if ( isset( $_GET['wcj_download_checkout_file_admin_delete_all'] ) && ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) ) {
484
- $order_id = $_GET['wcj_download_checkout_file_admin_delete_all'];
485
- $total_files = get_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', true );
486
- for ( $i = 1; $i <= $total_files; $i++ ) {
487
- if ( '' != ( $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true ) ) ) {
488
- unlink( wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name );
 
 
489
  }
490
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i );
491
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i );
 
492
  }
493
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files' );
494
- wp_safe_redirect( remove_query_arg( 'wcj_download_checkout_file_admin_delete_all' ) );
495
- exit;
496
- }
497
- // User file download
498
- if ( isset( $_GET['wcj_download_checkout_file'] ) && isset( $_GET['_wpnonce'] ) && ( false !== wp_verify_nonce( $_GET['_wpnonce'], 'wcj_download_checkout_file' ) ) ) {
499
- $i = $_GET['wcj_download_checkout_file'];
500
- if ( ! empty( $_GET['wcj_download_checkout_file_order_id'] ) ) {
501
- $order_id = $_GET['wcj_download_checkout_file_order_id'];
502
- if ( ! ( $order = wc_get_order( $order_id ) ) ) {
503
- return;
504
- }
505
- if ( isset( $_GET['key'] ) ) {
506
- // Thank you page
507
- if ( ! $order->key_is_valid( $_GET['key'] ) ) {
508
  return;
509
  }
510
- } else {
511
- // My Account
512
- if ( ! wcj_is_user_logged_in() || $order->get_customer_id() != wcj_get_current_user_id() ) {
513
- return;
 
 
 
 
 
 
514
  }
 
 
 
 
 
 
 
515
  }
516
- $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
517
- $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
518
- $file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
519
- } else {
520
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
521
- $tmp_file_name = $session_data['tmp_name'];
522
- $file_name = $session_data['name'];
523
- }
524
- header( "Expires: 0" );
525
- header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
526
- header( "Cache-Control: private", false );
527
- header( 'Content-disposition: attachment; filename=' . $file_name );
528
- header( "Content-Transfer-Encoding: binary" );
529
- header( "Content-Length: ". filesize( $tmp_file_name ) );
530
- readfile( $tmp_file_name );
531
- exit();
532
  }
533
- }
534
-
535
- /**
536
- * is_visible.
537
- *
538
- * @version 3.6.0
539
- * @since 2.4.7
540
- */
541
- function is_visible( $i, $order_id = 0 ) {
542
 
543
- if ( apply_filters( 'wcj_checkout_files_always_visible_on_empty_cart', false ) && 0 == $order_id && WC()->cart->is_empty() ) {
544
- // Added for "One Page Checkout" plugin compatibility.
545
- return true;
546
- }
 
 
 
 
 
547
 
548
- // Include by user role
549
- $user_roles = wcj_get_option( 'wcj_checkout_files_upload_show_user_roles_' . $i, '' );
550
- if ( ! empty( $user_roles ) && ! in_array( wcj_get_current_user_first_role(), $user_roles ) ) {
551
- return false;
552
- }
553
 
554
- // Exclude by user role
555
- $user_roles = wcj_get_option( 'wcj_checkout_files_upload_hide_user_roles_' . $i, '' );
556
- if ( ! empty( $user_roles ) && in_array( wcj_get_current_user_first_role(), $user_roles ) ) {
557
- return false;
558
- }
559
 
560
- // Include by product id
561
- $products_in = wcj_get_option( 'wcj_checkout_files_upload_show_products_in_' . $i );
562
- if ( ! empty( $products_in ) ) {
563
- $do_skip_by_products = true;
564
- if ( 0 != $order_id ) {
565
- $the_order = wc_get_order( $order_id );
566
- $the_items = $the_order->get_items();
567
- } else {
568
- $the_items = WC()->cart->get_cart();
569
  }
570
- foreach ( $the_items as $cart_item_key => $values ) {
571
- if ( in_array( $values['product_id'], $products_in ) ) {
572
- $do_skip_by_products = false;
573
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
574
  }
575
  }
576
- if ( $do_skip_by_products ) return false;
577
- }
578
 
579
- // Exclude by product id
580
- $products_in = wcj_get_option( 'wcj_checkout_files_upload_hide_products_in_' . $i );
581
- if ( ! empty( $products_in ) ) {
582
- if ( 0 != $order_id ) {
583
- $the_order = wc_get_order( $order_id );
584
- $the_items = $the_order->get_items();
585
- } else {
586
- $the_items = WC()->cart->get_cart();
587
- }
588
- foreach ( $the_items as $cart_item_key => $values ) {
589
- if ( in_array( $values['product_id'], $products_in ) ) {
590
- return false;
 
591
  }
592
  }
593
- }
594
 
595
- // Include by product category
596
- $categories_in = wcj_get_option( 'wcj_checkout_files_upload_show_cats_in_' . $i );
597
- if ( ! empty( $categories_in ) ) {
598
- $do_skip_by_cats = true;
599
- if ( 0 != $order_id ) {
600
- $the_order = wc_get_order( $order_id );
601
- $the_items = $the_order->get_items();
602
- } else {
603
- $the_items = WC()->cart->get_cart();
604
- }
605
- foreach ( $the_items as $cart_item_key => $values ) {
606
- $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
607
- if ( empty( $product_categories ) ) continue;
608
- foreach( $product_categories as $product_category ) {
609
- if ( in_array( $product_category->term_id, $categories_in ) ) {
610
- $do_skip_by_cats = false;
 
 
 
 
 
 
611
  break;
612
  }
613
  }
614
- if ( ! $do_skip_by_cats ) break;
 
 
615
  }
616
- if ( $do_skip_by_cats ) return false;
617
- }
618
 
619
- // Exclude by product category
620
- $categories_in = wcj_get_option( 'wcj_checkout_files_upload_hide_cats_in_' . $i );
621
- if ( ! empty( $categories_in ) ) {
622
- if ( 0 != $order_id ) {
623
- $the_order = wc_get_order( $order_id );
624
- $the_items = $the_order->get_items();
625
- } else {
626
- $the_items = WC()->cart->get_cart();
627
- }
628
- foreach ( $the_items as $cart_item_key => $values ) {
629
- $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
630
- if ( empty( $product_categories ) ) continue;
631
- foreach( $product_categories as $product_category ) {
632
- if ( in_array( $product_category->term_id, $categories_in ) ) {
633
- return false;
 
 
 
634
  }
635
  }
636
  }
637
- }
638
 
639
- // Include by product tag
640
- $tags_in = wcj_get_option( 'wcj_checkout_files_upload_show_tags_in_' . $i );
641
- if ( ! empty( $tags_in ) ) {
642
- $do_skip_by_tags = true;
643
- if ( 0 != $order_id ) {
644
- $the_order = wc_get_order( $order_id );
645
- $the_items = $the_order->get_items();
646
- } else {
647
- $the_items = WC()->cart->get_cart();
648
- }
649
- foreach ( $the_items as $cart_item_key => $values ) {
650
- $product_tags = get_the_terms( $values['product_id'], 'product_tag' );
651
- if ( empty( $product_tags ) ) continue;
652
- foreach( $product_tags as $product_tag ) {
653
- if ( in_array( $product_tag->term_id, $tags_in ) ) {
654
- $do_skip_by_tags = false;
 
 
 
 
 
 
655
  break;
656
  }
657
  }
658
- if ( ! $do_skip_by_tags ) break;
 
 
659
  }
660
- if ( $do_skip_by_tags ) return false;
661
- }
662
 
663
- // Exclude by product tag
664
- $tags_in = wcj_get_option( 'wcj_checkout_files_upload_hide_tags_in_' . $i );
665
- if ( ! empty( $tags_in ) ) {
666
- if ( 0 != $order_id ) {
667
- $the_order = wc_get_order( $order_id );
668
- $the_items = $the_order->get_items();
669
- } else {
670
- $the_items = WC()->cart->get_cart();
671
- }
672
- foreach ( $the_items as $cart_item_key => $values ) {
673
- $product_tags = get_the_terms( $values['product_id'], 'product_tag' );
674
- if ( empty( $product_tags ) ) continue;
675
- foreach( $product_tags as $product_tag ) {
676
- if ( in_array( $product_tag->term_id, $tags_in ) ) {
677
- return false;
 
 
 
678
  }
679
  }
680
  }
681
- }
682
 
683
- return true;
684
- }
685
 
686
- /**
687
- * maybe_get_image.
688
- *
689
- * @version 3.7.0
690
- * @since 3.7.0
691
- */
692
- function maybe_get_image( $link, $i, $order_id = 0 ) {
693
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_form_template_field_show_images', 'no' ) ) {
694
- if ( 0 != $order_id && isset( $_GET['key'] ) && ( $order = wc_get_order( $order_id ) ) && $order->key_is_valid( $_GET['key'] ) ) {
695
- $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
696
- $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
697
- } else {
698
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
699
- $tmp_file_name = $session_data['tmp_name'];
 
 
 
 
 
 
 
 
700
  }
701
- if ( @is_array( getimagesize( $tmp_file_name ) ) ) {
702
- return '<img style="' . wcj_get_option( 'wcj_checkout_files_upload_form_template_field_image_style', 'width:64px;' ) . '" src="' . $link. '"> ';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
703
  }
704
- }
705
- return '';
706
- }
707
-
708
- /**
709
- * get_the_form.
710
- *
711
- * @version 5.5.9
712
- * @since 2.5.0
713
- */
714
- function get_the_form( $i, $file_name, $order_id = 0 ) {
715
- $html = '';
716
- $html .= '<form enctype="multipart/form-data" action="" method="POST">';
717
- $html .= wcj_get_option( 'wcj_checkout_files_upload_form_template_before', '<table>' );
718
- if ( '' != ( $the_label = wcj_get_option( 'wcj_checkout_files_upload_label_' . $i, '' ) ) ) {
719
- $template = wcj_get_option( 'wcj_checkout_files_upload_form_template_label',
720
- '<tr><td colspan="2"><label for="%field_id%">%field_label%</label>%required_html%</td></tr>' );
721
- $required_html = ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_required_' . $i, 'no' ) ) ?
722
- '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
723
- $html .= str_replace(
724
- array( '%field_id%', '%field_label%', '%required_html%' ),
725
- array( 'wcj_checkout_files_upload_' . $i, $the_label, $required_html ),
726
- $template
727
- );
728
- }
729
- if ( '' == $file_name ) {
730
- $field_html = '<input type="file" name="wcj_checkout_files_upload_' . $i . '" id="wcj_checkout_files_upload_' . $i .
731
  '" accept="' . wcj_get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) . '">';
732
- $button_html = '<input type="submit"' .
733
  ' class="button alt"' .
734
  ' style="width:100%;"' .
735
  ' name="wcj_upload_checkout_file_' . $i . '"' .
736
  ' id="wcj_upload_checkout_file_' . $i . '"' .
737
- ' value="' . wcj_get_option( 'wcj_checkout_files_upload_label_upload_button_' . $i, __( 'Upload', 'woocommerce-jetpack' ) ) . '"' .
738
  ' data-value="' . wcj_get_option( 'wcj_checkout_files_upload_label_upload_button_' . $i, __( 'Upload', 'woocommerce-jetpack' ) ) . '">';
739
- } else {
740
- $link = esc_url(add_query_arg( array( 'wcj_download_checkout_file' => $i, '_wpnonce' => wp_create_nonce( 'wcj_download_checkout_file' ), 'wcj_download_checkout_file_order_id' => $order_id ) ));
741
- $field_html = '<a href="' . esc_url($link) . '">' . $this->maybe_get_image( $link, $i, $order_id ) . $file_name . '</a>';
742
- $button_html = '<input type="submit"' .
 
 
 
 
 
 
743
  ' class="button"' .
744
  ' style="width:100%;"' .
745
  ' name="wcj_remove_checkout_file_' . $i . '"' .
746
  ' id="wcj_remove_checkout_file_' . $i . '"' .
747
- ' value="' . wcj_get_option( 'wcj_checkout_files_upload_label_remove_button_' . $i, __( 'Remove', 'woocommerce-jetpack' ) ) . '"' .
748
  ' data-value="' . wcj_get_option( 'wcj_checkout_files_upload_label_remove_button_' . $i, __( 'Remove', 'woocommerce-jetpack' ) ) . '">';
749
- }
750
- $template = wcj_get_option( 'wcj_checkout_files_upload_form_template_field',
751
- '<tr><td style="width:50%;max-width:50vw;">%field_html%</td><td style="width:50%;">%button_html%</td></tr>' );
752
- $html .= str_replace(
753
- array( '%field_html%', '%button_html%' ),
754
- array( $field_html, $button_html ),
755
- $template
756
- );
757
- $html .= wcj_get_option( 'wcj_checkout_files_upload_form_template_after', '</table>' );
758
- if ( 0 != $order_id ) {
759
- $html .= '<input type="hidden" name="wcj_checkout_files_upload_order_id_' . $i . '" value="' . $order_id . '">';
760
- }
761
- $html .= '</form>';
762
- return $html;
763
- }
764
-
765
- /**
766
- * add_files_upload_form_to_thankyou_and_myaccount_page.
767
- *
768
- * @version 2.5.6
769
- * @since 2.5.0
770
- */
771
- function add_files_upload_form_to_thankyou_and_myaccount_page( $order_id ) {
772
- $html = '';
773
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
774
- $current_filter = current_filter();
775
- for ( $i = 1; $i <= $total_number; $i++ ) {
776
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) && $this->is_visible( $i, $order_id ) ) {
777
- if (
778
- ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_thankyou_' . $i, 'no' ) && 'woocommerce_thankyou' === $current_filter ) ||
 
 
 
779
  ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_myaccount_' . $i, 'no' ) && 'woocommerce_view_order' === $current_filter )
780
- ) {
781
- $file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
782
- $html .= $this->get_the_form( $i, $file_name, $order_id );
 
783
  }
784
  }
 
785
  }
786
- echo $html;
787
- }
788
 
789
- /**
790
- * add_files_upload_form_to_checkout_frontend.
791
- *
792
- * @version 2.5.2
793
- * @since 2.4.5
794
- */
795
- function add_files_upload_form_to_checkout_frontend() {
796
- $this->add_files_upload_form_to_checkout_frontend_all();
797
- }
798
-
799
- /**
800
- * add_files_upload_form_to_checkout_frontend_all.
801
- *
802
- * @version 3.4.0
803
- * @since 2.5.2
804
- */
805
- function add_files_upload_form_to_checkout_frontend_all( $is_direct_call = false ) {
806
- $html = '';
807
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
808
- if ( ! $is_direct_call ) {
809
- $current_filter = current_filter();
810
- $current_filter_priority = wcj_current_filter_priority();
811
  }
812
- for ( $i = 1; $i <= $total_number; $i++ ) {
813
- $is_filter_ok = ( $is_direct_call ) ? true : (
814
- $current_filter === wcj_get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' ) &&
815
- $current_filter_priority == wcj_get_option( 'wcj_checkout_files_upload_hook_priority_' . $i, 10 )
816
- );
817
- if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) && $is_filter_ok && $this->is_visible( $i ) ) {
818
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
819
- $file_name = ( null !== $session_data ? $session_data['name'] : '' );
820
- $html .= $this->get_the_form( $i, $file_name );
 
 
 
 
 
 
821
  }
 
 
 
 
 
 
 
 
 
 
 
 
822
  }
823
- echo $html;
824
- }
825
 
826
- }
827
 
828
  endif;
829
 
5
  * @version 5.5.9
6
  * @since 2.4.5
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Checkout_Files_Upload' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Checkout_Customization.
18
  *
19
+ * @version 2.7.0
 
 
20
  */
21
+ class WCJ_Checkout_Files_Upload extends WCJ_Module {
22
+
23
+ /**
24
+ * Constructor.
25
+ *
26
+ * @version 5.2.0
27
+ * @since 2.4.5
28
+ * @todo styling options
29
+ */
30
+ public function __construct() {
31
+
32
+ $this->id = 'checkout_files_upload';
33
+ $this->short_desc = __( 'Checkout Files Upload', 'woocommerce-jetpack' );
34
+ $this->desc = __( 'Let customers upload files on (or after) the checkout (1 file allowed in free version).', 'woocommerce-jetpack' );
35
+ $this->desc_pro = __( 'Let customers upload files on (or after) the checkout.', 'woocommerce-jetpack' );
36
+ $this->link_slug = 'woocommerce-checkout-files-upload';
37
+ parent::__construct();
38
+
39
+ if ( $this->is_enabled() ) {
40
+ $this->init_settings();
41
+ add_action( 'add_meta_boxes', array( $this, 'add_file_admin_order_meta_box' ) );
42
+ add_action( 'init', array( $this, 'process_checkout_files_upload' ) );
43
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_remove_on_empty_cart', 'no' ) ) {
44
+ add_action( 'woocommerce_cart_item_removed', array( $this, 'remove_files_on_empty_cart' ), PHP_INT_MAX, 2 );
45
  }
46
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
47
+ for ( $i = 1; $i <= $total_number; $i++ ) {
48
+ $the_hook = wcj_get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' );
49
+ if ( 'disable' != ( $the_hook ) ) {
50
+ add_action( $the_hook, array( $this, 'add_files_upload_form_to_checkout_frontend' ), wcj_get_option( 'wcj_checkout_files_upload_hook_priority_' . $i, 10 ) );
51
+ }
52
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_thankyou_' . $i, 'no' ) ) {
53
+ add_action( 'woocommerce_thankyou', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
54
+ }
55
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_myaccount_' . $i, 'no' ) ) {
56
+ add_action( 'woocommerce_view_order', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
57
+ }
58
  }
59
+ add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_files_to_order' ), PHP_INT_MAX, 2 );
60
+ add_action( 'woocommerce_after_checkout_validation', array( $this, 'validate_on_checkout' ) );
61
+ add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
62
+ add_action( 'woocommerce_email_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
63
+ add_filter( 'woocommerce_email_attachments', array( $this, 'add_files_to_email_attachments' ), PHP_INT_MAX, 3 );
64
  }
 
 
 
 
 
65
  }
 
66
 
67
+ /**
68
+ * Init_settings.
69
+ *
70
+ * @version 3.9.0
71
+ * @since 3.8.0
72
+ * @todo (dev) (maybe) init settings on demand only
73
+ */
74
+ public function init_settings() {
75
+ $this->templates_settings = wcj_get_option( 'wcj_checkout_files_upload_templates', array() );
76
+ $this->templates_settings = wp_parse_args(
77
+ $this->templates_settings,
78
+ array(
79
+ 'order_before' => '',
80
+ /* translators: %s: search term */
81
+ 'order_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
82
+ 'order_after' => '',
83
+ 'order_image_style' => 'width:64px;',
84
+ 'email_before' => '',
85
+ /* translators: %s: search term */
86
+ 'email_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
87
+ 'email_after' => '',
88
+ )
89
+ );
90
+ $this->additional_admin_emails_settings = wcj_get_option( 'wcj_checkout_files_upload_additional_admin_emails', array() );
91
+ $this->additional_admin_emails_settings = wp_parse_args(
92
+ $this->additional_admin_emails_settings,
93
+ array(
94
+ 'actions' => array(),
95
+ 'do_attach' => 'yes',
96
+ )
97
+ );
98
+ $this->checkout_files_upload_notice_type = wcj_get_option( 'wcj_checkout_files_upload_notice_type', 'wc_add_notice' );
99
+ }
100
+
101
+ /**
102
+ * Add_files_to_email_attachments.
103
+ *
104
+ * @version 2.7.0
105
+ * @since 2.5.5
106
+ * @param array $attachments defines the attachments.
107
+ * @param bool | string $status defines the status.
108
+ * @param string | int $order defines the order.
109
+ */
110
+ public function add_files_to_email_attachments( $attachments, $status, $order ) {
111
+ if (
112
+ ( 'new_order' === $status && 'yes' === wcj_get_option( 'wcj_checkout_files_upload_attach_to_admin_new_order', 'yes' ) ) ||
113
  ( 'customer_processing_order' === $status && 'yes' === wcj_get_option( 'wcj_checkout_files_upload_attach_to_customer_processing_order', 'yes' ) )
114
+ ) {
115
+ $total_files = get_post_meta( wcj_get_order_id( $order ), '_wcj_checkout_files_total_files', true );
116
+ for ( $i = 1; $i <= $total_files; $i++ ) {
117
+ $attachments[] = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( wcj_get_order_id( $order ), '_wcj_checkout_files_upload_' . $i, true );
118
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  }
120
+ return $attachments;
121
+ }
122
+
123
+ /**
124
+ * Add_files_to_order_display.
125
+ *
126
+ * @version 5.5.9
127
+ * @since 2.4.7
128
+ * @todo (maybe) somehow add `%image%` to emails also
129
+ * @param string | int $order defines the order.
130
+ */
131
+ public function add_files_to_order_display( $order ) {
132
+ $order_id = wcj_get_order_id( $order );
133
+ $html = '';
134
+ $total_files = get_post_meta( $order_id, '_wcj_checkout_files_total_files', true );
135
+ $do_add_img = false;
136
+ if ( 'woocommerce_email_after_order_table' === current_filter() ) {
137
+ $template_before = $this->templates_settings['email_before'];
138
+ $template_after = $this->templates_settings['email_after'];
139
+ $template = $this->templates_settings['email_item'];
140
+ } else {
141
+ $template_before = $this->templates_settings['order_before'];
142
+ $template_after = $this->templates_settings['order_after'];
143
+ $template = $this->templates_settings['order_item'];
144
+ $do_add_img = ( false !== strpos( $template, '%image%' ) );
145
  if ( $do_add_img ) {
146
+ $img_style = $this->templates_settings['order_image_style'];
147
+ }
148
+ }
149
+ for ( $i = 1; $i <= $total_files; $i++ ) {
150
+ $real_file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i, true );
151
+ if ( '' != $real_file_name ) {
152
+ $img = '';
153
+ if ( $do_add_img ) {
154
+ $order_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i, true );
155
+ if ( @is_array( getimagesize( $order_file_name ) ) ) {
156
+ $link = add_query_arg(
157
+ array(
158
+ 'wcj_download_checkout_file' => $i,
159
+ '_wpnonce' => wp_create_nonce( 'wcj_download_checkout_file' ),
160
+ 'wcj_download_checkout_file_order_id' => $order_id,
161
+ )
162
+ );
163
+ $img = '<img style="' . $img_style . '" src="' . $link . '"> ';
164
+ }
165
  }
166
+ $html .= wcj_handle_replacements(
167
+ array(
168
+ '%file_name%' => $real_file_name,
169
+ '%image%' => $img,
170
+ ),
171
+ $template
172
+ );
173
  }
174
+ }
175
+ if ( '' != $html ) {
176
+ echo $template_before . $html . $template_after;
 
177
  }
178
  }
 
 
 
 
179
 
180
+ /**
181
+ * Add_notice.
182
+ *
183
+ * @version 3.9.0
184
+ * @since 3.9.0
185
+ * @param string $message defines the message.
186
+ * @param string $notice_type defines the notice_type.
187
+ */
188
+ public function add_notice( $message, $notice_type = 'success' ) {
189
+ if ( 'wc_add_notice' === $this->checkout_files_upload_notice_type ) {
190
+ wc_add_notice( $message, $notice_type );
191
+ } elseif ( 'wc_print_notice' === $this->checkout_files_upload_notice_type ) {
192
+ wc_print_notice( $message, $notice_type );
193
+ }
194
  }
 
195
 
196
+ /**
197
+ * Validate_on_checkout.
198
+ *
199
+ * @version 3.9.0
200
+ * @since 2.4.5
201
+ * @param string $posted defines the posted.
202
+ */
203
+ public function validate_on_checkout( $posted ) {
204
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
205
+ for ( $i = 1; $i <= $total_number; $i++ ) {
206
+ if (
207
  'yes' === wcj_get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) &&
208
  $this->is_visible( $i ) &&
209
  'disable' != wcj_get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' )
210
+ ) {
211
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_required_' . $i, 'no' ) && null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
212
+ // Is required.
213
+ $this->add_notice( wcj_get_option( 'wcj_checkout_files_upload_notice_required_' . $i, __( 'File is required!', 'woocommerce-jetpack' ) ), 'error' );
214
+ }
215
+ if ( null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
216
+ continue;
217
+ }
218
+ $file_name = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
219
+ $file_name = $file_name['name'];
220
+ $file_type = '.' . pathinfo( $file_name, PATHINFO_EXTENSION );
221
+ $file_accept = wcj_get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' );
222
+ if ( '' != ( $file_accept ) ) {
223
+ // Validate file type.
224
+ $file_accept = explode( ',', $file_accept );
225
+ if ( is_array( $file_accept ) && ! empty( $file_accept ) ) {
226
+ if ( ! in_array( $file_type, $file_accept ) ) {
227
+ $this->add_notice(
228
+ sprintf(
229
+ wcj_get_option(
230
+ 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
231
+ /* translators: %s: search term */
232
+ __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' )
233
+ ),
234
+ $file_name
235
+ ),
236
+ 'error'
237
+ );
238
+ }
239
  }
240
  }
241
+ if ( $this->is_extension_blocked( $file_type ) ) {
242
+ $this->add_notice(
243
+ sprintf(
244
+ wcj_get_option(
245
+ 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
246
+ /* translators: %s: search term */
247
+ __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' )
248
+ ),
249
+ $file_name
250
+ ),
251
+ 'error'
252
+ );
253
+ }
254
  }
255
  }
256
  }
 
257
 
258
+ /**
259
+ * Add_file_admin_order_meta_box.
260
+ *
261
+ * @version 2.4.5
262
+ * @since 2.4.5
263
+ */
264
+ public function add_file_admin_order_meta_box() {
265
+ $screen = 'shop_order';
266
+ $context = 'side';
267
+ $priority = 'high';
268
+ add_meta_box(
269
+ 'wc-jetpack-' . $this->id,
270
+ __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Uploaded Files', 'woocommerce-jetpack' ),
271
+ array( $this, 'create_file_admin_order_meta_box' ),
272
+ $screen,
273
+ $context,
274
+ $priority
275
+ );
276
+ }
277
 
278
+ /**
279
+ * Create_file_admin_order_meta_box.
280
+ *
281
+ * @version 5.5.9
282
+ * @since 2.4.5
283
+ */
284
+ public function create_file_admin_order_meta_box() {
285
+ $order_id = get_the_ID();
286
+ $html = '';
287
+ $total_files = get_post_meta( $order_id, '_wcj_checkout_files_total_files', true );
288
+ $files_exists = false;
289
+ for ( $i = 1; $i <= $total_files; $i++ ) {
290
+ $order_file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i, true );
291
+ $real_file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i, true );
292
+ if ( '' != $order_file_name ) {
293
+ $files_exists = true;
294
+ $html .= '<p><a href="' . add_query_arg(
295
+ array(
296
+ 'wcj_download_checkout_file_admin' => $order_file_name,
297
+ 'wcj_checkout_file_number' => $i,
298
+ )
299
+ ) . '">' . $real_file_name . '</a></p>';
300
+ }
301
  }
302
+ if ( ! $files_exists ) {
303
+ $html .= '<p><em>' . __( 'No files uploaded.', 'woocommerce-jetpack' ) . '</em></p>';
304
+ } else {
305
+ $html .= '<p><a style="color:#a00;" href="' . add_query_arg( 'wcj_download_checkout_file_admin_delete_all', $order_id ) . '"' . wcj_get_js_confirmation() . '>' .
 
306
  __( 'Delete all files', 'woocommerce-jetpack' ) . '</a></p>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
  }
308
+ echo $html;
309
+ }
310
+
311
+ /**
312
+ * Is_extension_blocked.
313
+ *
314
+ * @version 3.2.3
315
+ * @since 3.2.3
316
+ * @param string $ext defines the ext.
317
+ */
318
+ public function is_extension_blocked( $ext ) {
319
+ if ( 'no' === wcj_get_option( 'wcj_checkout_files_upload_block_files_enabled', 'yes' ) ) {
320
+ return false;
321
+ }
322
+ $ext = strtolower( $ext );
323
+ if ( strlen( $ext ) > 0 && '.' === $ext[0] ) {
324
+ $ext = substr( $ext, 1 );
325
+ }
326
+ $blocked_file_exts = wcj_get_option(
327
+ 'wcj_checkout_files_upload_block_files_exts',
328
+ 'bat|exe|cmd|sh|php|php0|php1|php2|php3|php4|php5|php6|php7|php8|php9|ph|ph0|ph1|ph2|ph3|ph4|ph5|ph6|ph7|ph8|ph9|pl|cgi|386|dll|com|torrent|js|app|jar|pif|vb|vbscript|wsf|asp|cer|csr|jsp|drv|sys|ade|adp|bas|chm|cpl|crt|csh|fxp|hlp|hta|inf|ins|isp|jse|htaccess|htpasswd|ksh|lnk|mdb|mde|mdt|mdw|msc|msi|msp|mst|ops|pcd|prg|reg|scr|sct|shb|shs|url|vbe|vbs|wsc|wsf|wsh|html|htm'
329
+ );
330
+ $blocked_file_exts = explode( '|', $blocked_file_exts );
331
+ return in_array( $ext, $blocked_file_exts );
332
+ }
333
+
334
+ /**
335
+ * Add_files_to_order.
336
+ *
337
+ * @version 3.4.0
338
+ * @since 2.4.5
339
+ * @param int $order_id defines the order_id.
340
+ * @param string $posted defines the posted.
341
+ */
342
+ public function add_files_to_order( $order_id, $posted ) {
343
+ $upload_dir = wcj_get_wcj_uploads_dir( 'checkout_files_upload' );
344
+ if ( ! file_exists( $upload_dir ) ) {
345
+ mkdir( $upload_dir, 0755, true );
346
+ }
347
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
348
+ for ( $i = 1; $i <= $total_number; $i++ ) {
349
+ if ( null !== wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
350
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
351
+ $file_name = $session_data['name'];
352
+ $ext = pathinfo( $file_name, PATHINFO_EXTENSION );
353
+ $download_file_name = $order_id . '_' . $i . '.' . $ext;
354
+ $file_path = $upload_dir . '/' . $download_file_name;
355
+ $tmp_file_name = $session_data['tmp_name'];
356
+ $file_data = file_get_contents( $tmp_file_name );
357
+ if ( ! $this->is_extension_blocked( $ext ) ) { // should already be validated earlier, but just in case...
358
+ file_put_contents( $file_path, $file_data );
359
  }
360
+ unlink( $tmp_file_name );
361
  wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
362
+ update_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i, $download_file_name );
363
+ update_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i, $file_name );
364
  }
365
  }
366
+ update_post_meta( $order_id, '_wcj_checkout_files_total_files', $total_number );
367
+ }
368
+
369
+ /**
370
+ * Remove_files_on_empty_cart.
371
+ *
372
+ * @version 3.9.0
373
+ * @since 3.6.0
374
+ * @param string $cart_item_key defines the cart_item_key.
375
+ * @param string | array $cart defines the cart.
376
+ */
377
+ public function remove_files_on_empty_cart( $cart_item_key, $cart ) {
378
+ if ( $cart->is_empty() ) {
379
+ wcj_session_maybe_start();
380
+ $any_files_removed = false;
381
+ $wcj_checkout_files_upload_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
382
+ for ( $i = 1; $i <= $wcj_checkout_files_upload_total_number; $i++ ) {
383
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
384
+ if ( null != ( $session_data ) ) {
385
+ $any_files_removed = true;
386
+ if ( isset( $session_data['tmp_name'] ) ) {
387
+ unlink( $session_data['tmp_name'] );
388
+ }
389
+ wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
390
+ }
391
+ }
392
+ if ( $any_files_removed && 'yes' === wcj_get_option( 'wcj_checkout_files_upload_remove_on_empty_cart_add_notice', 'no' ) ) {
393
+ $this->add_notice( wcj_get_option( 'wcj_checkout_files_upload_notice_remove_on_empty_cart', __( 'Files were successfully removed.', 'woocommerce-jetpack' ) ) );
394
+ }
395
  }
396
  }
 
 
 
 
 
 
 
 
 
 
 
 
397
 
398
+ /**
399
+ * Get_order_full_file_name.
400
+ *
401
+ * @version 3.8.0
402
+ * @since 3.8.0
403
+ * @todo use where needed
404
+ * @param int $order_id defines the order_id.
405
+ * @param string | int $file_num defines the file_num.
406
+ */
407
+ public function get_order_full_file_name( $order_id, $file_num ) {
408
+ return wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_wcj_checkout_files_upload_' . $file_num, true );
409
+ }
410
+
411
+ /**
412
+ * Process_checkout_files_upload.
413
+ *
414
+ * @version 3.9.0
415
+ * @since 2.4.5
416
+ * @todo add option for admin to delete files one by one (i.e. not all at once)
417
+ * @todo `$this->additional_admin_emails_settings` - more customization options, e.g.: admin email, subject, content, from
418
+ */
419
+ public function process_checkout_files_upload() {
420
+ wcj_session_maybe_start();
421
+ $admin_email = wcj_get_option( 'admin_email' );
422
+ $admin_email_subject = __( 'Booster for WooCommerce: Checkout Files Upload: %action%', 'woocommerce-jetpack' );
423
+ /* translators: %s: search term */
424
+ $admin_email_content = __( 'Order ID: %1$order_id%; File name: %2$file_name%', 'woocommerce-jetpack' );
425
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
426
+ // Remove file.
427
+ for ( $i = 1; $i <= $total_number; $i++ ) {
428
+ if ( isset( $_POST[ 'wcj_remove_checkout_file_' . $i ] ) ) {
429
+ if ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ) {
430
+ $order_id = sanitize_text_field( wp_unslash( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) );
431
+ $order_file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i, true );
432
+ if ( '' != $order_file_name ) {
433
+ $file_path = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
434
+ unlink( $file_path );
435
+ $file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i, true );
436
+ $this->add_notice(
437
+ sprintf(
438
+ wcj_get_option(
439
+ 'wcj_checkout_files_upload_notice_success_remove_' . $i,
440
+ /* translators: %s: search term */
441
+ __( 'File "%s" was successfully removed.', 'woocommerce-jetpack' )
442
+ ),
443
+ $file_name
444
+ )
445
  );
446
+ delete_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i );
447
+ delete_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i );
448
+ if ( in_array( 'remove_file', $this->additional_admin_emails_settings['actions'] ) ) {
449
+ wp_mail(
450
+ $admin_email,
451
+ wcj_handle_replacements(
452
+ array(
453
+ '%action%' => __( 'File Removed', 'woocommerce-jetpack' ),
454
+ ),
455
+ $admin_email_subject
456
+ ),
457
+ wcj_handle_replacements(
458
+ array(
459
+ '%order_id%' => sanitize_text_field( wp_unslash( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ),
460
+ '%file_name%' => $file_name,
461
+ ),
462
+ $admin_email_content
463
+ )
464
+ );
465
+ }
466
+ do_action( 'wcj_checkout_files_upload', 'remove_file', sanitize_text_field( wp_unslash( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ), $file_name );
467
  }
468
+ } else {
469
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
470
+ $file_name = $session_data['name'];
471
+ unlink( $session_data['tmp_name'] );
472
+ wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
473
+ $this->add_notice(
474
+ sprintf(
475
+ wcj_get_option(
476
+ 'wcj_checkout_files_upload_notice_success_remove_' . $i,
477
+ /* translators: %s: search term */
478
+ __( 'File "%s" was successfully removed.', 'woocommerce-jetpack' )
479
+ ),
480
+ $file_name
481
+ )
482
+ );
483
+ do_action( 'wcj_checkout_files_upload', 'remove_file', false, $file_name );
484
  }
 
 
 
 
 
 
 
 
485
  }
486
  }
487
+ // Upload file.
488
+ for ( $i = 1; $i <= $total_number; $i++ ) {
489
+ if ( isset( $_POST[ 'wcj_upload_checkout_file_' . $i ] ) ) {
490
+ $file_name = 'wcj_checkout_files_upload_' . $i;
491
+ if ( isset( $_FILES[ $file_name ] ) && '' != $_FILES[ $file_name ]['tmp_name'] ) {
492
+ // Validate.
493
+ $is_valid = true;
494
+ $real_file_name = $_FILES[ $file_name ]['name'];
495
+ $file_type = '.' . pathinfo( $real_file_name, PATHINFO_EXTENSION );
496
+ $file_accept = wcj_get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' );
497
+ if ( '' != ( $file_accept ) ) {
498
+ // Validate file type.
499
+ $file_accept = explode( ',', $file_accept );
500
+ if ( is_array( $file_accept ) && ! empty( $file_accept ) ) {
501
+ if ( ! in_array( $file_type, $file_accept ) ) {
502
+ $this->add_notice(
503
+ sprintf(
504
+ wcj_get_option(
505
+ 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
506
+ /* translators: %s: search term */
507
+ __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' )
508
+ ),
509
+ $real_file_name
510
+ ),
511
+ 'error'
512
+ );
513
+ $is_valid = false;
514
+ }
515
  }
516
  }
517
+ if ( $this->is_extension_blocked( $file_type ) ) {
518
+ $this->add_notice(
519
+ sprintf(
520
+ wcj_get_option(
521
+ 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
522
+ /* translators: %s: search term */
523
+ __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' )
524
+ ),
525
+ $real_file_name
526
+ ),
527
+ 'error'
528
+ );
529
+ $is_valid = false;
530
+ }
531
+ if ( $is_valid ) {
532
+ // To session.
533
+ $tmp_dest_file = tempnam( sys_get_temp_dir(), 'wcj' );
534
+ move_uploaded_file( $_FILES[ $file_name ]['tmp_name'], $tmp_dest_file );
535
+ $session_data = $_FILES[ $file_name ];
536
+ $session_data['tmp_name'] = $tmp_dest_file;
537
+ wcj_session_set( $file_name, $session_data );
538
+ $this->add_notice(
539
+ sprintf(
540
+ wcj_get_option(
541
+ 'wcj_checkout_files_upload_notice_success_upload_' . $i,
542
+ /* translators: %s: search term */
543
+ __( 'File "%s" was successfully uploaded.', 'woocommerce-jetpack' )
544
+ ),
545
+ $_FILES[ $file_name ]['name']
546
+ )
547
+ );
548
+ // To order.
549
+ if ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ) {
550
+ $this->add_files_to_order( sanitize_text_field( wp_unslash( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ), null );
551
+ if ( in_array( 'upload_file', $this->additional_admin_emails_settings['actions'] ) ) {
552
+ $attachments = ( 'no' === $this->additional_admin_emails_settings['do_attach'] ?
553
+ array() : array( $this->get_order_full_file_name( sanitize_text_field( wp_unslash( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ), $i ) ) );
554
+ wp_mail(
555
+ $admin_email,
556
+ wcj_handle_replacements(
557
+ array(
558
+ '%action%' => __( 'File Uploaded', 'woocommerce-jetpack' ),
559
+ ),
560
+ $admin_email_subject
561
+ ),
562
+ wcj_handle_replacements(
563
+ array(
564
+ '%order_id%' => sanitize_text_field( wp_unslash( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ),
565
+ '%file_name%' => $_FILES[ $file_name ]['name'],
566
+ ),
567
+ $admin_email_content
568
+ ),
569
+ '',
570
+ $attachments
571
+ );
572
+ }
573
  }
574
+ // Action.
575
+ do_action(
576
+ 'wcj_checkout_files_upload',
577
+ 'upload_file',
578
+ ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ? $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] : false ),
579
+ $_FILES[ $file_name ]['name']
580
+ );
581
  }
582
+ } else {
583
+ $this->add_notice(
584
+ wcj_get_option(
585
+ 'wcj_checkout_files_upload_notice_upload_no_file_' . $i,
586
+ __( 'Please select file to upload!', 'woocommerce-jetpack' )
587
+ ),
588
+ 'notice'
589
+ );
590
  }
 
 
 
591
  }
592
  }
593
+ // Admin file download.
594
+ if ( isset( $_GET['wcj_download_checkout_file_admin'] ) ) {
595
+ $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . sanitize_text_field( wp_unslash( $_GET['wcj_download_checkout_file_admin'] ) );
596
+ $file_name = get_post_meta( $_GET['post'], '_' . 'wcj_checkout_files_upload_real_name_' . sanitize_text_field( wp_unslash( $_GET['wcj_checkout_file_number'] ) ), true );
597
+ if ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) {
598
+ header( 'Expires: 0' );
599
+ header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
600
+ header( 'Cache-Control: private', false );
601
+ header( 'Content-disposition: attachment; filename=' . $file_name );
602
+ header( 'Content-Transfer-Encoding: binary' );
603
+ header( 'Content-Length: ' . filesize( $tmp_file_name ) );
604
+ readfile( $tmp_file_name );
605
+ exit();
606
+ }
607
  }
608
+ // Admin all files delete.
609
+ if ( isset( $_GET['wcj_download_checkout_file_admin_delete_all'] ) && ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) ) {
610
+ $order_id = sanitize_text_field( wp_unslash( $_GET['wcj_download_checkout_file_admin_delete_all'] ) );
611
+ $total_files = get_post_meta( $order_id, '_wcj_checkout_files_total_files', true );
612
+ for ( $i = 1; $i <= $total_files; $i++ ) {
613
+ if ( '' != ( $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true ) ) ) {
614
+ unlink( wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name );
615
+ }
616
+ delete_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i );
617
+ delete_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i );
618
  }
619
+ delete_post_meta( $order_id, '_wcj_checkout_files_total_files' );
620
+ wp_safe_redirect( remove_query_arg( 'wcj_download_checkout_file_admin_delete_all' ) );
621
+ exit;
622
  }
623
+ // User file download.
624
+ if ( isset( $_GET['wcj_download_checkout_file'] ) && isset( $_GET['_wpnonce'] ) && ( false !== wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_wpnonce'] ) ), 'wcj_download_checkout_file' ) ) ) {
625
+ $i = sanitize_text_field( wp_unslash( $_GET['wcj_download_checkout_file'] ) );
626
+ if ( ! empty( $_GET['wcj_download_checkout_file_order_id'] ) ) {
627
+ $order_id = sanitize_text_field( wp_unslash( $_GET['wcj_download_checkout_file_order_id'] ) );
628
+ if ( ! ( $order = wc_get_order( $order_id ) ) ) {
 
 
 
 
 
 
 
 
 
629
  return;
630
  }
631
+ if ( isset( $_GET['key'] ) ) {
632
+ // Thank you page.
633
+ if ( ! $order->key_is_valid( sanitize_text_field( wp_unslash( $_GET['key'] ) ) ) ) {
634
+ return;
635
+ }
636
+ } else {
637
+ // My Account.
638
+ if ( ! wcj_is_user_logged_in() || $order->get_customer_id() != wcj_get_current_user_id() ) {
639
+ return;
640
+ }
641
  }
642
+ $order_file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i, true );
643
+ $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
644
+ $file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i, true );
645
+ } else {
646
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
647
+ $tmp_file_name = $session_data['tmp_name'];
648
+ $file_name = $session_data['name'];
649
  }
650
+ header( 'Expires: 0' );
651
+ header( 'Cache-Control: must-revalidate, post-check=0, pre-check=0' );
652
+ header( 'Cache-Control: private', false );
653
+ header( 'Content-disposition: attachment; filename=' . $file_name );
654
+ header( 'Content-Transfer-Encoding: binary' );
655
+ header( 'Content-Length: ' . filesize( $tmp_file_name ) );
656
+ readfile( $tmp_file_name );
657
+ exit();
658
+ }
 
 
 
 
 
 
 
659
  }
 
 
 
 
 
 
 
 
 
660
 
661
+ /**
662
+ * Is_visible.
663
+ *
664
+ * @version 3.6.0
665
+ * @since 2.4.7
666
+ * @param int $i defines the value of i.
667
+ * @param int $order_id defines the order_id.
668
+ */
669
+ public function is_visible( $i, $order_id = 0 ) {
670
 
671
+ if ( apply_filters( 'wcj_checkout_files_always_visible_on_empty_cart', false ) && 0 == $order_id && WC()->cart->is_empty() ) {
672
+ // Added for "One Page Checkout" plugin compatibility.
673
+ return true;
674
+ }
 
675
 
676
+ // Include by user role.
677
+ $user_roles = wcj_get_option( 'wcj_checkout_files_upload_show_user_roles_' . $i, '' );
678
+ if ( ! empty( $user_roles ) && ! in_array( wcj_get_current_user_first_role(), $user_roles ) ) {
679
+ return false;
680
+ }
681
 
682
+ // Exclude by user role.
683
+ $user_roles = wcj_get_option( 'wcj_checkout_files_upload_hide_user_roles_' . $i, '' );
684
+ if ( ! empty( $user_roles ) && in_array( wcj_get_current_user_first_role(), $user_roles ) ) {
685
+ return false;
 
 
 
 
 
686
  }
687
+
688
+ // Include by product id.
689
+ $products_in = wcj_get_option( 'wcj_checkout_files_upload_show_products_in_' . $i );
690
+ if ( ! empty( $products_in ) ) {
691
+ $do_skip_by_products = true;
692
+ if ( 0 != $order_id ) {
693
+ $the_order = wc_get_order( $order_id );
694
+ $the_items = $the_order->get_items();
695
+ } else {
696
+ $the_items = WC()->cart->get_cart();
697
+ }
698
+ foreach ( $the_items as $cart_item_key => $values ) {
699
+ if ( in_array( $values['product_id'], $products_in ) ) {
700
+ $do_skip_by_products = false;
701
+ break;
702
+ }
703
+ }
704
+ if ( $do_skip_by_products ) {
705
+ return false;
706
  }
707
  }
 
 
708
 
709
+ // Exclude by product id.
710
+ $products_in = wcj_get_option( 'wcj_checkout_files_upload_hide_products_in_' . $i );
711
+ if ( ! empty( $products_in ) ) {
712
+ if ( 0 != $order_id ) {
713
+ $the_order = wc_get_order( $order_id );
714
+ $the_items = $the_order->get_items();
715
+ } else {
716
+ $the_items = WC()->cart->get_cart();
717
+ }
718
+ foreach ( $the_items as $cart_item_key => $values ) {
719
+ if ( in_array( $values['product_id'], $products_in ) ) {
720
+ return false;
721
+ }
722
  }
723
  }
 
724
 
725
+ // Include by product category.
726
+ $categories_in = wcj_get_option( 'wcj_checkout_files_upload_show_cats_in_' . $i );
727
+ if ( ! empty( $categories_in ) ) {
728
+ $do_skip_by_cats = true;
729
+ if ( 0 != $order_id ) {
730
+ $the_order = wc_get_order( $order_id );
731
+ $the_items = $the_order->get_items();
732
+ } else {
733
+ $the_items = WC()->cart->get_cart();
734
+ }
735
+ foreach ( $the_items as $cart_item_key => $values ) {
736
+ $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
737
+ if ( empty( $product_categories ) ) {
738
+ continue;
739
+ }
740
+ foreach ( $product_categories as $product_category ) {
741
+ if ( in_array( $product_category->term_id, $categories_in ) ) {
742
+ $do_skip_by_cats = false;
743
+ break;
744
+ }
745
+ }
746
+ if ( ! $do_skip_by_cats ) {
747
  break;
748
  }
749
  }
750
+ if ( $do_skip_by_cats ) {
751
+ return false;
752
+ }
753
  }
 
 
754
 
755
+ // Exclude by product category.
756
+ $categories_in = wcj_get_option( 'wcj_checkout_files_upload_hide_cats_in_' . $i );
757
+ if ( ! empty( $categories_in ) ) {
758
+ if ( 0 != $order_id ) {
759
+ $the_order = wc_get_order( $order_id );
760
+ $the_items = $the_order->get_items();
761
+ } else {
762
+ $the_items = WC()->cart->get_cart();
763
+ }
764
+ foreach ( $the_items as $cart_item_key => $values ) {
765
+ $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
766
+ if ( empty( $product_categories ) ) {
767
+ continue;
768
+ }
769
+ foreach ( $product_categories as $product_category ) {
770
+ if ( in_array( $product_category->term_id, $categories_in ) ) {
771
+ return false;
772
+ }
773
  }
774
  }
775
  }
 
776
 
777
+ // Include by product tag
778
+ $tags_in = wcj_get_option( 'wcj_checkout_files_upload_show_tags_in_' . $i );
779
+ if ( ! empty( $tags_in ) ) {
780
+ $do_skip_by_tags = true;
781
+ if ( 0 != $order_id ) {
782
+ $the_order = wc_get_order( $order_id );
783
+ $the_items = $the_order->get_items();
784
+ } else {
785
+ $the_items = WC()->cart->get_cart();
786
+ }
787
+ foreach ( $the_items as $cart_item_key => $values ) {
788
+ $product_tags = get_the_terms( $values['product_id'], 'product_tag' );
789
+ if ( empty( $product_tags ) ) {
790
+ continue;
791
+ }
792
+ foreach ( $product_tags as $product_tag ) {
793
+ if ( in_array( $product_tag->term_id, $tags_in ) ) {
794
+ $do_skip_by_tags = false;
795
+ break;
796
+ }
797
+ }
798
+ if ( ! $do_skip_by_tags ) {
799
  break;
800
  }
801
  }
802
+ if ( $do_skip_by_tags ) {
803
+ return false;
804
+ }
805
  }
 
 
806
 
807
+ // Exclude by product tag.
808
+ $tags_in = wcj_get_option( 'wcj_checkout_files_upload_hide_tags_in_' . $i );
809
+ if ( ! empty( $tags_in ) ) {
810
+ if ( 0 != $order_id ) {
811
+ $the_order = wc_get_order( $order_id );
812
+ $the_items = $the_order->get_items();
813
+ } else {
814
+ $the_items = WC()->cart->get_cart();
815
+ }
816
+ foreach ( $the_items as $cart_item_key => $values ) {
817
+ $product_tags = get_the_terms( $values['product_id'], 'product_tag' );
818
+ if ( empty( $product_tags ) ) {
819
+ continue;
820
+ }
821
+ foreach ( $product_tags as $product_tag ) {
822
+ if ( in_array( $product_tag->term_id, $tags_in ) ) {
823
+ return false;
824
+ }
825
  }
826
  }
827
  }
 
828
 
829
+ return true;
830
+ }
831
 
832
+ /**
833
+ * Maybe_get_image.
834
+ *
835
+ * @version 3.7.0
836
+ * @since 3.7.0
837
+ * @param string $link defines the link.
838
+ * @param int $i defines the value of i.
839
+ * @param int $order_id defines the order_id.
840
+ */
841
+ public function maybe_get_image( $link, $i, $order_id = 0 ) {
842
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_form_template_field_show_images', 'no' ) ) {
843
+ $order = wc_get_order( $order_id );
844
+ if ( 0 != $order_id && isset( $_GET['key'] ) && ( $order ) && $order->key_is_valid( sanitize_text_field( wp_unslash( $_GET['key'] ) ) ) ) {
845
+ $order_file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_' . $i, true );
846
+ $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
847
+ } else {
848
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
849
+ $tmp_file_name = $session_data['tmp_name'];
850
+ }
851
+ if ( @is_array( getimagesize( $tmp_file_name ) ) ) {
852
+ return '<img style="' . wcj_get_option( 'wcj_checkout_files_upload_form_template_field_image_style', 'width:64px;' ) . '" src="' . $link . '"> ';
853
+ }
854
  }
855
+ return '';
856
+ }
857
+
858
+ /**
859
+ * Get_the_form.
860
+ *
861
+ * @version 5.5.9
862
+ * @since 2.5.0
863
+ * @param int $i defines the value of i.
864
+ * @param string $file_name defines the file_name.
865
+ * @param int $order_id defines the order_id.
866
+ */
867
+ public function get_the_form( $i, $file_name, $order_id = 0 ) {
868
+ $html = '';
869
+ $html .= '<form enctype="multipart/form-data" action="" method="POST">';
870
+ $html .= wcj_get_option( 'wcj_checkout_files_upload_form_template_before', '<table>' );
871
+ $the_label = wcj_get_option( 'wcj_checkout_files_upload_label_' . $i, '' );
872
+ if ( '' != ( $the_label ) ) {
873
+ $template = wcj_get_option(
874
+ 'wcj_checkout_files_upload_form_template_label',
875
+ '<tr><td colspan="2"><label for="%field_id%">%field_label%</label>%required_html%</td></tr>'
876
+ );
877
+ $required_html = ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_required_' . $i, 'no' ) ) ?
878
+ '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
879
+ $html .= str_replace(
880
+ array( '%field_id%', '%field_label%', '%required_html%' ),
881
+ array( 'wcj_checkout_files_upload_' . $i, $the_label, $required_html ),
882
+ $template
883
+ );
884
  }
885
+ if ( '' == $file_name ) {
886
+ $field_html = '<input type="file" name="wcj_checkout_files_upload_' . $i . '" id="wcj_checkout_files_upload_' . $i .
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
887
  '" accept="' . wcj_get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) . '">';
888
+ $button_html = '<input type="submit"' .
889
  ' class="button alt"' .
890
  ' style="width:100%;"' .
891
  ' name="wcj_upload_checkout_file_' . $i . '"' .
892
  ' id="wcj_upload_checkout_file_' . $i . '"' .
893
+ ' value="' . wcj_get_option( 'wcj_checkout_files_upload_label_upload_button_' . $i, __( 'Upload', 'woocommerce-jetpack' ) ) . '"' .
894
  ' data-value="' . wcj_get_option( 'wcj_checkout_files_upload_label_upload_button_' . $i, __( 'Upload', 'woocommerce-jetpack' ) ) . '">';
895
+ } else {
896
+ $link = add_query_arg(
897
+ array(
898
+ 'wcj_download_checkout_file' => $i,
899
+ '_wpnonce' => wp_create_nonce( 'wcj_download_checkout_file' ),
900
+ 'wcj_download_checkout_file_order_id' => $order_id,
901
+ )
902
+ );
903
+ $field_html = '<a href="' . $link . '">' . $this->maybe_get_image( $link, $i, $order_id ) . $file_name . '</a>';
904
+ $button_html = '<input type="submit"' .
905
  ' class="button"' .
906
  ' style="width:100%;"' .
907
  ' name="wcj_remove_checkout_file_' . $i . '"' .
908
  ' id="wcj_remove_checkout_file_' . $i . '"' .
909
+ ' value="' . wcj_get_option( 'wcj_checkout_files_upload_label_remove_button_' . $i, __( 'Remove', 'woocommerce-jetpack' ) ) . '"' .
910
  ' data-value="' . wcj_get_option( 'wcj_checkout_files_upload_label_remove_button_' . $i, __( 'Remove', 'woocommerce-jetpack' ) ) . '">';
911
+ }
912
+ $template = wcj_get_option(
913
+ 'wcj_checkout_files_upload_form_template_field',
914
+ '<tr><td style="width:50%;max-width:50vw;">%field_html%</td><td style="width:50%;">%button_html%</td></tr>'
915
+ );
916
+ $html .= str_replace(
917
+ array( '%field_html%', '%button_html%' ),
918
+ array( $field_html, $button_html ),
919
+ $template
920
+ );
921
+ $html .= wcj_get_option( 'wcj_checkout_files_upload_form_template_after', '</table>' );
922
+ if ( 0 != $order_id ) {
923
+ $html .= '<input type="hidden" name="wcj_checkout_files_upload_order_id_' . $i . '" value="' . $order_id . '">';
924
+ }
925
+ $html .= '</form>';
926
+ return $html;
927
+ }
928
+
929
+ /**
930
+ * Add_files_upload_form_to_thankyou_and_myaccount_page.
931
+ *
932
+ * @version 2.5.6
933
+ * @since 2.5.0
934
+ * @param int $order_id defines the order_id.
935
+ */
936
+ public function add_files_upload_form_to_thankyou_and_myaccount_page( $order_id ) {
937
+ $html = '';
938
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
939
+ $current_filter = current_filter();
940
+ for ( $i = 1; $i <= $total_number; $i++ ) {
941
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) && $this->is_visible( $i, $order_id ) ) {
942
+ if (
943
+ ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_thankyou_' . $i, 'no' ) && 'woocommerce_thankyou' === $current_filter ) ||
944
  ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_add_to_myaccount_' . $i, 'no' ) && 'woocommerce_view_order' === $current_filter )
945
+ ) {
946
+ $file_name = get_post_meta( $order_id, '_wcj_checkout_files_upload_real_name_' . $i, true );
947
+ $html .= $this->get_the_form( $i, $file_name, $order_id );
948
+ }
949
  }
950
  }
951
+ echo $html;
952
  }
 
 
953
 
954
+ /**
955
+ * Add_files_upload_form_to_checkout_frontend.
956
+ *
957
+ * @version 2.5.2
958
+ * @since 2.4.5
959
+ */
960
+ public function add_files_upload_form_to_checkout_frontend() {
961
+ $this->add_files_upload_form_to_checkout_frontend_all();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
962
  }
963
+
964
+
965
+ /**
966
+ * Add_files_upload_form_to_checkout_frontend_all.
967
+ *
968
+ * @version 3.4.0
969
+ * @since 2.5.2
970
+ * @param bool $is_direct_call check the is_direct_call.
971
+ */
972
+ public function add_files_upload_form_to_checkout_frontend_all( $is_direct_call = false ) {
973
+ $html = '';
974
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
975
+ if ( ! $is_direct_call ) {
976
+ $current_filter = current_filter();
977
+ $current_filter_priority = wcj_current_filter_priority();
978
  }
979
+ for ( $i = 1; $i <= $total_number; $i++ ) {
980
+ $is_filter_ok = ( $is_direct_call ) ? true : (
981
+ wcj_get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' ) === $current_filter &&
982
+ wcj_get_option( 'wcj_checkout_files_upload_hook_priority_' . $i, 10 ) == $current_filter_priority
983
+ );
984
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) && $is_filter_ok && $this->is_visible( $i ) ) {
985
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
986
+ $file_name = ( null !== $session_data ? $session_data['name'] : '' );
987
+ $html .= $this->get_the_form( $i, $file_name );
988
+ }
989
+ }
990
+ echo $html;
991
  }
 
 
992
 
993
+ }
994
 
995
  endif;
996
 
includes/class-wcj-coupon-by-user-role.php CHANGED
@@ -5,100 +5,123 @@
5
  * @version 5.2.0
6
  * @since 3.6.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Coupon_By_User_Role' ) ) :
13
-
14
- class WCJ_Coupon_By_User_Role extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.2.0
20
- * @since 3.6.0
21
- * @todo (maybe) init all options in constructor
22
- * @todo (maybe) use another error code (instead of 10000)
23
  */
24
- function __construct() {
25
 
26
- $this->id = 'coupon_by_user_role';
27
- $this->short_desc = __( 'Coupon by User Role', 'woocommerce-jetpack' );
28
- $this->desc = __( 'Coupons by user roles. Invalidate per Coupon (Plus). Custom coupon invalid messages (Plus)', 'woocommerce-jetpack' );
29
- $this->desc_pro = __( 'Coupons by user roles.', 'woocommerce-jetpack' );
30
- $this->link_slug = 'woocommerce-coupon-by-user-role';
31
- parent::__construct();
 
 
 
32
 
33
- if ( $this->is_enabled() ) {
34
- add_filter( 'woocommerce_coupons_enabled', array( $this, 'coupons_enabled' ), PHP_INT_MAX, 1 );
35
- add_filter( 'woocommerce_coupon_is_valid', array( $this, 'coupon_valid' ), PHP_INT_MAX, 3 );
36
- add_filter( 'woocommerce_coupon_error', array( $this, 'coupon_not_valid_message' ), PHP_INT_MAX, 3 );
37
- if ( $this->invalid_per_coupon_enabled = ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_coupon_by_user_role_invalid_per_coupon', 'no' ) ) ) ) {
38
- $this->meta_box_screen = 'shop_coupon';
39
- $this->meta_box_context = 'side';
40
- $this->meta_box_priority = 'default';
41
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
42
- add_action( 'save_post_shop_coupon', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
 
 
 
 
 
 
 
 
 
43
  }
44
  }
45
- }
46
 
47
- /**
48
- * coupons_enabled.
49
- *
50
- * @version 3.6.0
51
- * @since 3.6.0
52
- */
53
- function coupons_enabled( $is_enabled ) {
54
- $disabled_user_roles = wcj_get_option( 'wcj_coupon_by_user_role_disabled', '' );
55
- if ( ! empty( $disabled_user_roles ) && in_array( wcj_get_current_user_first_role(), $disabled_user_roles ) ) {
56
- return false;
 
 
 
57
  }
58
- return $is_enabled;
59
- }
60
 
61
- /**
62
- * coupon_valid.
63
- *
64
- * @version 3.6.0
65
- * @since 3.6.0
66
- * @todo (maybe) check if `$coupon->get_id()` is working in WC below v3.0.0
67
- */
68
- function coupon_valid( $valid, $coupon, $discounts ) {
69
- $invalid_user_roles = wcj_get_option( 'wcj_coupon_by_user_role_invalid', '' );
70
- if ( empty( $invalid_user_roles ) ) {
71
- $invalid_user_roles = array();
72
- }
73
- if ( $this->invalid_per_coupon_enabled ) {
74
- $invalid_user_roles_per_coupon = get_post_meta( $coupon->get_id(), '_' . 'wcj_coupon_by_user_role_invalid', true );
75
- if ( ! empty( $invalid_user_roles_per_coupon ) ) {
76
- $invalid_user_roles = array_merge( $invalid_user_roles, $invalid_user_roles_per_coupon );
77
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
79
- if ( ! empty( $invalid_user_roles ) && in_array( wcj_get_current_user_first_role(), $invalid_user_roles ) ) {
80
- throw new Exception( apply_filters( 'booster_option', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ),
81
- get_option( 'wcj_coupon_by_user_role_invalid_message', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ) ) ), 10000 );
82
- return false;
83
- }
84
- return $valid;
85
- }
86
 
87
- /**
88
- * coupon_not_valid_message.
89
- *
90
- * @version 3.6.0
91
- * @since 3.6.0
92
- */
93
- function coupon_not_valid_message( $message, $code, $coupon ) {
94
- if ( 10000 === $code ) {
95
- return apply_filters( 'booster_option', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ),
96
- get_option( 'wcj_coupon_by_user_role_invalid_message', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ) ) );
 
 
 
 
 
 
 
 
97
  }
98
- return $message;
99
- }
100
 
101
- }
102
 
103
  endif;
104
 
5
  * @version 5.2.0
6
  * @since 3.6.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Coupon_By_User_Role' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Coupon_By_User_Role.
 
 
 
 
 
18
  */
19
+ class WCJ_Coupon_By_User_Role extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.2.0
25
+ * @since 3.6.0
26
+ * @todo (maybe) init all options in constructor
27
+ * @todo (maybe) use another error code (instead of 10000)
28
+ */
29
+ public function __construct() {
30
 
31
+ $this->id = 'coupon_by_user_role';
32
+ $this->short_desc = __( 'Coupon by User Role', 'woocommerce-jetpack' );
33
+ $this->desc = __( 'Coupons by user roles. Invalidate per Coupon (Plus). Custom coupon invalid messages (Plus)', 'woocommerce-jetpack' );
34
+ $this->desc_pro = __( 'Coupons by user roles.', 'woocommerce-jetpack' );
35
+ $this->link_slug = 'woocommerce-coupon-by-user-role';
36
+ parent::__construct();
37
+
38
+ if ( $this->is_enabled() ) {
39
+ add_filter( 'woocommerce_coupons_enabled', array( $this, 'coupons_enabled' ), PHP_INT_MAX, 1 );
40
+ add_filter( 'woocommerce_coupon_is_valid', array( $this, 'coupon_valid' ), PHP_INT_MAX, 3 );
41
+ add_filter( 'woocommerce_coupon_error', array( $this, 'coupon_not_valid_message' ), PHP_INT_MAX, 3 );
42
+ $this->invalid_per_coupon_enabled = ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_coupon_by_user_role_invalid_per_coupon', 'no' ) ) );
43
+ if ( $this->invalid_per_coupon_enabled ) {
44
+ $this->meta_box_screen = 'shop_coupon';
45
+ $this->meta_box_context = 'side';
46
+ $this->meta_box_priority = 'default';
47
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
48
+ add_action( 'save_post_shop_coupon', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
49
+ }
50
  }
51
  }
 
52
 
53
+ /**
54
+ * Coupons_enabled.
55
+ *
56
+ * @version 3.6.0
57
+ * @since 3.6.0
58
+ * @param string | bool $is_enabled check the coupons enabled.
59
+ */
60
+ public function coupons_enabled( $is_enabled ) {
61
+ $disabled_user_roles = wcj_get_option( 'wcj_coupon_by_user_role_disabled', '' );
62
+ if ( ! empty( $disabled_user_roles ) && in_array( wcj_get_current_user_first_role(), $disabled_user_roles ) ) {
63
+ return false;
64
+ }
65
+ return $is_enabled;
66
  }
 
 
67
 
68
+ /**
69
+ * Coupon_valid.
70
+ *
71
+ * @version 3.6.0
72
+ * @since 3.6.0
73
+ * @todo (maybe) check if `$coupon->get_id()` is working in WC below v3.0.0
74
+ * @param string | bool $valid defines the valid.
75
+ * @param string | array $coupon defines the coupon.
76
+ * @param int $discounts defines the discounts.
77
+ * @throws Exception Use for Exception.
78
+ */
79
+ public function coupon_valid( $valid, $coupon, $discounts ) {
80
+ $invalid_user_roles = wcj_get_option( 'wcj_coupon_by_user_role_invalid', '' );
81
+ if ( empty( $invalid_user_roles ) ) {
82
+ $invalid_user_roles = array();
 
83
  }
84
+ if ( $this->invalid_per_coupon_enabled ) {
85
+ $invalid_user_roles_per_coupon = get_post_meta( $coupon->get_id(), '_wcj_coupon_by_user_role_invalid', true );
86
+ if ( ! empty( $invalid_user_roles_per_coupon ) ) {
87
+ $invalid_user_roles = array_merge( $invalid_user_roles, $invalid_user_roles_per_coupon );
88
+ }
89
+ }
90
+ if ( ! empty( $invalid_user_roles ) && in_array( wcj_get_current_user_first_role(), $invalid_user_roles, true ) ) {
91
+ throw new Exception(
92
+ apply_filters(
93
+ 'booster_option',
94
+ __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ),
95
+ get_option( 'wcj_coupon_by_user_role_invalid_message', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ) )
96
+ ),
97
+ 10000
98
+ );
99
+ return false;
100
+ }
101
+ return $valid;
102
  }
 
 
 
 
 
 
 
103
 
104
+ /**
105
+ * Coupon_not_valid_message.
106
+ *
107
+ * @version 3.6.0
108
+ * @since 3.6.0
109
+ * @param string $message defines the message.
110
+ * @param string | int $code defines the code.
111
+ * @param string | array $coupon defines the coupon.
112
+ */
113
+ public function coupon_not_valid_message( $message, $code, $coupon ) {
114
+ if ( 10000 === $code ) {
115
+ return apply_filters(
116
+ 'booster_option',
117
+ __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ),
118
+ get_option( 'wcj_coupon_by_user_role_invalid_message', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ) )
119
+ );
120
+ }
121
+ return $message;
122
  }
 
 
123
 
124
+ }
125
 
126
  endif;
127
 
includes/class-wcj-coupon-code-generator.php CHANGED
@@ -5,138 +5,149 @@
5
  * @version 5.2.0
6
  * @since 3.2.3
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Coupon_Code_Generator' ) ) :
13
-
14
- class WCJ_Coupon_Code_Generator extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.2.0
20
- * @since 3.2.3
21
- * @todo user ID in coupon code
22
- * @todo add option to generate code only on button (in meta box) pressed
23
- * @todo `wp_ajax_nopriv_wcj_generate_coupon_code` ?
24
  */
25
- function __construct() {
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- $this->id = 'coupon_code_generator';
28
- $this->short_desc = __( 'Coupon Code Generator', 'woocommerce-jetpack' );
29
- $this->desc = __( 'Coupon code generator (Multiple generation algorithms available in Plus).', 'woocommerce-jetpack' );
30
- $this->desc_pro = __( 'Coupon code generator.', 'woocommerce-jetpack' );
31
- $this->link_slug = 'woocommerce-coupon-code-generator';
32
- parent::__construct();
33
 
34
- if ( $this->is_enabled() ) {
35
- if ( 'yes' === wcj_get_option( 'wcj_coupons_code_generator_enabled', 'no' ) ) {
36
- add_action( 'wp_ajax_wcj_generate_coupon_code', array( $this, 'ajax_generate_coupon_code' ) );
37
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_generate_coupon_code_script' ) );
 
38
  }
39
  }
40
- }
41
 
42
- /**
43
- * enqueue_generate_coupon_code_script.
44
- *
45
- * @version 3.1.3
46
- * @since 3.1.3
47
- */
48
- function enqueue_generate_coupon_code_script() {
49
- global $pagenow;
50
- if ( 'post-new.php' === $pagenow && isset( $_GET['post_type'] ) && 'shop_coupon' === $_GET['post_type'] ) {
51
- wp_enqueue_script( 'wcj-coupons-code-generator', wcj_plugin_url() . '/includes/js/wcj-coupons-code-generator.js', array( 'jquery' ), WCJ()->version, true );
52
- wp_localize_script( 'wcj-coupons-code-generator', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
53
- }
54
- }
55
 
56
- /**
57
- * random_string.
58
- *
59
- * @version 3.2.3
60
- * @since 3.2.3
61
- * @todo (maybe) $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
62
- */
63
- function random_string( $length = 32, $characters = 'abcdefghijklmnopqrstuvwxyz' ) {
64
- $characters_length = strlen( $characters );
65
- $random_string = '';
66
- for ( $i = 0; $i < $length; $i++ ) {
67
- $random_string .= $characters[ rand( 0, $characters_length - 1 ) ];
68
  }
69
- return $random_string;
70
- }
71
 
72
- /**
73
- * generate_coupon_code.
74
- *
75
- * @version 3.2.3
76
- * @since 3.1.3
77
- * @todo (maybe) more algorithms
78
- */
79
- function generate_coupon_code( $str = '', $algorithm = '', $length = '' ) {
80
- if ( '' === $str ) {
81
- $str = time();
82
- }
83
- if ( '' === $algorithm ) {
84
- $algorithm = apply_filters( 'booster_option', 'crc32', wcj_get_option( 'wcj_coupons_code_generator_algorithm', 'crc32' ) );
85
- }
86
- switch ( $algorithm ) {
87
- case 'random_letters_and_numbers':
88
- $code = $this->random_string( 32, '0123456789abcdefghijklmnopqrstuvwxyz' );
89
- break;
90
- case 'random_letters':
91
- $code = $this->random_string( 32, 'abcdefghijklmnopqrstuvwxyz' );
92
- break;
93
- case 'random_numbers':
94
- $code = $this->random_string( 32, '0123456789' );
95
- break;
96
- case 'md5':
97
- $code = md5( $str );
98
- break;
99
- case 'sha1':
100
- $code = sha1( $str );
101
- break;
102
- default: // 'crc32'
103
- $code = sprintf( '%08x', crc32( $str ) );
104
- break;
105
- }
106
- if ( '' === $length ) {
107
- $length = apply_filters( 'booster_option', 0, wcj_get_option( 'wcj_coupons_code_generator_length', 0 ) );
108
- }
109
- if ( $length > 0 && strlen( $code ) > $length ) {
110
- $code = substr( $code, 0, $length );
111
  }
112
- return $code;
113
- }
114
 
115
- /**
116
- * ajax_generate_coupon_code.
117
- *
118
- * @version 3.1.3
119
- * @since 3.1.3
120
- * @todo (maybe) optionally generate some description for coupon (e.g. "Automatically generated coupon [YYYY-MM-DD]")
121
- */
122
- function ajax_generate_coupon_code() {
123
- $attempts = 0;
124
- while ( true ) {
125
- $coupon_code = $this->generate_coupon_code();
126
- $coupon = new WC_Coupon( $coupon_code );
127
- if ( ! $coupon->get_id() ) {
128
- echo $coupon_code;
129
- die();
 
130
  }
131
- $attempts++;
132
- if ( $attempts > 100 ) { // shouldn't happen, but just in case...
133
- echo '';
134
- die();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
  }
 
 
 
 
 
 
 
136
  }
137
- }
138
 
139
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
 
141
  endif;
142
 
5
  * @version 5.2.0
6
  * @since 3.2.3
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Coupon_Code_Generator' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Coupon_Code_Generator.
 
 
 
 
 
 
18
  */
19
+ class WCJ_Coupon_Code_Generator extends WCJ_Module {
20
+
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.2.0
25
+ * @since 3.2.3
26
+ * @todo user ID in coupon code
27
+ * @todo add option to generate code only on button (in meta box) pressed
28
+ * @todo `wp_ajax_nopriv_wcj_generate_coupon_code` ?
29
+ */
30
+ public function __construct() {
31
 
32
+ $this->id = 'coupon_code_generator';
33
+ $this->short_desc = __( 'Coupon Code Generator', 'woocommerce-jetpack' );
34
+ $this->desc = __( 'Coupon code generator (Multiple generation algorithms available in Plus).', 'woocommerce-jetpack' );
35
+ $this->desc_pro = __( 'Coupon code generator.', 'woocommerce-jetpack' );
36
+ $this->link_slug = 'woocommerce-coupon-code-generator';
37
+ parent::__construct();
38
 
39
+ if ( $this->is_enabled() ) {
40
+ if ( 'yes' === wcj_get_option( 'wcj_coupons_code_generator_enabled', 'no' ) ) {
41
+ add_action( 'wp_ajax_wcj_generate_coupon_code', array( $this, 'ajax_generate_coupon_code' ) );
42
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_generate_coupon_code_script' ) );
43
+ }
44
  }
45
  }
 
46
 
47
+ /**
48
+ * Enqueue_generate_coupon_code_script.
49
+ *
50
+ * @version 3.1.3
51
+ * @since 3.1.3
52
+ */
53
+ public function enqueue_generate_coupon_code_script() {
54
+ global $pagenow;
 
 
 
 
 
55
 
56
+ if ( 'post-new.php' === $pagenow && isset( $_GET['post_type'] ) && 'shop_coupon' === $_GET['post_type'] ) {
57
+ wp_enqueue_script( 'wcj-coupons-code-generator', wcj_plugin_url() . '/includes/js/wcj-coupons-code-generator.js', array( 'jquery' ), w_c_j()->version, true );
58
+ wp_localize_script( 'wcj-coupons-code-generator', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
59
+ }
 
 
 
 
 
 
 
 
60
  }
 
 
61
 
62
+ /**
63
+ * Random_string.
64
+ *
65
+ * @version 3.2.3
66
+ * @since 3.2.3
67
+ * @todo (maybe) $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.
68
+ * @param int $length defines the length.
69
+ * @param string $characters defines the characters.
70
+ */
71
+ public function random_string( $length = 32, $characters = 'abcdefghijklmnopqrstuvwxyz' ) {
72
+ $characters_length = strlen( $characters );
73
+ $random_string = '';
74
+ for ( $i = 0; $i < $length; $i++ ) {
75
+ $random_string .= $characters[ wp_rand( 0, $characters_length - 1 ) ];
76
+ }
77
+ return $random_string;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
 
 
79
 
80
+ /**
81
+ * Generate_coupon_code.
82
+ *
83
+ * @version 3.2.3
84
+ * @since 3.1.3
85
+ * @todo (maybe) more algorithms
86
+ * @param string $str used for str.
87
+ * @param string $algorithm used fore algorithm.
88
+ * @param int $length used for length.
89
+ */
90
+ public function generate_coupon_code( $str = '', $algorithm = '', $length = '' ) {
91
+ if ( '' === $str ) {
92
+ $str = time();
93
+ }
94
+ if ( '' === $algorithm ) {
95
+ $algorithm = apply_filters( 'booster_option', 'crc32', wcj_get_option( 'wcj_coupons_code_generator_algorithm', 'crc32' ) );
96
  }
97
+ switch ( $algorithm ) {
98
+ case 'random_letters_and_numbers':
99
+ $code = $this->random_string( 32, '0123456789abcdefghijklmnopqrstuvwxyz' );
100
+ break;
101
+ case 'random_letters':
102
+ $code = $this->random_string( 32, 'abcdefghijklmnopqrstuvwxyz' );
103
+ break;
104
+ case 'random_numbers':
105
+ $code = $this->random_string( 32, '0123456789' );
106
+ break;
107
+ case 'md5':
108
+ $code = md5( $str );
109
+ break;
110
+ case 'sha1':
111
+ $code = sha1( $str );
112
+ break;
113
+ default: // 'crc32'
114
+ $code = sprintf( '%08x', crc32( $str ) );
115
+ break;
116
  }
117
+ if ( '' === $length ) {
118
+ $length = apply_filters( 'booster_option', 0, wcj_get_option( 'wcj_coupons_code_generator_length', 0 ) );
119
+ }
120
+ if ( $length > 0 && strlen( $code ) > $length ) {
121
+ $code = substr( $code, 0, $length );
122
+ }
123
+ return $code;
124
  }
 
125
 
126
+ /**
127
+ * Ajax_generate_coupon_code.
128
+ *
129
+ * @version 3.1.3
130
+ * @since 3.1.3
131
+ * @todo (maybe) optionally generate some description for coupon (e.g. "Automatically generated coupon [YYYY-MM-DD]")
132
+ */
133
+ public function ajax_generate_coupon_code() {
134
+ $attempts = 0;
135
+ while ( true ) {
136
+ $coupon_code = $this->generate_coupon_code();
137
+ $coupon = new WC_Coupon( $coupon_code );
138
+ if ( ! $coupon->get_id() ) {
139
+ echo wp_kses_post( $coupon_code );
140
+ die();
141
+ }
142
+ $attempts++;
143
+ if ( $attempts > 100 ) { // shouldn't happen, but just in case...
144
+ echo '';
145
+ die();
146
+ }
147
+ }
148
+ }
149
+
150
+ }
151
 
152
  endif;
153
 
includes/class-wcj-cross-sells.php CHANGED
@@ -5,211 +5,237 @@
5
  * @version 5.5.9
6
  * @since 3.5.3
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Cross_Sells' ) ) :
13
 
14
- class WCJ_Cross_Sells extends WCJ_Module {
15
-
16
- /**
17
- * Constructor.
18
- *
19
- * @version 5.2.0
20
- * @since 3.5.3
21
- * @todo [feature] add pop up box (for `wcj_cross_sells_replace_with_cross_sells`)
22
- */
23
- function __construct() {
24
-
25
- $this->id = 'cross_sells';
26
- $this->short_desc = __( 'Cross-sells', 'woocommerce-jetpack' );
27
- $this->extra_desc = __( 'Cross-sells are products which you promote in the cart, based on the current product.', 'woocommerce' ) . '<br>' .
28
- sprintf( __( 'You can also use %s shortcode to display cross-sells anywhere on your site, for example on checkout page with %s module.', 'woocommerce-jetpack' ),
 
 
 
 
 
29
  '<code>[wcj_cross_sell_display]</code>',
30
  '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=cart_and_checkout&section=checkout_custom_info' ) . '">' .
31
- __( 'Checkout Custom Info', 'woocommerce-jetpack' ) . '</a>' );
32
- $this->desc = __( 'Customize cross-sells products display. Global Cross-sells (Plus); Exclude "Not in Stock" Products (Plus); Replace Cart Products with Cross-sells (Plus).', 'woocommerce-jetpack' );
33
- $this->desc_pro = __( 'Customize cross-sells products display. Global Cross-sells; Exclude "Not in Stock" Products; Replace Cart Products with Cross-sells.', 'woocommerce-jetpack' );
34
- $this->link_slug = 'woocommerce-cross-sells';
35
- parent::__construct();
36
-
37
- if ( $this->is_enabled() ) {
38
- add_filter( 'woocommerce_cross_sells_total', array( $this, 'cross_sells_total' ), PHP_INT_MAX );
39
- add_filter( 'woocommerce_cross_sells_columns', array( $this, 'cross_sells_columns' ), PHP_INT_MAX );
40
- add_filter( 'woocommerce_cross_sells_orderby', array( $this, 'cross_sells_orderby' ), PHP_INT_MAX );
41
- if ( ! WCJ_IS_WC_VERSION_BELOW_3_3_0 ) {
42
- add_filter( 'woocommerce_cross_sells_order', array( $this, 'cross_sells_order' ), PHP_INT_MAX );
43
- }
44
- if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
45
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_cross_sells_global_enabled', 'no' ) ) ) {
46
- add_filter( 'woocommerce_product_get_cross_sell_ids', array( $this, 'cross_sells_ids' ), PHP_INT_MAX, 2 );
47
  }
48
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_cross_sells_exclude_not_in_stock', 'no' ) ) ) {
49
- add_filter( 'woocommerce_product_get_cross_sell_ids', array( $this, 'cross_sells_exclude_not_in_stock' ), PHP_INT_MAX, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  }
51
  }
52
- if ( 'yes' === wcj_get_option( 'wcj_cross_sells_hide', 'no' ) ) {
53
- add_action( 'init', array( $this, 'hide_cross_sells' ), PHP_INT_MAX );
54
- }
55
- if ( 'no_changes' != wcj_get_option( 'wcj_cross_sells_position', 'no_changes' ) ) {
56
- add_action( 'init', array( $this, 'reposition_cross_sells' ), PHP_INT_MAX );
57
- }
58
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_cross_sells_replace_with_cross_sells', 'no' ) ) ) {
59
- add_filter( 'woocommerce_product_add_to_cart_url', array( $this, 'replace_with_cross_sells_to_url' ), PHP_INT_MAX, 2 );
60
- add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'remove_from_cart_by_product_id' ) );
61
- }
62
- }
63
 
64
- }
65
 
66
- /**
67
- * replace_with_cross_sells_to_url.
68
- *
69
- * @version 5.5.9
70
- * @since 3.9.0
71
- * @todo [dev] re-check variable products
72
- */
73
- function replace_with_cross_sells_to_url( $url, $product ) {
74
- if ( is_cart() && ( $_cart = WC()->cart ) ) {
75
- $product_id = $product->get_id();
76
- $product_ids_to_remove = array();
77
- foreach ( $_cart->get_cart() as $cart_item_key => $values ) {
78
- $_product = wc_get_product( $values['product_id'] );
79
- $cross_sell_ids = $_product->get_cross_sell_ids();
80
- if ( in_array( $product_id, $cross_sell_ids ) ) {
81
- $product_ids_to_remove[] = $values['product_id'];
 
 
 
 
 
 
 
82
  }
83
  }
84
- if ( ! empty( $product_ids_to_remove ) ) {
85
- $url = esc_url(add_query_arg( array( 'wcj-remove-from-cart' => implode( ',', array_unique( $product_ids_to_remove ) ) ), $url ));
86
- }
87
  }
88
- return $url;
89
- }
90
 
91
- /**
92
- * remove_from_cart_by_product_id.
93
- *
94
- * @version 3.9.0
95
- * @since 3.9.0
96
- * @todo [dev] AJAX
97
- */
98
- function remove_from_cart_by_product_id() {
99
- if ( isset( $_GET['wcj-remove-from-cart'] ) ) {
100
- if ( $_cart = WC()->cart ) {
101
- $product_ids_to_remove = explode( ',', $_GET['wcj-remove-from-cart'] );
102
- foreach ( $_cart->get_cart() as $cart_item_key => $values ) {
103
- if ( in_array( $values['product_id'], $product_ids_to_remove ) ) {
104
- $_cart->remove_cart_item( $cart_item_key );
 
 
105
  }
106
  }
 
 
107
  }
108
- wp_safe_redirect( remove_query_arg( 'wcj-remove-from-cart' ) );
109
- exit;
110
  }
111
- }
112
 
113
- /**
114
- * reposition_cross_sells.
115
- *
116
- * @version 3.6.0
117
- * @since 3.6.0
118
- * @todo [dev] (maybe) check `woocommerce\templates\cart\cart.php` for more positions
119
- */
120
- function reposition_cross_sells() {
121
- $this->hide_cross_sells();
122
- add_action( wcj_get_option( 'wcj_cross_sells_position', 'no_changes' ), 'woocommerce_cross_sell_display', wcj_get_option( 'wcj_cross_sells_position_priority', 10 ) );
123
- }
124
 
125
- /**
126
- * hide_cross_sells.
127
- *
128
- * @version 3.6.0
129
- * @since 3.6.0
130
- */
131
- function hide_cross_sells() {
132
- remove_action( 'woocommerce_cart_collaterals', 'woocommerce_cross_sell_display' );
133
- }
134
 
135
- /**
136
- * cross_sells_exclude_not_in_stock.
137
- *
138
- * @version 5.4.9
139
- * @since 3.9.0
140
- */
141
- function cross_sells_exclude_not_in_stock( $ids, $_product ) {
142
- foreach ($ids as $key => $product_id) {
143
- $product = wc_get_product($product_id);
144
- if (!$product->managing_stock() && !$product->is_in_stock()) {
145
- unset($ids[$key]);
 
 
 
146
  }
 
147
  }
148
- return $ids;
149
- }
150
 
151
- /**
152
- * cross_sells_ids.
153
- *
154
- * @version 3.6.0
155
- * @since 3.6.0
156
- * @todo [dev] (maybe) ids instead of list
157
- * @todo [dev] (maybe) on cart update (i.e. product removed) cross-sells are not updated (so it may be needed to reload page manually to see new cross-sells)
158
- * @todo [feature] (maybe) on per category/tag basis
159
- */
160
- function cross_sells_ids( $ids, $_product ) {
161
- $global_cross_sells = wcj_get_option( 'wcj_cross_sells_global_ids', '' );
162
- if ( ! empty( $global_cross_sells ) ) {
163
- $global_cross_sells = array_unique( $global_cross_sells );
164
- $product_id = wcj_get_product_id_or_variation_parent_id( $_product );
165
- if ( false !== ( $key = array_search( $product_id, $global_cross_sells ) ) ) {
166
- unset( $global_cross_sells[ $key ] );
 
 
 
 
167
  }
 
168
  }
169
- return ( empty( $global_cross_sells ) ? $ids : array_unique( array_merge( $ids, $global_cross_sells ) ) );
170
- }
171
 
172
- /**
173
- * cross_sells_order.
174
- *
175
- * @version 3.5.3
176
- * @since 3.5.3
177
- */
178
- function cross_sells_order( $order ) {
179
- return ( 'no_changes' != ( $_order = wcj_get_option( 'wcj_cross_sells_order', 'no_changes' ) ) ? $_order : $order );
180
- }
 
 
181
 
182
- /**
183
- * cross_sells_orderby.
184
- *
185
- * @version 3.5.3
186
- * @since 3.5.3
187
- */
188
- function cross_sells_orderby( $orderby ) {
189
- return ( 'no_changes' != ( $_orderby = wcj_get_option( 'wcj_cross_sells_orderby', 'no_changes' ) ) ? $_orderby : $orderby );
190
- }
 
 
191
 
192
- /**
193
- * cross_sells_columns.
194
- *
195
- * @version 3.5.3
196
- * @since 3.5.3
197
- */
198
- function cross_sells_columns( $columns ) {
199
- return ( 0 != ( $_columns = wcj_get_option( 'wcj_cross_sells_columns', 0 ) ) ? $_columns : $columns );
200
- }
 
 
201
 
202
- /**
203
- * cross_sells_total.
204
- *
205
- * @version 3.6.0
206
- * @since 3.5.3
207
- */
208
- function cross_sells_total( $limit ) {
209
- return ( 0 != ( $_limit = wcj_get_option( 'wcj_cross_sells_total', 0 ) ) ? $_limit : $limit );
210
- }
 
 
211
 
212
- }
213
 
214
  endif;
215
 
5
  * @version 5.5.9
6
  * @since 3.5.3
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Cross_Sells' ) ) :
16
 
17
+ /**
18
+ * WCJ_Cross_Sells.
19
+ */
20
+ class WCJ_Cross_Sells extends WCJ_Module {
21
+
22
+ /**
23
+ * Constructor.
24
+ *
25
+ * @version 5.2.0
26
+ * @since 3.5.3
27
+ * @todo [feature] add pop up box (for `wcj_cross_sells_replace_with_cross_sells`)
28
+ */
29
+ public function __construct() {
30
+
31
+ $this->id = 'cross_sells';
32
+ $this->short_desc = __( 'Cross-sells', 'woocommerce-jetpack' );
33
+ $this->extra_desc = __( 'Cross-sells are products which you promote in the cart, based on the current product.', 'woocommerce' ) . '<br>' .
34
+ sprintf(
35
+ /* translators: %s: translation added */
36
+ __( 'You can also use %1$s shortcode to display cross-sells anywhere on your site, for example on checkout page with %2$s module.', 'woocommerce-jetpack' ),
37
  '<code>[wcj_cross_sell_display]</code>',
38
  '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=cart_and_checkout&section=checkout_custom_info' ) . '">' .
39
+ __( 'Checkout Custom Info', 'woocommerce-jetpack' ) . '</a>'
40
+ );
41
+ $this->desc = __( 'Customize cross-sells products display. Global Cross-sells (Plus); Exclude "Not in Stock" Products (Plus); Replace Cart Products with Cross-sells (Plus).', 'woocommerce-jetpack' );
42
+ $this->desc_pro = __( 'Customize cross-sells products display. Global Cross-sells; Exclude "Not in Stock" Products; Replace Cart Products with Cross-sells.', 'woocommerce-jetpack' );
43
+ $this->link_slug = 'woocommerce-cross-sells';
44
+ parent::__construct();
45
+
46
+ if ( $this->is_enabled() ) {
47
+ add_filter( 'woocommerce_cross_sells_total', array( $this, 'cross_sells_total' ), PHP_INT_MAX );
48
+ add_filter( 'woocommerce_cross_sells_columns', array( $this, 'cross_sells_columns' ), PHP_INT_MAX );
49
+ add_filter( 'woocommerce_cross_sells_orderby', array( $this, 'cross_sells_orderby' ), PHP_INT_MAX );
50
+ if ( ! WCJ_IS_WC_VERSION_BELOW_3_3_0 ) {
51
+ add_filter( 'woocommerce_cross_sells_order', array( $this, 'cross_sells_order' ), PHP_INT_MAX );
 
 
 
52
  }
53
+ if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
54
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_cross_sells_global_enabled', 'no' ) ) ) {
55
+ add_filter( 'woocommerce_product_get_cross_sell_ids', array( $this, 'cross_sells_ids' ), PHP_INT_MAX, 2 );
56
+ }
57
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_cross_sells_exclude_not_in_stock', 'no' ) ) ) {
58
+ add_filter( 'woocommerce_product_get_cross_sell_ids', array( $this, 'cross_sells_exclude_not_in_stock' ), PHP_INT_MAX, 2 );
59
+ }
60
+ }
61
+ if ( 'yes' === wcj_get_option( 'wcj_cross_sells_hide', 'no' ) ) {
62
+ add_action( 'init', array( $this, 'hide_cross_sells' ), PHP_INT_MAX );
63
+ }
64
+ if ( 'no_changes' !== wcj_get_option( 'wcj_cross_sells_position', 'no_changes' ) ) {
65
+ add_action( 'init', array( $this, 'reposition_cross_sells' ), PHP_INT_MAX );
66
+ }
67
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_cross_sells_replace_with_cross_sells', 'no' ) ) ) {
68
+ add_filter( 'woocommerce_product_add_to_cart_url', array( $this, 'replace_with_cross_sells_to_url' ), PHP_INT_MAX, 2 );
69
+ add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'remove_from_cart_by_product_id' ) );
70
  }
71
  }
 
 
 
 
 
 
 
 
 
 
 
72
 
73
+ }
74
 
75
+ /**
76
+ * Replace_with_cross_sells_to_url.
77
+ *
78
+ * @version 5.5.9
79
+ * @since 3.9.0
80
+ * @todo [dev] re-check variable products
81
+ * @param string $url defines the url.
82
+ * @param string | array $product defines the product.
83
+ */
84
+ public function replace_with_cross_sells_to_url( $url, $product ) {
85
+ $_cart = WC()->cart;
86
+ if ( is_cart() && $_cart ) {
87
+ $product_id = $product->get_id();
88
+ $product_ids_to_remove = array();
89
+ foreach ( $_cart->get_cart() as $cart_item_key => $values ) {
90
+ $_product = wc_get_product( $values['product_id'] );
91
+ $cross_sell_ids = $_product->get_cross_sell_ids();
92
+ if ( in_array( $product_id, $cross_sell_ids ) ) {
93
+ $product_ids_to_remove[] = $values['product_id'];
94
+ }
95
+ }
96
+ if ( ! empty( $product_ids_to_remove ) ) {
97
+ $url = esc_url( add_query_arg( array( 'wcj-remove-from-cart' => implode( ',', array_unique( $product_ids_to_remove ) ) ), $url ) );
98
  }
99
  }
100
+ return $url;
 
 
101
  }
 
 
102
 
103
+ /**
104
+ * Remove_from_cart_by_product_id.
105
+ *
106
+ * @version 3.9.0
107
+ * @since 3.9.0
108
+ * @todo [dev] AJAX
109
+ */
110
+ public function remove_from_cart_by_product_id() {
111
+ $_cart = WC()->cart;
112
+ if ( isset( $_GET['wcj-remove-from-cart'] ) ) {
113
+ if ( isset( $_cart ) ) {
114
+ $product_ids_to_remove = explode( ',', $_GET['wcj-remove-from-cart'] );
115
+ foreach ( $_cart->get_cart() as $cart_item_key => $values ) {
116
+ if ( in_array( $values['product_id'], $product_ids_to_remove ) ) {
117
+ $_cart->remove_cart_item( $cart_item_key );
118
+ }
119
  }
120
  }
121
+ wp_safe_redirect( remove_query_arg( 'wcj-remove-from-cart' ) );
122
+ exit;
123
  }
 
 
124
  }
 
125
 
126
+ /**
127
+ * Reposition_cross_sells.
128
+ *
129
+ * @version 3.6.0
130
+ * @since 3.6.0
131
+ * @todo [dev] (maybe) check `woocommerce\templates\cart\cart.php` for more positions
132
+ */
133
+ public function reposition_cross_sells() {
134
+ $this->hide_cross_sells();
135
+ add_action( wcj_get_option( 'wcj_cross_sells_position', 'no_changes' ), 'woocommerce_cross_sell_display', wcj_get_option( 'wcj_cross_sells_position_priority', 10 ) );
136
+ }
137
 
138
+ /**
139
+ * Hide_cross_sells.
140
+ *
141
+ * @version 3.6.0
142
+ * @since 3.6.0
143
+ */
144
+ public function hide_cross_sells() {
145
+ remove_action( 'woocommerce_cart_collaterals', 'woocommerce_cross_sell_display' );
146
+ }
147
 
148
+ /**
149
+ * Cross_sells_exclude_not_in_stock.
150
+ *
151
+ * @version 5.4.9
152
+ * @since 3.9.0
153
+ * @param int $ids defines the ids.
154
+ * @param string | array $_product defines the _product.
155
+ */
156
+ public function cross_sells_exclude_not_in_stock( $ids, $_product ) {
157
+ foreach ( $ids as $key => $product_id ) {
158
+ $product = wc_get_product( $product_id );
159
+ if ( ! $product->managing_stock() && ! $product->is_in_stock() ) {
160
+ unset( $ids[ $key ] );
161
+ }
162
  }
163
+ return $ids;
164
  }
 
 
165
 
166
+ /**
167
+ * Cross_sells_ids.
168
+ *
169
+ * @version 3.6.0
170
+ * @since 3.6.0
171
+ * @todo [dev] (maybe) ids instead of list
172
+ * @todo [dev] (maybe) on cart update (i.e. product removed) cross-sells are not updated (so it may be needed to reload page manually to see new cross-sells)
173
+ * @todo [feature] (maybe) on per category/tag basis
174
+ * @param int $ids defines the ids.
175
+ * @param string | array $_product defines the _product.
176
+ */
177
+ public function cross_sells_ids( $ids, $_product ) {
178
+ $global_cross_sells = wcj_get_option( 'wcj_cross_sells_global_ids', '' );
179
+ $key = array_search( $product_id, $global_cross_sells, true );
180
+ if ( ! empty( $global_cross_sells ) ) {
181
+ $global_cross_sells = array_unique( $global_cross_sells );
182
+ $product_id = wcj_get_product_id_or_variation_parent_id( $_product );
183
+ if ( false !== $key ) {
184
+ unset( $global_cross_sells[ $key ] );
185
+ }
186
  }
187
+ return ( empty( $global_cross_sells ) ? $ids : array_unique( array_merge( $ids, $global_cross_sells ) ) );
188
  }
 
 
189
 
190
+ /**
191
+ * Cross_sells_order.
192
+ *
193
+ * @version 3.5.3
194
+ * @since 3.5.3
195
+ * @param string | array $order defines the order.
196
+ */
197
+ public function cross_sells_order( $order ) {
198
+ $_order = wcj_get_option( 'wcj_cross_sells_order', 'no_changes' );
199
+ return ( 'no_changes' !== ( $_order ) ? $_order : $order );
200
+ }
201
 
202
+ /**
203
+ * Cross_sells_orderby.
204
+ *
205
+ * @version 3.5.3
206
+ * @since 3.5.3
207
+ * @param string | array $orderby defines the orderby.
208
+ */
209
+ public function cross_sells_orderby( $orderby ) {
210
+ $_orderby = wcj_get_option( 'wcj_cross_sells_orderby', 'no_changes' );
211
+ return ( 'no_changes' !== ( $_orderby ) ? $_orderby : $orderby );
212
+ }
213
 
214
+ /**
215
+ * Cross_sells_columns.
216
+ *
217
+ * @version 3.5.3
218
+ * @since 3.5.3
219
+ * @param string | int $columns defines the columns.
220
+ */
221
+ public function cross_sells_columns( $columns ) {
222
+ $_columns = wcj_get_option( 'wcj_cross_sells_columns', 0 );
223
+ return ( '0' !== ( $_columns ) ? $_columns : $columns );
224
+ }
225
 
226
+ /**
227
+ * Cross_sells_total.
228
+ *
229
+ * @version 3.6.0
230
+ * @since 3.5.3
231
+ * @param int $limit defines the limit.
232
+ */
233
+ public function cross_sells_total( $limit ) {
234
+ $_limit = wcj_get_option( 'wcj_cross_sells_total', 0 );
235
+ return ( '0' !== ( $_limit ) ? $_limit : $limit );
236
+ }
237
 
238
+ }
239
 
240
  endif;
241
 
includes/class-wcj-crowdfunding.php CHANGED
@@ -5,89 +5,100 @@
5
  * @version 5.4.0
6
  * @since 2.2.6
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Crowdfunding' ) ) :
13
-
14
- class WCJ_Crowdfunding extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.4.0
20
- * @since 2.2.6
21
  */
22
- function __construct() {
23
 
24
- $this->id = 'crowdfunding';
25
- $this->short_desc = __( 'Crowdfunding', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Add crowdfunding products to WooCommerce.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-crowdfunding';
28
- $this->extra_desc = __( 'When enabled, module will add Crowdfunding metabox to product edit.', 'woocommerce-jetpack' ) . '<br>' .
29
- '<ol>' .
 
 
 
 
 
 
 
 
30
  '<li>' .
31
  sprintf(
 
32
  __( 'To add crowdfunding info to the product, use <a href="%s" target="_blank">Booster\'s crowdfunding shortcodes</a>.', 'woocommerce-jetpack' ),
33
  'https://booster.io/category/shortcodes/products-crowdfunding/'
34
  ) .
35
- '</li>' .
36
- '<li>' .
37
- sprintf(
38
- __( 'Shortcodes could be used for example in <a href="%s">Product Info module</a>.', 'woocommerce-jetpack' ),
39
- admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=products&section=product_custom_info' )
40
- ) .
41
- '</li>' .
42
- '<li>' .
43
- sprintf(
44
- __( 'To change add to cart button labels use <a href="%s">Add to Cart Labels module</a>.', 'woocommerce-jetpack' ),
45
- admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=labels&section=add_to_cart' )
46
- ).
47
- '</li>' .
48
- '<li>' .
49
- sprintf(
50
- __( 'If you want to allow customers to choose dynamic price, Use <a href="%s">Product Open Pricing (Name Your Price) module</a>.', 'woocommerce-jetpack' ),
51
- admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=prices_and_currencies&section=product_open_pricing' )
52
- ).
53
- '</li>' .
54
- '</ol>';
55
- parent::__construct();
 
 
 
56
 
57
- if ( $this->is_enabled() ) {
58
 
59
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
60
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
61
 
62
- add_action( 'woocommerce_is_purchasable', array( $this, 'check_dates' ), PHP_INT_MAX, 2 );
 
63
  }
64
- }
65
 
66
- /**
67
- * check_dates.
68
- *
69
- * @version 2.7.0
70
- * @since 2.2.6
71
- */
72
- function check_dates( $purchasable, $_product ) {
73
- $_product_id = wcj_get_product_id_or_variation_parent_id( $_product );
74
- $goal = get_post_meta( $_product_id, '_' . 'wcj_crowdfunding_goal_sum', true );
75
- if ( 0 != $goal ) {
76
- $start_date_str = get_post_meta( $_product_id, '_' . 'wcj_crowdfunding_startdate', true );
77
- $end_date_str = get_post_meta( $_product_id, '_' . 'wcj_crowdfunding_deadline', true );
78
- $start_date = ( '' != $start_date_str ) ? strtotime( $start_date_str ) : 0;
79
- $end_date = ( '' != $end_date_str ) ? strtotime( $end_date_str ) : 0;
80
- if ( $start_date > 0 && ( $start_date - current_time( 'timestamp' ) ) > 0 ) {
81
- $purchasable = false;
82
- }
83
- if ( $end_date > 0 && ( $end_date - current_time( 'timestamp' ) ) < 0 ) {
84
- $purchasable = false;
 
 
 
85
  }
 
86
  }
87
- return $purchasable;
88
- }
89
 
90
- }
91
 
92
  endif;
93
 
5
  * @version 5.4.0
6
  * @since 2.2.6
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Crowdfunding' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Crowdfunding.
 
 
 
18
  */
19
+ class WCJ_Crowdfunding extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.4.0
25
+ * @since 2.2.6
26
+ */
27
+ public function __construct() {
28
+
29
+ $this->id = 'crowdfunding';
30
+ $this->short_desc = __( 'Crowdfunding', 'woocommerce-jetpack' );
31
+ $this->desc = __( 'Add crowdfunding products to WooCommerce.', 'woocommerce-jetpack' );
32
+ $this->link_slug = 'woocommerce-crowdfunding';
33
+ $this->extra_desc = __( 'When enabled, module will add Crowdfunding metabox to product edit.', 'woocommerce-jetpack' ) . '<br>' .
34
+ '<ol>' .
35
  '<li>' .
36
  sprintf(
37
+ /* translators: %s: translation added */
38
  __( 'To add crowdfunding info to the product, use <a href="%s" target="_blank">Booster\'s crowdfunding shortcodes</a>.', 'woocommerce-jetpack' ),
39
  'https://booster.io/category/shortcodes/products-crowdfunding/'
40
  ) .
41
+ '</li>' .
42
+ '<li>' .
43
+ sprintf(
44
+ /* translators: %s: translation added */
45
+ __( 'Shortcodes could be used for example in <a href="%s">Product Info module</a>.', 'woocommerce-jetpack' ),
46
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=products&section=product_custom_info' )
47
+ ) .
48
+ '</li>' .
49
+ '<li>' .
50
+ sprintf(
51
+ /* translators: %s: translation added */
52
+ __( 'To change add to cart button labels use <a href="%s">Add to Cart Labels module</a>.', 'woocommerce-jetpack' ),
53
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=labels&section=add_to_cart' )
54
+ ) .
55
+ '</li>' .
56
+ '<li>' .
57
+ sprintf(
58
+ /* translators: %s: translation added */
59
+ __( 'If you want to allow customers to choose dynamic price, Use <a href="%s">Product Open Pricing (Name Your Price) module</a>.', 'woocommerce-jetpack' ),
60
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=prices_and_currencies&section=product_open_pricing' )
61
+ ) .
62
+ '</li>' .
63
+ '</ol>';
64
+ parent::__construct();
65
 
66
+ if ( $this->is_enabled() ) {
67
 
68
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
69
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
70
 
71
+ add_action( 'woocommerce_is_purchasable', array( $this, 'check_dates' ), PHP_INT_MAX, 2 );
72
+ }
73
  }
 
74
 
75
+ /**
76
+ * Check_dates.
77
+ *
78
+ * @version 2.7.0
79
+ * @since 2.2.6
80
+ * @param bool $purchasable defines the purchasable.
81
+ * @param string | array $_product defines the _product.
82
+ */
83
+ public function check_dates( $purchasable, $_product ) {
84
+ $_product_id = wcj_get_product_id_or_variation_parent_id( $_product );
85
+ $goal = get_post_meta( $_product_id, '_wcj_crowdfunding_goal_sum', true );
86
+ if ( 0 !== $goal ) {
87
+ $start_date_str = get_post_meta( $_product_id, '_wcj_crowdfunding_startdate', true );
88
+ $end_date_str = get_post_meta( $_product_id, '_wcj_crowdfunding_deadline', true );
89
+ $start_date = ( '' != $start_date_str ) ? strtotime( $start_date_str ) : 0;
90
+ $end_date = ( '' != $end_date_str ) ? strtotime( $end_date_str ) : 0;
91
+ if ( $start_date > 0 && ( $start_date - current_time( 'timestamp' ) ) > 0 ) {
92
+ $purchasable = false;
93
+ }
94
+ if ( $end_date > 0 && ( $end_date - current_time( 'timestamp' ) ) < 0 ) {
95
+ $purchasable = false;
96
+ }
97
  }
98
+ return $purchasable;
99
  }
 
 
100
 
101
+ }
102
 
103
  endif;
104
 
includes/class-wcj-currency-exchange-rates.php CHANGED
@@ -5,277 +5,301 @@
5
  * @version 5.4.0
6
  * @since 2.3.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Currency_Exchange_Rates' ) ) :
13
-
14
- class WCJ_Currency_Exchange_Rates extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.2.0
20
  */
21
- function __construct() {
 
 
 
 
 
 
 
22
 
23
- $this->id = 'currency_exchange_rates';
24
- $this->short_desc = __( 'Currency Exchange Rates', 'woocommerce-jetpack' );
25
- $this->desc = __( 'Automatic currency exchange rates for WooCommerce (1 allowed in free version). If you want to change the currency rate with real conversion then enable it', 'woocommerce-jetpack' );
26
- $this->desc_pro = __( 'Automatic currency exchange rates for WooCommerce. If you want to change the currency rate with real conversion then enable it', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-currency-exchange-rates';
28
- parent::__construct();
29
 
30
- add_action( 'wp_ajax_' . 'wcj_ajax_get_exchange_rates', array( $this, 'wcj_ajax_get_exchange_rates' ) );
31
- add_action( 'wp_ajax_nopriv_' . 'wcj_ajax_get_exchange_rates', array( $this, 'wcj_ajax_get_exchange_rates' ) );
32
 
33
- if ( $this->is_enabled() ) {
34
- include_once( 'exchange-rates/class-wcj-exchange-rates-crons.php' );
35
- add_action( 'admin_init', array( $this, 'maybe_update_all_rates' ) );
36
- add_filter( 'wcj_currency_exchange_rate', array( $this, 'force_dot_as_exchange_rate_decimal_separator' ) );
 
 
37
  }
38
- include_once( 'exchange-rates/class-wcj-exchange-rates.php' );
39
- }
40
 
41
- /**
42
- * force_dot_as_exchange_rate_decimal_separator.
43
- *
44
- * @version 5.2.0
45
- * @since 5.2.0
46
- *
47
- * @param $value
48
- *
49
- * @return mixed
50
- */
51
- function force_dot_as_exchange_rate_decimal_separator( $value ) {
52
- if ( 'yes' !== wcj_get_option( 'wcj_currency_exchange_rates_point_decimal_separator', 'no' ) ) {
 
 
 
53
  return $value;
54
  }
55
- $value = str_replace( ',', '.', $value );
56
- return $value;
57
- }
58
 
59
- /**
60
- * maybe_update_all_rates.
61
- *
62
- * @version 3.4.5
63
- * @since 3.4.5
64
- */
65
- function maybe_update_all_rates() {
66
- if ( isset( $_GET['wcj_currency_exchange_rates_update_now'] ) ) {
67
- do_action( 'auto_update_exchange_rates_hook' );
68
- wp_safe_redirect( remove_query_arg( 'wcj_currency_exchange_rates_update_now' ) );
 
69
  }
70
- }
71
 
72
- /**
73
- * wcj_ajax_get_exchange_rates.
74
- *
75
- * @version 2.7.0
76
- * @since 2.6.0
77
- * @todo (maybe) move this to `class-wcj-exchange-rates.php`
78
- */
79
- function wcj_ajax_get_exchange_rates() {
80
- echo wcj_get_exchange_rate( $_POST['wcj_currency_from'], $_POST['wcj_currency_to'] );
81
- die();
82
- }
83
 
84
- /**
85
- * add_currency_pair_setting.
86
- *
87
- * @version 3.2.4
88
- */
89
- function add_currency_pair_setting( $currency_from, $currency_to, $settings ) {
90
- if ( $currency_from != $currency_to ) {
91
- $field_id = 'wcj_currency_exchange_rates_' . sanitize_title( $currency_from . $currency_to );
92
- foreach ( $settings as $setting ) {
93
- if ( $setting['id'] === $field_id ) {
94
- return $settings;
 
 
 
 
95
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  }
97
- $custom_attributes = array(
98
- 'currency_from' => $currency_from,
99
- 'currency_to' => $currency_to,
100
- 'multiply_by_field_id' => $field_id,
101
- );
102
- $settings[] = array(
103
- 'title' => $currency_from . ' / ' . $currency_to,
104
- 'id' => $field_id,
105
- 'default' => 0,
106
- 'type' => 'exchange_rate',
107
- 'custom_attributes_button' => $custom_attributes,
108
- 'value' => $currency_from . '/' . $currency_to,
109
- );
110
  }
111
- return $settings;
112
- }
113
 
114
- /**
115
- * get_all_currencies_exchange_rates_currencies.
116
- *
117
- * @version 2.9.0
118
- * @since 2.9.0
119
- */
120
- function get_all_currencies_exchange_rates_currencies() {
121
- $currencies = array();
122
- // Additional currencies (via filter)
123
- $additional_currencies = apply_filters( 'wcj_currency_exchange_rates_additional_currencies', array() );
124
- foreach ( $additional_currencies as $additional_currency ) {
125
- $currencies[] = $additional_currency;
126
- }
127
- // Additional currencies (via custom currencies section)
128
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_currency_exchange_custom_currencies_total_number', 1 ) );
129
- for ( $i = 1; $i <= $total_number; $i++ ) {
130
- if ( 'disabled' != ( $additional_currency = wcj_get_option( 'wcj_currency_exchange_custom_currencies_' . $i, 'disabled' ) ) ) {
131
  $currencies[] = $additional_currency;
132
  }
133
- }
134
- if ( wcj_is_module_enabled( 'price_by_country' ) ) {
135
- // Currency Pairs - Price by Country
136
- if ( 'manual' != apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_price_by_country_auto_exchange_rates', 'manual' ) ) ) {
137
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_price_by_country_total_groups_number', 1 ) ); $i++ ) {
138
- $currency_to = wcj_get_option( 'wcj_price_by_country_exchange_rate_currency_group_' . $i );
139
- $currencies[] = $currency_to;
140
  }
141
  }
142
- }
143
- if ( wcj_is_module_enabled( 'multicurrency' ) ) {
144
- // Currency Pairs - Multicurrency
145
- if ( 'manual' != apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_multicurrency_exchange_rate_update_auto', 'manual' ) ) ) {
146
- for ( $i = 1; $i <= apply_filters( 'booster_option', 2, wcj_get_option( 'wcj_multicurrency_total_number', 2 ) ); $i++ ) {
147
- $currency_to = wcj_get_option( 'wcj_multicurrency_currency_' . $i );
148
- $currencies[] = $currency_to;
 
149
  }
150
  }
151
- }
152
- if ( wcj_is_module_enabled( 'multicurrency_base_price' ) ) {
153
- // Currency Pairs - Multicurrency Product Base Price
154
- if ( 'manual' != apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_multicurrency_base_price_exchange_rate_update', 'manual' ) ) ) {
155
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_multicurrency_base_price_total_number', 1 ) ); $i++ ) {
156
- $currency_to = wcj_get_option( 'wcj_multicurrency_base_price_currency_' . $i );
157
- $currencies[] = $currency_to;
 
158
  }
159
  }
160
- }
161
- if ( wcj_is_module_enabled( 'currency_per_product' ) ) {
162
- // Currency Pairs - Currency per Product
163
- if ( 'manual' != apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_currency_per_product_exchange_rate_update', 'manual' ) ) ) {
164
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_currency_per_product_total_number', 1 ) ); $i++ ) {
165
- $currency_to = wcj_get_option( 'wcj_currency_per_product_currency_' . $i );
166
- $currencies[] = $currency_to;
 
167
  }
168
  }
169
- }
170
- if ( wcj_is_module_enabled( 'payment_gateways_currency' ) ) {
171
- if ( 'manual' != apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_gateways_currency_exchange_rate_update_auto', 'manual' ) ) ) {
172
- // Currency Pairs - Gateway Currency
173
- global $woocommerce;
174
- $available_gateways = $woocommerce->payment_gateways->payment_gateways();
175
- foreach ( $available_gateways as $key => $gateway ) {
176
- $currency_to = wcj_get_option( 'wcj_gateways_currency_' . $key );
177
- if ( 'no_changes' != $currency_to ) {
178
  $currencies[] = $currency_to;
179
  }
180
  }
181
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
183
- return $currencies;
184
- }
185
 
186
- /**
187
- * add_currency_pair_server_setting.
188
- *
189
- * @version 3.2.4
190
- * @since 3.2.4
191
- */
192
- function add_currency_pair_server_setting( $currency_from, $currency_to, $default_server, $settings ) {
193
- if ( $currency_from != $currency_to ) {
194
- $field_id = 'wcj_currency_exchange_rates_server_' . sanitize_title( $currency_from . $currency_to );
195
- foreach ( $settings as $setting ) {
196
- if ( $setting['id'] === $field_id ) {
197
- return $settings;
 
 
 
 
 
198
  }
 
 
 
 
 
 
 
 
 
 
 
199
  }
200
- $settings[] = array(
201
- 'desc' => __( 'Exchange Rates Server', 'woocommerce-jetpack' ),
202
- 'id' => $field_id,
203
- 'default' => 'default_server',
204
- 'type' => 'select',
205
- 'options' => array_merge(
206
- array( 'default_server' => sprintf( __( 'Use default: %s', 'woocommerce-jetpack' ), $default_server ) ),
207
- wcj_get_currency_exchange_rate_servers()
208
- ),
209
- );
210
  }
211
- return $settings;
212
- }
213
 
214
- /**
215
- * add_currency_pair_offset_percent_setting.
216
- *
217
- * @version 3.4.5
218
- * @since 3.4.5
219
- */
220
- function add_currency_pair_offset_percent_setting( $currency_from, $currency_to, $default_offset, $settings ) {
221
- if ( $currency_from != $currency_to ) {
222
- $field_id = 'wcj_currency_exchange_rates_offset_percent_' . sanitize_title( $currency_from . $currency_to );
223
- foreach ( $settings as $setting ) {
224
- if ( $setting['id'] === $field_id ) {
225
- return $settings;
 
 
 
 
 
226
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
227
  }
228
- $settings[] = array(
229
- 'desc' => __( 'Exchange Rates Offset (Percent)', 'woocommerce-jetpack' ),
230
- 'id' => $field_id,
231
- 'default' => 'default_offset',
232
- 'type' => 'select',
233
- 'options' => array(
234
- 'default_offset' => sprintf( __( 'Use default: %s%%', 'woocommerce-jetpack' ), $default_offset ),
235
- 'custom_offset' => __( 'Custom offset', 'woocommerce-jetpack' ),
236
- ),
237
- );
238
- $settings[] = array(
239
- 'desc' => __( 'Custom offset (Percent)', 'woocommerce-jetpack' ),
240
- 'desc_tip' => __( 'Used when "Custom offset" option is selected above.', 'woocommerce-jetpack' ),
241
- 'id' => $field_id . '_' . 'custom_offset',
242
- 'default' => 0,
243
- 'type' => 'number',
244
- 'custom_attributes' => array( 'step' => '0.001' ),
245
- );
246
  }
247
- return $settings;
248
- }
249
 
250
- /**
251
- * get_all_currencies_exchange_rates_settings.
252
- *
253
- * @version 3.4.5
254
- * @since 2.9.0
255
- */
256
- function get_all_currencies_exchange_rates_settings( $add_extra_settings = false ) {
257
- if ( $add_extra_settings ) {
258
- // Server
259
- $exchange_rate_servers = wcj_get_currency_exchange_rate_servers();
260
- $exchange_rate_server = wcj_get_option( 'wcj_currency_exchange_rates_server', 'ecb' );
261
- $default_server = ( isset( $exchange_rate_servers[ $exchange_rate_server ] ) ? $exchange_rate_servers[ $exchange_rate_server ] : $exchange_rate_server );
262
- // Offset
263
- $default_offset = wcj_get_option( 'wcj_currency_exchange_rates_offset_percent', 0 );
264
- }
265
- $settings = array();
266
- $currency_from = wcj_get_option( 'woocommerce_currency' );
267
- $currencies = $this->get_all_currencies_exchange_rates_currencies();
268
- foreach ( $currencies as $currency ) {
269
- $settings = $this->add_currency_pair_setting( $currency_from, $currency, $settings );
270
  if ( $add_extra_settings ) {
271
- $settings = $this->add_currency_pair_server_setting( $currency_from, $currency, $default_server, $settings );
272
- $settings = $this->add_currency_pair_offset_percent_setting( $currency_from, $currency, $default_offset, $settings );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  }
 
274
  }
275
- return $settings;
276
- }
277
 
278
- }
279
 
280
  endif;
281
 
5
  * @version 5.4.0
6
  * @since 2.3.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Currency_Exchange_Rates' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Currency_Exchange_Rates.
 
 
18
  */
19
+ class WCJ_Currency_Exchange_Rates extends WCJ_Module {
20
+
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.2.0
25
+ */
26
+ public function __construct() {
27
 
28
+ $this->id = 'currency_exchange_rates';
29
+ $this->short_desc = __( 'Currency Exchange Rates', 'woocommerce-jetpack' );
30
+ $this->desc = __( 'Automatic currency exchange rates for WooCommerce (1 allowed in free version). If you want to change the currency rate with real conversion then enable it', 'woocommerce-jetpack' );
31
+ $this->desc_pro = __( 'Automatic currency exchange rates for WooCommerce. If you want to change the currency rate with real conversion then enable it', 'woocommerce-jetpack' );
32
+ $this->link_slug = 'woocommerce-currency-exchange-rates';
33
+ parent::__construct();
34
 
35
+ add_action( 'wp_ajax_wcj_ajax_get_exchange_rates', array( $this, 'wcj_ajax_get_exchange_rates' ) );
36
+ add_action( 'wp_ajax_nopriv_wcj_ajax_get_exchange_rates', array( $this, 'wcj_ajax_get_exchange_rates' ) );
37
 
38
+ if ( $this->is_enabled() ) {
39
+ include_once 'exchange-rates/class-wcj-exchange-rates-crons.php';
40
+ add_action( 'admin_init', array( $this, 'maybe_update_all_rates' ) );
41
+ add_filter( 'wcj_currency_exchange_rate', array( $this, 'force_dot_as_exchange_rate_decimal_separator' ) );
42
+ }
43
+ include_once 'exchange-rates/class-wcj-exchange-rates.php';
44
  }
 
 
45
 
46
+ /**
47
+ * Force_dot_as_exchange_rate_decimal_separator.
48
+ *
49
+ * @version 5.2.0
50
+ * @since 5.2.0
51
+ *
52
+ * @param string $value defines the value.
53
+ *
54
+ * @return mixed
55
+ */
56
+ public function force_dot_as_exchange_rate_decimal_separator( $value ) {
57
+ if ( 'yes' !== wcj_get_option( 'wcj_currency_exchange_rates_point_decimal_separator', 'no' ) ) {
58
+ return $value;
59
+ }
60
+ $value = str_replace( ',', '.', $value );
61
  return $value;
62
  }
 
 
 
63
 
64
+ /**
65
+ * Maybe_update_all_rates.
66
+ *
67
+ * @version 3.4.5
68
+ * @since 3.4.5
69
+ */
70
+ public function maybe_update_all_rates() {
71
+ if ( isset( $_GET['wcj_currency_exchange_rates_update_now'] ) ) {
72
+ do_action( 'auto_update_exchange_rates_hook' );
73
+ wp_safe_redirect( remove_query_arg( 'wcj_currency_exchange_rates_update_now' ) );
74
+ }
75
  }
 
76
 
77
+ /**
78
+ * Wcj_ajax_get_exchange_rates.
79
+ *
80
+ * @version 2.7.0
81
+ * @since 2.6.0
82
+ * @todo (maybe) move this to `class-wcj-exchange-rates.php`
83
+ */
84
+ public function wcj_ajax_get_exchange_rates() {
85
+ echo wcj_get_exchange_rate( sanitize_text_field( wp_unslash( $_POST['wcj_currency_from'] ) ), sanitize_text_field( wp_unslash( $_POST['wcj_currency_to'] ) ) );
86
+ die();
87
+ }
88
 
89
+ /**
90
+ * Add_currency_pair_setting.
91
+ *
92
+ * @version 3.2.4
93
+ * @param string $currency_from defines the currency_from.
94
+ * @param string $currency_to defines the currency_to.
95
+ * @param array $settings defines the settings.
96
+ */
97
+ public function add_currency_pair_setting( $currency_from, $currency_to, $settings ) {
98
+ if ( $currency_from !== $currency_to ) {
99
+ $field_id = 'wcj_currency_exchange_rates_' . sanitize_title( $currency_from . $currency_to );
100
+ foreach ( $settings as $setting ) {
101
+ if ( $setting['id'] === $field_id ) {
102
+ return $settings;
103
+ }
104
  }
105
+ $custom_attributes = array(
106
+ 'currency_from' => $currency_from,
107
+ 'currency_to' => $currency_to,
108
+ 'multiply_by_field_id' => $field_id,
109
+ );
110
+ $settings[] = array(
111
+ 'title' => $currency_from . ' / ' . $currency_to,
112
+ 'id' => $field_id,
113
+ 'default' => 0,
114
+ 'type' => 'exchange_rate',
115
+ 'custom_attributes_button' => $custom_attributes,
116
+ 'value' => $currency_from . '/' . $currency_to,
117
+ );
118
  }
119
+ return $settings;
 
 
 
 
 
 
 
 
 
 
 
 
120
  }
 
 
121
 
122
+ /**
123
+ * Get_all_currencies_exchange_rates_currencies.
124
+ *
125
+ * @version 2.9.0
126
+ * @since 2.9.0
127
+ */
128
+ public function get_all_currencies_exchange_rates_currencies() {
129
+ $currencies = array();
130
+ // Additional currencies (via filter).
131
+ $additional_currencies = apply_filters( 'wcj_currency_exchange_rates_additional_currencies', array() );
132
+ foreach ( $additional_currencies as $additional_currency ) {
 
 
 
 
 
 
133
  $currencies[] = $additional_currency;
134
  }
135
+ // Additional currencies (via custom currencies section).
136
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_currency_exchange_custom_currencies_total_number', 1 ) );
137
+ for ( $i = 1; $i <= $total_number; $i++ ) {
138
+ $additional_currency = wcj_get_option( 'wcj_currency_exchange_custom_currencies_' . $i, 'disabled' );
139
+ if ( 'disabled' !== ( $additional_currency ) ) {
140
+ $currencies[] = $additional_currency;
 
141
  }
142
  }
143
+ if ( wcj_is_module_enabled( 'price_by_country' ) ) {
144
+ // Currency Pairs - Price by Country.
145
+ if ( 'manual' !== apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_price_by_country_auto_exchange_rates', 'manual' ) ) ) {
146
+ $wcj_price_by_country_total_groups_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_price_by_country_total_groups_number', 1 ) );
147
+ for ( $i = 1; $i <= $wcj_price_by_country_total_groups_number; $i++ ) {
148
+ $currency_to = wcj_get_option( 'wcj_price_by_country_exchange_rate_currency_group_' . $i );
149
+ $currencies[] = $currency_to;
150
+ }
151
  }
152
  }
153
+ if ( wcj_is_module_enabled( 'multicurrency' ) ) {
154
+ // Currency Pairs - Multicurrency.
155
+ $wcj_multicurrency_total_number = apply_filters( 'booster_option', 2, wcj_get_option( 'wcj_multicurrency_total_number', 2 ) );
156
+ if ( 'manual' !== apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_multicurrency_exchange_rate_update_auto', 'manual' ) ) ) {
157
+ for ( $i = 1; $i <= $wcj_multicurrency_total_number; $i++ ) {
158
+ $currency_to = wcj_get_option( 'wcj_multicurrency_currency_' . $i );
159
+ $currencies[] = $currency_to;
160
+ }
161
  }
162
  }
163
+ if ( wcj_is_module_enabled( 'multicurrency_base_price' ) ) {
164
+ // Currency Pairs - Multicurrency Product Base Price.
165
+ $wcj_multicurrency_base_price_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_multicurrency_base_price_total_number', 1 ) );
166
+ if ( 'manual' !== apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_multicurrency_base_price_exchange_rate_update', 'manual' ) ) ) {
167
+ for ( $i = 1; $i <= $wcj_multicurrency_base_price_total_number; $i++ ) {
168
+ $currency_to = wcj_get_option( 'wcj_multicurrency_base_price_currency_' . $i );
169
+ $currencies[] = $currency_to;
170
+ }
171
  }
172
  }
173
+ if ( wcj_is_module_enabled( 'currency_per_product' ) ) {
174
+ // Currency Pairs - Currency per Product.
175
+ $wcj_currency_per_product_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_currency_per_product_total_number', 1 ) );
176
+ if ( 'manual' !== apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_currency_per_product_exchange_rate_update', 'manual' ) ) ) {
177
+ for ( $i = 1; $i <= $wcj_currency_per_product_total_number; $i++ ) {
178
+ $currency_to = wcj_get_option( 'wcj_currency_per_product_currency_' . $i );
 
 
 
179
  $currencies[] = $currency_to;
180
  }
181
  }
182
  }
183
+ if ( wcj_is_module_enabled( 'payment_gateways_currency' ) ) {
184
+ if ( 'manual' !== apply_filters( 'booster_option', 'manual', wcj_get_option( 'wcj_gateways_currency_exchange_rate_update_auto', 'manual' ) ) ) {
185
+ // Currency Pairs - Gateway Currency.
186
+ global $woocommerce;
187
+ $available_gateways = $woocommerce->payment_gateways->payment_gateways();
188
+ foreach ( $available_gateways as $key => $gateway ) {
189
+ $currency_to = wcj_get_option( 'wcj_gateways_currency_' . $key );
190
+ if ( 'no_changes' !== $currency_to ) {
191
+ $currencies[] = $currency_to;
192
+ }
193
+ }
194
+ }
195
+ }
196
+ return $currencies;
197
  }
 
 
198
 
199
+ /**
200
+ * Add_currency_pair_server_setting.
201
+ *
202
+ * @version 3.2.4
203
+ * @since 3.2.
204
+ * @param string $currency_from defines the currency_from.
205
+ * @param string $currency_to defines the currency_to.
206
+ * @param string | array $default_server defines the default_server.
207
+ * @param array $settings defines the settings.
208
+ */
209
+ public function add_currency_pair_server_setting( $currency_from, $currency_to, $default_server, $settings ) {
210
+ if ( $currency_from !== $currency_to ) {
211
+ $field_id = 'wcj_currency_exchange_rates_server_' . sanitize_title( $currency_from . $currency_to );
212
+ foreach ( $settings as $setting ) {
213
+ if ( $setting['id'] === $field_id ) {
214
+ return $settings;
215
+ }
216
  }
217
+ $settings[] = array(
218
+ 'desc' => __( 'Exchange Rates Server', 'woocommerce-jetpack' ),
219
+ 'id' => $field_id,
220
+ 'default' => 'default_server',
221
+ 'type' => 'select',
222
+ 'options' => array_merge(
223
+ /* translators: %s: translation added */
224
+ array( 'default_server' => sprintf( __( 'Use default: %s', 'woocommerce-jetpack' ), $default_server ) ),
225
+ wcj_get_currency_exchange_rate_servers()
226
+ ),
227
+ );
228
  }
229
+ return $settings;
 
 
 
 
 
 
 
 
 
230
  }
 
 
231
 
232
+ /**
233
+ * Add_currency_pair_offset_percent_setting.
234
+ *
235
+ * @version 3.4.5
236
+ * @since 3.4.5
237
+ * @param string $currency_from defines the currency_from.
238
+ * @param string $currency_to defines the currency_to.
239
+ * @param string | array $default_offset defines the default_offset.
240
+ * @param array $settings defines the settings.
241
+ */
242
+ public function add_currency_pair_offset_percent_setting( $currency_from, $currency_to, $default_offset, $settings ) {
243
+ if ( $currency_from !== $currency_to ) {
244
+ $field_id = 'wcj_currency_exchange_rates_offset_percent_' . sanitize_title( $currency_from . $currency_to );
245
+ foreach ( $settings as $setting ) {
246
+ if ( $setting['id'] === $field_id ) {
247
+ return $settings;
248
+ }
249
  }
250
+ $settings[] = array(
251
+ 'desc' => __( 'Exchange Rates Offset (Percent)', 'woocommerce-jetpack' ),
252
+ 'id' => $field_id,
253
+ 'default' => 'default_offset',
254
+ 'type' => 'select',
255
+ 'options' => array(
256
+ /* translators: %s: translation added */
257
+ 'default_offset' => sprintf( __( 'Use default: %s%%', 'woocommerce-jetpack' ), $default_offset ),
258
+ 'custom_offset' => __( 'Custom offset', 'woocommerce-jetpack' ),
259
+ ),
260
+ );
261
+ $settings[] = array(
262
+ 'desc' => __( 'Custom offset (Percent)', 'woocommerce-jetpack' ),
263
+ 'desc_tip' => __( 'Used when "Custom offset" option is selected above.', 'woocommerce-jetpack' ),
264
+ 'id' => $field_id . '_custom_offset',
265
+ 'default' => 0,
266
+ 'type' => 'number',
267
+ 'custom_attributes' => array( 'step' => '0.001' ),
268
+ );
269
  }
270
+ return $settings;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  }
 
 
272
 
273
+ /**
274
+ * Aet_all_currencies_exchange_rates_settings.
275
+ *
276
+ * @version 3.4.5
277
+ * @since 2.9.0
278
+ * @param bool $add_extra_settings defines the add_extra_settings.
279
+ */
280
+ public function get_all_currencies_exchange_rates_settings( $add_extra_settings = false ) {
 
 
 
 
 
 
 
 
 
 
 
 
281
  if ( $add_extra_settings ) {
282
+ // Server.
283
+ $exchange_rate_servers = wcj_get_currency_exchange_rate_servers();
284
+ $exchange_rate_server = wcj_get_option( 'wcj_currency_exchange_rates_server', 'ecb' );
285
+ $default_server = ( isset( $exchange_rate_servers[ $exchange_rate_server ] ) ? $exchange_rate_servers[ $exchange_rate_server ] : $exchange_rate_server );
286
+ // Offset.
287
+ $default_offset = wcj_get_option( 'wcj_currency_exchange_rates_offset_percent', 0 );
288
+ }
289
+ $settings = array();
290
+ $currency_from = wcj_get_option( 'woocommerce_currency' );
291
+ $currencies = $this->get_all_currencies_exchange_rates_currencies();
292
+ foreach ( $currencies as $currency ) {
293
+ $settings = $this->add_currency_pair_setting( $currency_from, $currency, $settings );
294
+ if ( $add_extra_settings ) {
295
+ $settings = $this->add_currency_pair_server_setting( $currency_from, $currency, $default_server, $settings );
296
+ $settings = $this->add_currency_pair_offset_percent_setting( $currency_from, $currency, $default_offset, $settings );
297
+ }
298
  }
299
+ return $settings;
300
  }
 
 
301
 
302
+ }
303
 
304
  endif;
305
 
includes/class-wcj-currency-external-products.php CHANGED
@@ -4,49 +4,55 @@
4
  *
5
  * @version 3.9.0
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Currency_External_Products' ) ) :
12
-
13
- class WCJ_Currency_External_Products extends WCJ_Module {
14
-
15
  /**
16
- * Constructor.
17
- *
18
- * @version 3.9.0
19
  */
20
- function __construct() {
21
-
22
- $this->id = 'currency_external_products';
23
- $this->short_desc = __( 'Currency for External Products', 'woocommerce-jetpack' );
24
- $this->desc = __( 'Set different currency for external products.', 'woocommerce-jetpack' );
25
- $this->link_slug = 'woocommerce-currency-for-external-products';
26
- parent::__construct();
27
-
28
- if ( $this->is_enabled() ) {
29
- if ( '' != wcj_get_option( 'wcj_currency_external_products_symbol', 'EUR' ) ) {
30
- add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX, 1 );
 
 
 
 
 
 
 
 
31
  }
32
  }
33
- }
34
 
35
- /**
36
- * change_currency_code.
37
- *
38
- * @version 2.7.0
39
- * @since 2.4.4
40
- */
41
- function change_currency_code( $currency ) {
42
- global $product;
43
- if ( is_object( $product ) && $product->is_type( 'external' ) ) {
44
- return wcj_get_option( 'wcj_currency_external_products_symbol', 'EUR' );
 
 
 
45
  }
46
- return $currency;
47
- }
48
 
49
- }
50
 
51
  endif;
52
 
4
  *
5
  * @version 3.9.0
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Currency_External_Products' ) ) :
 
 
 
15
  /**
16
+ * WCJ_Currency_External_Products.
 
 
17
  */
18
+ class WCJ_Currency_External_Products extends WCJ_Module {
19
+
20
+ /**
21
+ * Constructor.
22
+ *
23
+ * @version 3.9.0
24
+ */
25
+ public function __construct() {
26
+
27
+ $this->id = 'currency_external_products';
28
+ $this->short_desc = __( 'Currency for External Products', 'woocommerce-jetpack' );
29
+ $this->desc = __( 'Set different currency for external products.', 'woocommerce-jetpack' );
30
+ $this->link_slug = 'woocommerce-currency-for-external-products';
31
+ parent::__construct();
32
+
33
+ if ( $this->is_enabled() ) {
34
+ if ( '' !== wcj_get_option( 'wcj_currency_external_products_symbol', 'EUR' ) ) {
35
+ add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX, 1 );
36
+ }
37
  }
38
  }
 
39
 
40
+ /**
41
+ * Change_currency_code.
42
+ *
43
+ * @version 2.7.0
44
+ * @since 2.4.4
45
+ * @param string | int $currency defines the currency.
46
+ */
47
+ public function change_currency_code( $currency ) {
48
+ global $product;
49
+ if ( is_object( $product ) && $product->is_type( 'external' ) ) {
50
+ return wcj_get_option( 'wcj_currency_external_products_symbol', 'EUR' );
51
+ }
52
+ return $currency;
53
  }
 
 
54
 
55
+ }
56
 
57
  endif;
58
 
includes/class-wcj-currency-per-product.php CHANGED
@@ -1,19 +1,23 @@
1
  <?php
2
-
3
  /**
4
  * Booster for WooCommerce - Module - Currency per Product
5
  *
6
  * @version 5.4.9
7
  * @since 2.5.2
8
  * @author Pluggabl LLC.
 
9
  */
10
 
11
- if (!defined('ABSPATH')) exit;
 
 
12
 
13
- if (!class_exists('WCJ_Currency_Per_Product')) :
 
 
 
 
14
 
15
- class WCJ_Currency_Per_Product extends WCJ_Module
16
- {
17
 
18
  /**
19
  * Constructor.
@@ -22,78 +26,78 @@ if (!class_exists('WCJ_Currency_Per_Product')) :
22
  * @since 2.5.2
23
  * @todo (maybe) add `$this->price_hooks_priority`
24
  */
25
- function __construct()
26
- {
27
-
28
  $this->id = 'currency_per_product';
29
- $this->short_desc = __('Currency per Product', 'woocommerce-jetpack');
30
- $this->desc = __('Display prices for products in different currencies (1 currency allowed in free version).', 'woocommerce-jetpack');
31
- $this->desc_pro = __('Display prices for products in different currencies.', 'woocommerce-jetpack');
32
  $this->link_slug = 'woocommerce-currency-per-product';
33
  parent::__construct();
34
 
35
- if ($this->is_enabled()) {
36
 
37
- $this->do_save_converted_prices = ('yes' === get_option('wcj_currency_per_product_save_prices', 'no'));
38
 
39
- $this->is_currency_per_product_by_product_enabled = ('yes' === get_option('wcj_currency_per_product_per_product', 'yes'));
40
- if ($this->is_currency_per_product_by_product_enabled) {
41
- add_action('add_meta_boxes', array($this, 'add_meta_box'));
42
- add_action('save_post_product', array($this, 'save_meta_box'), PHP_INT_MAX, 2);
43
  }
44
 
45
- // Currency code and symbol
46
- add_filter('woocommerce_currency', array($this, 'change_currency_code'), PHP_INT_MAX, 10);
47
 
48
- // Add to cart
49
- add_filter('woocommerce_add_cart_item_data', array($this, 'add_cart_item_data'), PHP_INT_MAX, 10, 3);
50
- add_filter('woocommerce_add_cart_item', array($this, 'add_cart_item'), PHP_INT_MAX, 10, 2);
51
- add_filter('woocommerce_get_cart_item_from_session', array($this, 'get_cart_item_from_session'), PHP_INT_MAX, 10, 3);
52
- add_filter('woocommerce_add_to_cart_validation', array($this, 'validate_on_add_to_cart'), PHP_INT_MAX, 2);
53
 
54
- // Price
55
- add_filter(WCJ_PRODUCT_GET_PRICE_FILTER, array($this, 'change_price'), PHP_INT_MAX, 10, 2);
56
- add_filter('woocommerce_product_variation_get_price', array($this, 'change_price'), PHP_INT_MAX, 10, 2);
57
 
58
- // Grouped
59
- add_filter('woocommerce_grouped_price_html', array($this, 'grouped_price_html'), PHP_INT_MAX, 10, 2);
60
 
61
- // Shipping
62
- add_filter('woocommerce_package_rates', array($this, 'change_shipping_price'), PHP_INT_MAX, 10, 2);
63
  }
64
  }
65
 
66
  /**
67
- * change_shipping_price.
68
  *
69
  * @version 5.4.9
70
  * @since 2.7.0
 
 
71
  */
72
- function change_shipping_price($package_rates, $package)
73
- {
74
- if (isset(WC()->cart)) {
75
- if (WC()->cart->is_empty()) {
76
  return $package_rates;
77
  }
78
- $cart_checkout_behaviour = get_option('wcj_currency_per_product_cart_checkout', 'convert_shop_default');
79
- switch ($cart_checkout_behaviour) {
80
  case 'leave_one_product':
81
  case 'leave_same_currency':
82
  case 'convert_first_product':
83
  case 'convert_last_product':
84
- $shop_currency = get_option('woocommerce_currency');
85
- if (false != ($_currency = $this->get_cart_checkout_currency()) && $_currency != $shop_currency) {
86
- $currency_exchange_rate = $this->get_currency_exchange_rate($_currency);
87
- if (0 != $currency_exchange_rate && 1 != $currency_exchange_rate) {
 
88
  $currency_exchange_rate = 1 / $currency_exchange_rate;
89
- return wcj_change_price_shipping_package_rates($package_rates, $currency_exchange_rate);
90
  } else {
91
  return $package_rates;
92
  }
93
  } else {
94
  return $package_rates;
95
  }
96
- default: // case 'convert_shop_default':
97
  return $package_rates;
98
  }
99
  }
@@ -101,100 +105,107 @@ if (!class_exists('WCJ_Currency_Per_Product')) :
101
  }
102
 
103
  /**
104
- * get_product_currency.
105
  *
106
  * @version 5.4.9
107
  * @since 2.9.0
108
- * @todo (maybe) return empty string or false, if it's shop default currency: `return ( get_option( 'woocommerce_currency' ) != ( $return = get_post_meta( $product_id, '_' . 'wcj_currency_per_product_currency', true ) ) ? $return : false );`
 
109
  */
110
- function get_product_currency($product_id)
111
- {
112
  // By users or user roles
113
- $do_check_by_users = ('yes' === get_option('wcj_currency_per_product_by_users_enabled', 'no'));
114
- $do_check_by_user_roles = ('yes' === get_option('wcj_currency_per_product_by_user_roles_enabled', 'no'));
115
- $do_check_by_product_cats = ('yes' === get_option('wcj_currency_per_product_by_product_cats_enabled', 'no'));
116
- $do_check_by_product_tags = ('yes' === get_option('wcj_currency_per_product_by_product_tags_enabled', 'no'));
117
- if ($do_check_by_users || $do_check_by_user_roles || $do_check_by_product_cats || $do_check_by_product_tags) {
118
- if ($do_check_by_users || $do_check_by_user_roles) {
119
- $product_author_id = get_post_field('post_author', $product_id);
120
  }
121
- if ($do_check_by_product_cats) {
122
- $_product_cats = wcj_get_the_terms($product_id, 'product_cat');
123
  }
124
- if ($do_check_by_product_tags) {
125
- $_product_tags = wcj_get_the_terms($product_id, 'product_tag');
126
  }
127
- $total_number = apply_filters('booster_option', 1, get_option('wcj_currency_per_product_total_number', 1));
128
- for ($i = 1; $i <= $total_number; $i++) {
129
- if ($do_check_by_users) {
130
- $users = get_option('wcj_currency_per_product_users_' . $i, '');
131
- if (!empty($users) && in_array($product_author_id, $users)) {
132
- return get_option('wcj_currency_per_product_currency_' . $i);
133
  }
134
  }
135
- if ($do_check_by_user_roles) {
136
- $user_roles = get_option('wcj_currency_per_product_user_roles_' . $i, '');
137
- if (!empty($user_roles) && wcj_is_user_role($user_roles, $product_author_id)) {
138
- return get_option('wcj_currency_per_product_currency_' . $i);
139
  }
140
  }
141
- if ($do_check_by_product_cats) {
142
- $product_cats = get_option('wcj_currency_per_product_product_cats_' . $i, '');
143
- if (!empty($_product_cats) && !empty($product_cats)) {
144
- $_intersect = array_intersect($_product_cats, $product_cats);
145
- if (!empty($_intersect)) {
146
- return get_option('wcj_currency_per_product_currency_' . $i);
147
  }
148
  }
149
  }
150
- if ($do_check_by_product_tags) {
151
- $product_tags = get_option('wcj_currency_per_product_product_tags_' . $i, '');
152
- if (!empty($_product_tags) && !empty($product_tags)) {
153
- $_intersect = array_intersect($_product_tags, $product_tags);
154
- if (!empty($_intersect)) {
155
- return get_option('wcj_currency_per_product_currency_' . $i);
156
  }
157
  }
158
  }
159
  }
160
  }
161
  // By product meta
162
- return ($this->is_currency_per_product_by_product_enabled ? get_post_meta($product_id, '_' . 'wcj_currency_per_product_currency', true) : false);
163
  }
164
 
165
  /**
166
- * validate_on_add_to_cart.
167
  *
168
  * @version 5.4.9
169
  * @since 2.7.0
 
 
170
  */
171
- function validate_on_add_to_cart($passed, $product_id)
172
- {
173
- $cart_checkout_behaviour = get_option('wcj_currency_per_product_cart_checkout', 'convert_shop_default');
174
- if ('leave_one_product' === $cart_checkout_behaviour) {
175
- foreach (WC()->cart->get_cart() as $cart_item) {
176
- if ($cart_item['product_id'] != $product_id) {
177
- wc_add_notice(get_option(
178
- 'wcj_currency_per_product_cart_checkout_leave_one_product',
179
- __('Only one product can be added to the cart. Clear the cart or finish the order, before adding another product to the cart.', 'woocommerce-jetpack')
180
- ), 'error');
 
 
181
  return false;
182
  }
183
  }
184
- } elseif ('leave_same_currency' === $cart_checkout_behaviour) {
185
- $shop_currency = get_option('woocommerce_currency');
186
- $product_currency = $this->get_product_currency($product_id);
187
- if ('' == $product_currency) {
188
  $product_currency = $shop_currency;
189
  }
190
- foreach (WC()->cart->get_cart() as $cart_item) {
191
- $cart_product_currency = (isset($cart_item['wcj_currency_per_product']) && '' != $cart_item['wcj_currency_per_product']) ?
192
  $cart_item['wcj_currency_per_product'] : $shop_currency;
193
- if ($cart_product_currency != $product_currency) {
194
- wc_add_notice(get_option(
195
- 'wcj_currency_per_product_cart_checkout_leave_same_currency',
196
- __('Only products with same currency can be added to the cart. Clear the cart or finish the order, before adding products with another currency to the cart.', 'woocommerce-jetpack')
197
- ), 'error');
 
 
 
198
  return false;
199
  }
200
  }
@@ -203,38 +214,40 @@ if (!class_exists('WCJ_Currency_Per_Product')) :
203
  }
204
 
205
  /**
206
- * grouped_price_html.
207
  *
208
  * @version 2.9.0
209
  * @since 2.5.2
 
 
210
  */
211
- function grouped_price_html($price_html, $_product)
212
- {
213
  $child_prices = array();
214
- foreach ($_product->get_children() as $child_id) {
215
- $child_prices[$child_id] = get_post_meta($child_id, '_price', true);
216
  }
217
- if (!empty($child_prices)) {
218
- asort($child_prices);
219
- $min_price = current($child_prices);
220
- $min_price_id = key($child_prices);
221
- end($child_prices);
222
- $max_price = current($child_prices);
223
- $max_price_id = key($child_prices);
224
- $min_currency_per_product_currency = $this->get_product_currency($min_price_id);
225
- $max_currency_per_product_currency = $this->get_product_currency($max_price_id);
226
  } else {
227
  $min_price = '';
228
  $max_price = '';
229
  }
230
 
231
- if ($min_price) {
232
- if ($min_price == $max_price && $min_currency_per_product_currency === $max_currency_per_product_currency) {
233
- $display_price = wc_price(wcj_get_product_display_price($_product, $min_price, 1), array('currency' => $min_currency_per_product_currency));
234
  } else {
235
- $from = wc_price(wcj_get_product_display_price($_product, $min_price, 1), array('currency' => $min_currency_per_product_currency));
236
- $to = wc_price(wcj_get_product_display_price($_product, $max_price, 1), array('currency' => $max_currency_per_product_currency));
237
- $display_price = sprintf(_x('%1$s&ndash;%2$s', 'Price range: from-to', 'woocommerce'), $from, $to);
 
238
  }
239
  $new_price_html = $display_price . $_product->get_price_suffix();
240
  return $new_price_html;
@@ -244,115 +257,126 @@ if (!class_exists('WCJ_Currency_Per_Product')) :
244
  }
245
 
246
  /**
247
- * get_currency_exchange_rate.
248
  *
249
  * @version 5.4.9
250
  * @since 2.5.2
 
251
  */
252
- function get_currency_exchange_rate($currency_code)
253
- {
254
- $total_number = apply_filters('booster_option', 1, get_option('wcj_currency_per_product_total_number', 1));
255
- for ($i = 1; $i <= $total_number; $i++) {
256
- if ($currency_code === get_option('wcj_currency_per_product_currency_' . $i)) {
257
- return (0 != ($rate = get_option('wcj_currency_per_product_exchange_rate_' . $i, 1)) ? (1 / $rate) : 1);
258
  }
259
  }
260
  return 1;
261
  }
262
 
263
  /**
264
- * maybe_return_saved_converted_price.
265
  *
266
  * @version 3.3.0
267
  * @since 3.3.0
 
 
268
  */
269
- function maybe_return_saved_converted_price($_product, $_currency)
270
- {
271
- if ($this->do_save_converted_prices) {
272
- $product_id = (isset($_product->wcj_currency_per_product_item_key) ? $_product->wcj_currency_per_product_item_key : wcj_get_product_id($_product));
273
- if (isset($this->saved_product_prices[$product_id][$_product->wcj_currency_per_product][$_currency])) {
274
- return $this->saved_product_prices[$product_id][$_product->wcj_currency_per_product][$_currency];
275
  }
276
  }
277
  return false;
278
  }
279
 
280
  /**
281
- * maybe_save_converted_price.
282
  *
283
  * @version 3.3.0
284
  * @since 3.3.0
 
 
 
285
  */
286
- function maybe_save_converted_price($price, $_product, $_currency)
287
- {
288
- if ($this->do_save_converted_prices) {
289
- $product_id = (isset($_product->wcj_currency_per_product_item_key) ? $_product->wcj_currency_per_product_item_key : wcj_get_product_id($_product));
290
- $this->saved_product_prices[$product_id][$_product->wcj_currency_per_product][$_currency] = $price;
291
  }
292
  return $price;
293
  }
294
 
295
  /**
296
- * change_price.
297
  *
298
  * @version 5.4.9
299
  * @since 2.5.2
 
 
300
  */
301
- function change_price($price, $_product)
302
- {
303
- if (isset($_product->wcj_currency_per_product)) {
304
- $cart_checkout_behaviour = get_option('wcj_currency_per_product_cart_checkout', 'convert_shop_default');
305
- switch ($cart_checkout_behaviour) {
306
  case 'leave_one_product':
307
  case 'leave_same_currency':
308
  return $price;
309
  case 'convert_first_product':
310
  case 'convert_last_product':
311
- $shop_currency = get_option('woocommerce_currency');
312
- if (false != ($_currency = $this->get_cart_checkout_currency()) && $_currency != $shop_currency) {
313
- if ($_product->wcj_currency_per_product === $_currency) {
 
314
  return $price;
315
  } else {
316
- if (false !== ($saved_price = $this->maybe_return_saved_converted_price($_product, $_currency))) {
 
317
  return $saved_price;
318
  }
319
- $exchange_rate_product = $this->get_currency_exchange_rate($_product->wcj_currency_per_product);
320
- $exchange_rate_cart_checkout = $this->get_currency_exchange_rate($_currency);
321
  $exchange_rate = $exchange_rate_product / $exchange_rate_cart_checkout;
322
- return $this->maybe_save_converted_price($price * $exchange_rate, $_product, $_currency);
323
  }
324
- } elseif ($_product->wcj_currency_per_product === $shop_currency) {
325
  return $price;
326
  } else {
327
- if (false !== ($saved_price = $this->maybe_return_saved_converted_price($_product, $shop_currency))) {
 
328
  return $saved_price;
329
  }
330
- $exchange_rate = $this->get_currency_exchange_rate($_product->wcj_currency_per_product);
331
- return $this->maybe_save_converted_price($price * $exchange_rate, $_product, $shop_currency);
332
  }
333
- default: // case 'convert_shop_default':
334
- $shop_currency = get_option('woocommerce_currency');
335
- if (false !== ($saved_price = $this->maybe_return_saved_converted_price($_product, $shop_currency))) {
 
336
  return $saved_price;
337
  }
338
- $exchange_rate = $this->get_currency_exchange_rate($_product->wcj_currency_per_product);
339
- return $this->maybe_save_converted_price($price * $exchange_rate, $_product, $shop_currency);
340
  }
341
  }
342
  return $price;
343
  }
344
 
345
  /**
346
- * get_cart_item_from_session.
347
  *
348
  * @version 3.3.0
349
  * @since 2.5.2
 
 
 
350
  */
351
- function get_cart_item_from_session($item, $values, $key)
352
- {
353
- if (array_key_exists('wcj_currency_per_product', $values)) {
354
  $item['data']->wcj_currency_per_product = $values['wcj_currency_per_product'];
355
- if ($this->do_save_converted_prices) {
356
  $item['data']->wcj_currency_per_product_item_key = $key;
357
  }
358
  }
@@ -360,32 +384,35 @@ if (!class_exists('WCJ_Currency_Per_Product')) :
360
  }
361
 
362
  /**
363
- * add_cart_item_data.
364
  *
365
  * @version 2.9.0
366
  * @since 2.5.2
 
 
 
367
  */
368
- function add_cart_item_data($cart_item_data, $product_id, $variation_id)
369
- {
370
- $currency_per_product_currency = $this->get_product_currency($product_id);
371
- if ('' != $currency_per_product_currency) {
372
  $cart_item_data['wcj_currency_per_product'] = $currency_per_product_currency;
373
  }
374
  return $cart_item_data;
375
  }
376
 
377
  /**
378
- * add_cart_item.
379
  *
380
  * @version 3.3.0
381
  * @since 2.5.2
382
  * @todo `wcj_currency_per_product_item_key` seems to be not working here
 
 
383
  */
384
- function add_cart_item($cart_item_data, $cart_item_key)
385
- {
386
- if (isset($cart_item_data['wcj_currency_per_product'])) {
387
  $cart_item_data['data']->wcj_currency_per_product = $cart_item_data['wcj_currency_per_product'];
388
- if ($this->do_save_converted_prices) {
389
  $cart_item_data['data']->wcj_currency_per_product_item_key = $cart_item_key;
390
  }
391
  }
@@ -393,117 +420,99 @@ if (!class_exists('WCJ_Currency_Per_Product')) :
393
  }
394
 
395
  /**
396
- * get_current_product_id_and_currency.
397
  *
398
  * @version 2.9.0
399
  * @since 2.7.0
400
  */
401
- function get_current_product_id_and_currency()
402
- {
403
- // Get ID
404
- $the_ID = false;
405
  global $product;
406
- if ($product) {
407
- $the_ID = wcj_get_product_id_or_variation_parent_id($product);
408
  }
409
- if (!$the_ID && isset($_REQUEST['product_id'])) {
410
- $the_ID = $_REQUEST['product_id'];
411
  }
412
- if (!$the_ID && isset($_POST['form'])) { // WooCommerce Bookings plugin
413
  $posted = array();
414
- parse_str($_POST['form'], $posted);
415
- $the_ID = isset($posted['add-to-cart']) ? $posted['add-to-cart'] : 0;
416
  }
417
- if (!$the_ID && '' != ($eventon_wc_product_id = get_post_meta(get_the_ID(), 'tx_woocommerce_product_id', true))) { // EventON plugin
418
- $the_ID = $eventon_wc_product_id;
 
419
  }
420
- if (!$the_ID) {
421
- $the_ID = get_the_ID();
422
  }
423
- // Get currency
424
- if ($the_ID && 'product' === get_post_type($the_ID)) {
425
- $currency_per_product_currency = $this->get_product_currency($the_ID);
426
- return ('' != $currency_per_product_currency) ? $currency_per_product_currency : false;
427
  }
428
  return false;
429
  }
430
 
431
  /**
432
- * get_cart_checkout_currency.
433
  *
434
  * @version 5.4.9
435
  * @since 2.7.0
436
  */
437
- function get_cart_checkout_currency()
438
- {
439
- $cart_checkout_behaviour = get_option('wcj_currency_per_product_cart_checkout', 'convert_shop_default');
440
- if (false !== ($value = apply_filters('wcj_currency_per_product_cart_checkout_currency', false, $cart_checkout_behaviour))) {
441
  return $value;
442
  }
443
- /*
444
- * `wcj_currency_per_product_cart_checkout_currency` filter example:
445
- *
446
- * if ( function_exists( 'YITH_Request_Quote' ) && isset( YITH_Request_Quote()->raq_content ) ) {
447
- * foreach ( YITH_Request_Quote()->raq_content as $raq_product ) {
448
- * if ( isset( $raq_product['product_id'] ) ) {
449
- * return get_post_meta( $raq_product['product_id'], '_' . 'wcj_currency_per_product_currency', true );
450
- * }
451
- * }
452
- * }
453
- *
454
- */
455
- if (!isset(WC()->cart) || WC()->cart->is_empty()) {
456
  return false;
457
  }
458
- if ('convert_shop_default' === $cart_checkout_behaviour) {
459
  return false;
460
  }
461
  $cart_items = WC()->cart->get_cart();
462
- if ('convert_last_product' === $cart_checkout_behaviour) {
463
- $cart_items = array_reverse($cart_items);
464
  }
465
- foreach ($cart_items as $cart_item) {
466
- return (isset($cart_item['wcj_currency_per_product'])) ? $cart_item['wcj_currency_per_product'] : false;
467
  }
468
  }
469
 
470
  /**
471
- * is_cart_or_checkout_or_ajax.
472
  *
473
  * @version 3.7.0
474
  * @since 2.7.0
475
  * @todo fix AJAX issue (for minicart)
476
  */
477
- function is_cart_or_checkout_or_ajax()
478
- {
479
  return apply_filters(
480
  'wcj_currency_per_product_is_cart_or_checkout',
481
- ((function_exists('is_cart') && is_cart()) || (function_exists('is_checkout') && is_checkout()) /* || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) */)
482
  );
483
- /*
484
- * `wcj_currency_per_product_is_cart_or_checkout` filter example:
485
- *
486
- * if ( function_exists( 'YITH_Request_Quote' ) && 0 != ( $raq_page_id = YITH_Request_Quote()->get_raq_page_id() ) && $raq_page_id == get_the_ID() ) {
487
- * return true;
488
- * }
489
- *
490
- */
491
  }
492
 
493
  /**
494
- * change_currency_code.
495
  *
496
  * @version 2.7.0
497
  * @since 2.5.2
 
498
  */
499
- function change_currency_code($currency)
500
- {
501
- if (false != ($_currency = $this->get_current_product_id_and_currency())) {
502
  return $_currency;
503
- } elseif ($this->is_cart_or_checkout_or_ajax()) {
504
- return (false != ($_currency = $this->get_cart_checkout_currency())) ? $_currency : $currency;
 
505
  }
506
- return $currency;
507
  }
508
  }
509
 
1
  <?php
 
2
  /**
3
  * Booster for WooCommerce - Module - Currency per Product
4
  *
5
  * @version 5.4.9
6
  * @since 2.5.2
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
+ if ( ! class_exists( 'WCJ_Currency_Per_Product' ) ) :
16
+ /**
17
+ * WCJ_Currency_Per_Product.
18
+ */
19
+ class WCJ_Currency_Per_Product extends WCJ_Module {
20
 
 
 
21
 
22
  /**
23
  * Constructor.
26
  * @since 2.5.2
27
  * @todo (maybe) add `$this->price_hooks_priority`
28
  */
29
+ public function __construct() {
 
 
30
  $this->id = 'currency_per_product';
31
+ $this->short_desc = __( 'Currency per Product', 'woocommerce-jetpack' );
32
+ $this->desc = __( 'Display prices for products in different currencies (1 currency allowed in free version).', 'woocommerce-jetpack' );
33
+ $this->desc_pro = __( 'Display prices for products in different currencies.', 'woocommerce-jetpack' );
34
  $this->link_slug = 'woocommerce-currency-per-product';
35
  parent::__construct();
36
 
37
+ if ( $this->is_enabled() ) {
38
 
39
+ $this->do_save_converted_prices = ( 'yes' === get_option( 'wcj_currency_per_product_save_prices', 'no' ) );
40
 
41
+ $this->is_currency_per_product_by_product_enabled = ( 'yes' === get_option( 'wcj_currency_per_product_per_product', 'yes' ) );
42
+ if ( $this->is_currency_per_product_by_product_enabled ) {
43
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
44
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
45
  }
46
 
47
+ // Currency code and symbol.
48
+ add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX, 10 );
49
 
50
+ // Add to cart.
51
+ add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_cart_item_data' ), PHP_INT_MAX, 10, 3 );
52
+ add_filter( 'woocommerce_add_cart_item', array( $this, 'add_cart_item' ), PHP_INT_MAX, 10, 2 );
53
+ add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'get_cart_item_from_session' ), PHP_INT_MAX, 10, 3 );
54
+ add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_on_add_to_cart' ), PHP_INT_MAX, 2 );
55
 
56
+ // Price.
57
+ add_filter( WCJ_PRODUCT_GET_PRICE_FILTER, array( $this, 'change_price' ), PHP_INT_MAX, 10, 2 );
58
+ add_filter( 'woocommerce_product_variation_get_price', array( $this, 'change_price' ), PHP_INT_MAX, 10, 2 );
59
 
60
+ // Grouped.
61
+ add_filter( 'woocommerce_grouped_price_html', array( $this, 'grouped_price_html' ), PHP_INT_MAX, 10, 2 );
62
 
63
+ // Shipping.
64
+ add_filter( 'woocommerce_package_rates', array( $this, 'change_shipping_price' ), PHP_INT_MAX, 10, 2 );
65
  }
66
  }
67
 
68
  /**
69
+ * Change_shipping_price.
70
  *
71
  * @version 5.4.9
72
  * @since 2.7.0
73
+ * @param int $package_rates defines the package_rates.
74
+ * @param string $package defines the package.
75
  */
76
+ public function change_shipping_price( $package_rates, $package ) {
77
+ if ( isset( WC()->cart ) ) {
78
+ if ( WC()->cart->is_empty() ) {
 
79
  return $package_rates;
80
  }
81
+ $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
82
+ switch ( $cart_checkout_behaviour ) {
83
  case 'leave_one_product':
84
  case 'leave_same_currency':
85
  case 'convert_first_product':
86
  case 'convert_last_product':
87
+ $shop_currency = get_option( 'woocommerce_currency' );
88
+ $_currency = $this->get_cart_checkout_currency();
89
+ if ( false !== ( $_currency ) && $_currency !== $shop_currency ) {
90
+ $currency_exchange_rate = $this->get_currency_exchange_rate( $_currency );
91
+ if ( 0 !== $currency_exchange_rate && 1 !== $currency_exchange_rate ) {
92
  $currency_exchange_rate = 1 / $currency_exchange_rate;
93
+ return wcj_change_price_shipping_package_rates( $package_rates, $currency_exchange_rate );
94
  } else {
95
  return $package_rates;
96
  }
97
  } else {
98
  return $package_rates;
99
  }
100
+ default:
101
  return $package_rates;
102
  }
103
  }
105
  }
106
 
107
  /**
108
+ * Get_product_currency.
109
  *
110
  * @version 5.4.9
111
  * @since 2.9.0
112
+ * @todo (maybe) return empty string or false, if it's shop default currency: `return ( get_option( 'woocommerce_currency' ) != ( $return = get_post_meta( $product_id, '_' . 'wcj_currency_per_product_currency', true ) ) ? $return : false );`.
113
+ * @param int $product_id defines the product_id.
114
  */
115
+ function get_product_currency( $product_id ) {
 
116
  // By users or user roles
117
+ $do_check_by_users = ( 'yes' === get_option( 'wcj_currency_per_product_by_users_enabled', 'no' ) );
118
+ $do_check_by_user_roles = ( 'yes' === get_option( 'wcj_currency_per_product_by_user_roles_enabled', 'no' ) );
119
+ $do_check_by_product_cats = ( 'yes' === get_option( 'wcj_currency_per_product_by_product_cats_enabled', 'no' ) );
120
+ $do_check_by_product_tags = ( 'yes' === get_option( 'wcj_currency_per_product_by_product_tags_enabled', 'no' ) );
121
+ if ( $do_check_by_users || $do_check_by_user_roles || $do_check_by_product_cats || $do_check_by_product_tags ) {
122
+ if ( $do_check_by_users || $do_check_by_user_roles ) {
123
+ $product_author_id = get_post_field( 'post_author', $product_id );
124
  }
125
+ if ( $do_check_by_product_cats ) {
126
+ $_product_cats = wcj_get_the_terms( $product_id, 'product_cat' );
127
  }
128
+ if ( $do_check_by_product_tags ) {
129
+ $_product_tags = wcj_get_the_terms( $product_id, 'product_tag' );
130
  }
131
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_currency_per_product_total_number', 1 ) );
132
+ for ( $i = 1; $i <= $total_number; $i++ ) {
133
+ if ( $do_check_by_users ) {
134
+ $users = get_option( 'wcj_currency_per_product_users_' . $i, '' );
135
+ if ( ! empty( $users ) && in_array( $product_author_id, $users ) ) {
136
+ return get_option( 'wcj_currency_per_product_currency_' . $i );
137
  }
138
  }
139
+ if ( $do_check_by_user_roles ) {
140
+ $user_roles = get_option( 'wcj_currency_per_product_user_roles_' . $i, '' );
141
+ if ( ! empty( $user_roles ) && wcj_is_user_role( $user_roles, $product_author_id ) ) {
142
+ return get_option( 'wcj_currency_per_product_currency_' . $i );
143
  }
144
  }
145
+ if ( $do_check_by_product_cats ) {
146
+ $product_cats = get_option( 'wcj_currency_per_product_product_cats_' . $i, '' );
147
+ if ( ! empty( $_product_cats ) && ! empty( $product_cats ) ) {
148
+ $_intersect = array_intersect( $_product_cats, $product_cats );
149
+ if ( ! empty( $_intersect ) ) {
150
+ return get_option( 'wcj_currency_per_product_currency_' . $i );
151
  }
152
  }
153
  }
154
+ if ( $do_check_by_product_tags ) {
155
+ $product_tags = get_option( 'wcj_currency_per_product_product_tags_' . $i, '' );
156
+ if ( ! empty( $_product_tags ) && ! empty( $product_tags ) ) {
157
+ $_intersect = array_intersect( $_product_tags, $product_tags );
158
+ if ( ! empty( $_intersect ) ) {
159
+ return get_option( 'wcj_currency_per_product_currency_' . $i );
160
  }
161
  }
162
  }
163
  }
164
  }
165
  // By product meta
166
+ return ( $this->is_currency_per_product_by_product_enabled ? get_post_meta( $product_id, '_wcj_currency_per_product_currency', true ) : false );
167
  }
168
 
169
  /**
170
+ * Validate_on_add_to_cart.
171
  *
172
  * @version 5.4.9
173
  * @since 2.7.0
174
+ * @param string $passed defines the passed.
175
+ * @param int $product_id defines the product_id.
176
  */
177
+ public function validate_on_add_to_cart( $passed, $product_id ) {
178
+ $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
179
+ if ( 'leave_one_product' === $cart_checkout_behaviour ) {
180
+ foreach ( WC()->cart->get_cart() as $cart_item ) {
181
+ if ( $cart_item['product_id'] !== $product_id ) {
182
+ wc_add_notice(
183
+ get_option(
184
+ 'wcj_currency_per_product_cart_checkout_leave_one_product',
185
+ __( 'Only one product can be added to the cart. Clear the cart or finish the order, before adding another product to the cart.', 'woocommerce-jetpack' )
186
+ ),
187
+ 'error'
188
+ );
189
  return false;
190
  }
191
  }
192
+ } elseif ( 'leave_same_currency' === $cart_checkout_behaviour ) {
193
+ $shop_currency = get_option( 'woocommerce_currency' );
194
+ $product_currency = $this->get_product_currency( $product_id );
195
+ if ( '' === $product_currency ) {
196
  $product_currency = $shop_currency;
197
  }
198
+ foreach ( WC()->cart->get_cart() as $cart_item ) {
199
+ $cart_product_currency = ( isset( $cart_item['wcj_currency_per_product'] ) && '' !== $cart_item['wcj_currency_per_product'] ) ?
200
  $cart_item['wcj_currency_per_product'] : $shop_currency;
201
+ if ( $cart_product_currency !== $product_currency ) {
202
+ wc_add_notice(
203
+ get_option(
204
+ 'wcj_currency_per_product_cart_checkout_leave_same_currency',
205
+ __( 'Only products with same currency can be added to the cart. Clear the cart or finish the order, before adding products with another currency to the cart.', 'woocommerce-jetpack' )
206
+ ),
207
+ 'error'
208
+ );
209
  return false;
210
  }
211
  }
214
  }
215
 
216
  /**
217
+ * Grouped_price_html.
218
  *
219
  * @version 2.9.0
220
  * @since 2.5.2
221
+ * @param string $price_html defines the price_html.
222
+ * @param string | array $_product defines the _product.
223
  */
224
+ public function grouped_price_html( $price_html, $_product ) {
 
225
  $child_prices = array();
226
+ foreach ( $_product->get_children() as $child_id ) {
227
+ $child_prices[ $child_id ] = get_post_meta( $child_id, '_price', true );
228
  }
229
+ if ( ! empty( $child_prices ) ) {
230
+ asort( $child_prices );
231
+ $min_price = current( $child_prices );
232
+ $min_price_id = key( $child_prices );
233
+ end( $child_prices );
234
+ $max_price = current( $child_prices );
235
+ $max_price_id = key( $child_prices );
236
+ $min_currency_per_product_currency = $this->get_product_currency( $min_price_id );
237
+ $max_currency_per_product_currency = $this->get_product_currency( $max_price_id );
238
  } else {
239
  $min_price = '';
240
  $max_price = '';
241
  }
242
 
243
+ if ( $min_price ) {
244
+ if ( $min_price === $max_price && $min_currency_per_product_currency === $max_currency_per_product_currency ) {
245
+ $display_price = wc_price( wcj_get_product_display_price( $_product, $min_price, 1 ), array( 'currency' => $min_currency_per_product_currency ) );
246
  } else {
247
+ $from = wc_price( wcj_get_product_display_price( $_product, $min_price, 1 ), array( 'currency' => $min_currency_per_product_currency ) );
248
+ $to = wc_price( wcj_get_product_display_price( $_product, $max_price, 1 ), array( 'currency' => $max_currency_per_product_currency ) );
249
+ /* translators: %s: translation added */
250
+ $display_price = sprintf( _x( '%1$s&ndash;%2$s', 'Price range: from-to', 'woocommerce' ), $from, $to );
251
  }
252
  $new_price_html = $display_price . $_product->get_price_suffix();
253
  return $new_price_html;
257
  }
258
 
259
  /**
260
+ * Get_currency_exchange_rate.
261
  *
262
  * @version 5.4.9
263
  * @since 2.5.2
264
+ * @param string | int $currency_code defines the currency_code.
265
  */
266
+ public function get_currency_exchange_rate( $currency_code ) {
267
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_currency_per_product_total_number', 1 ) );
268
+ for ( $i = 1; $i <= $total_number; $i++ ) {
269
+ if ( get_option( 'wcj_currency_per_product_currency_' . $i ) === $currency_code ) {
270
+ $rate = get_option( 'wcj_currency_per_product_exchange_rate_' . $i, 1 );
271
+ return ( 0 !== ( $rate ) ? ( 1 / $rate ) : 1 );
272
  }
273
  }
274
  return 1;
275
  }
276
 
277
  /**
278
+ * Maybe_return_saved_converted_price.
279
  *
280
  * @version 3.3.0
281
  * @since 3.3.0
282
+ * @param string | array $_product defines the _product.
283
+ * @param int | string $_currency defines the _currency.
284
  */
285
+ public function maybe_return_saved_converted_price( $_product, $_currency ) {
286
+ if ( $this->do_save_converted_prices ) {
287
+ $product_id = ( isset( $_product->wcj_currency_per_product_item_key ) ? $_product->wcj_currency_per_product_item_key : wcj_get_product_id( $_product ) );
288
+ if ( isset( $this->saved_product_prices[ $product_id ][ $_product->wcj_currency_per_product ][ $_currency ] ) ) {
289
+ return $this->saved_product_prices[ $product_id ][ $_product->wcj_currency_per_product ][ $_currency ];
 
290
  }
291
  }
292
  return false;
293
  }
294
 
295
  /**
296
+ * Maybe_save_converted_price.
297
  *
298
  * @version 3.3.0
299
  * @since 3.3.0
300
+ * @param int $price defines the price.
301
+ * @param string | array $_product defines the _product.
302
+ * @param int | string $_currency defines the _currency.
303
  */
304
+ public function maybe_save_converted_price( $price, $_product, $_currency ) {
305
+ if ( $this->do_save_converted_prices ) {
306
+ $product_id = ( isset( $_product->wcj_currency_per_product_item_key ) ? $_product->wcj_currency_per_product_item_key : wcj_get_product_id( $_product ) );
307
+ $this->saved_product_prices[ $product_id ][ $_product->wcj_currency_per_product ][ $_currency ] = $price;
 
308
  }
309
  return $price;
310
  }
311
 
312
  /**
313
+ * Change_price.
314
  *
315
  * @version 5.4.9
316
  * @since 2.5.2
317
+ * @param int $price defines the price.
318
+ * @param string | array $_product defines the _product.
319
  */
320
+ public function change_price( $price, $_product ) {
321
+ if ( isset( $_product->wcj_currency_per_product ) ) {
322
+ $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
323
+ switch ( $cart_checkout_behaviour ) {
 
324
  case 'leave_one_product':
325
  case 'leave_same_currency':
326
  return $price;
327
  case 'convert_first_product':
328
  case 'convert_last_product':
329
+ $shop_currency = get_option( 'woocommerce_currency' );
330
+ $_currency = $this->get_cart_checkout_currency();
331
+ if ( false !== ( $_currency ) && $_currency !== $shop_currency ) {
332
+ if ( $_product->wcj_currency_per_product === $_currency ) {
333
  return $price;
334
  } else {
335
+ $saved_price = $this->maybe_return_saved_converted_price( $_product, $_currency );
336
+ if ( false !== ( $saved_price ) ) {
337
  return $saved_price;
338
  }
339
+ $exchange_rate_product = $this->get_currency_exchange_rate( $_product->wcj_currency_per_product );
340
+ $exchange_rate_cart_checkout = $this->get_currency_exchange_rate( $_currency );
341
  $exchange_rate = $exchange_rate_product / $exchange_rate_cart_checkout;
342
+ return $this->maybe_save_converted_price( $price * $exchange_rate, $_product, $_currency );
343
  }
344
+ } elseif ( $_product->wcj_currency_per_product === $shop_currency ) {
345
  return $price;
346
  } else {
347
+ $saved_price = $this->maybe_return_saved_converted_price( $_product, $shop_currency );
348
+ if ( false !== ( $saved_price ) ) {
349
  return $saved_price;
350
  }
351
+ $exchange_rate = $this->get_currency_exchange_rate( $_product->wcj_currency_per_product );
352
+ return $this->maybe_save_converted_price( $price * $exchange_rate, $_product, $shop_currency );
353
  }
354
+ default:
355
+ $shop_currency = get_option( 'woocommerce_currency' );
356
+ $saved_price = $this->maybe_return_saved_converted_price( $_product, $shop_currency );
357
+ if ( false !== ( $saved_price ) ) {
358
  return $saved_price;
359
  }
360
+ $exchange_rate = $this->get_currency_exchange_rate( $_product->wcj_currency_per_product );
361
+ return $this->maybe_save_converted_price( $price * $exchange_rate, $_product, $shop_currency );
362
  }
363
  }
364
  return $price;
365
  }
366
 
367
  /**
368
+ * Get_cart_item_from_session.
369
  *
370
  * @version 3.3.0
371
  * @since 2.5.2
372
+ * @param array $item defines the item.
373
+ * @param array $values defines the values.
374
+ * @param string | array $key defines the key.
375
  */
376
+ public function get_cart_item_from_session( $item, $values, $key ) {
377
+ if ( array_key_exists( 'wcj_currency_per_product', $values ) ) {
 
378
  $item['data']->wcj_currency_per_product = $values['wcj_currency_per_product'];
379
+ if ( $this->do_save_converted_prices ) {
380
  $item['data']->wcj_currency_per_product_item_key = $key;
381
  }
382
  }
384
  }
385
 
386
  /**
387
+ * Add_cart_item_data.
388
  *
389
  * @version 2.9.0
390
  * @since 2.5.2
391
+ * @param array $cart_item_data defines the cart_item_data.
392
+ * @param int $product_id defines the product_id.
393
+ * @param int $variation_id defines the variation_id.
394
  */
395
+ public function add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
396
+ $currency_per_product_currency = $this->get_product_currency( $product_id );
397
+ if ( '' !== $currency_per_product_currency ) {
 
398
  $cart_item_data['wcj_currency_per_product'] = $currency_per_product_currency;
399
  }
400
  return $cart_item_data;
401
  }
402
 
403
  /**
404
+ * Add_cart_item.
405
  *
406
  * @version 3.3.0
407
  * @since 2.5.2
408
  * @todo `wcj_currency_per_product_item_key` seems to be not working here
409
+ * @param array $cart_item_data defines the cart_item_data.
410
+ * @param int | string $cart_item_key defines the cart_item_key.
411
  */
412
+ public function add_cart_item( $cart_item_data, $cart_item_key ) {
413
+ if ( isset( $cart_item_data['wcj_currency_per_product'] ) ) {
 
414
  $cart_item_data['data']->wcj_currency_per_product = $cart_item_data['wcj_currency_per_product'];
415
+ if ( $this->do_save_converted_prices ) {
416
  $cart_item_data['data']->wcj_currency_per_product_item_key = $cart_item_key;
417
  }
418
  }
420
  }
421
 
422
  /**
423
+ * Get_current_product_id_and_currency.
424
  *
425
  * @version 2.9.0
426
  * @since 2.7.0
427
  */
428
+ public function get_current_product_id_and_currency() {
429
+ // Get ID.
430
+ $the_id = false;
 
431
  global $product;
432
+ if ( $product ) {
433
+ $the_id = wcj_get_product_id_or_variation_parent_id( $product );
434
  }
435
+ if ( ! $the_id && isset( $_REQUEST['product_id'] ) ) {
436
+ $the_id = $_REQUEST['product_id'];
437
  }
438
+ if ( ! $the_id && isset( $_POST['form'] ) ) { // WooCommerce Bookings plugin.
439
  $posted = array();
440
+ parse_str( $_POST['form'], $posted );
441
+ $the_id = isset( $posted['add-to-cart'] ) ? $posted['add-to-cart'] : 0;
442
  }
443
+ $eventon_wc_product_id = get_post_meta( get_the_ID(), 'tx_woocommerce_product_id', true );
444
+ if ( ! $the_id && '' !== ( $eventon_wc_product_id ) ) { // EventON plugin.
445
+ $the_id = $eventon_wc_product_id;
446
  }
447
+ if ( ! $the_id ) {
448
+ $the_id = get_the_ID();
449
  }
450
+ // Get currency.
451
+ if ( $the_id && 'product' === get_post_type( $the_id ) ) {
452
+ $currency_per_product_currency = $this->get_product_currency( $the_id );
453
+ return ( '' !== $currency_per_product_currency ) ? $currency_per_product_currency : false;
454
  }
455
  return false;
456
  }
457
 
458
  /**
459
+ * Get_cart_checkout_currency.
460
  *
461
  * @version 5.4.9
462
  * @since 2.7.0
463
  */
464
+ public function get_cart_checkout_currency() {
465
+ $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
466
+ $value = apply_filters( 'wcj_currency_per_product_cart_checkout_currency', false, $cart_checkout_behaviour );
467
+ if ( false !== ( $value ) ) {
468
  return $value;
469
  }
470
+
471
+ if ( ! isset( WC()->cart ) || WC()->cart->is_empty() ) {
 
 
 
 
 
 
 
 
 
 
 
472
  return false;
473
  }
474
+ if ( 'convert_shop_default' === $cart_checkout_behaviour ) {
475
  return false;
476
  }
477
  $cart_items = WC()->cart->get_cart();
478
+ if ( 'convert_last_product' === $cart_checkout_behaviour ) {
479
+ $cart_items = array_reverse( $cart_items );
480
  }
481
+ foreach ( $cart_items as $cart_item ) {
482
+ return ( isset( $cart_item['wcj_currency_per_product'] ) ) ? $cart_item['wcj_currency_per_product'] : false;
483
  }
484
  }
485
 
486
  /**
487
+ * Is_cart_or_checkout_or_ajax.
488
  *
489
  * @version 3.7.0
490
  * @since 2.7.0
491
  * @todo fix AJAX issue (for minicart)
492
  */
493
+ public function is_cart_or_checkout_or_ajax() {
 
494
  return apply_filters(
495
  'wcj_currency_per_product_is_cart_or_checkout',
496
+ ( ( function_exists( 'is_cart' ) && is_cart() ) || ( function_exists( 'is_checkout' ) && is_checkout() ) )
497
  );
 
 
 
 
 
 
 
 
498
  }
499
 
500
  /**
501
+ * Change_currency_code.
502
  *
503
  * @version 2.7.0
504
  * @since 2.5.2
505
+ * @param int | string $currency defines the currency.
506
  */
507
+ public function change_currency_code( $currency ) {
508
+ $_currency = $this->get_current_product_id_and_currency();
509
+ if ( false !== ( $_currency ) ) {
510
  return $_currency;
511
+ } elseif ( $this->is_cart_or_checkout_or_ajax() ) {
512
+ $_currency = $this->get_cart_checkout_currency();
513
+ return ( false !== ( $_currency ) ) ? $_currency : $currency;
514
  }
515
+ return $currency;
516
  }
517
  }
518
 
includes/class-wcj-currency.php CHANGED
@@ -1,192 +1,207 @@
1
  <?php
2
  /**
3
- * Booster for WooCommerce - Module - Currencies
4
  *
5
  * @version 3.9.0
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Currencies' ) ) :
12
-
13
- class WCJ_Currencies extends WCJ_Module {
14
-
15
  /**
16
- * Constructor.
17
- *
18
- * @version 3.2.4
19
- * @todo [dev] (maybe) update description
20
- * @todo [dev] (maybe) "add additional currencies" checkbox
21
- * @todo [dev] (maybe) save settings as array
22
- * @todo [dev] (maybe) fix missing country flags
23
  */
24
- function __construct() {
25
-
26
- $this->id = 'currency';
27
- $this->short_desc = __( 'Currencies', 'woocommerce-jetpack' );
28
- $this->desc = __( 'Add all world currencies and cryptocurrencies to your store; change currency symbol (Plus); add custom currencies (1 allowed in free version).', 'woocommerce-jetpack' );
29
- $this->desc_pro = __( 'Add all world currencies and cryptocurrencies to your store; change currency symbol; add custom currencies.', 'woocommerce-jetpack' );
30
- $this->link_slug = 'woocommerce-all-currencies';
31
- parent::__construct();
32
-
33
- if ( $this->is_enabled() ) {
34
- add_filter( 'woocommerce_currencies', array( $this, 'add_all_currencies'), PHP_INT_MAX );
35
- add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol'), PHP_INT_MAX, 2 );
36
- add_filter( 'woocommerce_general_settings', array( $this, 'add_edit_currency_symbol_field' ), PHP_INT_MAX );
 
 
 
 
 
 
 
 
 
 
 
 
37
  }
38
- }
39
 
40
- /**
41
- * get_custom_currencies.
42
- *
43
- * @version 3.9.0
44
- * @since 3.9.0
45
- */
46
- function get_custom_currencies() {
47
- $custom_currencies = array();
48
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_currency_custom_currency_total_number', 1 ) ); $i++ ) {
49
- $custom_currency_code = wcj_get_option( 'wcj_currency_custom_currency_code_' . $i, '' );
50
- $custom_currency_name = wcj_get_option( 'wcj_currency_custom_currency_name_' . $i, '' );
51
- if ( '' != $custom_currency_code && '' != $custom_currency_name ) {
52
- $custom_currencies[ $custom_currency_code ] = $custom_currency_name;
 
 
53
  }
 
54
  }
55
- return $custom_currencies;
56
- }
57
 
58
- /**
59
- * get_additional_currencies.
60
- *
61
- * @version 3.9.0
62
- * @since 3.9.0
63
- * @todo [dev] (maybe) add more cryptocurrencies
64
- */
65
- function get_additional_currencies() {
66
- return array(
67
- // Crypto
68
- 'AUR' => __( 'Auroracoin', 'woocommerce-jetpack' ),
69
- 'BCC' => __( 'BitConnect', 'woocommerce-jetpack' ),
70
- 'BCH' => __( 'Bitcoin Cash', 'woocommerce-jetpack' ),
71
- 'KOI' => __( 'Coinye', 'woocommerce-jetpack' ),
72
- 'XDN' => __( 'DigitalNote', 'woocommerce-jetpack' ),
73
- 'EMC' => __( 'Emercoin', 'woocommerce-jetpack' ),
74
- 'ETC' => __( 'Ethereum Classic', 'woocommerce-jetpack' ),
75
- 'ETH' => __( 'Ethereum', 'woocommerce-jetpack' ),
76
- 'FMC' => __( 'Freemasoncoin', 'woocommerce-jetpack' ),
77
- 'GRC' => __( 'Gridcoin', 'woocommerce-jetpack' ),
78
- 'IOT' => __( 'IOTA', 'woocommerce-jetpack' ),
79
- 'LTC' => __( 'Litecoin', 'woocommerce-jetpack' ),
80
- 'MZC' => __( 'MazaCoin', 'woocommerce-jetpack' ),
81
- 'XMR' => __( 'Monero', 'woocommerce-jetpack' ),
82
- 'NMC' => __( 'Namecoin', 'woocommerce-jetpack' ),
83
- 'XEM' => __( 'NEM', 'woocommerce-jetpack' ),
84
- 'NXT' => __( 'Nxt', 'woocommerce-jetpack' ),
85
- 'MSC' => __( 'Omni', 'woocommerce-jetpack' ),
86
- 'PPC' => __( 'Peercoin', 'woocommerce-jetpack' ),
87
- 'POT' => __( 'PotCoin', 'woocommerce-jetpack' ),
88
- 'XPM' => __( 'Primecoin', 'woocommerce-jetpack' ),
89
- 'XRP' => __( 'Ripple', 'woocommerce-jetpack' ),
90
- 'SIL' => __( 'SixEleven', 'woocommerce-jetpack' ),
91
- 'AMP' => __( 'Synereo AMP', 'woocommerce-jetpack' ),
92
- 'TIT' => __( 'Titcoin', 'woocommerce-jetpack' ),
93
- 'UBQ' => __( 'Ubiq', 'woocommerce-jetpack' ),
94
- 'VTC' => __( 'Vertcoin', 'woocommerce-jetpack' ),
95
- 'ZEC' => __( 'Zcash', 'woocommerce-jetpack' ),
96
- // Other
97
- 'XDR' => __( 'Special Drawing Rights', 'woocommerce-jetpack' ),
98
- // Virtual
99
- 'MYC' => __( 'myCred', 'woocommerce-jetpack' ),
100
- );
101
- }
102
-
103
- /**
104
- * get_additional_currency_symbol.
105
- *
106
- * @version 3.9.0
107
- * @since 3.9.0
108
- */
109
- function get_additional_currency_symbol( $currency_code ) {
110
- return $currency_code;
111
- }
112
-
113
- /**
114
- * add_all_currencies.
115
- *
116
- * @version 3.9.0
117
- */
118
- function add_all_currencies( $currencies ) {
119
- return array_merge( $currencies, $this->get_additional_currencies(), $this->get_custom_currencies() );
120
- }
121
 
122
- /**
123
- * get_saved_currency_symbol.
124
- *
125
- * @version 3.9.0
126
- * @since 3.9.0
127
- */
128
- function get_saved_currency_symbol( $currency, $default_symbol ) {
129
- if ( false === ( $saved_currency_symbol = wcj_get_option( 'wcj_currency_' . $currency, false ) ) ) {
130
- return ( in_array( $currency, array_keys( $this->get_additional_currencies() ) ) ? $this->get_additional_currency_symbol( $currency ) : $default_symbol );
131
- } else {
132
- return $saved_currency_symbol;
133
  }
134
- }
135
 
136
- /**
137
- * change_currency_symbol.
138
- *
139
- * @version 3.9.0
140
- */
141
- function change_currency_symbol( $currency_symbol, $currency ) {
142
- // Maybe return saved value
143
- if ( isset( $this->saved_symbol[ $currency ] ) ) {
144
- return $this->saved_symbol[ $currency ];
145
  }
146
- // Maybe hide symbol
147
- if ( 'yes' === wcj_get_option( 'wcj_currency_hide_symbol', 'no' ) ) {
148
- return '';
 
 
 
 
 
 
 
 
 
 
 
 
 
149
  }
150
- // Custom currencies
151
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_currency_custom_currency_total_number', 1 ) ); $i++ ) {
152
- $custom_currency_code = wcj_get_option( 'wcj_currency_custom_currency_code_' . $i, '' );
153
- $custom_currency_name = wcj_get_option( 'wcj_currency_custom_currency_name_' . $i, '' );
154
- if ( '' != $custom_currency_code && '' != $custom_currency_name && $currency === $custom_currency_code ) {
155
- $this->saved_symbol[ $currency ] = do_shortcode( wcj_get_option( 'wcj_currency_custom_currency_symbol_' . $i, '' ) );
 
 
 
 
 
156
  return $this->saved_symbol[ $currency ];
157
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  }
159
- // List
160
- $this->saved_symbol[ $currency ] = apply_filters( 'booster_option', $currency_symbol, do_shortcode( $this->get_saved_currency_symbol( $currency, $currency_symbol ) ) );
161
- return $this->saved_symbol[ $currency ];
162
- }
163
 
164
- /**
165
- * add_edit_currency_symbol_field.
166
- *
167
- * @version 3.9.0
168
- * @todo [dev] (maybe) remove this
169
- */
170
- function add_edit_currency_symbol_field( $settings ) {
171
- $updated_settings = array();
172
- foreach ( $settings as $section ) {
173
- if ( isset( $section['id'] ) && 'woocommerce_currency_pos' == $section['id'] ) {
174
- $updated_settings[] = array(
175
- 'name' => __( 'Booster: Currency Symbol', 'woocommerce-jetpack' ),
176
- 'desc_tip' => __( 'This sets the currency symbol.', 'woocommerce-jetpack' ),
177
- 'id' => 'wcj_currency_' . get_woocommerce_currency(),
178
- 'type' => 'text',
179
- 'default' => get_woocommerce_currency_symbol(),
180
- 'desc' => apply_filters( 'booster_message', '', 'desc' ),
181
- 'custom_attributes' => apply_filters( 'booster_message', '', 'readonly' ),
182
- );
 
 
 
183
  }
184
- $updated_settings[] = $section;
185
  }
186
- return $updated_settings;
187
- }
188
 
189
- }
190
 
191
  endif;
192
 
1
  <?php
2
  /**
3
+ * Booster for WooCommerce - Module - currencies
4
  *
5
  * @version 3.9.0
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Currencies' ) ) :
 
 
 
15
  /**
16
+ * WCJ_Currencies.
 
 
 
 
 
 
17
  */
18
+ class WCJ_Currencies extends WCJ_Module {
19
+
20
+ /**
21
+ * Constructor.
22
+ *
23
+ * @version 3.2.4
24
+ * @todo [dev] (maybe) update description
25
+ * @todo [dev] (maybe) "add additional currencies" checkbox
26
+ * @todo [dev] (maybe) save settings as array
27
+ * @todo [dev] (maybe) fix missing country flags
28
+ */
29
+ public function __construct() {
30
+
31
+ $this->id = 'currency';
32
+ $this->short_desc = __( 'Currencies', 'woocommerce-jetpack' );
33
+ $this->desc = __( 'Add all world currencies and cryptocurrencies to your store; change currency symbol (Plus); add custom currencies (1 allowed in free version).', 'woocommerce-jetpack' );
34
+ $this->desc_pro = __( 'Add all world currencies and cryptocurrencies to your store; change currency symbol; add custom currencies.', 'woocommerce-jetpack' );
35
+ $this->link_slug = 'woocommerce-all-currencies';
36
+ parent::__construct();
37
+
38
+ if ( $this->is_enabled() ) {
39
+ add_filter( 'woocommerce_currencies', array( $this, 'add_all_currencies' ), PHP_INT_MAX );
40
+ add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol' ), PHP_INT_MAX, 2 );
41
+ add_filter( 'woocommerce_general_settings', array( $this, 'add_edit_currency_symbol_field' ), PHP_INT_MAX );
42
+ }
43
  }
 
44
 
45
+ /**
46
+ * Get_custom_currencies.
47
+ *
48
+ * @version 3.9.0
49
+ * @since 3.9.0
50
+ */
51
+ public function get_custom_currencies() {
52
+ $custom_currencies = array();
53
+ $wcj_currency_custom_currency_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_currency_custom_currency_total_number', 1 ) );
54
+ for ( $i = 1; $i <= $wcj_currency_custom_currency_total_number; $i++ ) {
55
+ $custom_currency_code = wcj_get_option( 'wcj_currency_custom_currency_code_' . $i, '' );
56
+ $custom_currency_name = wcj_get_option( 'wcj_currency_custom_currency_name_' . $i, '' );
57
+ if ( '' !== $custom_currency_code && '' !== $custom_currency_name ) {
58
+ $custom_currencies[ $custom_currency_code ] = $custom_currency_name;
59
+ }
60
  }
61
+ return $custom_currencies;
62
  }
 
 
63
 
64
+ /**
65
+ * Get_additional_currencies.
66
+ *
67
+ * @version 3.9.0
68
+ * @since 3.9.0
69
+ * @todo [dev] (maybe) add more cryptocurrencies
70
+ */
71
+ public function get_additional_currencies() {
72
+ return array(
73
+ // Crypto.
74
+ 'AUR' => __( 'Auroracoin', 'woocommerce-jetpack' ),
75
+ 'BCC' => __( 'BitConnect', 'woocommerce-jetpack' ),
76
+ 'BCH' => __( 'Bitcoin Cash', 'woocommerce-jetpack' ),
77
+ 'KOI' => __( 'Coinye', 'woocommerce-jetpack' ),
78
+ 'XDN' => __( 'DigitalNote', 'woocommerce-jetpack' ),
79
+ 'EMC' => __( 'Emercoin', 'woocommerce-jetpack' ),
80
+ 'ETC' => __( 'Ethereum Classic', 'woocommerce-jetpack' ),
81
+ 'ETH' => __( 'Ethereum', 'woocommerce-jetpack' ),
82
+ 'FMC' => __( 'Freemasoncoin', 'woocommerce-jetpack' ),
83
+ 'GRC' => __( 'Gridcoin', 'woocommerce-jetpack' ),
84
+ 'IOT' => __( 'IOTA', 'woocommerce-jetpack' ),
85
+ 'LTC' => __( 'Litecoin', 'woocommerce-jetpack' ),
86
+ 'MZC' => __( 'MazaCoin', 'woocommerce-jetpack' ),
87
+ 'XMR' => __( 'Monero', 'woocommerce-jetpack' ),
88
+ 'NMC' => __( 'Namecoin', 'woocommerce-jetpack' ),
89
+ 'XEM' => __( 'NEM', 'woocommerce-jetpack' ),
90
+ 'NXT' => __( 'Nxt', 'woocommerce-jetpack' ),
91
+ 'MSC' => __( 'Omni', 'woocommerce-jetpack' ),
92
+ 'PPC' => __( 'Peercoin', 'woocommerce-jetpack' ),
93
+ 'POT' => __( 'PotCoin', 'woocommerce-jetpack' ),
94
+ 'XPM' => __( 'Primecoin', 'woocommerce-jetpack' ),
95
+ 'XRP' => __( 'Ripple', 'woocommerce-jetpack' ),
96
+ 'SIL' => __( 'SixEleven', 'woocommerce-jetpack' ),
97
+ 'AMP' => __( 'Synereo AMP', 'woocommerce-jetpack' ),
98
+ 'TIT' => __( 'Titcoin', 'woocommerce-jetpack' ),
99
+ 'UBQ' => __( 'Ubiq', 'woocommerce-jetpack' ),
100
+ 'VTC' => __( 'Vertcoin', 'woocommerce-jetpack' ),
101
+ 'ZEC' => __( 'Zcash', 'woocommerce-jetpack' ),
102
+ // Other.
103
+ 'XDR' => __( 'Special Drawing Rights', 'woocommerce-jetpack' ),
104
+ // Virtual.
105
+ 'MYC' => __( 'myCred', 'woocommerce-jetpack' ),
106
+ );
107
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
109
+ /**
110
+ * Get_additional_currency_symbol.
111
+ *
112
+ * @version 3.9.0
113
+ * @since 3.9.0
114
+ * @param string | int $currency_code defines the currency_code.
115
+ */
116
+ public function get_additional_currency_symbol( $currency_code ) {
117
+ return $currency_code;
 
 
118
  }
 
119
 
120
+ /**
121
+ * Add_all_currencies.
122
+ *
123
+ * @version 3.9.0
124
+ * @param string | int $currencies defines the currencies.
125
+ */
126
+ public function add_all_currencies( $currencies ) {
127
+ return array_merge( $currencies, $this->get_additional_currencies(), $this->get_custom_currencies() );
 
128
  }
129
+
130
+ /**
131
+ * Get_saved_currency_symbol.
132
+ *
133
+ * @version 3.9.0
134
+ * @since 3.9.0
135
+ * @param string | int $currency defines the currency.
136
+ * @param string $default_symbol defines the default_symbol.
137
+ */
138
+ public function get_saved_currency_symbol( $currency, $default_symbol ) {
139
+ $saved_currency_symbol = wcj_get_option( 'wcj_currency_' . $currency, false );
140
+ if ( false === ( $saved_currency_symbol ) ) {
141
+ return ( in_array( $currency, array_keys( $this->get_additional_currencies() ), true ) ? $this->get_additional_currency_symbol( $currency ) : $default_symbol );
142
+ } else {
143
+ return $saved_currency_symbol;
144
+ }
145
  }
146
+
147
+ /**
148
+ * Change_currency_symbol.
149
+ *
150
+ * @version 3.9.0
151
+ * @param string $currency_symbol defines the currency_symbol.
152
+ * @param string | int $currency defines the currency.
153
+ */
154
+ public function change_currency_symbol( $currency_symbol, $currency ) {
155
+ // Maybe return saved value.
156
+ if ( isset( $this->saved_symbol[ $currency ] ) ) {
157
  return $this->saved_symbol[ $currency ];
158
  }
159
+ // Maybe hide symbol.
160
+ if ( 'yes' === wcj_get_option( 'wcj_currency_hide_symbol', 'no' ) ) {
161
+ return '';
162
+ }
163
+ // Custom currencies.
164
+ $wcj_currency_custom_currency_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_currency_custom_currency_total_number', 1 ) );
165
+ for ( $i = 1; $i <= $wcj_currency_custom_currency_total_number; $i++ ) {
166
+ $custom_currency_code = wcj_get_option( 'wcj_currency_custom_currency_code_' . $i, '' );
167
+ $custom_currency_name = wcj_get_option( 'wcj_currency_custom_currency_name_' . $i, '' );
168
+ if ( '' !== $custom_currency_code && '' !== $custom_currency_name && $currency === $custom_currency_code ) {
169
+ $this->saved_symbol[ $currency ] = do_shortcode( wcj_get_option( 'wcj_currency_custom_currency_symbol_' . $i, '' ) );
170
+ return $this->saved_symbol[ $currency ];
171
+ }
172
+ }
173
+ // List.
174
+ $this->saved_symbol[ $currency ] = apply_filters( 'booster_option', $currency_symbol, do_shortcode( $this->get_saved_currency_symbol( $currency, $currency_symbol ) ) );
175
+ return $this->saved_symbol[ $currency ];
176
  }
 
 
 
 
177
 
178
+ /**
179
+ * Add_edit_currency_symbol_field.
180
+ *
181
+ * @version 3.9.0
182
+ * @todo [dev] (maybe) remove this
183
+ * @param array $settings defines the settings.
184
+ */
185
+ public function add_edit_currency_symbol_field( $settings ) {
186
+ $updated_settings = array();
187
+ foreach ( $settings as $section ) {
188
+ if ( isset( $section['id'] ) && 'woocommerce_currency_pos' === $section['id'] ) {
189
+ $updated_settings[] = array(
190
+ 'name' => __( 'Booster: Currency Symbol', 'woocommerce-jetpack' ),
191
+ 'desc_tip' => __( 'This sets the currency symbol.', 'woocommerce-jetpack' ),
192
+ 'id' => 'wcj_currency_' . get_woocommerce_currency(),
193
+ 'type' => 'text',
194
+ 'default' => get_woocommerce_currency_symbol(),
195
+ 'desc' => apply_filters( 'booster_message', '', 'desc' ),
196
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'readonly' ),
197
+ );
198
+ }
199
+ $updated_settings[] = $section;
200
  }
201
+ return $updated_settings;
202
  }
 
 
203
 
204
+ }
205
 
206
  endif;
207
 
includes/class-wcj-custom-css.php CHANGED
@@ -5,86 +5,92 @@
5
  * @version 4.0.0
6
  * @since 2.7.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Custom_CSS' ) ) :
13
-
14
- class WCJ_Custom_CSS extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 4.0.0
20
- * @since 2.7.0
21
- * @todo [dev] `do_shortcode()`
22
- * @todo [dev] wp_safe_redirect after saving settings
23
- * @todo [dev] (maybe) set `add_action` `priority` to `PHP_INT_MAX`
24
  */
25
- function __construct() {
26
 
27
- $this->id = 'custom_css';
28
- $this->short_desc = __( 'Custom CSS', 'woocommerce-jetpack' );
29
- $this->desc = __( 'Separate custom CSS for front and back end. Per product CSS.', 'woocommerce-jetpack' );
30
- $this->link_slug = 'woocommerce-booster-custom-css';
31
- parent::__construct();
 
 
 
 
 
32
 
33
- if ( $this->is_enabled() ) {
34
- // Frontend
35
- if ( '' != wcj_get_option( 'wcj_general_custom_css', '' ) ) {
36
- add_action( 'wp_' . wcj_get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'hook_custom_css' ) );
37
- }
38
- // Admin
39
- if ( '' != wcj_get_option( 'wcj_general_custom_admin_css', '' ) ) {
40
- add_action( 'admin_' . wcj_get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'hook_custom_admin_css' ) );
41
- }
42
- // Per product
43
- if ( 'yes' === wcj_get_option( 'wcj_custom_css_per_product', 'no' ) ) {
44
- add_action( 'wp_' . wcj_get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'maybe_add_per_product_css' ) );
45
- // Settings
46
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
47
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
 
 
 
 
 
 
 
48
  }
49
  }
50
- }
51
 
52
- /**
53
- * maybe_add_per_product_css.
54
- *
55
- * @version 2.8.0
56
- * @since 2.8.0
57
- */
58
- function maybe_add_per_product_css() {
59
- $post_id = get_the_ID();
60
- if ( $post_id > 0 && 'yes' === get_post_meta( $post_id, '_' . 'wcj_product_css_enabled', true ) ) {
61
- if ( '' != ( $css = get_post_meta( $post_id, '_' . 'wcj_product_css', true ) ) ) {
62
- echo '<style>' . $css . '</style>';
 
 
63
  }
64
  }
65
- }
66
 
67
- /**
68
- * hook_custom_css.
69
- *
70
- * @version 2.7.0
71
- * @since 2.7.0
72
- */
73
- function hook_custom_css() {
74
- echo '<style>' . wcj_get_option( 'wcj_general_custom_css', '' ) . '</style>';
75
- }
76
 
77
- /**
78
- * hook_custom_admin_css.
79
- *
80
- * @version 2.7.0
81
- * @since 2.7.0
82
- */
83
- function hook_custom_admin_css() {
84
- echo '<style>' . wcj_get_option( 'wcj_general_custom_admin_css', '' ) . '</style>';
85
- }
86
 
87
- }
88
 
89
  endif;
90
 
5
  * @version 4.0.0
6
  * @since 2.7.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Custom_CSS' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Custom_CSS.
 
 
 
 
 
 
18
  */
19
+ class WCJ_Custom_CSS extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 4.0.0
25
+ * @since 2.7.0
26
+ * @todo [dev] `do_shortcode()`
27
+ * @todo [dev] wp_safe_redirect after saving settings
28
+ * @todo [dev] (maybe) set `add_action` `priority` to `PHP_INT_MAX`
29
+ */
30
+ public function __construct() {
31
 
32
+ $this->id = 'custom_css';
33
+ $this->short_desc = __( 'Custom CSS', 'woocommerce-jetpack' );
34
+ $this->desc = __( 'Separate custom CSS for front and back end. Per product CSS.', 'woocommerce-jetpack' );
35
+ $this->link_slug = 'woocommerce-booster-custom-css';
36
+ parent::__construct();
37
+
38
+ if ( $this->is_enabled() ) {
39
+ // Frontend.
40
+ if ( '' !== wcj_get_option( 'wcj_general_custom_css', '' ) ) {
41
+ add_action( 'wp_' . wcj_get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'hook_custom_css' ) );
42
+ }
43
+ // Admin.
44
+ if ( '' !== wcj_get_option( 'wcj_general_custom_admin_css', '' ) ) {
45
+ add_action( 'admin_' . wcj_get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'hook_custom_admin_css' ) );
46
+ }
47
+ // Per product.
48
+ if ( 'yes' === wcj_get_option( 'wcj_custom_css_per_product', 'no' ) ) {
49
+ add_action( 'wp_' . wcj_get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'maybe_add_per_product_css' ) );
50
+ // Settings.
51
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
52
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
53
+ }
54
  }
55
  }
 
56
 
57
+ /**
58
+ * Maybe_add_per_product_css.
59
+ *
60
+ * @version 2.8.0
61
+ * @since 2.8.0
62
+ */
63
+ public function maybe_add_per_product_css() {
64
+ $post_id = get_the_ID();
65
+ if ( $post_id > 0 && 'yes' === get_post_meta( $post_id, '_wcj_product_css_enabled', true ) ) {
66
+ $css = get_post_meta( $post_id, '_wcj_product_css', true );
67
+ if ( '' !== ( $css ) ) {
68
+ echo '<style>' . wp_kses_post( $css ) . '</style>';
69
+ }
70
  }
71
  }
 
72
 
73
+ /**
74
+ * Hook_custom_css.
75
+ *
76
+ * @version 2.7.0
77
+ * @since 2.7.0
78
+ */
79
+ public function hook_custom_css() {
80
+ echo '<style>' . wp_kses_post( wcj_get_option( 'wcj_general_custom_css', '' ) ) . '</style>';
81
+ }
82
 
83
+ /**
84
+ * Hook_custom_admin_css.
85
+ *
86
+ * @version 2.7.0
87
+ * @since 2.7.0
88
+ */
89
+ public function hook_custom_admin_css() {
90
+ echo '<style>' . wp_kses_post( wcj_get_option( 'wcj_general_custom_admin_css', '' ) ) . '</style>';
91
+ }
92
 
93
+ }
94
 
95
  endif;
96
 
includes/class-wcj-custom-js.php CHANGED
@@ -5,61 +5,66 @@
5
  * @version 4.0.0
6
  * @since 2.8.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Custom_JS' ) ) :
13
-
14
- class WCJ_Custom_JS extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 4.0.0
20
- * @since 2.8.0
21
- * @todo [dev] wp_safe_redirect after saving settings
22
- * @todo [dev] (maybe) set `add_action` `priority` to `PHP_INT_MAX`
23
  */
24
- function __construct() {
25
 
26
- $this->id = 'custom_js';
27
- $this->short_desc = __( 'Custom JS', 'woocommerce-jetpack' );
28
- $this->desc = __( 'Separate custom JS for front and back end.', 'woocommerce-jetpack' );
29
- $this->link_slug = 'woocommerce-booster-custom-js';
30
- parent::__construct();
 
 
 
 
31
 
32
- if ( $this->is_enabled() ) {
33
- if ( '' != wcj_get_option( 'wcj_custom_js_frontend', '' ) ) {
34
- add_action( 'wp_' . wcj_get_option( 'wcj_custom_js_hook', 'head' ), array( $this, 'custom_frontend_js' ) );
35
- }
36
- if ( '' != wcj_get_option( 'wcj_custom_js_backend', '' ) ) {
37
- add_action( 'admin_' . wcj_get_option( 'wcj_custom_js_hook', 'head' ), array( $this, 'custom_backend_js' ) );
 
 
 
 
 
 
 
38
  }
39
  }
40
- }
41
 
42
- /**
43
- * custom_frontend_js.
44
- *
45
- * @version 2.9.1
46
- * @since 2.8.0
47
- */
48
- function custom_frontend_js() {
49
- echo '<script>' . do_shortcode( wcj_get_option( 'wcj_custom_js_frontend', '' ) ) . '</script>';
50
- }
51
 
52
- /**
53
- * custom_backend_js.
54
- *
55
- * @version 2.9.1
56
- * @since 2.8.0
57
- */
58
- function custom_backend_js() {
59
- echo '<script>' . do_shortcode( wcj_get_option( 'wcj_custom_js_backend', '' ) ) . '</script>';
60
- }
61
 
62
- }
63
 
64
  endif;
65
 
5
  * @version 4.0.0
6
  * @since 2.8.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Custom_JS' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Custom_JS.
 
 
 
 
 
18
  */
19
+ class WCJ_Custom_JS extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 4.0.0
25
+ * @since 2.8.0
26
+ * @todo [dev] wp_safe_redirect after saving settings
27
+ * @todo [dev] (maybe) set `add_action` `priority` to `PHP_INT_MAX`
28
+ */
29
+ public function __construct() {
30
 
31
+ $this->id = 'custom_js';
32
+ $this->short_desc = __( 'Custom JS', 'woocommerce-jetpack' );
33
+ $this->desc = __( 'Separate custom JS for front and back end.', 'woocommerce-jetpack' );
34
+ $this->link_slug = 'woocommerce-booster-custom-js';
35
+ parent::__construct();
36
+
37
+ if ( $this->is_enabled() ) {
38
+ if ( '' !== wcj_get_option( 'wcj_custom_js_frontend', '' ) ) {
39
+ add_action( 'wp_' . wcj_get_option( 'wcj_custom_js_hook', 'head' ), array( $this, 'custom_frontend_js' ) );
40
+ }
41
+ if ( '' !== wcj_get_option( 'wcj_custom_js_backend', '' ) ) {
42
+ add_action( 'admin_' . wcj_get_option( 'wcj_custom_js_hook', 'head' ), array( $this, 'custom_backend_js' ) );
43
+ }
44
  }
45
  }
 
46
 
47
+ /**
48
+ * Custom_frontend_js.
49
+ *
50
+ * @version 2.9.1
51
+ * @since 2.8.0
52
+ */
53
+ public function custom_frontend_js() {
54
+ echo '<script>' . do_shortcode( wcj_get_option( 'wcj_custom_js_frontend', '' ) ) . '</script>';
55
+ }
56
 
57
+ /**
58
+ * Custom_backend_js.
59
+ *
60
+ * @version 2.9.1
61
+ * @since 2.8.0
62
+ */
63
+ public function custom_backend_js() {
64
+ echo '<script>' . do_shortcode( wcj_get_option( 'wcj_custom_js_backend', '' ) ) . '</script>';
65
+ }
66
 
67
+ }
68
 
69
  endif;
70
 
includes/class-wcj-custom-php.php CHANGED
@@ -5,85 +5,98 @@
5
  * @version 4.0.1
6
  * @since 4.0.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Custom_PHP' ) ) :
13
-
14
- class WCJ_Custom_PHP extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 4.0.1
20
- * @since 4.0.0
21
- * @todo [dev] maybe remove `wcj_disable_custom_php` from URL on settings save
22
- * @todo [dev] allow tab in content (i.e. settings (textarea))
23
  */
24
- function __construct() {
25
 
26
- $this->id = 'custom_php';
27
- $this->short_desc = __( 'Custom PHP', 'woocommerce-jetpack' );
28
- $this->desc = __( 'Custom PHP tool.', 'woocommerce-jetpack' );
29
- $this->extra_desc = sprintf(
30
- __( 'Please note that if you enable the module and enter non-valid PHP code here, your site will become unavailable. To fix this you will have to add %s attribute to the URL (you must be logged as shop manager or admin (for this reason custom PHP code is not executed on %s page)).', 'woocommerce-jetpack' ),
31
- '<code>wcj_disable_custom_php</code>', '<strong>wp-login.php</strong>' ) . ' ' .
32
- sprintf( __( 'E.g.: %s', 'woocommerce-jetpack' ),
33
- '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=custom_php&wcj_disable_custom_php' ) . '">' .
34
- admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=custom_php&wcj_disable_custom_php' ) . '</a>' );
35
- $this->link_slug = 'woocommerce-booster-custom-php';
36
- parent::__construct();
37
 
38
- add_action( 'woojetpack_after_settings_save', array( $this, 'create_php_file' ), PHP_INT_MAX, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
 
40
- if ( $this->is_enabled() ) {
41
- if ( isset( $_GET['wcj_disable_custom_php'] ) ) {
42
- if ( wcj_current_user_can( 'manage_woocommerce' ) ) {
43
- // Stop custom PHP execution
 
 
 
 
 
 
 
 
 
 
 
44
  return;
45
- } elseif ( ! wcj_is_user_logged_in() ) {
46
- // Redirect to login page
47
- wp_redirect( wp_login_url( add_query_arg( '', '' ) ) );
48
- exit;
49
  }
50
- }
51
- if ( $GLOBALS['pagenow'] === 'wp-login.php' ) {
52
- // Stop custom PHP execution if it's the login page
53
- return;
54
- }
55
- // Executing custom PHP code
56
- $file_path = wcj_get_wcj_uploads_dir( 'custom_php', false ) . DIRECTORY_SEPARATOR . 'booster.php';
57
- if ( file_exists( $file_path ) ) {
58
- include_once( $file_path );
59
  }
60
  }
61
- }
62
 
63
- /**
64
- * create_php_file.
65
- *
66
- * @version 4.0.0
67
- * @since 4.0.0
68
- * @todo [dev] `unlink` and `rmdir` on settings reset
69
- * @todo [dev] on empty content - delete dir also (`rmdir`)
70
- */
71
- function create_php_file( $sections, $current_section ) {
72
- if ( $this->id === $current_section ) {
73
- $file_content = wcj_get_option( 'wcj_custom_php', '' );
74
- if ( '' !== $file_content ) {
75
- $file_path = wcj_get_wcj_uploads_dir( 'custom_php' ) . DIRECTORY_SEPARATOR . 'booster.php';
76
- file_put_contents( $file_path, '<?php' . PHP_EOL . $file_content );
77
- } else {
78
- $file_path = wcj_get_wcj_uploads_dir( 'custom_php', false ) . DIRECTORY_SEPARATOR . 'booster.php';
79
- if ( file_exists( $file_path ) ) {
80
- unlink( $file_path );
 
 
 
81
  }
82
  }
83
  }
84
- }
85
 
86
- }
87
 
88
  endif;
89
 
5
  * @version 4.0.1
6
  * @since 4.0.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Custom_PHP' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Custom_PHP.
 
 
 
 
 
18
  */
19
+ class WCJ_Custom_PHP extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 4.0.1
25
+ * @since 4.0.0
26
+ * @todo [dev] maybe remove `wcj_disable_custom_php` from URL on settings save
27
+ * @todo [dev] allow tab in content (i.e. settings (textarea))
28
+ */
29
+ public function __construct() {
 
 
30
 
31
+ $this->id = 'custom_php';
32
+ $this->short_desc = __( 'Custom PHP', 'woocommerce-jetpack' );
33
+ $this->desc = __( 'Custom PHP tool.', 'woocommerce-jetpack' );
34
+ $this->extra_desc = sprintf(
35
+ /* translators: %s: translation added */
36
+ __( 'Please note that if you enable the module and enter non-valid PHP code here, your site will become unavailable. To fix this you will have to add %1$s attribute to the URL (you must be logged as shop manager or admin (for this reason custom PHP code is not executed on %2$s page)).', 'woocommerce-jetpack' ),
37
+ '<code>wcj_disable_custom_php</code>',
38
+ '<strong>wp-login.php</strong>'
39
+ ) . ' ' .
40
+ sprintf(
41
+ /* translators: %s: translation added */
42
+ __( 'E.g.: %s', 'woocommerce-jetpack' ),
43
+ '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=custom_php&wcj_disable_custom_php' ) . '">' .
44
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=custom_php&wcj_disable_custom_php' ) . '</a>'
45
+ );
46
+ $this->link_slug = 'woocommerce-booster-custom-php';
47
+ parent::__construct();
48
 
49
+ add_action( 'woojetpack_after_settings_save', array( $this, 'create_php_file' ), PHP_INT_MAX, 2 );
50
+
51
+ if ( $this->is_enabled() ) {
52
+ if ( isset( $_GET['wcj_disable_custom_php'] ) ) {
53
+ if ( wcj_current_user_can( 'manage_woocommerce' ) ) {
54
+ // Stop custom PHP execution.
55
+ return;
56
+ } elseif ( ! wcj_is_user_logged_in() ) {
57
+ // Redirect to login page.
58
+ wp_safe_redirect( wp_login_url( add_query_arg( '', '' ) ) );
59
+ exit;
60
+ }
61
+ }
62
+ if ( 'wp-login.php' === $GLOBALS['pagenow'] ) {
63
+ // Stop custom PHP execution if it's the login page.
64
  return;
 
 
 
 
65
  }
66
+ // Executing custom PHP code.
67
+ $file_path = wcj_get_wcj_uploads_dir( 'custom_php', false ) . DIRECTORY_SEPARATOR . 'booster.php';
68
+ if ( file_exists( $file_path ) ) {
69
+ include_once $file_path;
70
+ }
 
 
 
 
71
  }
72
  }
 
73
 
74
+ /**
75
+ * Create_php_file.
76
+ *
77
+ * @version 4.0.0
78
+ * @since 4.0.0
79
+ * @todo [dev] `unlink` and `rmdir` on settings reset
80
+ * @todo [dev] on empty content - delete dir also (`rmdir`).
81
+ * @param string | array $sections defines the sections.
82
+ * @param string | array $current_section defines the current_section.
83
+ */
84
+ public function create_php_file( $sections, $current_section ) {
85
+ if ( $this->id === $current_section ) {
86
+ $file_content = wcj_get_option( 'wcj_custom_php', '' );
87
+ if ( '' !== $file_content ) {
88
+ $file_path = wcj_get_wcj_uploads_dir( 'custom_php' ) . DIRECTORY_SEPARATOR . 'booster.php';
89
+ file_put_contents( $file_path, '<?php' . PHP_EOL . $file_content );
90
+ } else {
91
+ $file_path = wcj_get_wcj_uploads_dir( 'custom_php', false ) . DIRECTORY_SEPARATOR . 'booster.php';
92
+ if ( file_exists( $file_path ) ) {
93
+ unlink( $file_path );
94
+ }
95
  }
96
  }
97
  }
 
98
 
99
+ }
100
 
101
  endif;
102
 
includes/class-wcj-debug-tools.php CHANGED
@@ -5,104 +5,113 @@
5
  * @version 5.5.9
6
  * @version 4.1.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Debug_Tools' ) ) :
13
-
14
- class WCJ_Debug_Tools extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 4.1.0
20
- * @version 4.1.0
21
  */
22
- function __construct() {
23
 
24
- $this->id = 'debug_tools';
25
- $this->short_desc = __( 'Debug Tools', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Booster for WooCommerce debug and log tools.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-booster-debug-tools';
28
- parent::__construct();
 
 
29
 
30
- $this->add_tools( array(
31
- 'debug_tools' => array(
32
- 'title' => __( 'Log', 'woocommerce-jetpack' ),
33
- 'desc' => __( 'Log.', 'woocommerce-jetpack' ),
34
- ),
35
- ) );
36
 
37
- }
 
 
 
 
 
 
 
38
 
39
- /**
40
- * create_debug_tools_tool.
41
- *
42
- * @version 5.5.9
43
- */
44
- function create_debug_tools_tool() {
45
- // Delete log
46
- if ( isset( $_GET['wcj_delete_log'] ) && wcj_is_user_role( 'administrator' ) ) {
47
- update_option( 'wcj_log', '' );
48
- if ( wp_safe_redirect( remove_query_arg( 'wcj_delete_log' ) ) ) {
49
- exit;
50
- }
51
  }
52
- // Header
53
- $the_tools = '';
54
- $the_tools .= '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
55
- $the_tools .= $this->get_tool_header_html( 'debug_tools' );
56
- $the_tools .= '<p><a href="' . esc_url(add_query_arg( 'wcj_delete_log', '1' )) . '">' . __( 'Delete Log', 'woocommerce-jetpack' ). '</a></p>';
57
- // Log
58
- $the_log = '';
59
- $the_log .= '<p style="font-style:italic;color:gray;">' . sprintf( __( 'Now: %s', 'woocommerce-jetpack' ), date( 'Y-m-d H:i:s' ) ) . '</p>';
60
- if ( '' != ( $log = wcj_get_option( 'wcj_log', '' ) ) ) {
61
- $the_log .= '<pre style="color:green;background-color:black;padding:5px;">' . $log . '</pre>';
62
- } else {
63
- $the_log .= '<p style="font-style:italic;color:gray;">' . __( 'Log is empty.', 'woocommerce-jetpack' ) . '</p>';
64
- }
65
- // Final output
66
- $html = '';
67
- $html .= '<div class="wrap">';
68
- $html .= '<p>' . $the_tools . '</p>';
69
- $html .= '<p>' . $the_log . '</p>';
70
- $html .= '</div>';
71
- $html .= '</div>';
72
- echo $html;
73
- }
74
 
75
- /**
76
- * get_system_info_table_array.
77
- *
78
- * @version 4.1.0
79
- * @since 2.5.7
80
- * @todo [feature] (maybe) 'DB_NAME', 'DB_USER', 'DB_PASSWORD', 'DB_HOST', 'DB_CHARSET', 'DB_COLLATE'
81
- */
82
- function get_system_info_table_array() {
83
- $system_info = array();
84
- $constants_array = array(
85
- 'WP_MEMORY_LIMIT',
86
- 'WP_MAX_MEMORY_LIMIT',
87
- 'WP_DEBUG',
88
- 'ABSPATH',
89
- 'DISABLE_WP_CRON',
90
- 'WP_CRON_LOCK_TIMEOUT',
91
- 'WCJ_WC_VERSION',
92
- 'WCJ_SESSION_TYPE',
93
- );
94
- foreach ( $constants_array as $the_constant ) {
95
- $system_info[] = array( $the_constant, ( defined( $the_constant ) ? constant( $the_constant ) : __( 'NOT DEFINED', 'woocommerce-jetpack' ) ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  }
97
- if ( isset( $_GET['wcj_debug'] ) ) {
98
- foreach ( $_SERVER as $server_var_id => $server_var_value ) {
99
- $system_info[] = array( $server_var_id, esc_html( $server_var_value ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  }
 
 
 
 
 
 
101
  }
102
- return $system_info;
103
- }
104
 
105
- }
106
 
107
  endif;
108
 
5
  * @version 5.5.9
6
  * @version 4.1.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Debug_Tools' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Debug_Tools.
 
 
 
18
  */
19
+ class WCJ_Debug_Tools extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 4.1.0
25
+ * @version 4.1.0
26
+ */
27
+ public function __construct() {
28
 
29
+ $this->id = 'debug_tools';
30
+ $this->short_desc = __( 'Debug Tools', 'woocommerce-jetpack' );
31
+ $this->desc = __( 'Booster for WooCommerce debug and log tools.', 'woocommerce-jetpack' );
32
+ $this->link_slug = 'woocommerce-booster-debug-tools';
33
+ parent::__construct();
 
34
 
35
+ $this->add_tools(
36
+ array(
37
+ 'debug_tools' => array(
38
+ 'title' => __( 'Log', 'woocommerce-jetpack' ),
39
+ 'desc' => __( 'Log.', 'woocommerce-jetpack' ),
40
+ ),
41
+ )
42
+ );
43
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
+ /**
47
+ * Create_debug_tools_tool.
48
+ *
49
+ * @version 5.5.9
50
+ */
51
+ public function create_debug_tools_tool() {
52
+ // Delete log.
53
+ if ( isset( $_GET['wcj_delete_log'] ) && wcj_is_user_role( 'administrator' ) ) {
54
+ update_option( 'wcj_log', '' );
55
+ if ( wp_safe_redirect( esc_url( remove_query_arg( 'wcj_delete_log' ) ) ) ) {
56
+ exit;
57
+ }
58
+ }
59
+ // Header.
60
+ $the_tools = '';
61
+ $the_tools .= '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
62
+ $the_tools .= $this->get_tool_header_html( 'debug_tools' );
63
+ $the_tools .= '<p><a href="' . esc_url( add_query_arg( 'wcj_delete_log', '1' ) ) . '">' . __( 'Delete Log', 'woocommerce-jetpack' ) . '</a></p>';
64
+ // Log.
65
+ $the_log = '';
66
+ /* translators: %s: translation added */
67
+ $the_log .= '<p style="font-style:italic;color:gray;">' . sprintf( __( 'Now: %s', 'woocommerce-jetpack' ), gmdate( 'Y-m-d H:i:s' ) ) . '</p>';
68
+ $log = wcj_get_option( 'wcj_log', '' );
69
+ if ( '' !== ( $log ) ) {
70
+ $the_log .= '<pre style="color:green;background-color:black;padding:5px;">' . $log . '</pre>';
71
+ } else {
72
+ $the_log .= '<p style="font-style:italic;color:gray;">' . __( 'Log is empty.', 'woocommerce-jetpack' ) . '</p>';
73
+ }
74
+ // Final output.
75
+ $html = '';
76
+ $html .= '<div class="wrap">';
77
+ $html .= '<p>' . $the_tools . '</p>';
78
+ $html .= '<p>' . $the_log . '</p>';
79
+ $html .= '</div>';
80
+ $html .= '</div>';
81
+ echo wp_kses_post( $html );
82
  }
83
+
84
+ /**
85
+ * Get_system_info_table_array.
86
+ *
87
+ * @version 4.1.0
88
+ * @since 2.5.7
89
+ * @todo [feature] (maybe) 'DB_NAME', 'DB_USER', 'DB_PASSWORD', 'DB_HOST', 'DB_CHARSET', 'DB_COLLATE'
90
+ */
91
+ public function get_system_info_table_array() {
92
+ $system_info = array();
93
+ $constants_array = array(
94
+ 'WP_MEMORY_LIMIT',
95
+ 'WP_MAX_MEMORY_LIMIT',
96
+ 'WP_DEBUG',
97
+ 'ABSPATH',
98
+ 'DISABLE_WP_CRON',
99
+ 'WP_CRON_LOCK_TIMEOUT',
100
+ 'WCJ_WC_VERSION',
101
+ 'WCJ_SESSION_TYPE',
102
+ );
103
+ foreach ( $constants_array as $the_constant ) {
104
+ $system_info[] = array( $the_constant, ( defined( $the_constant ) ? constant( $the_constant ) : __( 'NOT DEFINED', 'woocommerce-jetpack' ) ) );
105
  }
106
+ if ( isset( $_GET['wcj_debug'] ) ) {
107
+ foreach ( $_SERVER as $server_var_id => $server_var_value ) {
108
+ $system_info[] = array( $server_var_id, esc_html( $server_var_value ) );
109
+ }
110
+ }
111
+ return $system_info;
112
  }
 
 
113
 
114
+ }
115
 
116
  endif;
117
 
includes/class-wcj-email-options.php CHANGED
@@ -5,164 +5,180 @@
5
  * @version 3.7.0
6
  * @since 2.9.1
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Email_Options' ) ) :
13
-
14
- class WCJ_Email_Options extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 3.5.0
20
- * @since 2.9.1
21
- * @todo meta customizer - check "gravity-forms-emails-woocommerce" plugin
22
  */
23
- function __construct() {
24
 
25
- $this->id = 'email_options';
26
- $this->short_desc = __( 'Email Options', 'woocommerce-jetpack' );
27
- $this->desc = __( 'WooCommerce email options. E.g.: add another email recipient(s) to all WooCommerce emails.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-email-options';
29
- parent::__construct();
 
 
 
30
 
31
- if ( $this->is_enabled() ) {
32
- // Email Forwarding
33
- if ( '' != wcj_get_option( 'wcj_emails_bcc_email', '' ) ) {
34
- add_filter( 'woocommerce_email_headers', array( $this, 'add_bcc_email' ), PHP_INT_MAX, 3 );
35
- }
36
- if ( '' != wcj_get_option( 'wcj_emails_cc_email', '' ) ) {
37
- add_filter( 'woocommerce_email_headers', array( $this, 'add_cc_email' ), PHP_INT_MAX, 3 );
38
- }
39
- // Product Info
40
- if ( 'yes' === wcj_get_option( 'wcj_product_info_in_email_order_item_name_enabled', 'no' ) ) {
41
- add_filter( 'woocommerce_order_item_name', array( $this, 'add_product_info_to_email_order_item_name' ), PHP_INT_MAX, 2 );
 
 
 
 
 
 
 
 
 
42
  }
43
- // Settings
44
- add_filter( 'woocommerce_email_settings', array( $this, 'add_email_forwarding_fields_to_wc_standard_settings' ), PHP_INT_MAX );
45
  }
46
- }
47
 
48
- /**
49
- * add_product_info_to_email_order_item_name.
50
- *
51
- * @version 3.7.0
52
- * @since 2.7.0
53
- */
54
- function add_product_info_to_email_order_item_name( $item_name, $item ) {
55
- if ( $item['product_id'] ) {
56
- global $post;
57
- $product_id = ( ! empty( $item['variation_id'] ) ? $item['variation_id'] : $item['product_id'] );
58
- $post = get_post( $product_id );
59
- setup_postdata( $post );
60
- $item_name .= do_shortcode( wcj_get_option( 'wcj_product_info_in_email_order_item_name', '[wcj_product_categories strip_tags="yes" before="<hr><em>" after="</em>"]' ) );
61
- wp_reset_postdata();
 
 
 
 
62
  }
63
- return $item_name;
64
- }
65
 
66
- /**
67
- * maybe_check_order_status.
68
- *
69
- * @version 3.5.0
70
- * @since 3.5.0
71
- */
72
- function maybe_check_order_status( $_object ) {
73
- $enable_order_statuses = apply_filters( 'booster_option', '', wcj_get_option( 'wcj_emails_forwarding_enable_order_status', '' ) );
74
- if ( ! empty( $enable_order_statuses ) && isset( $_object ) && is_object( $_object ) && 'WC_Order' === get_class( $_object ) ) {
75
- if ( ! in_array( $_object->get_status(), $enable_order_statuses ) ) {
76
- return false;
 
 
77
  }
 
78
  }
79
- return true;
80
- }
81
 
82
- /**
83
- * Add another email recipient to all WooCommerce emails.
84
- *
85
- * @version 3.5.0
86
- */
87
- function add_bcc_email( $email_headers, $id, $_object ) {
88
- return ( $this->maybe_check_order_status( $_object ) ? $email_headers . "Bcc: " . wcj_get_option( 'wcj_emails_bcc_email', '' ) . "\r\n" : $email_headers );
89
- }
 
 
 
90
 
91
- /**
92
- * Add another email recipient to all WooCommerce emails.
93
- *
94
- * @version 3.5.0
95
- */
96
- function add_cc_email( $email_headers, $id, $_object ) {
97
- return ( $this->maybe_check_order_status( $_object ) ? $email_headers . "Cc: " . wcj_get_option( 'wcj_emails_cc_email', '' ) . "\r\n" : $email_headers );
98
- }
 
 
 
99
 
100
- /**
101
- * get_emails_forwarding_settings.
102
- *
103
- * @version 3.5.0
104
- * @since 2.3.9
105
- */
106
- function get_emails_forwarding_settings( $extended_title = false ) {
107
- return array(
108
- array(
109
- 'title' => ( $extended_title ) ?
110
- __( 'Booster: Email Forwarding Options', 'woocommerce-jetpack' ) :
111
- __( 'Email Forwarding Options', 'woocommerce-jetpack' ),
112
- 'type' => 'title',
113
- 'desc' => __( 'This section lets you add another email recipient(s) to all WooCommerce emails. Leave blank to disable.', 'woocommerce-jetpack' ),
114
- 'id' => 'wcj_emails_forwarding_options',
115
- ),
116
- array(
117
- 'title' => __( 'Cc Email', 'woocommerce-jetpack' ),
118
- 'desc_tip' => __( 'Cc to email, e.g. youremail@yourdomain.com. Leave blank to disable.', 'woocommerce-jetpack' ),
119
- 'id' => 'wcj_emails_cc_email',
120
- 'default' => '',
121
- 'type' => 'text',
122
- ),
123
- array(
124
- 'title' => __( 'Bcc Email', 'woocommerce-jetpack' ),
125
- 'desc_tip' => __( 'Bcc to email, e.g. youremail@yourdomain.com. Leave blank to disable.', 'woocommerce-jetpack' ),
126
- 'id' => 'wcj_emails_bcc_email',
127
- 'default' => '',
128
- 'type' => 'text',
129
- ),
130
- array(
131
- 'title' => __( 'Orders Emails: Enable for Statuses', 'woocommerce-jetpack' ),
132
- 'desc' => apply_filters( 'booster_message', '', 'desc' ),
133
- 'desc_tip' => __( 'If you want to forward emails for certain orders only, set order statuses here. Leave blank to send for all orders statuses.', 'woocommerce-jetpack' ),
134
- 'id' => 'wcj_emails_forwarding_enable_order_status',
135
- 'default' => '',
136
- 'type' => 'multiselect',
137
- 'class' => 'chosen_select',
138
- 'options' => wcj_get_order_statuses(),
139
- 'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
140
- ),
141
- array(
142
- 'type' => 'sectionend',
143
- 'id' => 'wcj_emails_forwarding_options',
144
- ),
145
- );
146
- }
 
147
 
148
- /**
149
- * add_email_forwarding_fields_to_wc_standard_settings.
150
- *
151
- * @version 2.3.9
152
- * @todo (maybe) remove this completely (and then move `get_emails_forwarding_settings()` to settings file)
153
- */
154
- function add_email_forwarding_fields_to_wc_standard_settings( $settings ) {
155
- $updated_settings = array();
156
- foreach ( $settings as $section ) {
157
- if ( isset( $section['id'] ) && 'email_template_options' == $section['id'] && isset( $section['type'] ) && 'title' == $section['type'] ) {
158
- $updated_settings = array_merge( $updated_settings, $this->get_emails_forwarding_settings( true ) );
 
 
 
159
  }
160
- $updated_settings[] = $section;
161
  }
162
- return $updated_settings;
163
- }
164
 
165
- }
166
 
167
  endif;
168
 
5
  * @version 3.7.0
6
  * @since 2.9.1
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Email_Options' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Debug_Tools.
 
 
 
 
18
  */
19
+ class WCJ_Email_Options extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 3.5.0
25
+ * @since 2.9.1
26
+ * @todo meta customizer - check "gravity-forms-emails-woocommerce" plugin
27
+ */
28
+ public function __construct() {
29
 
30
+ $this->id = 'email_options';
31
+ $this->short_desc = __( 'Email Options', 'woocommerce-jetpack' );
32
+ $this->desc = __( 'WooCommerce email options. E.g.: add another email recipient(s) to all WooCommerce emails.', 'woocommerce-jetpack' );
33
+ $this->link_slug = 'woocommerce-email-options';
34
+ parent::__construct();
35
+
36
+ if ( $this->is_enabled() ) {
37
+ // Email Forwarding.
38
+ if ( '' !== wcj_get_option( 'wcj_emails_bcc_email', '' ) ) {
39
+ add_filter( 'woocommerce_email_headers', array( $this, 'add_bcc_email' ), PHP_INT_MAX, 3 );
40
+ }
41
+ if ( '' !== wcj_get_option( 'wcj_emails_cc_email', '' ) ) {
42
+ add_filter( 'woocommerce_email_headers', array( $this, 'add_cc_email' ), PHP_INT_MAX, 3 );
43
+ }
44
+ // Product Info.
45
+ if ( 'yes' === wcj_get_option( 'wcj_product_info_in_email_order_item_name_enabled', 'no' ) ) {
46
+ add_filter( 'woocommerce_order_item_name', array( $this, 'add_product_info_to_email_order_item_name' ), PHP_INT_MAX, 2 );
47
+ }
48
+ // Settings.
49
+ add_filter( 'woocommerce_email_settings', array( $this, 'add_email_forwarding_fields_to_wc_standard_settings' ), PHP_INT_MAX );
50
  }
 
 
51
  }
 
52
 
53
+ /**
54
+ * Add_product_info_to_email_order_item_name.
55
+ *
56
+ * @version 3.7.0
57
+ * @since 2.7.0
58
+ * @param string $item_name defines the item_name.
59
+ * @param array $item defines the item.
60
+ */
61
+ public function add_product_info_to_email_order_item_name( $item_name, $item ) {
62
+ if ( $item['product_id'] ) {
63
+ global $post;
64
+ $product_id = ( ! empty( $item['variation_id'] ) ? $item['variation_id'] : $item['product_id'] );
65
+ $posts = get_post( $product_id );
66
+ setup_postdata( $posts );
67
+ $item_name .= do_shortcode( wcj_get_option( 'wcj_product_info_in_email_order_item_name', '[wcj_product_categories strip_tags="yes" before="<hr><em>" after="</em>"]' ) );
68
+ wp_reset_postdata();
69
+ }
70
+ return $item_name;
71
  }
 
 
72
 
73
+ /**
74
+ * Maybe_check_order_status.
75
+ *
76
+ * @version 3.5.0
77
+ * @since 3.5.0
78
+ * @param string $_object | array $_object defines the _object.
79
+ */
80
+ public function maybe_check_order_status( $_object ) {
81
+ $enable_order_statuses = apply_filters( 'booster_option', '', wcj_get_option( 'wcj_emails_forwarding_enable_order_status', '' ) );
82
+ if ( ! empty( $enable_order_statuses ) && isset( $_object ) && is_object( $_object ) && 'WC_Order' === get_class( $_object ) ) {
83
+ if ( ! in_array( $_object->get_status(), $enable_order_statuses, true ) ) {
84
+ return false;
85
+ }
86
  }
87
+ return true;
88
  }
 
 
89
 
90
+ /**
91
+ * Add another email recipient to all WooCommerce emails.
92
+ *
93
+ * @version 3.5.0
94
+ * @param string $email_headers defines the email_headers.
95
+ * @param int $id defines the id.
96
+ * @param string | array $_object defines the _object.
97
+ */
98
+ public function add_bcc_email( $email_headers, $id, $_object ) {
99
+ return ( $this->maybe_check_order_status( $_object ) ? $email_headers . 'Bcc: ' . wcj_get_option( 'wcj_emails_bcc_email', '' ) . "\r\n" : $email_headers );
100
+ }
101
 
102
+ /**
103
+ * Add another email recipient to all WooCommerce emails.
104
+ *
105
+ * @version 3.5.0
106
+ * @param string $email_headers defines the email_headers.
107
+ * @param int $id defines the id.
108
+ * @param string | array $_object defines the _object.
109
+ */
110
+ public function add_cc_email( $email_headers, $id, $_object ) {
111
+ return ( $this->maybe_check_order_status( $_object ) ? $email_headers . 'Cc: ' . wcj_get_option( 'wcj_emails_cc_email', '' ) . "\r\n" : $email_headers );
112
+ }
113
 
114
+ /**
115
+ * Get_emails_forwarding_settings.
116
+ *
117
+ * @version 3.5.0
118
+ * @since 2.3.9
119
+ * @param string | bool $extended_title defines the extended_title.
120
+ */
121
+ public function get_emails_forwarding_settings( $extended_title = false ) {
122
+ return array(
123
+ array(
124
+ 'title' => ( $extended_title ) ?
125
+ __( 'Booster: Email Forwarding Options', 'woocommerce-jetpack' ) :
126
+ __( 'Email Forwarding Options', 'woocommerce-jetpack' ),
127
+ 'type' => 'title',
128
+ 'desc' => __( 'This section lets you add another email recipient(s) to all WooCommerce emails. Leave blank to disable.', 'woocommerce-jetpack' ),
129
+ 'id' => 'wcj_emails_forwarding_options',
130
+ ),
131
+ array(
132
+ 'title' => __( 'Cc Email', 'woocommerce-jetpack' ),
133
+ 'desc_tip' => __( 'Cc to email, e.g. youremail@yourdomain.com. Leave blank to disable.', 'woocommerce-jetpack' ),
134
+ 'id' => 'wcj_emails_cc_email',
135
+ 'default' => '',
136
+ 'type' => 'text',
137
+ ),
138
+ array(
139
+ 'title' => __( 'Bcc Email', 'woocommerce-jetpack' ),
140
+ 'desc_tip' => __( 'Bcc to email, e.g. youremail@yourdomain.com. Leave blank to disable.', 'woocommerce-jetpack' ),
141
+ 'id' => 'wcj_emails_bcc_email',
142
+ 'default' => '',
143
+ 'type' => 'text',
144
+ ),
145
+ array(
146
+ 'title' => __( 'Orders Emails: Enable for Statuses', 'woocommerce-jetpack' ),
147
+ 'desc' => apply_filters( 'booster_message', '', 'desc' ),
148
+ 'desc_tip' => __( 'If you want to forward emails for certain orders only, set order statuses here. Leave blank to send for all orders statuses.', 'woocommerce-jetpack' ),
149
+ 'id' => 'wcj_emails_forwarding_enable_order_status',
150
+ 'default' => '',
151
+ 'type' => 'multiselect',
152
+ 'class' => 'chosen_select',
153
+ 'options' => wcj_get_order_statuses(),
154
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
155
+ ),
156
+ array(
157
+ 'type' => 'sectionend',
158
+ 'id' => 'wcj_emails_forwarding_options',
159
+ ),
160
+ );
161
+ }
162
 
163
+ /**
164
+ * Add_email_forwarding_fields_to_wc_standard_settings.
165
+ *
166
+ * @version 2.3.9
167
+ * @todo (maybe) remove this completely (and then move `get_emails_forwarding_settings()` to settings file)
168
+ * @param array $settings defines the settings.
169
+ */
170
+ public function add_email_forwarding_fields_to_wc_standard_settings( $settings ) {
171
+ $updated_settings = array();
172
+ foreach ( $settings as $section ) {
173
+ if ( isset( $section['id'] ) && 'email_template_options' === $section['id'] && isset( $section['type'] ) && 'title' === $section['type'] ) {
174
+ $updated_settings = array_merge( $updated_settings, $this->get_emails_forwarding_settings( true ) );
175
+ }
176
+ $updated_settings[] = $section;
177
  }
178
+ return $updated_settings;
179
  }
 
 
180
 
181
+ }
182
 
183
  endif;
184
 
includes/class-wcj-emails-verification.php CHANGED
@@ -5,254 +5,318 @@
5
  * @version 5.5.9
6
  * @since 2.8.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Email_Verification' ) ) :
13
-
14
- class WCJ_Email_Verification extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.2.0
20
- * @since 2.8.0
21
  */
22
- function __construct() {
 
 
 
 
 
 
 
 
23
 
24
- $this->id = 'emails_verification';
25
- $this->short_desc = __( 'Email Verification', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Add WooCommerce email verification. Customize verification email subject, content and template (Plus).', 'woocommerce-jetpack' );
27
- $this->desc_pro = __( 'Add WooCommerce email verification.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-email-verification';
29
- parent::__construct();
30
 
31
- if ( $this->is_enabled() ) {
32
- add_action( 'init', array( $this, 'process_email_verification' ), PHP_INT_MAX );
33
- add_filter( 'woocommerce_registration_redirect', array( $this, 'prevent_user_login_automatically_after_register' ), PHP_INT_MAX );
34
- add_filter( 'wp_authenticate_user', array( $this, 'check_if_user_email_is_verified' ), PHP_INT_MAX );
35
- add_action( 'user_register', array( $this, 'reset_and_mail_activation_link' ), PHP_INT_MAX );
36
- add_filter( 'manage_users_columns', array( $this, 'add_verified_email_column' ) );
37
- add_filter( 'manage_users_custom_column', array( $this, 'render_verified_email_column' ), 10, 3 );
38
- add_action( 'wp', array( $this, 'prevent_login' ), PHP_INT_MAX );
39
- add_filter( 'woocommerce_registration_auth_new_customer', array( $this, 'woocommerce_registration_auth_new_customer' ) );
40
- add_filter( 'authenticate', array( $this, 'prevent_authenticate' ), PHP_INT_MAX );
 
41
  }
42
- }
43
 
44
- /**
45
- * prevent_login.
46
- *
47
- * @version 5.2.0
48
- * @since 5.2.0
49
- */
50
- function prevent_login() {
51
- if (
 
 
52
  'yes' !== wcj_get_option( 'wcj_emails_verification_prevent_user_login', 'no' )
53
  || is_admin()
54
  || ! is_user_logged_in()
55
- || empty( $user = wp_get_current_user() ) ||
56
  ! is_wp_error( $this->check_if_user_email_is_verified( get_userdata( $user->ID ) ) )
57
- ) {
58
- return;
 
 
59
  }
60
- wp_logout();
61
- }
62
 
63
- /**
64
- * prevent_authenticate.
65
- *
66
- * @version 5.2.0
67
- * @since 5.2.0
68
- *
69
- * @param $user
70
- *
71
- * @return WP_Error
72
- */
73
- function prevent_authenticate( $user ) {
74
- if (
75
  'yes' !== wcj_get_option( 'wcj_emails_verification_prevent_user_login', 'no' )
76
  || is_wp_error( $user )
77
  || is_null( $user )
78
- || 0 == $user->ID
79
- ) {
 
 
 
 
 
 
 
 
80
  return $user;
81
  }
82
- setup_userdata( $user->ID );
83
- $user_data = get_userdata( $user->ID );
84
- $response = $this->check_if_user_email_is_verified( $user_data );
85
- if ( is_wp_error( $response ) ) {
86
- return $response;
87
- }
88
- return $user;
89
- }
90
 
91
- /**
92
- * woocommerce_registration_auth_new_customer.
93
- *
94
- * @version 5.2.0
95
- * @since 5.2.0
96
- *
97
- * @param $allowed
98
- *
99
- * @return bool
100
- */
101
- function woocommerce_registration_auth_new_customer( $allowed ) {
102
- if ( 'yes' !== wcj_get_option( 'wcj_emails_verification_prevent_user_login', 'no' ) ) {
 
 
 
103
  return $allowed;
104
  }
105
- $allowed = false;
106
- return $allowed;
107
- }
108
 
109
- /**
110
- * add_verified_email_column.
111
- *
112
- * @version 3.1.0
113
- * @since 3.1.0
114
- * @todo (maybe) add option to enable/disable the column
115
- */
116
- function add_verified_email_column( $columns ) {
117
- $columns['wcj_is_verified_email'] = __( 'Verified', 'woocommerce-jetpack' );
118
- return $columns;
119
- }
 
120
 
121
- /**
122
- * render_verified_email_column.
123
- *
124
- * @version 3.1.0
125
- * @since 3.1.0
126
- */
127
- function render_verified_email_column( $output, $column_name, $user_id ) {
128
- if ( 'wcj_is_verified_email' === $column_name ) {
129
- $replaced_values = array(
130
- '1' => '<span title="' . __( 'Email verified', 'woocommerce-jetpack' ) . '">&#9745;</span>',
131
- '0' => '<span title="' . __( 'Email not verified', 'woocommerce-jetpack' ) . '">&#10006;</span>',
132
- );
133
- return str_replace( array_keys( $replaced_values ), array_values( $replaced_values ), get_user_meta( $user_id, 'wcj_is_activated', true ) );
 
 
 
 
 
134
  }
135
- return $output;
136
- }
137
 
138
- /**
139
- * prevent_user_login_automatically_after_register.
140
- *
141
- * @version 5.5.9
142
- * @since 2.8.0
143
- */
144
- function prevent_user_login_automatically_after_register( $redirect_to ) {
145
- wp_logout();
146
- return esc_url(add_query_arg( 'wcj_activate_account_message', '', $redirect_to ));
147
- }
 
148
 
149
- /**
150
- * check_if_user_email_is_verified.
151
- *
152
- * @version 5.5.9
153
- * @since 2.8.0
154
- */
155
- function check_if_user_email_is_verified( $userdata ) {
156
- if (
157
- ( 'yes' === wcj_get_option( 'wcj_emails_verification_already_registered_enabled', 'no' ) && ! get_user_meta( $userdata->ID, 'wcj_is_activated', true ) ) ||
158
- ( 'no' === wcj_get_option( 'wcj_emails_verification_already_registered_enabled', 'no' ) && '0' === get_user_meta( $userdata->ID, 'wcj_is_activated', true ) )
159
- ) {
160
- if ( isset( $userdata->roles ) && ! empty( $userdata->roles ) ) {
161
- $userdata_roles = wcj_get_array( $userdata->roles );
162
- $skip_user_roles = wcj_get_array( wcj_get_option( 'wcj_emails_verification_skip_user_roles', array( 'administrator' ) ) );
163
- $_intersect = array_intersect( $userdata_roles, $skip_user_roles );
164
- if ( ! empty( $_intersect ) ) {
165
- return $userdata;
 
 
166
  }
 
 
 
 
 
 
 
 
167
  }
168
- $error_message = do_shortcode( wcj_get_option( 'wcj_emails_verification_error_message',
169
- __( 'Your account has to be activated before you can login. You can resend email with verification link by clicking <a href="%resend_verification_url%">here</a>.', 'woocommerce-jetpack' )
170
- ) );
171
- $error_message = str_replace( '%resend_verification_url%', esc_url(add_query_arg( 'wcj_user_id', $userdata->ID, wc_get_page_permalink( 'myaccount' ) )), $error_message );
172
- $userdata = new WP_Error( 'booster_email_verified_error', $error_message );
173
  }
174
- return $userdata;
175
- }
176
 
177
- /**
178
- * reset_and_mail_activation_link.
179
- *
180
- * @version 5.5.9
181
- * @since 2.8.0
182
- * @todo %site_name% etc. in `wcj_emails_verification_email_subject`
183
- */
184
- function reset_and_mail_activation_link( $user_id ) {
185
- $user_info = get_userdata( $user_id );
186
- $code = mb_strtoupper(strval(bin2hex(openssl_random_pseudo_bytes(16))));
187
- $url = wp_nonce_url(add_query_arg( 'wcj_verify_email', base64_encode( json_encode( array( 'id' => $user_id, 'code' => $code ) ) ), wc_get_page_permalink( 'myaccount' ) ));
188
- $email_content = do_shortcode( apply_filters( 'booster_option',
189
- __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ),
190
- get_option( 'wcj_emails_verification_email_content',
191
- __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ) ) ) );
192
- $email_content = str_replace( '%verification_url%', $url, $email_content );
193
- $email_subject = do_shortcode( apply_filters( 'booster_option',
194
- __( 'Please activate your account', 'woocommerce-jetpack' ),
195
- get_option( 'wcj_emails_verification_email_subject',
196
- __( 'Please activate your account', 'woocommerce-jetpack' ) ) ) );
197
- update_user_meta( $user_id, 'wcj_is_activated', '0' );
198
- update_user_meta( $user_id, 'wcj_activation_code', $code );
199
- if ( 'wc' === apply_filters( 'booster_option', 'plain', wcj_get_option( 'wcj_emails_verification_email_template', 'plain' ) ) ) {
200
- $email_content = wcj_wrap_in_wc_email_template( $email_content,
201
- get_option( 'wcj_emails_verification_email_template_wc_heading', __( 'Activate your account', 'woocommerce-jetpack' ) ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  }
203
- wc_mail( $user_info->user_email, $email_subject, $email_content );
204
- }
205
 
206
- /**
207
- * process_email_verification.
208
- *
209
- * @version 5.5.9
210
- * @since 2.8.0
211
- */
212
- function process_email_verification() {
213
- if ( isset( $_GET['wcj_verified_email'] ) ) {
214
- if ( function_exists( 'wc_add_notice' ) ) {
215
- $data = json_decode( base64_decode( $_GET['wcj_verified_email'] ), true );
216
- if ( ! empty( $data['id'] ) && ! empty( $data['code'] ) && get_user_meta( $data['id'], 'wcj_activation_code', true ) == $data['code'] ) {
217
- wc_add_notice( do_shortcode( wcj_get_option( 'wcj_emails_verification_success_message',
218
- __( '<strong>Success:</strong> Your account has been activated!', 'woocommerce-jetpack' ) ) ) );
 
 
 
 
 
 
 
219
  }
220
- }
221
- } elseif ( isset( $_GET['wcj_verify_email'] ) ) {
222
- $data = json_decode( base64_decode( $_GET['wcj_verify_email'] ), true );
223
- if ( ! empty( $data['id'] ) && ! empty( $data['code'] ) && get_user_meta( $data['id'], 'wcj_activation_code', true ) == $data['code'] ) {
224
- update_user_meta( $data['id'], 'wcj_is_activated', '1' );
225
- if ( 'yes' === wcj_get_option( 'wcj_emails_verification_redirect_on_success', 'yes' ) ) {
226
- wp_set_current_user( $data['id'] );
227
- wp_set_auth_cookie( $data['id'] );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
228
  }
229
- $url = ( '' != ( $custom_url = wcj_get_option( 'wcj_emails_verification_redirect_on_success_custom_url', '' ) ) ? $custom_url : wc_get_page_permalink( 'myaccount' ) );
230
- wp_safe_redirect( add_query_arg( 'wcj_verified_email', $_GET['wcj_verify_email'], $url ) );
231
- exit;
232
- } elseif ( ! empty( $data['id'] ) ) {
233
- $_notice = do_shortcode(
234
- get_option( 'wcj_emails_verification_failed_message',
235
- __( '<strong>Error:</strong> Activation failed, please contact our administrator. You can resend email with verification link by clicking <a href="%resend_verification_url%">here</a>.', 'woocommerce-jetpack' )
 
 
 
 
 
 
 
 
 
 
236
  )
237
  );
238
- $_notice = str_replace( '%resend_verification_url%', esc_url(add_query_arg( 'wcj_user_id', $data['id'], wc_get_page_permalink( 'myaccount' ) )), $_notice );
239
- wc_add_notice( $_notice, 'error' );
240
- } else {
241
- $_notice = wcj_get_option( 'wcj_emails_verification_failed_message_no_user_id',
242
- __( '<strong>Error:</strong> Activation failed, please contact our administrator.', 'woocommerce-jetpack' ) );
243
- wc_add_notice( $_notice, 'error' );
244
  }
245
- } elseif ( isset( $_GET['wcj_activate_account_message'] ) ) {
246
- wc_add_notice( do_shortcode( wcj_get_option( 'wcj_emails_verification_activation_message',
247
- __( 'Thank you for your registration. Your account has to be activated before you can login. Please check your email.', 'woocommerce-jetpack' ) ) ) );
248
- } elseif ( isset( $_GET['wcj_user_id'] ) ) {
249
- $this->reset_and_mail_activation_link( $_GET['wcj_user_id'] );
250
- wc_add_notice( do_shortcode( wcj_get_option( 'wcj_emails_verification_email_resend_message',
251
- __( '<strong>Success:</strong> Your activation email has been resent. Please check your email.', 'woocommerce-jetpack' ) ) ) );
252
  }
253
- }
254
 
255
- }
256
 
257
  endif;
258
 
5
  * @version 5.5.9
6
  * @since 2.8.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Email_Verification' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Currencies.
 
 
 
18
  */
19
+ class WCJ_Email_Verification extends WCJ_Module {
20
+
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.2.0
25
+ * @since 2.8.0
26
+ */
27
+ public function __construct() {
28
 
29
+ $this->id = 'emails_verification';
30
+ $this->short_desc = __( 'Email Verification', 'woocommerce-jetpack' );
31
+ $this->desc = __( 'Add WooCommerce email verification. Customize verification email subject, content and template (Plus).', 'woocommerce-jetpack' );
32
+ $this->desc_pro = __( 'Add WooCommerce email verification.', 'woocommerce-jetpack' );
33
+ $this->link_slug = 'woocommerce-email-verification';
34
+ parent::__construct();
35
 
36
+ if ( $this->is_enabled() ) {
37
+ add_action( 'init', array( $this, 'process_email_verification' ), PHP_INT_MAX );
38
+ add_filter( 'woocommerce_registration_redirect', array( $this, 'prevent_user_login_automatically_after_register' ), PHP_INT_MAX );
39
+ add_filter( 'wp_authenticate_user', array( $this, 'check_if_user_email_is_verified' ), PHP_INT_MAX );
40
+ add_action( 'user_register', array( $this, 'reset_and_mail_activation_link' ), PHP_INT_MAX );
41
+ add_filter( 'manage_users_columns', array( $this, 'add_verified_email_column' ) );
42
+ add_filter( 'manage_users_custom_column', array( $this, 'render_verified_email_column' ), 10, 3 );
43
+ add_action( 'wp', array( $this, 'prevent_login' ), PHP_INT_MAX );
44
+ add_filter( 'woocommerce_registration_auth_new_customer', array( $this, 'woocommerce_registration_auth_new_customer' ) );
45
+ add_filter( 'authenticate', array( $this, 'prevent_authenticate' ), PHP_INT_MAX );
46
+ }
47
  }
 
48
 
49
+ /**
50
+ * Prevent_login.
51
+ *
52
+ * @version 5.2.0
53
+ * @since 5.2.0
54
+ */
55
+ public function prevent_login() {
56
+ $user = wp_get_current_user();
57
+
58
+ if (
59
  'yes' !== wcj_get_option( 'wcj_emails_verification_prevent_user_login', 'no' )
60
  || is_admin()
61
  || ! is_user_logged_in()
62
+ || empty( $user ) ||
63
  ! is_wp_error( $this->check_if_user_email_is_verified( get_userdata( $user->ID ) ) )
64
+ ) {
65
+ return;
66
+ }
67
+ wp_logout();
68
  }
 
 
69
 
70
+ /**
71
+ * Prevent_authenticate.
72
+ *
73
+ * @version 5.2.0
74
+ * @since 5.2.0
75
+ * @param string $user defines the user.
76
+ * @return WP_Error
77
+ */
78
+ public function prevent_authenticate( $user ) {
79
+ if (
 
 
80
  'yes' !== wcj_get_option( 'wcj_emails_verification_prevent_user_login', 'no' )
81
  || is_wp_error( $user )
82
  || is_null( $user )
83
+ || 0 === $user->ID
84
+ ) {
85
+ return $user;
86
+ }
87
+ setup_userdata( $user->ID );
88
+ $user_data = get_userdata( $user->ID );
89
+ $response = $this->check_if_user_email_is_verified( $user_data );
90
+ if ( is_wp_error( $response ) ) {
91
+ return $response;
92
+ }
93
  return $user;
94
  }
 
 
 
 
 
 
 
 
95
 
96
+ /**
97
+ * Woocommerce_registration_auth_new_customer.
98
+ *
99
+ * @version 5.2.0
100
+ * @since 5.2.0
101
+ *
102
+ * @param bool $allowed check auth.
103
+ *
104
+ * @return bool
105
+ */
106
+ public function woocommerce_registration_auth_new_customer( $allowed ) {
107
+ if ( 'yes' !== wcj_get_option( 'wcj_emails_verification_prevent_user_login', 'no' ) ) {
108
+ return $allowed;
109
+ }
110
+ $allowed = false;
111
  return $allowed;
112
  }
 
 
 
113
 
114
+ /**
115
+ * Add_verified_email_column.
116
+ *
117
+ * @version 3.1.0
118
+ * @since 3.1.0
119
+ * @todo (maybe) add option to enable/disable the column
120
+ * @param array $columns defines email coulmn.
121
+ */
122
+ public function add_verified_email_column( $columns ) {
123
+ $columns['wcj_is_verified_email'] = __( 'Verified', 'woocommerce-jetpack' );
124
+ return $columns;
125
+ }
126
 
127
+ /**
128
+ * Render_verified_email_column.
129
+ *
130
+ * @version 3.1.0
131
+ * @since 3.1.0
132
+ * @param string $output defines the output.
133
+ * @param string $column_name defines the column_name.
134
+ * @param int $user_id defines the user_id.
135
+ */
136
+ public function render_verified_email_column( $output, $column_name, $user_id ) {
137
+ if ( 'wcj_is_verified_email' === $column_name ) {
138
+ $replaced_values = array(
139
+ '1' => '<span title="' . __( 'Email verified', 'woocommerce-jetpack' ) . '">&#9745;</span>',
140
+ '0' => '<span title="' . __( 'Email not verified', 'woocommerce-jetpack' ) . '">&#10006;</span>',
141
+ );
142
+ return str_replace( array_keys( $replaced_values ), array_values( $replaced_values ), get_user_meta( $user_id, 'wcj_is_activated', true ) );
143
+ }
144
+ return $output;
145
  }
 
 
146
 
147
+ /**
148
+ * Prevent_user_login_automatically_after_register.
149
+ *
150
+ * @version 5.5.9
151
+ * @since 2.8.0
152
+ * @param string $redirect_to defines the redirect_to.
153
+ */
154
+ public function prevent_user_login_automatically_after_register( $redirect_to ) {
155
+ wp_logout();
156
+ return esc_url( add_query_arg( 'wcj_activate_account_message', '', $redirect_to ) );
157
+ }
158
 
159
+ /**
160
+ * Check_if_user_email_is_verified.
161
+ *
162
+ * @version 5.5.9
163
+ * @since 2.8.0
164
+ * @param array $userdata defines the userdata.
165
+ */
166
+ public function check_if_user_email_is_verified( $userdata ) {
167
+ if (
168
+ ( 'yes' === wcj_get_option( 'wcj_emails_verification_already_registered_enabled', 'no' ) && ! get_user_meta( $userdata->ID, 'wcj_is_activated', true ) ) ||
169
+ ( 'no' === wcj_get_option( 'wcj_emails_verification_already_registered_enabled', 'no' ) && '0' === get_user_meta( $userdata->ID, 'wcj_is_activated', true ) )
170
+ ) {
171
+ if ( isset( $userdata->roles ) && ! empty( $userdata->roles ) ) {
172
+ $userdata_roles = wcj_get_array( $userdata->roles );
173
+ $skip_user_roles = wcj_get_array( wcj_get_option( 'wcj_emails_verification_skip_user_roles', array( 'administrator' ) ) );
174
+ $_intersect = array_intersect( $userdata_roles, $skip_user_roles );
175
+ if ( ! empty( $_intersect ) ) {
176
+ return $userdata;
177
+ }
178
  }
179
+ $error_message = do_shortcode(
180
+ wcj_get_option(
181
+ 'wcj_emails_verification_error_message',
182
+ __( 'Your account has to be activated before you can login. You can resend email with verification link by clicking <a href="%resend_verification_url%">here</a>.', 'woocommerce-jetpack' )
183
+ )
184
+ );
185
+ $error_message = str_replace( '%resend_verification_url%', esc_url( add_query_arg( 'wcj_user_id', $userdata->ID, wc_get_page_permalink( 'myaccount' ) ) ), $error_message );
186
+ $userdata = new WP_Error( 'booster_email_verified_error', $error_message );
187
  }
188
+ return $userdata;
 
 
 
 
189
  }
 
 
190
 
191
+ /**
192
+ * Reset_and_mail_activation_link.
193
+ *
194
+ * @version 5.5.9
195
+ * @since 2.8.0
196
+ * @todo %site_name% etc. in `wcj_emails_verification_email_subject`
197
+ * @param int $user_id defines the user_id.
198
+ */
199
+ public function reset_and_mail_activation_link( $user_id ) {
200
+ $user_info = get_userdata( $user_id );
201
+ $code = mb_strtoupper( strval( bin2hex( openssl_random_pseudo_bytes( 16 ) ) ) );
202
+ $url = wp_nonce_url(
203
+ add_query_arg(
204
+ 'wcj_verify_email',
205
+ base64_encode(
206
+ wp_json_encode(
207
+ array(
208
+ 'id' => $user_id,
209
+ 'code' => $code,
210
+ )
211
+ )
212
+ ),
213
+ wc_get_page_permalink( 'myaccount' )
214
+ )
215
+ );
216
+ $email_content = do_shortcode(
217
+ apply_filters(
218
+ 'booster_option',
219
+ __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ),
220
+ get_option(
221
+ 'wcj_emails_verification_email_content',
222
+ __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' )
223
+ )
224
+ )
225
+ );
226
+ $email_content = str_replace( '%verification_url%', $url, $email_content );
227
+ $email_subject = do_shortcode(
228
+ apply_filters(
229
+ 'booster_option',
230
+ __( 'Please activate your account', 'woocommerce-jetpack' ),
231
+ get_option(
232
+ 'wcj_emails_verification_email_subject',
233
+ __( 'Please activate your account', 'woocommerce-jetpack' )
234
+ )
235
+ )
236
+ );
237
+ update_user_meta( $user_id, 'wcj_is_activated', '0' );
238
+ update_user_meta( $user_id, 'wcj_activation_code', $code );
239
+ if ( 'wc' === apply_filters( 'booster_option', 'plain', wcj_get_option( 'wcj_emails_verification_email_template', 'plain' ) ) ) {
240
+ $email_content = wcj_wrap_in_wc_email_template(
241
+ $email_content,
242
+ get_option( 'wcj_emails_verification_email_template_wc_heading', __( 'Activate your account', 'woocommerce-jetpack' ) )
243
+ );
244
+ }
245
+ wc_mail( $user_info->user_email, $email_subject, $email_content );
246
  }
 
 
247
 
248
+ /**
249
+ * Process_email_verification.
250
+ *
251
+ * @version 5.5.9
252
+ * @since 2.8.0
253
+ */
254
+ public function process_email_verification() {
255
+ if ( isset( $_GET['wcj_verified_email'] ) ) {
256
+ if ( function_exists( 'wc_add_notice' ) ) {
257
+ $data = json_decode( base64_decode( $_GET['wcj_verified_email'] ), true );
258
+ if ( ! empty( $data['id'] ) && ! empty( $data['code'] ) && get_user_meta( $data['id'], 'wcj_activation_code', true ) === $data['code'] ) {
259
+ wc_add_notice(
260
+ do_shortcode(
261
+ wcj_get_option(
262
+ 'wcj_emails_verification_success_message',
263
+ __( '<strong>Success:</strong> Your account has been activated!', 'woocommerce-jetpack' )
264
+ )
265
+ )
266
+ );
267
+ }
268
  }
269
+ } elseif ( isset( $_GET['wcj_verify_email'] ) ) {
270
+ $data = json_decode( base64_decode( sanitize_text_field( wp_unslash( $_GET['wcj_verify_email'] ) ) ), true );
271
+ if ( ! empty( $data['id'] ) && ! empty( $data['code'] ) && get_user_meta( $data['id'], 'wcj_activation_code', true ) === $data['code'] ) {
272
+ update_user_meta( $data['id'], 'wcj_is_activated', '1' );
273
+ if ( 'yes' === wcj_get_option( 'wcj_emails_verification_redirect_on_success', 'yes' ) ) {
274
+ wp_set_current_user( $data['id'] );
275
+ wp_set_auth_cookie( $data['id'] );
276
+ }
277
+ $custom_url = wcj_get_option( 'wcj_emails_verification_redirect_on_success_custom_url', '' );
278
+ $url = ( '' !== ( $custom_url ) ? $custom_url : wc_get_page_permalink( 'myaccount' ) );
279
+ wp_safe_redirect( add_query_arg( 'wcj_verified_email', sanitize_text_field( wp_unslash( $_GET['wcj_verify_email'] ) ), $url ) );
280
+ exit;
281
+ } elseif ( ! empty( $data['id'] ) ) {
282
+ $_notice = do_shortcode(
283
+ get_option(
284
+ 'wcj_emails_verification_failed_message',
285
+ __( '<strong>Error:</strong> Activation failed, please contact our administrator. You can resend email with verification link by clicking <a href="%resend_verification_url%">here</a>.', 'woocommerce-jetpack' )
286
+ )
287
+ );
288
+ $_notice = str_replace( '%resend_verification_url%', esc_url( add_query_arg( 'wcj_user_id', $data['id'], wc_get_page_permalink( 'myaccount' ) ) ), $_notice );
289
+ wc_add_notice( $_notice, 'error' );
290
+ } else {
291
+ $_notice = wcj_get_option(
292
+ 'wcj_emails_verification_failed_message_no_user_id',
293
+ __( '<strong>Error:</strong> Activation failed, please contact our administrator.', 'woocommerce-jetpack' )
294
+ );
295
+ wc_add_notice( $_notice, 'error' );
296
  }
297
+ } elseif ( isset( $_GET['wcj_activate_account_message'] ) ) {
298
+ wc_add_notice(
299
+ do_shortcode(
300
+ wcj_get_option(
301
+ 'wcj_emails_verification_activation_message',
302
+ __( 'Thank you for your registration. Your account has to be activated before you can login. Please check your email.', 'woocommerce-jetpack' )
303
+ )
304
+ )
305
+ );
306
+ } elseif ( isset( $_GET['wcj_user_id'] ) ) {
307
+ $this->reset_and_mail_activation_link( $_GET['wcj_user_id'] );
308
+ wc_add_notice(
309
+ do_shortcode(
310
+ wcj_get_option(
311
+ 'wcj_emails_verification_email_resend_message',
312
+ __( '<strong>Success:</strong> Your activation email has been resent. Please check your email.', 'woocommerce-jetpack' )
313
+ )
314
  )
315
  );
 
 
 
 
 
 
316
  }
 
 
 
 
 
 
 
317
  }
 
318
 
319
+ }
320
 
321
  endif;
322
 
includes/class-wcj-emails.php CHANGED
@@ -4,132 +4,158 @@
4
  *
5
  * @version 5.2.0
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_Emails' ) ) :
12
-
13
- class WCJ_Emails extends WCJ_Module {
14
-
15
  /**
16
- * Constructor.
17
- *
18
- * @version 5.2.0
19
  */
20
- function __construct() {
 
 
 
 
 
 
 
21
 
22
- $this->id = 'emails';
23
- $this->short_desc = __( 'Custom Emails', 'woocommerce-jetpack' );
24
- $this->desc = __( 'Add custom emails to WooCommerce (1 custom email allowed in free version).', 'woocommerce-jetpack' );
25
- $this->desc_pro = __( 'Add custom emails to WooCommerce.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-custom-emails';
27
- parent::__construct();
28
 
29
- if ( $this->is_enabled() ) {
30
- add_filter( 'woocommerce_email_actions', array( $this, 'add_custom_woocommerce_email_actions' ) );
31
- add_filter( 'woocommerce_email_classes', array( $this, 'add_custom_emails_to_wc' ) );
32
- add_filter( 'woocommerce_resend_order_emails_available', array( $this, 'add_custom_emails_to_wc_resend_order_emails' ) );
33
- if ( ! WCJ_IS_WC_VERSION_BELOW_3_2_0 ) {
34
- add_filter( 'woocommerce_order_actions', array( $this, 'add_custom_emails_order_actions' ), PHP_INT_MAX, 1 );
35
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
36
- add_action( 'woocommerce_order_action_' . 'wcj_send_email_custom' . '_' . $i,
37
- array( $this, 'do_custom_emails_order_actions' ), PHP_INT_MAX, 1 );
 
 
 
 
 
 
38
  }
39
  }
40
  }
41
- }
42
 
43
- /**
44
- * do_custom_emails_order_actions.
45
- *
46
- * @version 3.2.0
47
- * @since 3.2.0
48
- */
49
- function do_custom_emails_order_actions( $order ) {
50
- $booster_action_prefix = 'woocommerce_order_action_' . 'wcj_send_email_custom' . '_';
51
- $_current_filter = current_filter();
52
- if ( substr( $_current_filter, 0, strlen( $booster_action_prefix ) ) === $booster_action_prefix ) {
53
- $email_nr = substr( $_current_filter, strlen( $booster_action_prefix ) );
54
- WC()->payment_gateways();
55
- WC()->shipping();
56
- WC()->mailer()->emails[ 'WC_Email_WCJ_Custom_' . $email_nr ]->trigger( $order->get_id(), $order );
57
- $order->add_order_note(
58
- sprintf( __( 'Booster: Emails: %s manually sent.', 'woocommerce-jetpack' ),
59
- get_option( 'wcj_emails_custom_emails_admin_title_' . $email_nr, __( 'Custom', 'woocommerce-jetpack' ) . ' #' . $email_nr ) ),
60
- false,
61
- true
62
- );
 
 
 
 
 
63
  }
64
- }
65
 
66
- /**
67
- * add_custom_emails_order_actions.
68
- *
69
- * @version 3.2.0
70
- * @since 3.2.0
71
- * @todo (maybe) add "Add Custom Email(s) to Order Actions" option (in WC >= 3.2.0); same to `woocommerce_order_action_`
72
- */
73
- function add_custom_emails_order_actions( $actions ) {
74
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
75
- $actions[ 'wcj_send_email_custom' . '_' . $i ] = sprintf( apply_filters( 'wcj_emails_custom_emails_order_action_text',
76
- __( 'Booster: Send Email: %s', 'woocommerce-jetpack' ), $i ),
 
 
 
 
 
 
 
77
  get_option( 'wcj_emails_custom_emails_admin_title_' . $i, __( 'Custom', 'woocommerce-jetpack' ) . ' #' . $i )
78
- );
 
 
79
  }
80
- return $actions;
81
- }
82
 
83
- /**
84
- * add_custom_woocommerce_email_actions.
85
- *
86
- * @version 2.9.1
87
- * @since 2.4.5
88
- */
89
- function add_custom_woocommerce_email_actions( $email_actions ) {
90
- $email_actions[] = 'woocommerce_checkout_order_processed';
91
- $order_statuses = wcj_get_order_statuses();
92
- foreach ( $order_statuses as $slug => $name ) {
93
- $email_actions[] = 'woocommerce_order_status_' . $slug;
94
- foreach ( $order_statuses as $slug2 => $name2 ) {
95
- if ( $slug != $slug2 ) {
96
- $email_actions[] = 'woocommerce_order_status_' . $slug . '_to_' . $slug2;
 
 
97
  }
98
  }
 
99
  }
100
- return $email_actions;
101
- }
102
 
103
- /**
104
- * add_custom_emails_to_wc_resend_order_emails.
105
- *
106
- * @version 2.3.9
107
- * @since 2.3.9
108
- */
109
- function add_custom_emails_to_wc_resend_order_emails( $emails ) {
110
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
111
- $emails[] = 'wcj_custom' . '_' . $i;
 
 
 
 
112
  }
113
- return $emails;
114
- }
115
 
116
- /**
117
- * add_custom_emails_to_wc.
118
- *
119
- * @version 2.3.9
120
- * @since 2.3.9
121
- */
122
- function add_custom_emails_to_wc( $emails ) {
123
- if ( ! class_exists( 'WC_Email_WCJ_Custom' ) ) {
124
- require_once( 'emails/class-wc-email-wcj-custom.php' );
125
- }
126
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
127
- $emails[ 'WC_Email_WCJ_Custom_' . $i ] = new WC_Email_WCJ_Custom( $i );
 
 
 
 
128
  }
129
- return $emails;
130
- }
131
 
132
- }
133
 
134
  endif;
135
 
4
  *
5
  * @version 5.2.0
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_Emails' ) ) :
 
 
 
15
  /**
16
+ * WCJ_Emails.
 
 
17
  */
18
+ class WCJ_Emails extends WCJ_Module {
19
+
20
+ /**
21
+ * Constructor.
22
+ *
23
+ * @version 5.2.0
24
+ */
25
+ public function __construct() {
26
 
27
+ $this->id = 'emails';
28
+ $this->short_desc = __( 'Custom Emails', 'woocommerce-jetpack' );
29
+ $this->desc = __( 'Add custom emails to WooCommerce (1 custom email allowed in free version).', 'woocommerce-jetpack' );
30
+ $this->desc_pro = __( 'Add custom emails to WooCommerce.', 'woocommerce-jetpack' );
31
+ $this->link_slug = 'woocommerce-custom-emails';
32
+ parent::__construct();
33
 
34
+ if ( $this->is_enabled() ) {
35
+ add_filter( 'woocommerce_email_actions', array( $this, 'add_custom_woocommerce_email_actions' ) );
36
+ add_filter( 'woocommerce_email_classes', array( $this, 'add_custom_emails_to_wc' ) );
37
+ add_filter( 'woocommerce_resend_order_emails_available', array( $this, 'add_custom_emails_to_wc_resend_order_emails' ) );
38
+ if ( ! WCJ_IS_WC_VERSION_BELOW_3_2_0 ) {
39
+ add_filter( 'woocommerce_order_actions', array( $this, 'add_custom_emails_order_actions' ), PHP_INT_MAX, 1 );
40
+ $wcj_emails_custom_emails_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_emails_custom_emails_total_number', 1 ) );
41
+ for ( $i = 1; $i <= $wcj_emails_custom_emails_total_number; $i++ ) {
42
+ add_action(
43
+ 'woocommerce_order_action_wcj_send_email_custom_' . $i,
44
+ array( $this, 'do_custom_emails_order_actions' ),
45
+ PHP_INT_MAX,
46
+ 1
47
+ );
48
+ }
49
  }
50
  }
51
  }
 
52
 
53
+ /**
54
+ * Do_custom_emails_order_actions.
55
+ *
56
+ * @version 3.2.0
57
+ * @since 3.2.0
58
+ * @param string | array $order defines the order.
59
+ */
60
+ public function do_custom_emails_order_actions( $order ) {
61
+ $booster_action_prefix = 'woocommerce_order_action_wcj_send_email_custom_';
62
+ $_current_filter = current_filter();
63
+ if ( substr( $_current_filter, 0, strlen( $booster_action_prefix ) ) === $booster_action_prefix ) {
64
+ $email_nr = substr( $_current_filter, strlen( $booster_action_prefix ) );
65
+ WC()->payment_gateways();
66
+ WC()->shipping();
67
+ WC()->mailer()->emails[ 'WC_Email_WCJ_Custom_' . $email_nr ]->trigger( $order->get_id(), $order );
68
+ $order->add_order_note(
69
+ sprintf(
70
+ /* translators: %s: translation added */
71
+ __( 'Booster: Emails: %s manually sent.', 'woocommerce-jetpack' ),
72
+ get_option( 'wcj_emails_custom_emails_admin_title_' . $email_nr, __( 'Custom', 'woocommerce-jetpack' ) . ' #' . $email_nr )
73
+ ),
74
+ false,
75
+ true
76
+ );
77
+ }
78
  }
 
79
 
80
+ /**
81
+ * Add_custom_emails_order_actions.
82
+ *
83
+ * @version 3.2.0
84
+ * @since 3.2.0
85
+ * @todo (maybe) add "Add Custom Email(s) to Order Actions" option (in WC >= 3.2.0); same to `woocommerce_order_action_`
86
+ * @param array $actions defines the actions.
87
+ */
88
+ public function add_custom_emails_order_actions( $actions ) {
89
+ $wcj_emails_custom_emails_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_emails_custom_emails_total_number', 1 ) );
90
+ for ( $i = 1; $i <= $wcj_emails_custom_emails_total_number; $i++ ) {
91
+ $actions[ 'wcj_send_email_custom_' . $i ] = sprintf(
92
+ apply_filters(
93
+ 'wcj_emails_custom_emails_order_action_text',
94
+ /* translators: %s: translation added */
95
+ __( 'Booster: Send Email: %s', 'woocommerce-jetpack' ),
96
+ $i
97
+ ),
98
  get_option( 'wcj_emails_custom_emails_admin_title_' . $i, __( 'Custom', 'woocommerce-jetpack' ) . ' #' . $i )
99
+ );
100
+ }
101
+ return $actions;
102
  }
 
 
103
 
104
+ /**
105
+ * Add_custom_woocommerce_email_actions.
106
+ *
107
+ * @version 2.9.1
108
+ * @since 2.4.5
109
+ * @param array $email_actions defines the email_actions.
110
+ */
111
+ public function add_custom_woocommerce_email_actions( $email_actions ) {
112
+ $email_actions[] = 'woocommerce_checkout_order_processed';
113
+ $order_statuses = wcj_get_order_statuses();
114
+ foreach ( $order_statuses as $slug => $name ) {
115
+ $email_actions[] = 'woocommerce_order_status_' . $slug;
116
+ foreach ( $order_statuses as $slug2 => $name2 ) {
117
+ if ( $slug !== $slug2 ) {
118
+ $email_actions[] = 'woocommerce_order_status_' . $slug . '_to_' . $slug2;
119
+ }
120
  }
121
  }
122
+ return $email_actions;
123
  }
 
 
124
 
125
+ /**
126
+ * Add_custom_emails_to_wc_resend_order_emails.
127
+ *
128
+ * @version 2.3.9
129
+ * @since 2.3.9
130
+ * @param array $emails defines the emails.
131
+ */
132
+ public function add_custom_emails_to_wc_resend_order_emails( $emails ) {
133
+ $wcj_emails_custom_emails_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_emails_custom_emails_total_number', 1 ) );
134
+ for ( $i = 1; $i <= $wcj_emails_custom_emails_total_number; $i++ ) {
135
+ $emails[] = 'wcj_custom_' . $i;
136
+ }
137
+ return $emails;
138
  }
 
 
139
 
140
+ /**
141
+ * Add_custom_emails_to_wc.
142
+ *
143
+ * @version 2.3.9
144
+ * @since 2.3.9
145
+ * @param array $emails defines the emails.
146
+ */
147
+ public function add_custom_emails_to_wc( $emails ) {
148
+ if ( ! class_exists( 'WC_Email_WCJ_Custom' ) ) {
149
+ require_once 'emails/class-wc-email-wcj-custom.php';
150
+ }
151
+ $wcj_emails_custom_emails_total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_emails_custom_emails_total_number', 1 ) );
152
+ for ( $i = 1; $i <= $wcj_emails_custom_emails_total_number; $i++ ) {
153
+ $emails[ 'WC_Email_WCJ_Custom_' . $i ] = new WC_Email_WCJ_Custom( $i );
154
+ }
155
+ return $emails;
156
  }
 
 
157
 
158
+ }
159
 
160
  endif;
161
 
includes/class-wcj-empty-cart-button.php CHANGED
@@ -5,76 +5,87 @@
5
  * @version 5.2.0
6
  * @since 2.2.1
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Empty_Cart_Button' ) ) :
13
-
14
- class WCJ_Empty_Cart_Button extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.2.0
20
- * @since 2.2.1
21
  */
22
- function __construct() {
23
 
24
- $this->id = 'empty_cart';
25
- $this->short_desc = __( 'Empty Cart Button', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Add (and customize) "Empty Cart" button to the cart and checkout pages. Customize empty cart button text (Plus). Different button positions on the cart page (Plus).', 'woocommerce-jetpack' );
27
- $this->desc_pro = __( 'Add (and customize) "Empty Cart" button to the cart and checkout pages.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-empty-cart-button';
29
- parent::__construct();
 
30
 
31
- if ( $this->is_enabled() ) {
32
- add_action( 'init', array( $this, 'maybe_empty_cart' ) );
33
- if ( 'disable' != ( $empty_cart_cart_position = apply_filters( 'booster_option', 'woocommerce_after_cart',
34
- get_option( 'wcj_empty_cart_position', 'woocommerce_after_cart' ) ) )
35
- ) {
36
- add_action( $empty_cart_cart_position, array( $this, 'add_empty_cart_link' ) );
37
- }
38
- if ( 'disable' != ( $empty_cart_checkout_position = wcj_get_option( 'wcj_empty_cart_checkout_position', 'disable' ) ) ) {
39
- $deprecated_hooks = array(
40
- 'woocommerce_checkout_before_customer_details' => 'woocommerce_before_checkout_form',
41
- 'woocommerce_checkout_billing' => 'woocommerce_before_checkout_form',
42
- 'woocommerce_checkout_shipping' => 'woocommerce_before_checkout_form',
43
- 'woocommerce_checkout_after_customer_details' => 'woocommerce_after_checkout_form',
44
- 'woocommerce_checkout_before_order_review' => 'woocommerce_after_checkout_form',
45
- 'woocommerce_checkout_order_review' => 'woocommerce_after_checkout_form',
46
- 'woocommerce_checkout_after_order_review' => 'woocommerce_after_checkout_form',
47
  );
48
- if ( isset( $deprecated_hooks[ $empty_cart_checkout_position ] ) ) {
49
- $empty_cart_checkout_position = $deprecated_hooks[ $empty_cart_checkout_position ];
50
- update_option( 'wcj_empty_cart_checkout_position', $empty_cart_checkout_position );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
52
- add_action( $empty_cart_checkout_position, array( $this, 'add_empty_cart_link' ) );
53
  }
54
  }
55
- }
56
 
57
- /**
58
- * add_empty_cart_link.
59
- *
60
- * @version 2.8.0
61
- */
62
- function add_empty_cart_link() {
63
- echo wcj_empty_cart_button_html();
64
- }
65
 
66
- /**
67
- * maybe_empty_cart.
68
- *
69
- * @version 2.8.0
70
- */
71
- function maybe_empty_cart() {
72
- if ( isset( $_POST['wcj_empty_cart'] ) && isset( WC()->cart ) ) {
73
- WC()->cart->empty_cart();
 
 
74
  }
75
- }
76
 
77
- }
78
 
79
  endif;
80
 
5
  * @version 5.2.0
6
  * @since 2.2.1
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Empty_Cart_Button' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Empty_Cart_Button.
 
 
 
18
  */
19
+ class WCJ_Empty_Cart_Button extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.2.0
25
+ * @since 2.2.1
26
+ */
27
+ public function __construct() {
28
 
29
+ $this->id = 'empty_cart';
30
+ $this->short_desc = __( 'Empty Cart Button', 'woocommerce-jetpack' );
31
+ $this->desc = __( 'Add (and customize) "Empty Cart" button to the cart and checkout pages. Customize empty cart button text (Plus). Different button positions on the cart page (Plus).', 'woocommerce-jetpack' );
32
+ $this->desc_pro = __( 'Add (and customize) "Empty Cart" button to the cart and checkout pages.', 'woocommerce-jetpack' );
33
+ $this->link_slug = 'woocommerce-empty-cart-button';
34
+ parent::__construct();
35
+
36
+ if ( $this->is_enabled() ) {
37
+ add_action( 'init', array( $this, 'maybe_empty_cart' ) );
38
+ $empty_cart_cart_position = apply_filters(
39
+ 'booster_option',
40
+ 'woocommerce_after_cart',
41
+ get_option( 'wcj_empty_cart_position', 'woocommerce_after_cart' )
 
 
 
42
  );
43
+ if ( 'disable' !== ( $empty_cart_cart_position )
44
+ ) {
45
+ add_action( $empty_cart_cart_position, array( $this, 'add_empty_cart_link' ) );
46
+ }
47
+ $empty_cart_checkout_position = wcj_get_option( 'wcj_empty_cart_checkout_position', 'disable' );
48
+ if ( 'disable' !== ( $empty_cart_checkout_position ) ) {
49
+ $deprecated_hooks = array(
50
+ 'woocommerce_checkout_before_customer_details' => 'woocommerce_before_checkout_form',
51
+ 'woocommerce_checkout_billing' => 'woocommerce_before_checkout_form',
52
+ 'woocommerce_checkout_shipping' => 'woocommerce_before_checkout_form',
53
+ 'woocommerce_checkout_after_customer_details' => 'woocommerce_after_checkout_form',
54
+ 'woocommerce_checkout_before_order_review' => 'woocommerce_after_checkout_form',
55
+ 'woocommerce_checkout_order_review' => 'woocommerce_after_checkout_form',
56
+ 'woocommerce_checkout_after_order_review' => 'woocommerce_after_checkout_form',
57
+ );
58
+ if ( isset( $deprecated_hooks[ $empty_cart_checkout_position ] ) ) {
59
+ $empty_cart_checkout_position = $deprecated_hooks[ $empty_cart_checkout_position ];
60
+ update_option( 'wcj_empty_cart_checkout_position', $empty_cart_checkout_position );
61
+ }
62
+ add_action( $empty_cart_checkout_position, array( $this, 'add_empty_cart_link' ) );
63
  }
 
64
  }
65
  }
 
66
 
67
+ /**
68
+ * Add_empty_cart_link.
69
+ *
70
+ * @version 2.8.0
71
+ */
72
+ public function add_empty_cart_link() {
73
+ echo wp_kses_post( wcj_empty_cart_button_html() );
74
+ }
75
 
76
+ /**
77
+ * Maybe_empty_cart.
78
+ *
79
+ * @version 2.8.0
80
+ */
81
+ public function maybe_empty_cart() {
82
+
83
+ if ( isset( $_POST['wcj_empty_cart'] ) && isset( WC()->cart ) ) {
84
+ WC()->cart->empty_cart();
85
+ }
86
  }
 
87
 
88
+ }
89
 
90
  endif;
91
 
includes/class-wcj-eu-vat-number.php CHANGED
@@ -5,468 +5,510 @@
5
  * @version 5.5.9
6
  * @since 2.3.9
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_EU_VAT_Number' ) ) :
13
-
14
- class WCJ_EU_VAT_Number extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.3.7
20
- * @todo [feature] add option to add "Verify" button to frontend
21
  */
22
- function __construct() {
23
-
24
- $this->id = 'eu_vat_number';
25
- $this->short_desc = __( 'EU VAT Number', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Collect and validate EU VAT numbers on the checkout. Automatically disable VAT for valid numbers. Add all EU countries VAT standard rates to WooCommerce. Show VAT field for EU countries only (Plus). Check for IP Location Country (Plus)', 'woocommerce-jetpack' );
27
- $this->desc_pro = __( 'Collect and validate EU VAT numbers on the checkout. Automatically disable VAT for valid numbers. Add all EU countries VAT standard rates to WooCommerce.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-eu-vat-number';
29
- parent::__construct();
30
-
31
- $this->add_tools( array(
32
- 'eu_countries_vat_rates' => array(
33
- 'title' => __( 'EU Countries VAT Rates', 'woocommerce-jetpack' ),
34
- 'desc' => __( 'Add all EU countries VAT standard rates to WooCommerce.', 'woocommerce-jetpack' ),
35
- ),
36
- ) );
37
-
38
- if ( $this->is_enabled() ) {
39
- add_action( 'init', array( $this, 'start_session' ) );
40
- add_filter( 'woocommerce_checkout_fields', array( $this, 'add_eu_vat_number_checkout_field_to_frontend' ), PHP_INT_MAX );
41
- add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_billing_eu_vat_number_field_to_admin_order_display' ), PHP_INT_MAX );
42
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
43
- add_action( 'wp_ajax_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
44
- add_action( 'wp_ajax_nopriv_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
45
- add_filter( 'wp', array( $this, 'maybe_exclude_vat' ), PHP_INT_MAX );
46
- add_filter( 'woocommerce_cart_tax_totals', array( $this, 'maybe_remove_tax_totals' ), 1 );
47
- add_filter( 'woocommerce_calculated_total', array( $this, 'maybe_recalculate_tax_totals' ), 1, 2 );
48
- add_action( 'woocommerce_after_checkout_validation', array( $this, 'checkout_validate_vat' ), PHP_INT_MAX );
49
- add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_eu_vat_number_customer_meta_field' ) );
50
- add_filter( 'default_checkout_billing_eu_vat_number', array( $this, 'add_default_checkout_billing_eu_vat_number' ), PHP_INT_MAX, 2 );
51
-
52
- if ( 'after_order_table' === wcj_get_option( 'wcj_eu_vat_number_display_position', 'after_order_table' ) ) {
53
- add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
54
- add_action( 'woocommerce_email_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
55
- } else {
56
- add_filter( 'woocommerce_order_formatted_billing_address', array( $this, 'add_eu_vat_number_to_order_billing_address' ), PHP_INT_MAX, 2 );
57
- add_filter( 'woocommerce_my_account_my_address_formatted_address', array( $this, 'add_eu_vat_number_to_my_account_billing_address' ), PHP_INT_MAX, 3 );
58
- add_filter( 'woocommerce_localisation_address_formats', array( $this, 'add_eu_vat_number_to_address_formats' ) );
59
- add_filter( 'woocommerce_formatted_address_replacements', array( $this, 'replace_eu_vat_number_in_address_formats' ), PHP_INT_MAX, 2 );
60
- }
 
 
 
 
 
 
 
 
 
 
61
 
62
- $this->eu_countries_vat_rates_tool = include_once( 'tools/class-wcj-eu-countries-vat-rates-tool.php' );
63
 
64
- // EU VAT number summary on order edit page
65
- if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_add_order_edit_metabox', 'no' ) ) {
66
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
67
- // "Validate VAT and remove taxes" button
68
- add_action( 'admin_init', array( $this, 'admin_validate_vat_and_maybe_remove_taxes' ), PHP_INT_MAX );
69
- }
70
 
71
- // Admin order edit - "Load billing address" button
72
- add_filter( 'woocommerce_ajax_get_customer_details', array( $this, 'add_billing_eu_vat_number_to_ajax_get_customer_details' ), PHP_INT_MAX, 3 );
 
73
  }
74
- }
75
 
76
- /**
77
- * maybe_recalculate_tax_totals.
78
- *
79
- * @version 4.6.0
80
- * @since 4.6.0
81
- *
82
- * @see https://gist.github.com/TimBHowe/fe9418b9224d8b8cb339
83
- * @param $total
84
- * @param $cart
85
- *
86
- * @return mixed
87
- */
88
- function maybe_recalculate_tax_totals( $total, $cart ) {
89
- if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_disable_for_valid_on_cart', 'no' ) && $this->need_to_exclude_vat() ) {
90
- return $total - $cart->get_taxes_total();
 
 
91
  }
92
- return $total;
93
- }
94
 
95
- /**
96
- * maybe_remove_tax_totals.
97
- *
98
- * @version 4.6.0
99
- * @since 4.6.0
100
- *
101
- * @see https://gist.github.com/TimBHowe/fe9418b9224d8b8cb339
102
- * @param $tax_totals
103
- *
104
- * @return array
105
- */
106
- function maybe_remove_tax_totals( $tax_totals ) {
107
- if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_disable_for_valid_on_cart', 'no' ) && $this->need_to_exclude_vat() ) {
108
- $tax_totals = array();
 
109
  }
110
- return $tax_totals;
111
- }
112
 
113
- /**
114
- * admin_validate_vat_and_maybe_remove_taxes.
115
- *
116
- * @version 3.3.0
117
- * @since 3.3.0
118
- */
119
- function admin_validate_vat_and_maybe_remove_taxes() {
120
- if ( isset( $_GET['validate_vat_and_maybe_remove_taxes'] ) ) {
121
- $order_id = $_GET['validate_vat_and_maybe_remove_taxes'];
122
- $order = wc_get_order( $order_id );
123
- if ( $order ) {
124
- $vat_id = get_post_meta( $order_id, '_billing_eu_vat_number', true );
125
- if ( '' != $vat_id && strlen( $vat_id ) > 2 ) {
126
- if ( wcj_validate_vat( substr( $vat_id, 0, 2 ), substr( $vat_id, 2 ) ) ) {
127
- foreach ( $order->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) {
128
- $item->set_taxes( false );
129
- }
130
- foreach ( $order->get_shipping_methods() as $item_id => $item ) {
131
- $item->set_taxes( false );
 
 
 
132
  }
133
- $order->update_taxes();
134
- $order->calculate_totals( false );
135
  }
136
  }
 
 
137
  }
138
- wp_safe_redirect( remove_query_arg( 'validate_vat_and_maybe_remove_taxes' ) );
139
- exit;
140
  }
141
- }
142
-
143
- /**
144
- * add_billing_eu_vat_number_to_ajax_get_customer_details.
145
- *
146
- * @version 3.3.0
147
- * @since 3.3.0
148
- */
149
- function add_billing_eu_vat_number_to_ajax_get_customer_details( $data, $customer, $user_id ) {
150
- $data['billing']['eu_vat_number'] = get_user_meta( $user_id, 'billing_eu_vat_number', true );
151
- return $data;
152
- }
153
 
154
- /**
155
- * add_meta_box.
156
- *
157
- * @version 2.6.0
158
- * @since 2.6.0
159
- */
160
- function add_meta_box() {
161
- $screen = ( isset( $this->meta_box_screen ) ) ? $this->meta_box_screen : 'shop_order';
162
- $context = ( isset( $this->meta_box_context ) ) ? $this->meta_box_context : 'side';
163
- $priority = ( isset( $this->meta_box_priority ) ) ? $this->meta_box_priority : 'low';
164
- add_meta_box(
165
- 'wc-jetpack-' . $this->id,
166
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . $this->short_desc,
167
- array( $this, 'create_meta_box' ),
168
- $screen,
169
- $context,
170
- $priority
171
- );
172
- }
173
-
174
- /**
175
- * create_meta_box.
176
- *
177
- * @version 5.5.9
178
- * @since 2.6.0
179
- */
180
- function create_meta_box() {
181
- $order_id = get_the_ID();
182
- $_order = wc_get_order( $order_id );
183
- $_customer_ip_address = ( WCJ_IS_WC_VERSION_BELOW_3 ? $_order->customer_ip_address : $_order->get_customer_ip_address() );
184
-
185
- // Country by IP
186
- if ( class_exists( 'WC_Geolocation' ) ) {
187
- // Get the country by IP
188
- $location = WC_Geolocation::geolocate_ip( $_customer_ip_address );
189
- // Base fallback
190
- if ( empty( $location['country'] ) ) {
191
- $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', wcj_get_option( 'woocommerce_default_country' ) ) );
192
- }
193
- $customer_country = ( isset( $location['country'] ) ) ? $location['country'] : '';
194
- } else {
195
- $customer_country = '';
196
  }
197
 
198
- // Customer EU VAT number
199
- $customer_eu_vat_number = get_post_meta( $order_id, '_billing_eu_vat_number', true );
200
- if ( '' == $customer_eu_vat_number ) {
201
- $customer_eu_vat_number = '-';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
202
  }
203
 
204
- // Taxes
205
- $taxes = '';
206
- $taxes_array = $_order->get_tax_totals();
207
- if ( empty( $taxes_array ) ) {
208
- $taxes = '-';
209
- } else {
210
- foreach ( $taxes_array as $tax ) {
211
- $taxes .= $tax->label . ': ' . $tax->formatted_amount . '<br>';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
  }
213
- }
214
 
215
- // Results table
216
- $table_data = array(
217
- array(
218
- __( 'Customer IP', 'woocommerce-jetpack' ),
219
- $_customer_ip_address
220
- ),
221
- array(
222
- __( 'Country by IP', 'woocommerce-jetpack' ),
223
- wcj_get_country_flag_by_code( $customer_country ) . ' ' . wcj_get_country_name_by_code( $customer_country ) . ' [' . $customer_country . ']'
224
- ),
225
- array(
226
- __( 'Customer EU VAT Number', 'woocommerce-jetpack' ),
227
- $customer_eu_vat_number
228
- ),
229
- array(
230
- __( 'Taxes', 'woocommerce-jetpack' ),
231
- $taxes,
232
- ),
233
- );
234
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
235
- echo '<p>' . '<a href="' . esc_url(add_query_arg( 'validate_vat_and_maybe_remove_taxes', $order_id )) . '">' .
236
- __( 'Validate VAT and remove taxes', 'woocommerce-jetpack' ) . '</a>' . '</p>';
237
- }
238
 
239
- /**
240
- * replace_eu_vat_number_in_address_formats.
241
- *
242
- * @version 2.5.2
243
- * @since 2.5.2
244
- */
245
- function replace_eu_vat_number_in_address_formats( $replacements, $args ) {
246
- $field_name = 'billing_' . $this->id;
247
- $replacements['{' . $field_name . '}'] = ( isset( $args[ $field_name ] ) ) ? $args[ $field_name ] : '';
248
- return $replacements;
249
- }
250
 
251
- /**
252
- * add_eu_vat_number_to_address_formats.
253
- *
254
- * @version 2.5.2
255
- * @since 2.5.2
256
- */
257
- function add_eu_vat_number_to_address_formats( $address_formats ) {
258
- $field_name = 'billing_' . $this->id;
259
- $modified_address_formats = array();
260
- foreach ( $address_formats as $country => $address_format ) {
261
- $modified_address_formats[ $country ] = $address_format . "\n{" . $field_name . '}';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
262
  }
263
- return $modified_address_formats;
264
- }
265
 
266
- /**
267
- * add_eu_vat_number_to_my_account_billing_address.
268
- *
269
- * @version 2.5.2
270
- * @since 2.5.2
271
- */
272
- function add_eu_vat_number_to_my_account_billing_address( $fields, $customer_id, $name ) {
273
- if ( 'billing' === $name ) {
274
- $field_name = 'billing_' . $this->id;
275
- $fields[ $field_name ] = get_user_meta( $customer_id, $field_name, true );
 
 
276
  }
277
- return $fields;
278
- }
279
 
280
- /**
281
- * add_eu_vat_number_to_order_billing_address.
282
- *
283
- * @version 2.7.0
284
- * @since 2.5.2
285
- */
286
- function add_eu_vat_number_to_order_billing_address( $fields, $_order ) {
287
- $field_name = 'billing_' . $this->id;
288
- $fields[ $field_name ] = get_post_meta( wcj_get_order_id( $_order ), '_' . $field_name, true );
289
- return $fields;
290
- }
 
 
 
 
291
 
292
- /**
293
- * add_eu_vat_number_to_order_display.
294
- *
295
- * @version 3.2.2
296
- * @since 2.4.7
297
- */
298
- function add_eu_vat_number_to_order_display( $order ) {
299
- $order_id = wcj_get_order_id( $order );
300
- $html = '';
301
- $option_name = '_billing_' . $this->id;
302
- $the_eu_vat_number = get_post_meta( $order_id, $option_name, true );
303
- if ( '' != $the_eu_vat_number ) {
304
- $the_label = wcj_get_option( 'wcj_eu_vat_number_field_label', __( 'EU VAT Number', 'woocommerce-jetpack' ) );
305
- $html .= '<p>' . '<strong>' . $the_label . '</strong>: ' . $the_eu_vat_number . '</p>';
 
306
  }
307
- echo $html;
308
- }
309
 
310
- /**
311
- * create_eu_countries_vat_rates_tool.
312
- *
313
- * @version 2.3.10
314
- * @since 2.3.10
315
- */
316
- function create_eu_countries_vat_rates_tool() {
317
- return $this->eu_countries_vat_rates_tool->create_eu_countries_vat_rates_tool( $this->get_tool_header_html( 'eu_countries_vat_rates' ) );
318
- }
 
 
 
 
319
 
320
- /**
321
- * add_default_checkout_billing_eu_vat_number.
322
- *
323
- * @version 4.3.0
324
- */
325
- function add_default_checkout_billing_eu_vat_number( $default_value, $field_key ) {
326
- if ( '' != ( $eu_vat_number_to_check = wcj_session_get( 'wcj_eu_vat_number_to_check' ) ) ) {
327
- return $eu_vat_number_to_check;
328
- } elseif ( is_user_logged_in() ) {
329
- $current_user = wp_get_current_user();
330
- if ( $meta = get_user_meta( $current_user->ID, 'billing_eu_vat_number', true ) ) {
331
- return $meta;
 
 
 
332
  }
 
333
  }
334
- return $default_value;
335
- }
336
 
337
- /**
338
- * add_eu_vat_number_customer_meta_field.
339
- */
340
- function add_eu_vat_number_customer_meta_field( $fields ) {
341
- $fields['billing']['fields']['billing_eu_vat_number'] = array(
342
- 'label' => wcj_get_option( 'wcj_eu_vat_number_field_label' ),
343
- 'description' => ''
344
- );
345
- return $fields;
346
- }
347
-
348
- /**
349
- * start_session.
350
- *
351
- * @version 4.9.0
352
- */
353
- function start_session() {
354
- if ( is_admin() ) {
355
- return;
356
  }
357
- wcj_session_maybe_start();
358
- $args = array();
359
- if ( isset( $_POST['post_data'] ) ) {
360
- parse_str( $_POST['post_data'], $args );
361
- if ( isset( $args['billing_eu_vat_number'] ) && wcj_session_get( 'wcj_eu_vat_number_to_check' ) != $args['billing_eu_vat_number'] ) {
362
- wcj_session_set( 'wcj_is_eu_vat_number_valid', null );
363
- wcj_session_set( 'wcj_eu_vat_number_to_check', null );
 
 
 
 
 
 
 
 
 
 
 
364
  }
 
365
  }
366
- }
367
 
368
- /**
369
- * restrictive_loading_valid.
370
- *
371
- * @version 4.9.0
372
- * @since 4.9.0
373
- *
374
- * @return bool
375
- */
376
- function restrictive_loading_valid() {
377
- if ( empty( $restrictive_loading_conditions = wcj_get_option( 'wcj_eu_vat_number_restrictive_loading', array() ) ) ) {
378
- return true;
379
  }
380
- foreach ( $restrictive_loading_conditions as $condition ) {
381
- if ( $condition() ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
  return true;
383
  }
 
 
 
 
 
 
384
  }
385
- return false;
386
- }
387
 
388
- /**
389
- * enqueue_scripts.
390
- *
391
- * @version 5.4.5
392
- */
393
- function enqueue_scripts() {
394
- if (
395
- 'no' === wcj_get_option( 'wcj_eu_vat_number_validate', 'yes' ) && 'no' === wcj_get_option( 'wcj_eu_vat_number_field_required', 'yes' ) ||
396
  ! $this->restrictive_loading_valid()
397
- ) {
398
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
399
  }
400
- wp_enqueue_script( 'wcj-eu-vat-number', wcj_plugin_url() . '/includes/js/wcj-eu-vat-number.js', array(), WCJ()->version, true );
401
- wp_localize_script( 'wcj-eu-vat-number', 'ajax_object', array(
402
- 'ajax_url' => admin_url( 'admin-ajax.php' ),
403
- 'eu_countries' => wcj_get_european_union_countries(),
404
- 'show_vat_field_for_eu_only' => wcj_get_option( 'wcj_eu_vat_number_show_vat_field_for_eu_only', 'no' ),
405
- 'is_vat_field_required_for_eu_only' => wcj_get_option( 'wcj_eu_vat_number_field_required', 'no' ),
406
- 'add_progress_text' => wcj_get_option( 'wcj_eu_vat_number_add_progress_text', 'no' ),
407
- 'progress_text_validating' => do_shortcode( wcj_get_option( 'wcj_eu_vat_number_progress_text_validating', __( 'Validating VAT. Please wait...', 'woocommerce-jetpack' ) ) ),
408
- 'progress_text_valid' => do_shortcode( wcj_get_option( 'wcj_eu_vat_number_progress_text_valid', __( 'VAT is valid.', 'woocommerce-jetpack' ) ) ),
409
- 'progress_text_not_valid' => do_shortcode( wcj_get_option( 'wcj_eu_vat_number_progress_text_not_valid', __( 'VAT is not valid.', 'woocommerce-jetpack' ) ) ),
410
- 'progress_text_validation_failed' => do_shortcode( wcj_get_option( 'wcj_eu_vat_number_progress_text_validation_failed', __( 'Validation failed. Please try again.', 'woocommerce-jetpack' ) ) ),
411
- ) );
412
- }
413
 
414
- /**
415
- * wcj_validate_eu_vat_number.
416
- *
417
- * @version 4.6.1
418
- */
419
- function wcj_validate_eu_vat_number( $param ) {
420
- $param = wp_parse_args( $param, array(
421
- 'wcj_eu_vat_number_to_check' => '',
422
- 'echo' => true
423
- ) );
424
- $eu_vat_number = isset( $param['wcj_eu_vat_number_to_check'] ) && '' != $param['wcj_eu_vat_number_to_check'] ? $param['wcj_eu_vat_number_to_check'] : '';
425
- $eu_vat_number = empty( $eu_vat_number ) && isset( $_POST['wcj_eu_vat_number_to_check'] ) && '' != $_POST['wcj_eu_vat_number_to_check'] ? $_POST['wcj_eu_vat_number_to_check'] : $eu_vat_number;
426
- if ( ! empty( $eu_vat_number ) ) {
427
- $eu_vat_number_to_check = substr( $eu_vat_number, 2 );
428
- $eu_vat_number_country_to_check = substr( $eu_vat_number, 0, 2 );
429
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_eu_vat_number_check_ip_location_country', 'no' ) ) ) {
430
- $location = WC_Geolocation::geolocate_ip();
431
- if ( empty( $location['country'] ) ) {
432
- $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', wcj_get_option( 'woocommerce_default_country' ) ) );
433
- }
434
- $is_valid = ( $location['country'] === $eu_vat_number_country_to_check ) ?
 
 
 
 
435
  wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check ) :
436
  false;
 
 
 
437
  } else {
438
- $is_valid = wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
439
  }
440
- } else {
441
- $is_valid = null;
442
- }
443
- wcj_session_set( 'wcj_is_eu_vat_number_valid', $is_valid );
444
- wcj_session_set( 'wcj_eu_vat_number_to_check', $eu_vat_number );
445
- $response = '3';
446
- if ( false === $is_valid ) {
447
- $response = '0';
448
- } elseif ( true === $is_valid ) {
449
- $response = '1';
450
- } elseif ( null === $is_valid ) {
451
- $response = '2';
452
- }
453
- if ( $param['echo'] ) {
454
- wp_send_json( array( 'result' => $response ) );
455
- } else {
456
- return $response;
457
  }
458
- }
459
 
460
- /**
461
- * need_to_exclude_vat.
462
- *
463
- * @version 4.7.1
464
- * @since 4.6.0
465
- *
466
- * @return bool
467
- */
468
- function need_to_exclude_vat() {
469
- if (
 
470
  (
471
  ( function_exists( 'is_checkout' ) && is_checkout() ) ||
472
  ( function_exists( 'is_cart' ) && is_cart() ) ||
@@ -476,143 +518,154 @@ class WCJ_EU_VAT_Number extends WCJ_Module {
476
  'yes' === wcj_get_option( 'wcj_eu_vat_number_validate', 'yes' ) &&
477
  'yes' === wcj_get_option( 'wcj_eu_vat_number_disable_for_valid', 'yes' ) &&
478
  (
479
- ( true === wcj_session_get( 'wcj_is_eu_vat_number_valid' ) && null !== ( $eu_vat_number = wcj_session_get( 'wcj_eu_vat_number_to_check' ) ) ) ||
480
- ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_disable_for_valid_by_user_vat', 'no' ) && is_user_logged_in() && ! empty( $eu_vat_number = get_user_meta( get_current_user_id(), 'billing_eu_vat_number', true ) ) && '1' === $this->wcj_validate_eu_vat_number( array( 'wcj_eu_vat_number_to_check' => $eu_vat_number, 'echo' => false ) ) )
 
 
 
 
 
481
  )
482
- ) {
483
- $preserve_base_country_check_passed = true;
484
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_eu_vat_number_preserve_in_base_country', 'no' ) ) ) {
485
- $location = wc_get_base_location();
486
- if ( empty( $location['country'] ) ) {
487
- $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', wcj_get_option( 'woocommerce_default_country' ) ) );
 
 
 
 
 
 
488
  }
489
- $selected_country = substr( $eu_vat_number, 0, 2 );
490
- if ( 'EL' === $selected_country ) {
491
- $selected_country = 'GR';
 
492
  }
493
- $preserve_base_country_check_passed = ( strtoupper( $location['country'] ) !== strtoupper( $selected_country ) );
494
- }
495
- if ( $preserve_base_country_check_passed ) {
496
- return true;
497
  } else {
498
- return false;
499
- }
500
- } else {
501
- if ( ! function_exists( 'WC' ) || ! empty( WC()->customer ) ) {
502
- return false;
503
  }
 
504
  }
505
- return false;
506
- }
507
 
508
- /**
509
- * maybe_exclude_vat.
510
- *
511
- * @version 4.6.0
512
- */
513
- function maybe_exclude_vat() {
514
- if ( $this->need_to_exclude_vat() ) {
515
- WC()->customer->set_is_vat_exempt( true );
516
- } else {
517
- if ( ! empty( WC()->customer ) ) {
518
- WC()->customer->set_is_vat_exempt( false );
 
519
  }
520
  }
521
- }
522
 
523
- /**
524
- * checkout_validate_vat.
525
- *
526
- * @version 5.5.0
527
- */
528
- function checkout_validate_vat( $_posted ) {
529
- $skip_country = wcj_get_option( 'wcj_eu_vat_number_advanced_skip_countries', 'no' );
530
- $skip_country = explode(',', $skip_country);
531
-
532
- if(!in_array($_posted['billing_country'],$skip_country))
533
- {
534
- if ('yes' === wcj_get_option( 'wcj_eu_vat_number_field_required', 'no' ) && '' == $_posted['billing_eu_vat_number'] ){
535
- if( in_array( $_posted['billing_country'] , wcj_get_european_union_countries() ) ) {
536
- wc_add_notice(
537
- __( '<strong>Billing EU VAT Number</strong>is a required field.', 'woocommerce-jetpack' ),
538
- 'error'
539
- );
540
- }
541
- }
542
- if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) {
543
- if (
544
- ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_field_required', 'no' ) && '' == $_posted['billing_eu_vat_number'] ) ||
545
- (
546
- '' != $_posted['billing_eu_vat_number'] ) &&
547
- '1' !== $this->wcj_validate_eu_vat_number( array( 'wcj_eu_vat_number_to_check' => $_posted['billing_eu_vat_number'], 'echo' => false )
548
- )
549
- ) {
550
- if( in_array( $_posted['billing_country'] , wcj_get_european_union_countries() ) ) {
551
  wc_add_notice(
552
- get_option( 'wcj_eu_vat_number_not_valid_message' , __( '<strong>EU VAT Number</strong> is not valid.', 'woocommerce-jetpack' ) ),
553
  'error'
554
  );
555
  }
556
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
557
  }
558
  }
559
- }
560
 
561
- /**
562
- * add_billing_eu_vat_number_field_to_admin_order_display.
563
- *
564
- * @version 4.6.0
565
- */
566
- function add_billing_eu_vat_number_field_to_admin_order_display( $fields ) {
567
- $vat_number = '';
568
-
569
- $fields[ $this->id ] = array(
570
- 'type' => 'text',
571
- 'label' => wcj_get_option( 'wcj_eu_vat_number_field_label' ),
572
- 'show' => true
573
- );
574
-
575
- // Try to read meta from 'vat_number' if '_billing_eu_vat_number' is empty
576
- if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_read_vat_number_meta', 'no' ) ) {
577
- global $post;
578
- $order = wc_get_order( $post->ID );
579
- if ( is_a( $order, 'WC_Order' ) ) {
580
- $metas = array( '_billing_eu_vat_number', '_vat_number', '_billing_vat_number' );
581
- foreach ( $metas as $meta ) {
582
- $vat_number = get_post_meta( $order->get_id(), $meta, true );
583
- if ( ! empty( $vat_number ) ) {
584
- break;
 
 
585
  }
 
586
  }
587
- $fields[ $this->id ]['value'] = $vat_number;
588
  }
 
 
589
  }
590
 
591
- return $fields;
592
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
593
 
594
- /**
595
- * add_eu_vat_number_checkout_field_to_frontend.
596
- *
597
- * @version 5.3.7
598
- */
599
- function add_eu_vat_number_checkout_field_to_frontend( $fields ) {
600
- $fields['billing'][ 'billing_' . $this->id ] = array(
601
- 'type' => 'text',
602
- 'label' => wcj_get_option( 'wcj_eu_vat_number_field_label' ),
603
- 'description' => wcj_get_option( 'wcj_eu_vat_number_field_description' ),
604
- 'placeholder' => wcj_get_option( 'wcj_eu_vat_number_field_placeholder' ),
605
- //'required' => ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_field_required', 'no' ) ),
606
- 'custom_attributes' => array(),
607
- 'clear' => ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_field_clear', 'yes' ) ),
608
- 'class' => array( wcj_get_option( 'wcj_eu_vat_number_field_class', 'form-row-wide' ) ),
609
- 'validate' => ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) ? array( 'eu-vat-number' ) : array(),
610
- );
611
- return $fields;
612
  }
613
 
614
- }
615
-
616
  endif;
617
 
618
- return new WCJ_EU_VAT_Number();
5
  * @version 5.5.9
6
  * @since 2.3.9
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_EU_VAT_Number' ) ) :
 
 
 
16
  /**
17
+ * WCJ_EU_VAT_Number.
 
 
 
18
  */
19
+ class WCJ_EU_VAT_Number extends WCJ_Module {
20
+
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.3.7
25
+ * @todo [feature] add option to add "Verify" button to frontend
26
+ */
27
+ public function __construct() {
28
+
29
+ $this->id = 'eu_vat_number';
30
+ $this->short_desc = __( 'EU VAT Number', 'woocommerce-jetpack' );
31
+ $this->desc = __( 'Collect and validate EU VAT numbers on the checkout. Automatically disable VAT for valid numbers. Add all EU countries VAT standard rates to WooCommerce. Show VAT field for EU countries only (Plus). Check for IP Location Country (Plus)', 'woocommerce-jetpack' );
32
+ $this->desc_pro = __( 'Collect and validate EU VAT numbers on the checkout. Automatically disable VAT for valid numbers. Add all EU countries VAT standard rates to WooCommerce.', 'woocommerce-jetpack' );
33
+ $this->link_slug = 'woocommerce-eu-vat-number';
34
+ parent::__construct();
35
+
36
+ $this->add_tools(
37
+ array(
38
+ 'eu_countries_vat_rates' => array(
39
+ 'title' => __( 'EU Countries VAT Rates', 'woocommerce-jetpack' ),
40
+ 'desc' => __( 'Add all EU countries VAT standard rates to WooCommerce.', 'woocommerce-jetpack' ),
41
+ ),
42
+ )
43
+ );
44
+
45
+ if ( $this->is_enabled() ) {
46
+ add_action( 'init', array( $this, 'start_session' ) );
47
+ add_filter( 'woocommerce_checkout_fields', array( $this, 'add_eu_vat_number_checkout_field_to_frontend' ), PHP_INT_MAX );
48
+ add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_billing_eu_vat_number_field_to_admin_order_display' ), PHP_INT_MAX );
49
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
50
+ add_action( 'wp_ajax_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
51
+ add_action( 'wp_ajax_nopriv_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
52
+ add_filter( 'wp', array( $this, 'maybe_exclude_vat' ), PHP_INT_MAX );
53
+ add_filter( 'woocommerce_cart_tax_totals', array( $this, 'maybe_remove_tax_totals' ), 1 );
54
+ add_filter( 'woocommerce_calculated_total', array( $this, 'maybe_recalculate_tax_totals' ), 1, 2 );
55
+ add_action( 'woocommerce_after_checkout_validation', array( $this, 'checkout_validate_vat' ), PHP_INT_MAX );
56
+ add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_eu_vat_number_customer_meta_field' ) );
57
+ add_filter( 'default_checkout_billing_eu_vat_number', array( $this, 'add_default_checkout_billing_eu_vat_number' ), PHP_INT_MAX, 2 );
58
+
59
+ if ( 'after_order_table' === wcj_get_option( 'wcj_eu_vat_number_display_position', 'after_order_table' ) ) {
60
+ add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
61
+ add_action( 'woocommerce_email_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
62
+ } else {
63
+ add_filter( 'woocommerce_order_formatted_billing_address', array( $this, 'add_eu_vat_number_to_order_billing_address' ), PHP_INT_MAX, 2 );
64
+ add_filter( 'woocommerce_my_account_my_address_formatted_address', array( $this, 'add_eu_vat_number_to_my_account_billing_address' ), PHP_INT_MAX, 3 );
65
+ add_filter( 'woocommerce_localisation_address_formats', array( $this, 'add_eu_vat_number_to_address_formats' ) );
66
+ add_filter( 'woocommerce_formatted_address_replacements', array( $this, 'replace_eu_vat_number_in_address_formats' ), PHP_INT_MAX, 2 );
67
+ }
68
 
69
+ $this->eu_countries_vat_rates_tool = include_once 'tools/class-wcj-eu-countries-vat-rates-tool.php';
70
 
71
+ // EU VAT number summary on order edit page.
72
+ if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_add_order_edit_metabox', 'no' ) ) {
73
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
74
+ // "Validate VAT and remove taxes" button.
75
+ add_action( 'admin_init', array( $this, 'admin_validate_vat_and_maybe_remove_taxes' ), PHP_INT_MAX );
76
+ }
77
 
78
+ // Admin order edit - "Load billing address" button.
79
+ add_filter( 'woocommerce_ajax_get_customer_details', array( $this, 'add_billing_eu_vat_number_to_ajax_get_customer_details' ), PHP_INT_MAX, 3 );
80
+ }
81
  }
 
82
 
83
+ /**
84
+ * Maybe_recalculate_tax_totals.
85
+ *
86
+ * @version 4.6.0
87
+ * @since 4.6.0
88
+ *
89
+ * @see https://gist.github.com/TimBHowe/fe9418b9224d8b8cb339
90
+ * @param int $total defines the total.
91
+ * @param array $cart defines the cart.
92
+ *
93
+ * @return mixed
94
+ */
95
+ public function maybe_recalculate_tax_totals( $total, $cart ) {
96
+ if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_disable_for_valid_on_cart', 'no' ) && $this->need_to_exclude_vat() ) {
97
+ return $total - $cart->get_taxes_total();
98
+ }
99
+ return $total;
100
  }
 
 
101
 
102
+ /**
103
+ * Maybe_remove_tax_totals.
104
+ *
105
+ * @version 4.6.0
106
+ * @since 4.6.0
107
+ *
108
+ * @see https://gist.github.com/TimBHowe/fe9418b9224d8b8cb339
109
+ * @param int | array $tax_totals defines the tax_totals.
110
+ * @return array
111
+ */
112
+ public function maybe_remove_tax_totals( $tax_totals ) {
113
+ if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_disable_for_valid_on_cart', 'no' ) && $this->need_to_exclude_vat() ) {
114
+ $tax_totals = array();
115
+ }
116
+ return $tax_totals;
117
  }
 
 
118
 
119
+ /**
120
+ * Admin_validate_vat_and_maybe_remove_taxes.
121
+ *
122
+ * @version 3.3.0
123
+ * @since 3.3.0
124
+ */
125
+ public function admin_validate_vat_and_maybe_remove_taxes() {
126
+ if ( isset( $_GET['validate_vat_and_maybe_remove_taxes'] ) ) {
127
+ $order_id = $_GET['validate_vat_and_maybe_remove_taxes'];
128
+ $order = wc_get_order( $order_id );
129
+ if ( $order ) {
130
+ $vat_id = get_post_meta( $order_id, '_billing_eu_vat_number', true );
131
+ if ( '' !== $vat_id && strlen( $vat_id ) > 2 ) {
132
+ if ( wcj_validate_vat( substr( $vat_id, 0, 2 ), substr( $vat_id, 2 ) ) ) {
133
+ foreach ( $order->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) {
134
+ $item->set_taxes( false );
135
+ }
136
+ foreach ( $order->get_shipping_methods() as $item_id => $item ) {
137
+ $item->set_taxes( false );
138
+ }
139
+ $order->update_taxes();
140
+ $order->calculate_totals( false );
141
  }
 
 
142
  }
143
  }
144
+ wp_safe_redirect( esc_url( remove_query_arg( 'validate_vat_and_maybe_remove_taxes' ) ) );
145
+ exit;
146
  }
 
 
147
  }
 
 
 
 
 
 
 
 
 
 
 
 
148
 
149
+ /**
150
+ * Add_billing_eu_vat_number_to_ajax_get_customer_details.
151
+ *
152
+ * @version 3.3.0
153
+ * @since 3.3.0
154
+ * @param array $data defines the data.
155
+ * @param string | array $customer defines the customer.
156
+ * @param int $user_id defines the user_id.
157
+ */
158
+ public function add_billing_eu_vat_number_to_ajax_get_customer_details( $data, $customer, $user_id ) {
159
+ $data['billing']['eu_vat_number'] = get_user_meta( $user_id, 'billing_eu_vat_number', true );
160
+ return $data;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  }
162
 
163
+ /**
164
+ * Add_meta_box.
165
+ *
166
+ * @version 2.6.0
167
+ * @since 2.6.0
168
+ */
169
+ public function add_meta_box() {
170
+ $screen = ( isset( $this->meta_box_screen ) ) ? $this->meta_box_screen : 'shop_order';
171
+ $context = ( isset( $this->meta_box_context ) ) ? $this->meta_box_context : 'side';
172
+ $priority = ( isset( $this->meta_box_priority ) ) ? $this->meta_box_priority : 'low';
173
+ add_meta_box(
174
+ 'wc-jetpack-' . $this->id,
175
+ __( 'Booster', 'woocommerce-jetpack' ) . ': ' . $this->short_desc,
176
+ array( $this, 'create_meta_box' ),
177
+ $screen,
178
+ $context,
179
+ $priority
180
+ );
181
  }
182
 
183
+ /**
184
+ * Create_meta_box.
185
+ *
186
+ * @version 5.5.9
187
+ * @since 2.6.0
188
+ */
189
+ public function create_meta_box() {
190
+ $order_id = get_the_ID();
191
+ $_order = wc_get_order( $order_id );
192
+ $_customer_ip_address = ( WCJ_IS_WC_VERSION_BELOW_3 ? $_order->customer_ip_address : $_order->get_customer_ip_address() );
193
+
194
+ // Country by IP.
195
+ if ( class_exists( 'WC_Geolocation' ) ) {
196
+ // Get the country by IP.
197
+ $location = WC_Geolocation::geolocate_ip( $_customer_ip_address );
198
+ // Base fallback.
199
+ if ( empty( $location['country'] ) ) {
200
+ $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', wcj_get_option( 'woocommerce_default_country' ) ) );
201
+ }
202
+ $customer_country = ( isset( $location['country'] ) ) ? $location['country'] : '';
203
+ } else {
204
+ $customer_country = '';
205
  }
 
206
 
207
+ // Customer EU VAT number.
208
+ $customer_eu_vat_number = get_post_meta( $order_id, '_billing_eu_vat_number', true );
209
+ if ( '' === $customer_eu_vat_number ) {
210
+ $customer_eu_vat_number = '-';
211
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
212
 
213
+ // Taxes.
214
+ $taxes = '';
215
+ $taxes_array = $_order->get_tax_totals();
216
+ if ( empty( $taxes_array ) ) {
217
+ $taxes = '-';
218
+ } else {
219
+ foreach ( $taxes_array as $tax ) {
220
+ $taxes .= $tax->label . ': ' . $tax->formatted_amount . '<br>';
221
+ }
222
+ }
 
223
 
224
+ // Results table.
225
+ $table_data = array(
226
+ array(
227
+ __( 'Customer IP', 'woocommerce-jetpack' ),
228
+ $_customer_ip_address,
229
+ ),
230
+ array(
231
+ __( 'Country by IP', 'woocommerce-jetpack' ),
232
+ wcj_get_country_flag_by_code( $customer_country ) . ' ' . wcj_get_country_name_by_code( $customer_country ) . ' [' . $customer_country . ']',
233
+ ),
234
+ array(
235
+ __( 'Customer EU VAT Number', 'woocommerce-jetpack' ),
236
+ $customer_eu_vat_number,
237
+ ),
238
+ array(
239
+ __( 'Taxes', 'woocommerce-jetpack' ),
240
+ $taxes,
241
+ ),
242
+ );
243
+ echo wp_kses_post(
244
+ wcj_get_table_html(
245
+ $table_data,
246
+ array(
247
+ 'table_class' => 'widefat striped',
248
+ 'table_heading_type' => 'vertical',
249
+ )
250
+ )
251
+ );
252
+ echo '<p><a href="' . esc_url( add_query_arg( 'validate_vat_and_maybe_remove_taxes', $order_id ) ) . '">' .
253
+ wp_kses_post( 'Validate VAT and remove taxes', 'woocommerce-jetpack' ) . '</a></p>';
254
  }
 
 
255
 
256
+ /**
257
+ * Replace_eu_vat_number_in_address_formats.
258
+ *
259
+ * @version 2.5.2
260
+ * @since 2.5.2
261
+ * @param string $replacements defines the replacements.
262
+ * @param string | array $args defines the args.
263
+ */
264
+ public function replace_eu_vat_number_in_address_formats( $replacements, $args ) {
265
+ $field_name = 'billing_' . $this->id;
266
+ $replacements[ '{' . $field_name . '}' ] = ( isset( $args[ $field_name ] ) ) ? $args[ $field_name ] : '';
267
+ return $replacements;
268
  }
 
 
269
 
270
+ /**
271
+ * Add_eu_vat_number_to_address_formats.
272
+ *
273
+ * @version 2.5.2
274
+ * @since 2.5.2
275
+ * @param array $address_formats defines the address_formats.
276
+ */
277
+ public function add_eu_vat_number_to_address_formats( $address_formats ) {
278
+ $field_name = 'billing_' . $this->id;
279
+ $modified_address_formats = array();
280
+ foreach ( $address_formats as $country => $address_format ) {
281
+ $modified_address_formats[ $country ] = $address_format . "\n{" . $field_name . '}';
282
+ }
283
+ return $modified_address_formats;
284
+ }
285
 
286
+ /**
287
+ * Add_eu_vat_number_to_my_account_billing_address.
288
+ *
289
+ * @version 2.5.2
290
+ * @since 2.5.2
291
+ * @param array $fields defines the fields.
292
+ * @param int $customer_id defines the customer_id.
293
+ * @param string $name defines the name.
294
+ */
295
+ public function add_eu_vat_number_to_my_account_billing_address( $fields, $customer_id, $name ) {
296
+ if ( 'billing' === $name ) {
297
+ $field_name = 'billing_' . $this->id;
298
+ $fields[ $field_name ] = get_user_meta( $customer_id, $field_name, true );
299
+ }
300
+ return $fields;
301
  }
 
 
302
 
303
+ /**
304
+ * Add_eu_vat_number_to_order_billing_address.
305
+ *
306
+ * @version 2.7.0
307
+ * @since 2.5.2
308
+ * @param array $fields defines the fields.
309
+ * @param string | array $_order defines the _order.
310
+ */
311
+ public function add_eu_vat_number_to_order_billing_address( $fields, $_order ) {
312
+ $field_name = 'billing_' . $this->id;
313
+ $fields[ $field_name ] = get_post_meta( wcj_get_order_id( $_order ), '_' . $field_name, true );
314
+ return $fields;
315
+ }
316
 
317
+ /**
318
+ * Add_eu_vat_number_to_order_display.
319
+ *
320
+ * @version 3.2.2
321
+ * @since 2.4.7
322
+ * @param array | string | int $order defines the order.
323
+ */
324
+ public function add_eu_vat_number_to_order_display( $order ) {
325
+ $order_id = wcj_get_order_id( $order );
326
+ $html = '';
327
+ $option_name = '_billing_' . $this->id;
328
+ $the_eu_vat_number = get_post_meta( $order_id, $option_name, true );
329
+ if ( '' !== $the_eu_vat_number ) {
330
+ $the_label = wcj_get_option( 'wcj_eu_vat_number_field_label', __( 'EU VAT Number', 'woocommerce-jetpack' ) );
331
+ $html .= '<p><strong>' . $the_label . '</strong>: ' . $the_eu_vat_number . '</p>';
332
  }
333
+ echo wp_kses_post( $html );
334
  }
 
 
335
 
336
+ /**
337
+ * Create_eu_countries_vat_rates_tool.
338
+ *
339
+ * @version 2.3.10
340
+ * @since 2.3.10
341
+ */
342
+ public function create_eu_countries_vat_rates_tool() {
343
+ return $this->eu_countries_vat_rates_tool->create_eu_countries_vat_rates_tool( $this->get_tool_header_html( 'eu_countries_vat_rates' ) );
 
 
 
 
 
 
 
 
 
 
 
344
  }
345
+
346
+ /**
347
+ * Add_default_checkout_billing_eu_vat_number.
348
+ *
349
+ * @version 4.3.0
350
+ * @param string | int $default_value defines the default_value.
351
+ * @param string | int $field_key defines the field_key.
352
+ */
353
+ public function add_default_checkout_billing_eu_vat_number( $default_value, $field_key ) {
354
+ $current_user = wp_get_current_user();
355
+ $meta = get_user_meta( $current_user->ID, 'billing_eu_vat_number', true );
356
+ $eu_vat_number_to_check = wcj_session_get( 'wcj_eu_vat_number_to_check' );
357
+ if ( '' !== ( $eu_vat_number_to_check ) ) {
358
+ return $eu_vat_number_to_check;
359
+ } elseif ( is_user_logged_in() ) {
360
+ if ( $meta ) {
361
+ return $meta;
362
+ }
363
  }
364
+ return $default_value;
365
  }
 
366
 
367
+ /**
368
+ * Add_eu_vat_number_customer_meta_field.
369
+ *
370
+ * @param array $fields defines the fields.
371
+ */
372
+ public function add_eu_vat_number_customer_meta_field( $fields ) {
373
+ $fields['billing']['fields']['billing_eu_vat_number'] = array(
374
+ 'label' => wcj_get_option( 'wcj_eu_vat_number_field_label' ),
375
+ 'description' => '',
376
+ );
377
+ return $fields;
378
  }
379
+
380
+ /**
381
+ * Start_session.
382
+ *
383
+ * @version 4.9.0
384
+ */
385
+ public function start_session() {
386
+ if ( is_admin() ) {
387
+ return;
388
+ }
389
+ wcj_session_maybe_start();
390
+ $args = array();
391
+ if ( isset( $_POST['post_data'] ) ) {
392
+ parse_str( $_POST['post_data'], $args );
393
+ if ( isset( $args['billing_eu_vat_number'] ) && wcj_session_get( 'wcj_eu_vat_number_to_check' ) !== $args['billing_eu_vat_number'] ) {
394
+ wcj_session_set( 'wcj_is_eu_vat_number_valid', null );
395
+ wcj_session_set( 'wcj_eu_vat_number_to_check', null );
396
+ }
397
+ }
398
+ }
399
+
400
+ /**
401
+ * Restrictive_loading_valid.
402
+ *
403
+ * @version 4.9.0
404
+ * @since 4.9.0
405
+ *
406
+ * @return bool
407
+ */
408
+ public function restrictive_loading_valid() {
409
+ $restrictive_loading_conditions = wcj_get_option( 'wcj_eu_vat_number_restrictive_loading', array() );
410
+ if ( empty( $restrictive_loading_conditions ) ) {
411
  return true;
412
  }
413
+ foreach ( $restrictive_loading_conditions as $condition ) {
414
+ if ( $condition() ) {
415
+ return true;
416
+ }
417
+ }
418
+ return false;
419
  }
 
 
420
 
421
+ /**
422
+ * Enqueue_scripts.
423
+ *
424
+ * @version 5.4.5
425
+ */
426
+ public function enqueue_scripts() {
427
+ if (
428
+ 'no' === wcj_get_option( 'wcj_eu_vat_number_validate', 'yes' ) && 'no' === wcj_get_option( 'wcj_eu_vat_number_field_required', 'yes' ) ||
429
  ! $this->restrictive_loading_valid()
430
+ ) {
431
+ return;
432
+ }
433
+ wp_enqueue_script( 'wcj-eu-vat-number', wcj_plugin_url() . '/includes/js/wcj-eu-vat-number.js', array(), w_c_j()->version, true );
434
+ wp_localize_script(
435
+ 'wcj-eu-vat-number',
436
+ 'ajax_object',
437
+ array(
438
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
439
+ 'eu_countries' => wcj_get_european_union_countries(),
440
+ 'show_vat_field_for_eu_only' => wcj_get_option( 'wcj_eu_vat_number_show_vat_field_for_eu_only', 'no' ),
441
+ 'is_vat_field_required_for_eu_only' => wcj_get_option( 'wcj_eu_vat_number_field_required', 'no' ),
442
+ 'add_progress_text' => wcj_get_option( 'wcj_eu_vat_number_add_progress_text', 'no' ),
443
+ 'progress_text_validating' => do_shortcode( wcj_get_option( 'wcj_eu_vat_number_progress_text_validating', __( 'Validating VAT. Please wait...', 'woocommerce-jetpack' ) ) ),
444
+ 'progress_text_valid' => do_shortcode( wcj_get_option( 'wcj_eu_vat_number_progress_text_valid', __( 'VAT is valid.', 'woocommerce-jetpack' ) ) ),
445
+ 'progress_text_not_valid' => do_shortcode( wcj_get_option( 'wcj_eu_vat_number_progress_text_not_valid', __( 'VAT is not valid.', 'woocommerce-jetpack' ) ) ),
446
+ 'progress_text_validation_failed' => do_shortcode( wcj_get_option( 'wcj_eu_vat_number_progress_text_validation_failed', __( 'Validation failed. Please try again.', 'woocommerce-jetpack' ) ) ),
447
+ )
448
+ );
449
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
450
 
451
+ /**
452
+ * Wcj_validate_eu_vat_number.
453
+ *
454
+ * @version 4.6.1
455
+ * @param array $param defines the param.
456
+ */
457
+ public function wcj_validate_eu_vat_number( $param ) {
458
+ $param = wp_parse_args(
459
+ $param,
460
+ array(
461
+ 'wcj_eu_vat_number_to_check' => '',
462
+ 'echo' => true,
463
+ )
464
+ );
465
+ $eu_vat_number = isset( $param['wcj_eu_vat_number_to_check'] ) && '' != $param['wcj_eu_vat_number_to_check'] ? $param['wcj_eu_vat_number_to_check'] : '';
466
+ $eu_vat_number = empty( $eu_vat_number ) && isset( $_POST['wcj_eu_vat_number_to_check'] ) && '' != $_POST['wcj_eu_vat_number_to_check'] ? $_POST['wcj_eu_vat_number_to_check'] : $eu_vat_number;
467
+ if ( ! empty( $eu_vat_number ) ) {
468
+ $eu_vat_number_to_check = substr( $eu_vat_number, 2 );
469
+ $eu_vat_number_country_to_check = substr( $eu_vat_number, 0, 2 );
470
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_eu_vat_number_check_ip_location_country', 'no' ) ) ) {
471
+ $location = WC_Geolocation::geolocate_ip();
472
+ if ( empty( $location['country'] ) ) {
473
+ $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', wcj_get_option( 'woocommerce_default_country' ) ) );
474
+ }
475
+ $is_valid = ( $location['country'] === $eu_vat_number_country_to_check ) ?
476
  wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check ) :
477
  false;
478
+ } else {
479
+ $is_valid = wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check );
480
+ }
481
  } else {
482
+ $is_valid = null;
483
+ }
484
+ wcj_session_set( 'wcj_is_eu_vat_number_valid', $is_valid );
485
+ wcj_session_set( 'wcj_eu_vat_number_to_check', $eu_vat_number );
486
+ $response = '3';
487
+ if ( false === $is_valid ) {
488
+ $response = '0';
489
+ } elseif ( true === $is_valid ) {
490
+ $response = '1';
491
+ } elseif ( null === $is_valid ) {
492
+ $response = '2';
493
+ }
494
+ if ( $param['echo'] ) {
495
+ wp_send_json( array( 'result' => $response ) );
496
+ } else {
497
+ return $response;
498
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
499
  }
 
500
 
501
+ /**
502
+ * Need_to_exclude_vat.
503
+ *
504
+ * @version 4.7.1
505
+ * @since 4.6.0
506
+ *
507
+ * @return bool
508
+ */
509
+ public function need_to_exclude_vat() {
510
+ $eu_vat_number = wcj_session_get( 'wcj_eu_vat_number_to_check' );
511
+ if (
512
  (
513
  ( function_exists( 'is_checkout' ) && is_checkout() ) ||
514
  ( function_exists( 'is_cart' ) && is_cart() ) ||
518
  'yes' === wcj_get_option( 'wcj_eu_vat_number_validate', 'yes' ) &&
519
  'yes' === wcj_get_option( 'wcj_eu_vat_number_disable_for_valid', 'yes' ) &&
520
  (
521
+ ( true === wcj_session_get( 'wcj_is_eu_vat_number_valid' ) && null !== ( $eu_vat_number ) ) ||
522
+ ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_disable_for_valid_by_user_vat', 'no' ) && is_user_logged_in() && ! empty( $eu_vat_number = get_user_meta( get_current_user_id(), 'billing_eu_vat_number', true ) ) && '1' === $this->wcj_validate_eu_vat_number(
523
+ array(
524
+ 'wcj_eu_vat_number_to_check' => $eu_vat_number,
525
+ 'echo' => false,
526
+ )
527
+ ) )
528
  )
529
+ ) {
530
+ $preserve_base_country_check_passed = true;
531
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_eu_vat_number_preserve_in_base_country', 'no' ) ) ) {
532
+ $location = wc_get_base_location();
533
+ if ( empty( $location['country'] ) ) {
534
+ $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', wcj_get_option( 'woocommerce_default_country' ) ) );
535
+ }
536
+ $selected_country = substr( $eu_vat_number, 0, 2 );
537
+ if ( 'EL' === $selected_country ) {
538
+ $selected_country = 'GR';
539
+ }
540
+ $preserve_base_country_check_passed = ( strtoupper( $location['country'] ) !== strtoupper( $selected_country ) );
541
  }
542
+ if ( $preserve_base_country_check_passed ) {
543
+ return true;
544
+ } else {
545
+ return false;
546
  }
 
 
 
 
547
  } else {
548
+ if ( ! function_exists( 'WC' ) || ! empty( WC()->customer ) ) {
549
+ return false;
550
+ }
 
 
551
  }
552
+ return false;
553
  }
 
 
554
 
555
+ /**
556
+ * Maybe_exclude_vat.
557
+ *
558
+ * @version 4.6.0
559
+ */
560
+ public function maybe_exclude_vat() {
561
+ if ( $this->need_to_exclude_vat() ) {
562
+ WC()->customer->set_is_vat_exempt( true );
563
+ } else {
564
+ if ( ! empty( WC()->customer ) ) {
565
+ WC()->customer->set_is_vat_exempt( false );
566
+ }
567
  }
568
  }
 
569
 
570
+ /**
571
+ * Checkout_validate_vat.
572
+ *
573
+ * @version 5.5.0
574
+ * @param array $_posted defines the _posted.
575
+ */
576
+ public function checkout_validate_vat( $_posted ) {
577
+ $skip_country = wcj_get_option( 'wcj_eu_vat_number_advanced_skip_countries', 'no' );
578
+ $skip_country = explode( ',', $skip_country );
579
+
580
+ if ( ! in_array( $_posted['billing_country'], $skip_country, true ) ) {
581
+ if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_field_required', 'no' ) && '' === $_posted['billing_eu_vat_number'] ) {
582
+ if ( in_array( $_posted['billing_country'], wcj_get_european_union_countries(), true ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
583
  wc_add_notice(
584
+ __( '<strong>Billing EU VAT Number</strong>is a required field.', 'woocommerce-jetpack' ),
585
  'error'
586
  );
587
  }
588
  }
589
+ if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) {
590
+ if (
591
+ ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_field_required', 'no' ) && '' === $_posted['billing_eu_vat_number'] ) ||
592
+ (
593
+ '' !== $_posted['billing_eu_vat_number'] ) &&
594
+ '1' !== $this->wcj_validate_eu_vat_number(
595
+ array(
596
+ 'wcj_eu_vat_number_to_check' => $_posted['billing_eu_vat_number'],
597
+ 'echo' => false,
598
+ )
599
+ )
600
+ ) {
601
+ if ( in_array( $_posted['billing_country'], wcj_get_european_union_countries(), true ) ) {
602
+ wc_add_notice(
603
+ get_option( 'wcj_eu_vat_number_not_valid_message', __( '<strong>EU VAT Number</strong> is not valid.', 'woocommerce-jetpack' ) ),
604
+ 'error'
605
+ );
606
+ }
607
+ }
608
+ }
609
  }
610
  }
 
611
 
612
+ /**
613
+ * Add_billing_eu_vat_number_field_to_admin_order_display.
614
+ *
615
+ * @version 4.6.0
616
+ * @param array $fields defines the fields.
617
+ */
618
+ public function add_billing_eu_vat_number_field_to_admin_order_display( $fields ) {
619
+ $vat_number = '';
620
+
621
+ $fields[ $this->id ] = array(
622
+ 'type' => 'text',
623
+ 'label' => wcj_get_option( 'wcj_eu_vat_number_field_label' ),
624
+ 'show' => true,
625
+ );
626
+
627
+ // Try to read meta from 'vat_number' if '_billing_eu_vat_number' is empty.
628
+ if ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_read_vat_number_meta', 'no' ) ) {
629
+ global $post;
630
+ $order = wc_get_order( $post->ID );
631
+ if ( is_a( $order, 'WC_Order' ) ) {
632
+ $metas = array( '_billing_eu_vat_number', '_vat_number', '_billing_vat_number' );
633
+ foreach ( $metas as $meta ) {
634
+ $vat_number = get_post_meta( $order->get_id(), $meta, true );
635
+ if ( ! empty( $vat_number ) ) {
636
+ break;
637
+ }
638
  }
639
+ $fields[ $this->id ]['value'] = $vat_number;
640
  }
 
641
  }
642
+
643
+ return $fields;
644
  }
645
 
646
+ /**
647
+ * Add_eu_vat_number_checkout_field_to_frontend.
648
+ *
649
+ * @version 5.3.
650
+ * @param array $fields defines the fields.
651
+ */
652
+ public function add_eu_vat_number_checkout_field_to_frontend( $fields ) {
653
+ $fields['billing'][ 'billing_' . $this->id ] = array(
654
+ 'type' => 'text',
655
+ 'label' => wcj_get_option( 'wcj_eu_vat_number_field_label' ),
656
+ 'description' => wcj_get_option( 'wcj_eu_vat_number_field_description' ),
657
+ 'placeholder' => wcj_get_option( 'wcj_eu_vat_number_field_placeholder' ),
658
+
659
+ 'custom_attributes' => array(),
660
+ 'clear' => ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_field_clear', 'yes' ) ),
661
+ 'class' => array( wcj_get_option( 'wcj_eu_vat_number_field_class', 'form-row-wide' ) ),
662
+ 'validate' => ( 'yes' === wcj_get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) ? array( 'eu-vat-number' ) : array(),
663
+ );
664
+ return $fields;
665
+ }
666
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
667
  }
668
 
 
 
669
  endif;
670
 
671
+ return new WCJ_EU_VAT_Number();
includes/class-wcj-export-import.php CHANGED
@@ -5,368 +5,395 @@
5
  * @version 5.5.9
6
  * @since 2.5.4
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Export_Import' ) ) :
13
-
14
- class WCJ_Export_Import extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.4.0
20
- * @since 2.5.4
21
- * @todo [feature] import products, customers and (maybe) orders
22
  */
23
- function __construct() {
24
 
25
- $this->id = 'export';
26
- $this->short_desc = __( 'Export', 'woocommerce-jetpack' );
27
- $this->desc = __( 'WooCommerce export tools. Additional export fields (1 field allowed in free version).', 'woocommerce-jetpack' );
28
- $this->desc_pro = sprintf( __( 'WooCommerce export tools. Check and use the shortcodes from <a href="%s" target=\'blank\'>here</a>', 'woocommerce-jetpack' ), 'https://booster.io/category/shortcodes/' );
29
- $this->link_slug = 'woocommerce-export-tools';
30
- parent::__construct();
 
 
31
 
32
- $this->add_tools( array(
33
- 'export_customers' => array(
34
- 'title' => __( 'Export Customers', 'woocommerce-jetpack' ),
35
- 'desc' => __( 'Export Customers.', 'woocommerce-jetpack' ),
36
- ),
37
- 'export_customers_from_orders' => array(
38
- 'title' => __( 'Export Customers from Orders', 'woocommerce-jetpack' ),
39
- 'desc' => __( 'Export Customers (extracted from orders).', 'woocommerce-jetpack' ) . ' ' .
40
- __( 'Customers are identified by billing email.', 'woocommerce-jetpack' ),
41
- ),
42
- 'export_orders' => array(
43
- 'title' => __( 'Export Orders', 'woocommerce-jetpack' ),
44
- 'desc' => __( 'Export Orders.', 'woocommerce-jetpack' ),
45
- ),
46
- 'export_orders_items' => array(
47
- 'title' => __( 'Export Orders Items', 'woocommerce-jetpack' ),
48
- 'desc' => __( 'Export Orders Items.', 'woocommerce-jetpack' ),
49
- ),
50
- 'export_products' => array(
51
- 'title' => __( 'Export Products', 'woocommerce-jetpack' ),
52
- 'desc' => __( 'Export Products.', 'woocommerce-jetpack' ),
53
- ),
54
- ) );
55
 
56
- $this->fields_helper = require_once( 'export/class-wcj-fields-helper.php' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
- if ( $this->is_enabled() ) {
59
- add_action( 'init', array( $this, 'export_csv' ) );
60
- add_action( 'init', array( $this, 'export_xml' ) );
61
- }
62
- }
63
 
64
- /**
65
- * export.
66
- *
67
- * @version 2.5.9
68
- * @since 2.4.8
69
- * @todo [dev] when filtering now using `strpos`, but other options would be `stripos` (case-insensitive) or strict equality
70
- * @todo [dev] (maybe) do filtering directly in WP_Query
71
- */
72
- function export( $tool_id ) {
73
- $data = array();
74
- switch ( $tool_id ) {
75
- case 'customers':
76
- $exporter = require_once( 'export/class-wcj-exporter-customers.php' );
77
- $data = $exporter->export_customers( $this->fields_helper );
78
- break;
79
- case 'customers_from_orders':
80
- $exporter = require_once( 'export/class-wcj-exporter-customers.php' );
81
- $data = $exporter->export_customers_from_orders( $this->fields_helper );
82
- break;
83
- case 'orders':
84
- $exporter = require_once( 'export/class-wcj-exporter-orders.php' );
85
- $data = $exporter->export_orders( $this->fields_helper );
86
- break;
87
- case 'orders_items':
88
- $exporter = require_once( 'export/class-wcj-exporter-orders.php' );
89
- $data = $exporter->export_orders_items( $this->fields_helper );
90
- break;
91
- case 'products':
92
- $exporter = require_once( 'export/class-wcj-exporter-products.php' );
93
- $data = $exporter->export_products( $this->fields_helper );
94
- break;
95
  }
96
- if ( isset( $_POST['wcj_export_filter_all_columns'] ) && '' != $_POST['wcj_export_filter_all_columns'] ) {
97
- foreach ( $data as $row_id => $row ) {
98
- if ( 0 == $row_id ) {
99
- continue;
100
- }
101
- $is_filtered = false;
102
- foreach ( $row as $cell ) {
103
- if ( false !== strpos( $cell, $_POST['wcj_export_filter_all_columns'] ) ) {
104
- $is_filtered = true;
105
- break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
106
  }
107
- }
108
- if ( ! $is_filtered ) {
109
- unset( $data[ $row_id ] );
110
  }
111
  }
 
112
  }
113
- return $data;
114
- }
115
 
116
- /**
117
- * export_xml.
118
- *
119
- * @version 2.5.9
120
- * @since 2.5.9
121
- * @todo [dev] templates for xml_start, xml_end, xml_item.
122
- * @todo [dev] `strip_tags`
123
- */
124
- function export_xml() {
125
- if ( isset( $_POST['wcj_export_xml'] ) ) {
126
- $data = $this->export( $_POST['wcj_export_xml'] );
127
- if ( is_array( $data ) ) {
128
- $xml = '';
129
- $xml .= '<?xml version = "1.0" encoding = "utf-8" ?>' . PHP_EOL . '<root>' . PHP_EOL;
130
- foreach ( $data as $row_num => $row ) {
131
- if ( 0 == $row_num ) {
 
 
 
 
 
 
132
  foreach ( $row as $cell_id => $cell_value ) {
133
- $cell_ids[ $cell_id ] = sanitize_title_with_dashes( $cell_value );
134
  }
135
- continue;
136
- }
137
- $xml .= '<item>' . PHP_EOL;
138
- foreach ( $row as $cell_id => $cell_value ) {
139
- $xml .= "\t" . '<' . $cell_ids[ $cell_id ] . '>' . $cell_value . '</' . $cell_ids[ $cell_id ] . '>' . PHP_EOL;
140
  }
141
- $xml .= '</item>' . PHP_EOL;
 
 
 
 
 
 
142
  }
143
- $xml .= '</root>';
144
- header( "Content-Disposition: attachment; filename=" . $_POST['wcj_export_xml'] . ".xml" );
145
- header( "Content-Type: Content-Type: text/html; charset=utf-8" );
146
- header( "Content-Description: File Transfer" );
147
- header( "Content-Length: " . strlen( $xml ) );
148
- echo $xml;
149
- die();
150
  }
151
  }
152
- }
153
 
154
- /**
155
- * smart_format_fields.
156
- *
157
- * @see https://stackoverflow.com/a/4617967/1193038
158
- *
159
- * @version 5.1.0
160
- * @since 5.1.0
161
- *
162
- * @param $row
163
- *
164
- * @return array
165
- */
166
- function smart_format_fields( $row ) {
167
- if ( 'no' === wcj_get_option( 'wcj_export_csv_smart_formatting', 'no' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  return $row;
169
  }
170
- $row = array_map( function ( $item ) {
171
- $item = str_replace( '"', '""', $item );
172
- if (
173
- false !== strpos( $item, '"' )
174
- || false !== strpos( $item, ',' )
175
- ) {
176
- $item = '"' . $item . '"';
177
- }
178
- return $item;
179
- }, $row );
180
- return $row;
181
- }
182
 
183
- /**
184
- * export_csv.
185
- *
186
- * @version 5.1.0
187
- * @since 2.4.8
188
- */
189
- function export_csv() {
190
- if ( isset( $_POST['wcj_export'] ) ) {
191
- $data = $this->export( $_POST['wcj_export'] );
192
- if ( is_array( $data ) ) {
193
- $csv = '';
194
- foreach ( $data as $row ) {
195
- $row = $this->smart_format_fields( $row );
196
- $csv .= implode( wcj_get_option( 'wcj_export_csv_separator', ',' ), $row ) . PHP_EOL;
197
- }
198
- if ( 'yes' === wcj_get_option( 'wcj_export_csv_add_utf_8_bom', 'yes' ) ) {
199
- $csv = "\xEF\xBB\xBF" . $csv; // UTF-8 BOM
 
 
 
 
 
 
 
200
  }
201
- header( "Content-Disposition: attachment; filename=" . $_POST['wcj_export'] . ".csv" );
202
- header( "Content-Type: Content-Type: text/html; charset=utf-8" );
203
- header( "Content-Description: File Transfer" );
204
- header( "Content-Length: " . strlen( $csv ) );
205
- echo $csv;
206
- die();
207
  }
208
  }
209
- }
210
 
211
- /**
212
- * export_filter_fields.
213
- *
214
- * @version 2.5.9
215
- * @since 2.5.5
216
- * @todo [dev] filter each field separately
217
- */
218
- function export_filter_fields( $tool_id ) {
219
- $fields = array();
220
- switch ( $tool_id ) {
221
- case 'orders':
222
- $fields = array(
223
- 'wcj_filter_by_order_billing_country' => __( 'Filter by Billing Country', 'woocommerce-jetpack' ),
224
- 'wcj_filter_by_product_title' => __( 'Filter by Product Title', 'woocommerce-jetpack' ),
225
- );
226
- break;
227
- case 'orders_items':
228
- $fields = array(
229
- 'wcj_filter_by_order_billing_country' => __( 'Filter by Billing Country', 'woocommerce-jetpack' ),
230
- );
231
- break;
232
- }
233
- if ( ! empty( $fields ) ) {
234
- $data = array();
235
- foreach( $fields as $field_id => $field_desc ) {
236
- $field_value = ( isset( $_POST[ $field_id ] ) ) ? $_POST[ $field_id ] : '';
 
 
 
 
 
 
237
  $data[] = array(
238
- '<label for="' . $field_id . '">' . $field_desc . '</label>',
239
- '<input name="' . $field_id . '" id="' . $field_id . '" type="text" value="' . $field_value . '">',
 
 
 
 
 
 
 
 
240
  );
241
  }
242
- $data[] = array(
243
- '<button class="button-primary" type="submit" name="wcj_export_filter" value="' . $tool_id . '">' . __( 'Filter', 'woocommerce-jetpack' ) . '</button>',
244
- '',
245
- );
246
- return wcj_get_table_html( $data, array( 'table_class' => 'widefat', 'table_style' => 'width:50%;min-width:300px;', 'table_heading_type' => 'vertical' ) );
247
  }
248
- }
249
 
250
- /**
251
- * export_date_fields.
252
- *
253
- * @version 5.5.9
254
- * @since 3.0.0
255
- * @todo [dev] maybe make `$dateformat` optional
256
- * @todo [dev] mark current (i.e. active) link (if exists)
257
- */
258
- function export_date_fields( $tool_id ) {
259
- $current_start_date = ( isset( $_GET['start_date'] ) ? $_GET['start_date'] : '' );
260
- $current_end_date = ( isset( $_GET['end_date'] ) ? $_GET['end_date'] : '' );
261
- $predefined_ranges = array();
262
- $predefined_ranges[] = '<a href="' . esc_url(add_query_arg( 'range', 'all_time', remove_query_arg( array( 'start_date', 'end_date' ) ) )) . '">' .
 
263
  __( 'All time', 'woocommerce-jetpack' ) . '</a>';
264
- foreach ( array_merge( wcj_get_reports_standard_ranges(), wcj_get_reports_custom_ranges() ) as $range_id => $range_data ) {
265
- $link = esc_url(add_query_arg( array(
266
- 'start_date' => $range_data['start_date'],
267
- 'end_date' => $range_data['end_date'],
268
- 'range' => $range_id,
269
- ) ));
270
- $predefined_ranges[] = '<a href="' . $link . '">' . $range_data['title'] . '</a>';
271
-
272
- }
273
- $predefined_ranges = implode( ' | ', $predefined_ranges );
274
- $dateformat = ' dateformat="yy-mm-dd"';
275
- $date_input_fields = '<form method="get" action="">' .
 
 
 
 
276
  '<input type="hidden" name="page" value="wcj-tools">' .
277
  '<input type="hidden" name="tab" value="export_' . $tool_id . '">' .
278
- '<strong>' . __( 'Custom:', 'woocommerce-jetpack' ) . '</strong>' . ' ' .
279
  '<input name="start_date" id="start_date" type="text" display="date"' . $dateformat . ' value="' . $current_start_date . '">' .
280
- '<strong>' . ' - ' . '</strong>' .
281
  '<input name="end_date" id="end_date" type="text" display="date"' . $dateformat . ' value="' . $current_end_date . '">' .
282
  ' ' .
283
  '<button class="button-primary" name="range" id="range" type="submit" value="custom">' . __( 'Go', 'woocommerce-jetpack' ) . '</button>' .
284
- '</form>';
285
- return $predefined_ranges . '<br>' . $date_input_fields;
286
- }
287
 
288
- /**
289
- * create_export_tool.
290
- *
291
- * @version 5.5.6
292
- * @since 2.4.8
293
- */
294
- function create_export_tool( $tool_id ) {
295
- echo '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
296
- echo $this->get_tool_header_html( 'export_' . $tool_id );
297
- echo '<p>' . $this->export_date_fields( $tool_id ) . '</p>';
298
- if ( ! isset( $_GET['range'] ) ) {
299
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
  }
301
- echo '<form method="post" action="">';
302
- echo '<p>' . $this->export_filter_fields( $tool_id ) . '</p>';
303
- echo '<p>';
304
- echo '<button class="button-primary" type="submit" name="wcj_export" value="' . $tool_id . '">' . __( 'Download CSV', 'woocommerce-jetpack' ) . '</button>';
305
- echo ' ';
306
- echo '<button class="button-primary" type="submit" name="wcj_export_xml" value="' . $tool_id . '">' .
307
- __( 'Download XML', 'woocommerce-jetpack' ) . '</button>';
308
- echo '<button style="float:right;margin-right:10px;" class="button-primary" type="submit" name="wcj_export_filter" value="' . $tool_id . '">' .
309
- __( 'Filter by All Fields', 'woocommerce-jetpack' ) . '</button>';
310
- echo '<input style="float:right;margin-right:10px;" type="text" name="wcj_export_filter_all_columns" value="' .
311
- ( isset( $_POST['wcj_export_filter_all_columns'] ) ? $_POST['wcj_export_filter_all_columns'] : '' ) . '">';
312
- echo '</p>';
313
- echo '</form>';
314
- $data = $this->export( $tool_id );
315
- echo ( is_array( $data ) ) ? wcj_get_table_html( $data, array( 'table_class' => 'widefat striped' ) ) : $data;
316
- echo '</div>';
317
- }
318
 
319
- /**
320
- * create_export_customers_tool.
321
- *
322
- * @version 2.4.8
323
- * @since 2.4.8
324
- */
325
- function create_export_customers_tool() {
326
- $this->create_export_tool( 'customers' );
327
- }
328
 
329
- /**
330
- * create_export_orders_tool.
331
- *
332
- * @version 2.4.8
333
- * @since 2.4.8
334
- */
335
- function create_export_orders_tool() {
336
- $this->create_export_tool( 'orders' );
337
- }
338
 
339
- /**
340
- * create_export_orders_items_tool.
341
- *
342
- * @version 2.5.9
343
- * @since 2.5.9
344
- */
345
- function create_export_orders_items_tool() {
346
- $this->create_export_tool( 'orders_items' );
347
- }
348
 
349
- /**
350
- * create_export_products_tool.
351
- *
352
- * @version 2.5.3
353
- * @since 2.5.3
354
- */
355
- function create_export_products_tool() {
356
- $this->create_export_tool( 'products' );
357
- }
358
 
359
- /**
360
- * create_export_customers_from_orders_tool.
361
- *
362
- * @version 2.4.8
363
- * @since 2.3.9
364
- */
365
- function create_export_customers_from_orders_tool() {
366
- $this->create_export_tool( 'customers_from_orders' );
367
- }
368
 
369
- }
370
 
371
  endif;
372
 
5
  * @version 5.5.9
6
  * @since 2.5.4
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Export_Import' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Currencies.
 
 
 
 
18
  */
19
+ class WCJ_Export_Import extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.4.0
25
+ * @since 2.5.4
26
+ * @todo [feature] import products, customers and (maybe) orders
27
+ */
28
+ public function __construct() {
29
 
30
+ $this->id = 'export';
31
+ $this->short_desc = __( 'Export', 'woocommerce-jetpack' );
32
+ $this->desc = __( 'WooCommerce export tools. Additional export fields (1 field allowed in free version).', 'woocommerce-jetpack' );
33
+ /* translators: %s: translation added */
34
+ $this->desc_pro = sprintf( __( 'WooCommerce export tools. Check and use the shortcodes from <a href="%s" target=\'blank\'>here</a>', 'woocommerce-jetpack' ), 'https://booster.io/category/shortcodes/' );
35
+ $this->link_slug = 'woocommerce-export-tools';
36
+ parent::__construct();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
37
 
38
+ $this->add_tools(
39
+ array(
40
+ 'export_customers' => array(
41
+ 'title' => __( 'Export Customers', 'woocommerce-jetpack' ),
42
+ 'desc' => __( 'Export Customers.', 'woocommerce-jetpack' ),
43
+ ),
44
+ 'export_customers_from_orders' => array(
45
+ 'title' => __( 'Export Customers from Orders', 'woocommerce-jetpack' ),
46
+ 'desc' => __( 'Export Customers (extracted from orders).', 'woocommerce-jetpack' ) . ' ' .
47
+ __( 'Customers are identified by billing email.', 'woocommerce-jetpack' ),
48
+ ),
49
+ 'export_orders' => array(
50
+ 'title' => __( 'Export Orders', 'woocommerce-jetpack' ),
51
+ 'desc' => __( 'Export Orders.', 'woocommerce-jetpack' ),
52
+ ),
53
+ 'export_orders_items' => array(
54
+ 'title' => __( 'Export Orders Items', 'woocommerce-jetpack' ),
55
+ 'desc' => __( 'Export Orders Items.', 'woocommerce-jetpack' ),
56
+ ),
57
+ 'export_products' => array(
58
+ 'title' => __( 'Export Products', 'woocommerce-jetpack' ),
59
+ 'desc' => __( 'Export Products.', 'woocommerce-jetpack' ),
60
+ ),
61
+ )
62
+ );
63
 
64
+ $this->fields_helper = require_once 'export/class-wcj-export-fields-helper.php';
 
 
 
 
65
 
66
+ if ( $this->is_enabled() ) {
67
+ add_action( 'init', array( $this, 'export_csv' ) );
68
+ add_action( 'init', array( $this, 'export_xml' ) );
69
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  }
71
+
72
+ /**
73
+ * Export.
74
+ *
75
+ * @version 2.5.9
76
+ * @since 2.4.8
77
+ * @todo [dev] when filtering now using `strpos`, but other options would be `stripos` (case-insensitive) or strict equality
78
+ * @todo [dev] (maybe) do filtering directly in WP_Query
79
+ * @param int $tool_id defines the tool_id.
80
+ */
81
+ public function export( $tool_id ) {
82
+ $data = array();
83
+ switch ( $tool_id ) {
84
+ case 'customers':
85
+ $exporter = require_once 'export/class-wcj-exporter-customers.php';
86
+ $data = $exporter->export_customers( $this->fields_helper );
87
+ break;
88
+ case 'customers_from_orders':
89
+ $exporter = require_once 'export/class-wcj-exporter-customers.php';
90
+ $data = $exporter->export_customers_from_orders( $this->fields_helper );
91
+ break;
92
+ case 'orders':
93
+ $exporter = require_once 'export/class-wcj-exporter-orders.php';
94
+ $data = $exporter->export_orders( $this->fields_helper );
95
+ break;
96
+ case 'orders_items':
97
+ $exporter = require_once 'export/class-wcj-exporter-orders.php';
98
+ $data = $exporter->export_orders_items( $this->fields_helper );
99
+ break;
100
+ case 'products':
101
+ $exporter = require_once 'export/class-wcj-exporter-products.php';
102
+ $data = $exporter->export_products( $this->fields_helper );
103
+ break;
104
+ }
105
+ if ( isset( $_POST['wcj_export_filter_all_columns'] ) && '' !== $_POST['wcj_export_filter_all_columns'] ) {
106
+ foreach ( $data as $row_id => $row ) {
107
+ if ( 0 === $row_id ) {
108
+ continue;
109
+ }
110
+ $is_filtered = false;
111
+ foreach ( $row as $cell ) {
112
+ if ( false !== strpos( $cell, sanitize_text_field( wp_unslash( $_POST['wcj_export_filter_all_columns'] ) ) ) ) {
113
+ $is_filtered = true;
114
+ break;
115
+ }
116
+ }
117
+ if ( ! $is_filtered ) {
118
+ unset( $data[ $row_id ] );
119
  }
 
 
 
120
  }
121
  }
122
+ return $data;
123
  }
 
 
124
 
125
+ /**
126
+ * Export_xml.
127
+ *
128
+ * @version 2.5.9
129
+ * @since 2.5.9
130
+ * @todo [dev] templates for xml_start, xml_end, xml_item.
131
+ * @todo [dev] `strip_tags`
132
+ */
133
+ public function export_xml() {
134
+ if ( isset( $_POST['wcj_export_xml'] ) ) {
135
+ $data = $this->export( sanitize_text_field( wp_unslash( $_POST['wcj_export_xml'] ) ) );
136
+ if ( is_array( $data ) ) {
137
+ $xml = '';
138
+ $xml .= '<?xml version = "1.0" encoding = "utf-8" ?>' . PHP_EOL . '<root>' . PHP_EOL;
139
+ foreach ( $data as $row_num => $row ) {
140
+ if ( 0 === $row_num ) {
141
+ foreach ( $row as $cell_id => $cell_value ) {
142
+ $cell_ids[ $cell_id ] = sanitize_title_with_dashes( $cell_value );
143
+ }
144
+ continue;
145
+ }
146
+ $xml .= '<item>' . PHP_EOL;
147
  foreach ( $row as $cell_id => $cell_value ) {
148
+ $xml .= "\t" . '<' . $cell_ids[ $cell_id ] . '>' . $cell_value . '</' . $cell_ids[ $cell_id ] . '>' . PHP_EOL;
149
  }
150
+ $xml .= '</item>' . PHP_EOL;
 
 
 
 
151
  }
152
+ $xml .= '</root>';
153
+ header( 'Content-Disposition: attachment; filename=' . sanitize_text_field( wp_unslash( $_POST['wcj_export_xml'] ) ) . '.xml' );
154
+ header( 'Content-Type: Content-Type: text/html; charset=utf-8' );
155
+ header( 'Content-Description: File Transfer' );
156
+ header( 'Content-Length: ' . strlen( $xml ) );
157
+ echo wp_kses_post( $xml );
158
+ die();
159
  }
 
 
 
 
 
 
 
160
  }
161
  }
 
162
 
163
+ /**
164
+ * Smart_format_fields.
165
+ *
166
+ * @see https://stackoverflow.com/a/4617967/1193038
167
+ *
168
+ * @version 5.1.0
169
+ * @since 5.1.0
170
+ *
171
+ * @param array $row defines the row.
172
+ *
173
+ * @return array
174
+ */
175
+ public function smart_format_fields( $row ) {
176
+ if ( 'no' === wcj_get_option( 'wcj_export_csv_smart_formatting', 'no' ) ) {
177
+ return $row;
178
+ }
179
+ $row = array_map(
180
+ function ( $item ) {
181
+ $item = str_replace( '"', '""', $item );
182
+ if (
183
+ false !== strpos( $item, '"' )
184
+ || false !== strpos( $item, ',' )
185
+ ) {
186
+ $item = '"' . $item . '"';
187
+ }
188
+ return $item;
189
+ },
190
+ $row
191
+ );
192
  return $row;
193
  }
 
 
 
 
 
 
 
 
 
 
 
 
194
 
195
+ /**
196
+ * Export_csv.
197
+ *
198
+ * @version 5.1.0
199
+ * @since 2.4.8
200
+ */
201
+ public function export_csv() {
202
+ if ( isset( $_POST['wcj_export'] ) ) {
203
+ $data = $this->export( sanitize_text_field( wp_unslash( $_POST['wcj_export'] ) ) );
204
+ if ( is_array( $data ) ) {
205
+ $csv = '';
206
+ foreach ( $data as $row ) {
207
+ $row = $this->smart_format_fields( $row );
208
+ $csv .= implode( wcj_get_option( 'wcj_export_csv_separator', ',' ), $row ) . PHP_EOL;
209
+ }
210
+ if ( 'yes' === wcj_get_option( 'wcj_export_csv_add_utf_8_bom', 'yes' ) ) {
211
+ $csv = "\xEF\xBB\xBF" . $csv; // UTF-8 BOM.
212
+ }
213
+ header( 'Content-Disposition: attachment; filename=' . sanitize_text_field( wp_unslash( $_POST['wcj_export'] ) ) . '.csv' );
214
+ header( 'Content-Type: Content-Type: text/html; charset=utf-8' );
215
+ header( 'Content-Description: File Transfer' );
216
+ header( 'Content-Length: ' . strlen( $csv ) );
217
+ echo wp_kses_post( $csv );
218
+ die();
219
  }
 
 
 
 
 
 
220
  }
221
  }
 
222
 
223
+ /**
224
+ * Export_filter_fields.
225
+ *
226
+ * @version 2.5.9
227
+ * @since 2.5.5
228
+ * @todo [dev] filter each field separately
229
+ * @param int $tool_id defines the tool_id.
230
+ */
231
+ public function export_filter_fields( $tool_id ) {
232
+ $fields = array();
233
+ switch ( $tool_id ) {
234
+ case 'orders':
235
+ $fields = array(
236
+ 'wcj_filter_by_order_billing_country' => __( 'Filter by Billing Country', 'woocommerce-jetpack' ),
237
+ 'wcj_filter_by_product_title' => __( 'Filter by Product Title', 'woocommerce-jetpack' ),
238
+ );
239
+ break;
240
+ case 'orders_items':
241
+ $fields = array(
242
+ 'wcj_filter_by_order_billing_country' => __( 'Filter by Billing Country', 'woocommerce-jetpack' ),
243
+ );
244
+ break;
245
+ }
246
+ if ( ! empty( $fields ) ) {
247
+ $data = array();
248
+ foreach ( $fields as $field_id => $field_desc ) {
249
+ $field_value = ( isset( $_POST[ $field_id ] ) ) ? sanitize_text_field( wp_unslash( $_POST[ $field_id ] ) ) : '';
250
+ $data[] = array(
251
+ '<label for="' . $field_id . '">' . $field_desc . '</label>',
252
+ '<input name="' . $field_id . '" id="' . $field_id . '" type="text" value="' . $field_value . '">',
253
+ );
254
+ }
255
  $data[] = array(
256
+ '<button class="button-primary" type="submit" name="wcj_export_filter" value="' . $tool_id . '">' . __( 'Filter', 'woocommerce-jetpack' ) . '</button>',
257
+ '',
258
+ );
259
+ return wcj_get_table_html(
260
+ $data,
261
+ array(
262
+ 'table_class' => 'widefat',
263
+ 'table_style' => 'width:50%;min-width:300px;',
264
+ 'table_heading_type' => 'vertical',
265
+ )
266
  );
267
  }
 
 
 
 
 
268
  }
 
269
 
270
+ /**
271
+ * Export_date_fields.
272
+ *
273
+ * @version 5.5.9
274
+ * @since 3.0.0
275
+ * @todo [dev] maybe make `$dateformat` optional
276
+ * @todo [dev] mark current (i.e. active) link (if exists)
277
+ * @param int $tool_id defines the tool_id.
278
+ */
279
+ public function export_date_fields( $tool_id ) {
280
+ $current_start_date = ( isset( $_GET['start_date'] ) ? sanitize_text_field( wp_unslash( $_GET['start_date'] ) ) : '' );
281
+ $current_end_date = ( isset( $_GET['end_date'] ) ? sanitize_text_field( wp_unslash( $_GET['end_date'] ) ) : '' );
282
+ $predefined_ranges = array();
283
+ $predefined_ranges[] = '<a href="' . esc_url( add_query_arg( 'range', 'all_time', remove_query_arg( array( 'start_date', 'end_date' ) ) ) ) . '">' .
284
  __( 'All time', 'woocommerce-jetpack' ) . '</a>';
285
+ foreach ( array_merge( wcj_get_reports_standard_ranges(), wcj_get_reports_custom_ranges() ) as $range_id => $range_data ) {
286
+ $link = esc_url(
287
+ add_query_arg(
288
+ array(
289
+ 'start_date' => $range_data['start_date'],
290
+ 'end_date' => $range_data['end_date'],
291
+ 'range' => $range_id,
292
+ )
293
+ )
294
+ );
295
+ $predefined_ranges[] = '<a href="' . $link . '">' . $range_data['title'] . '</a>';
296
+
297
+ }
298
+ $predefined_ranges = implode( ' | ', $predefined_ranges );
299
+ $dateformat = ' dateformat="yy-mm-dd"';
300
+ $date_input_fields = '<form method="get" action="">' .
301
  '<input type="hidden" name="page" value="wcj-tools">' .
302
  '<input type="hidden" name="tab" value="export_' . $tool_id . '">' .
303
+ '<strong>' . __( 'Custom:', 'woocommerce-jetpack' ) . '</strong> ' .
304
  '<input name="start_date" id="start_date" type="text" display="date"' . $dateformat . ' value="' . $current_start_date . '">' .
305
+ '<strong> - </strong>' .
306
  '<input name="end_date" id="end_date" type="text" display="date"' . $dateformat . ' value="' . $current_end_date . '">' .
307
  ' ' .
308
  '<button class="button-primary" name="range" id="range" type="submit" value="custom">' . __( 'Go', 'woocommerce-jetpack' ) . '</button>' .
309
+ '</form>';
310
+ return $predefined_ranges . '<br>' . $date_input_fields;
311
+ }
312
 
313
+ /**
314
+ * Create_export_tool.
315
+ *
316
+ * @version 5.5.6
317
+ * @since 2.4.8
318
+ * @param int $tool_id defines the tool_id.
319
+ */
320
+ public function create_export_tool( $tool_id ) {
321
+ echo '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
322
+ echo wp_kses_post( $this->get_tool_header_html( 'export_' . $tool_id ) );
323
+ echo '<p>' . wp_kses_post( $this->export_date_fields( $tool_id ) ) . '</p>';
324
+ if ( ! isset( $_GET['range'] ) ) {
325
+ echo '</div>';
326
+ return;
327
+ }
328
+ echo '<form method="post" action="">';
329
+ echo '<p>' . wp_kses_post( $this->export_filter_fields( $tool_id ) ) . '</p>';
330
+ echo '<p>';
331
+ echo '<button class="button-primary" type="submit" name="wcj_export" value="' . wp_kses_post( $tool_id ) . '">' . wp_kses_post( 'Download CSV', 'woocommerce-jetpack' ) . '</button>';
332
+ echo ' ';
333
+ echo '<button class="button-primary" type="submit" name="wcj_export_xml" value="' . wp_kses_post( $tool_id ) . '">' .
334
+ wp_kses_post( 'Download XML', 'woocommerce-jetpack' ) . '</button>';
335
+ echo '<button style="float:right;margin-right:10px;" class="button-primary" type="submit" name="wcj_export_filter" value="' . wp_kses_post( $tool_id ) . '">' .
336
+ wp_kses_post( 'Filter by All Fields', 'woocommerce-jetpack' ) . '</button>';
337
+ echo '<input style="float:right;margin-right:10px;" type="text" name="wcj_export_filter_all_columns" value="' .
338
+ ( isset( $_POST['wcj_export_filter_all_columns'] ) ? wp_kses_post( sanitize_text_field( wp_unslash( $_POST['wcj_export_filter_all_columns'] ) ) ) : '' ) . '">';
339
+ echo '</p>';
340
+ echo '</form>';
341
+ $data = $this->export( $tool_id );
342
+ echo is_array( $data ) ? wcj_get_table_html( $data, array( 'table_class' => 'widefat striped' ) ) : ( $data );
343
+ echo '</div>';
344
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
345
 
346
+ /**
347
+ * Create_export_customers_tool.
348
+ *
349
+ * @version 2.4.8
350
+ * @since 2.4.8
351
+ */
352
+ public function create_export_customers_tool() {
353
+ $this->create_export_tool( 'customers' );
354
+ }
355
 
356
+ /**
357
+ * Create_export_orders_tool.
358
+ *
359
+ * @version 2.4.8
360
+ * @since 2.4.8
361
+ */
362
+ public function create_export_orders_tool() {
363
+ $this->create_export_tool( 'orders' );
364
+ }
365
 
366
+ /**
367
+ * Create_export_orders_items_tool.
368
+ *
369
+ * @version 2.5.9
370
+ * @since 2.5.9
371
+ */
372
+ public function create_export_orders_items_tool() {
373
+ $this->create_export_tool( 'orders_items' );
374
+ }
375
 
376
+ /**
377
+ * Create_export_products_tool.
378
+ *
379
+ * @version 2.5.3
380
+ * @since 2.5.3
381
+ */
382
+ public function create_export_products_tool() {
383
+ $this->create_export_tool( 'products' );
384
+ }
385
 
386
+ /**
387
+ * Create_export_customers_from_orders_tool.
388
+ *
389
+ * @version 2.4.8
390
+ * @since 2.3.9
391
+ */
392
+ public function create_export_customers_from_orders_tool() {
393
+ $this->create_export_tool( 'customers_from_orders' );
394
+ }
395
 
396
+ }
397
 
398
  endif;
399
 
includes/class-wcj-free-price.php CHANGED
@@ -5,167 +5,185 @@
5
  * @version 5.2.0
6
  * @since 2.5.9
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Free_Price' ) ) :
13
-
14
- class WCJ_Free_Price extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.2.0
20
- * @since 2.5.9
21
- * @todo single in grouped is treated as "related"
22
  */
23
- function __construct() {
24
-
25
- $this->id = 'free_price';
26
- $this->short_desc = __( 'Free Price Labels', 'woocommerce-jetpack' );
27
- $this->desc = __( 'Set free price labels (Variable products allowed in Plus).', 'woocommerce-jetpack' );
28
- $this->desc_pro = __( 'Set free price labels.', 'woocommerce-jetpack' );
29
- $this->link_slug = 'woocommerce-free-price-labels';
30
- parent::__construct();
31
-
32
- if ( $this->is_enabled() ) {
33
- if ( WCJ_IS_WC_VERSION_BELOW_3 ) {
34
- add_filter( 'woocommerce_free_price_html', array( $this, 'modify_free_price_simple_external_custom' ), PHP_INT_MAX, 2 );
35
- add_filter( 'woocommerce_grouped_free_price_html', array( $this, 'modify_free_price_grouped' ), PHP_INT_MAX, 2 );
36
- add_filter( 'woocommerce_variable_free_price_html', array( $this, 'modify_free_price_variable' ), PHP_INT_MAX, 2 );
37
- add_filter( 'woocommerce_variation_free_price_html', array( $this, 'modify_free_price_variation' ), PHP_INT_MAX, 2 );
38
- } else {
39
- add_filter( 'woocommerce_get_price_html', array( $this, 'maybe_modify_price' ), PHP_INT_MAX, 2 );
 
 
 
 
 
 
 
 
 
 
40
  }
41
  }
42
- }
43
 
44
- /**
45
- * are_all_prices_free
46
- *
47
- * @version 2.7.0
48
- * @since 2.7.0
49
- */
50
- function are_all_prices_free( $_product, $type ) {
51
- if ( 'variable' === $type ) {
52
- $prices = $_product->get_variation_prices( true );
53
- $min_price = current( $prices['price'] );
54
- $max_price = end( $prices['price'] );
55
- if ( '' !== $min_price && '' !== $max_price ) {
56
- return ( 0 == $min_price && 0 == $max_price );
57
- }
58
- } elseif ( 'variable' === $type ) {
59
- $child_prices = array();
60
- foreach ( $_product->get_children() as $child_id ) {
61
- $child = wc_get_product( $child_id );
62
- if ( '' !== $child->get_price() ) {
63
- $child_prices[] = wcj_get_product_display_price( $child );
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  }
65
  }
66
- if ( ! empty( $child_prices ) ) {
67
- $min_price = min( $child_prices );
68
- $max_price = max( $child_prices );
69
- } else {
70
- $min_price = '';
71
- $max_price = '';
72
- }
73
- if ( '' !== $min_price && '' !== $max_price ) {
74
- return ( 0 == $min_price && 0 == $max_price );
75
- }
76
  }
77
- return false;
78
- }
79
 
80
- /**
81
- * maybe_modify_price
82
- *
83
- * @version 2.7.0
84
- * @since 2.7.0
85
- */
86
- function maybe_modify_price( $price, $_product ) {
87
- if ( '' !== $price ) {
88
- if ( 0 == $_product->get_price() ) {
89
- if ( $_product->is_type( 'grouped' ) ) {
90
- return ( $this->are_all_prices_free( $_product, 'grouped' ) ) ? $this->modify_free_price_grouped( $price, $_product ) : $price;
91
- } elseif ( $_product->is_type( 'variable' ) ) {
92
- return ( $this->are_all_prices_free( $_product, 'variable' ) ) ? $this->modify_free_price_variable( $price, $_product ) : $price;
93
- } elseif ( $_product->is_type( 'variation' ) ) {
94
- return $this->modify_free_price_variation( $price, $_product );
95
- } else {
96
- return $this->modify_free_price_simple_external_custom( $price, $_product );
 
 
 
97
  }
98
  }
 
99
  }
100
- return $price;
101
- }
102
 
103
- /**
104
- * get_view_id
105
- *
106
- * @version 2.5.9
107
- * @since 2.5.9
108
- */
109
- function get_view_id( $product_id ) {
110
- $view = 'single'; // default
111
- if ( is_single( $product_id ) ) {
112
- $view = 'single';
113
- } elseif ( is_single() ) {
114
- $view = 'related';
115
- } elseif ( is_front_page() ) {
116
- $view = 'home';
117
- } elseif ( is_page() ) {
118
- $view = 'page';
119
- } elseif ( is_archive() ) {
120
- $view = 'archive';
 
 
 
121
  }
122
- return $view;
123
- }
124
 
125
- /**
126
- * modify_free_price_simple_external_custom.
127
- *
128
- * @version 2.7.0
129
- * @since 2.5.9
130
- */
131
- function modify_free_price_simple_external_custom( $price, $_product ) {
132
- $default = '<span class="amount">' . __( 'Free!', 'woocommerce' ) . '</span>';
133
- return ( $_product->is_type( 'external' ) ) ?
 
 
134
  do_shortcode( wcj_get_option( 'wcj_free_price_external_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), $default ) ) :
135
- do_shortcode( wcj_get_option( 'wcj_free_price_simple_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), $default ) );
136
- }
137
 
138
- /**
139
- * modify_free_price_grouped.
140
- *
141
- * @version 2.7.0
142
- * @since 2.5.9
143
- */
144
- function modify_free_price_grouped( $price, $_product ) {
145
- return do_shortcode( wcj_get_option( 'wcj_free_price_grouped_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), __( 'Free!', 'woocommerce' ) ) );
146
- }
 
 
147
 
148
- /**
149
- * modify_free_price_variable.
150
- *
151
- * @version 2.7.0
152
- * @since 2.5.9
153
- */
154
- function modify_free_price_variable( $price, $_product ) {
155
- return do_shortcode( apply_filters( 'booster_option', __( 'Free!', 'woocommerce' ), wcj_get_option( 'wcj_free_price_variable_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), __( 'Free!', 'woocommerce' ) ) ) );
156
- }
 
 
157
 
158
- /**
159
- * modify_free_price_variation.
160
- *
161
- * @version 2.5.9
162
- * @since 2.5.9
163
- */
164
- function modify_free_price_variation( $price, $_product ) {
165
- return do_shortcode( apply_filters( 'booster_option', __( 'Free!', 'woocommerce' ), wcj_get_option( 'wcj_free_price_variable_variation', __( 'Free!', 'woocommerce' ) ) ) );
166
- }
 
 
167
 
168
- }
169
 
170
  endif;
171
 
5
  * @version 5.2.0
6
  * @since 2.5.9
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Free_Price' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Free_Price.
 
 
 
 
18
  */
19
+ class WCJ_Free_Price extends WCJ_Module {
20
+
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.2.0
25
+ * @since 2.5.9
26
+ * @todo single in grouped is treated as "related"
27
+ */
28
+ public function __construct() {
29
+
30
+ $this->id = 'free_price';
31
+ $this->short_desc = __( 'Free Price Labels', 'woocommerce-jetpack' );
32
+ $this->desc = __( 'Set free price labels (Variable products allowed in Plus).', 'woocommerce-jetpack' );
33
+ $this->desc_pro = __( 'Set free price labels.', 'woocommerce-jetpack' );
34
+ $this->link_slug = 'woocommerce-free-price-labels';
35
+ parent::__construct();
36
+
37
+ if ( $this->is_enabled() ) {
38
+ if ( WCJ_IS_WC_VERSION_BELOW_3 ) {
39
+ add_filter( 'woocommerce_free_price_html', array( $this, 'modify_free_price_simple_external_custom' ), PHP_INT_MAX, 2 );
40
+ add_filter( 'woocommerce_grouped_free_price_html', array( $this, 'modify_free_price_grouped' ), PHP_INT_MAX, 2 );
41
+ add_filter( 'woocommerce_variable_free_price_html', array( $this, 'modify_free_price_variable' ), PHP_INT_MAX, 2 );
42
+ add_filter( 'woocommerce_variation_free_price_html', array( $this, 'modify_free_price_variation' ), PHP_INT_MAX, 2 );
43
+ } else {
44
+ add_filter( 'woocommerce_get_price_html', array( $this, 'maybe_modify_price' ), PHP_INT_MAX, 2 );
45
+ }
46
  }
47
  }
 
48
 
49
+ /**
50
+ * Are_all_prices_free
51
+ *
52
+ * @version 2.7.0
53
+ * @since 2.7.0
54
+ * @param string | array $_product defines the _product.
55
+ * @param string $type defines the type.
56
+ */
57
+ public function are_all_prices_free( $_product, $type ) {
58
+ if ( 'variable' === $type ) {
59
+ $prices = $_product->get_variation_prices( true );
60
+ $min_price = current( $prices['price'] );
61
+ $max_price = end( $prices['price'] );
62
+ if ( '' !== $min_price && '' !== $max_price ) {
63
+ return ( 0 === $min_price && 0 === $max_price );
64
+ }
65
+ } elseif ( 'variable' === $type ) {
66
+ $child_prices = array();
67
+ foreach ( $_product->get_children() as $child_id ) {
68
+ $child = wc_get_product( $child_id );
69
+ if ( '' !== $child->get_price() ) {
70
+ $child_prices[] = wcj_get_product_display_price( $child );
71
+ }
72
+ }
73
+ if ( ! empty( $child_prices ) ) {
74
+ $min_price = min( $child_prices );
75
+ $max_price = max( $child_prices );
76
+ } else {
77
+ $min_price = '';
78
+ $max_price = '';
79
+ }
80
+ if ( '' !== $min_price && '' !== $max_price ) {
81
+ return ( 0 === $min_price && 0 === $max_price );
82
  }
83
  }
84
+ return false;
 
 
 
 
 
 
 
 
 
85
  }
 
 
86
 
87
+ /**
88
+ * Maybe_modify_price
89
+ *
90
+ * @version 2.7.0
91
+ * @since 2.7.0
92
+ * @param int $price defines the price.
93
+ * @param string | array $_product defines the _product.
94
+ */
95
+ public function maybe_modify_price( $price, $_product ) {
96
+ if ( '' !== $price ) {
97
+ if ( 0 === $_product->get_price() ) {
98
+ if ( $_product->is_type( 'grouped' ) ) {
99
+ return ( $this->are_all_prices_free( $_product, 'grouped' ) ) ? $this->modify_free_price_grouped( $price, $_product ) : $price;
100
+ } elseif ( $_product->is_type( 'variable' ) ) {
101
+ return ( $this->are_all_prices_free( $_product, 'variable' ) ) ? $this->modify_free_price_variable( $price, $_product ) : $price;
102
+ } elseif ( $_product->is_type( 'variation' ) ) {
103
+ return $this->modify_free_price_variation( $price, $_product );
104
+ } else {
105
+ return $this->modify_free_price_simple_external_custom( $price, $_product );
106
+ }
107
  }
108
  }
109
+ return $price;
110
  }
 
 
111
 
112
+ /**
113
+ * Get_view_id
114
+ *
115
+ * @version 2.5.9
116
+ * @since 2.5.9
117
+ * @param int $product_id defines the product_id.
118
+ */
119
+ public function get_view_id( $product_id ) {
120
+ $view = 'single'; // default.
121
+ if ( is_single( $product_id ) ) {
122
+ $view = 'single';
123
+ } elseif ( is_single() ) {
124
+ $view = 'related';
125
+ } elseif ( is_front_page() ) {
126
+ $view = 'home';
127
+ } elseif ( is_page() ) {
128
+ $view = 'page';
129
+ } elseif ( is_archive() ) {
130
+ $view = 'archive';
131
+ }
132
+ return $view;
133
  }
 
 
134
 
135
+ /**
136
+ * Modify_free_price_simple_external_custom.
137
+ *
138
+ * @version 2.7.0
139
+ * @since 2.5.9
140
+ * @param int $price defines the price.
141
+ * @param string | array $_product defines the _product.
142
+ */
143
+ public function modify_free_price_simple_external_custom( $price, $_product ) {
144
+ $default = '<span class="amount">' . __( 'Free!', 'woocommerce' ) . '</span>';
145
+ return ( $_product->is_type( 'external' ) ) ?
146
  do_shortcode( wcj_get_option( 'wcj_free_price_external_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), $default ) ) :
147
+ do_shortcode( wcj_get_option( 'wcj_free_price_simple_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), $default ) );
148
+ }
149
 
150
+ /**
151
+ * Modify_free_price_grouped.
152
+ *
153
+ * @version 2.7.0
154
+ * @since 2.5.9
155
+ * @param int $price defines the price.
156
+ * @param string | array $_product defines the _product.
157
+ */
158
+ public function modify_free_price_grouped( $price, $_product ) {
159
+ return do_shortcode( wcj_get_option( 'wcj_free_price_grouped_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), __( 'Free!', 'woocommerce' ) ) );
160
+ }
161
 
162
+ /**
163
+ * Modify_free_price_variable.
164
+ *
165
+ * @version 2.7.0
166
+ * @since 2.5.9
167
+ * @param int $price defines the price.
168
+ * @param string | array $_product defines the _product.
169
+ */
170
+ public function modify_free_price_variable( $price, $_product ) {
171
+ return do_shortcode( apply_filters( 'booster_option', __( 'Free!', 'woocommerce' ), wcj_get_option( 'wcj_free_price_variable_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), __( 'Free!', 'woocommerce' ) ) ) );
172
+ }
173
 
174
+ /**
175
+ * Modify_free_price_variation.
176
+ *
177
+ * @version 2.5.9
178
+ * @since 2.5.9
179
+ * @param int $price defines the price.
180
+ * @param string | array $_product defines the _product.
181
+ */
182
+ public function modify_free_price_variation( $price, $_product ) {
183
+ return do_shortcode( apply_filters( 'booster_option', __( 'Free!', 'woocommerce' ), wcj_get_option( 'wcj_free_price_variable_variation', __( 'Free!', 'woocommerce' ) ) ) );
184
+ }
185
 
186
+ }
187
 
188
  endif;
189
 
includes/class-wcj-general.php CHANGED
@@ -4,268 +4,300 @@
4
  *
5
  * @version 5.5.9
6
  * @author Pluggabl LLC.
 
7
  */
8
 
9
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
10
 
11
  if ( ! class_exists( 'WCJ_General' ) ) :
12
-
13
- class WCJ_General extends WCJ_Module {
14
-
15
  /**
16
- * Constructor.
17
- *
18
- * @version 4.5.0
19
- * @todo [dev] maybe expand `$this->desc` (e.g.: Custom roles tool, shortcodes in WordPress text widgets etc.)
20
  */
21
- function __construct() {
22
 
23
- $this->id = 'general';
24
- $this->short_desc = __( 'General', 'woocommerce-jetpack' );
25
- $this->desc = __( 'Booster for WooCommerce general front-end tools.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-booster-general-tools';
27
- parent::__construct();
 
 
28
 
29
- $this->add_tools( array(
30
- 'custom_roles' => array(
31
- 'title' => __( 'Add/Manage Custom Roles', 'woocommerce-jetpack' ),
32
- 'tab_title' => __( 'Custom Roles', 'woocommerce-jetpack' ),
33
- 'desc' => __( 'Manage Custom Roles.', 'woocommerce-jetpack' ),
34
- ),
35
- ) );
36
 
37
- $this->current_php_memory_limit = '';
38
- $this->current_php_time_limit = '';
 
 
 
 
 
 
 
39
 
40
- if ( $this->is_enabled() ) {
 
41
 
42
- // PHP Memory Limit
43
- if ( 0 != ( $php_memory_limit = wcj_get_option( 'wcj_admin_tools_php_memory_limit', 0 ) ) ) {
44
- ini_set( 'memory_limit', $php_memory_limit . 'M' );
45
- }
46
- $this->current_php_memory_limit = sprintf( ' ' . __( 'Current PHP memory limit: %s.', 'woocommerce-jetpack' ), ini_get( 'memory_limit' ) );
 
 
 
 
47
 
48
- // PHP Time Limit
49
- if ( 0 != ( $php_time_limit = wcj_get_option( 'wcj_admin_tools_php_time_limit', 0 ) ) ) {
50
- set_time_limit( $php_time_limit );
51
- }
52
- $this->current_php_time_limit = sprintf( ' ' . __( 'Current PHP time limit: %s seconds.', 'woocommerce-jetpack' ), ini_get( 'max_execution_time' ) );
 
53
 
54
- // Recalculate cart totals
55
- if ( 'yes' === wcj_get_option( 'wcj_general_advanced_recalculate_cart_totals', 'no' ) ) {
56
- add_action( 'wp_loaded', array( $this, 'fix_mini_cart' ), PHP_INT_MAX );
57
- }
58
 
59
- // Shortcodes in text widgets
60
- if ( 'yes' === wcj_get_option( 'wcj_general_shortcodes_in_text_widgets_enabled' ) ) {
61
- add_filter( 'widget_text', 'do_shortcode' );
62
- }
63
 
64
- // PayPal email per product
65
- if ( 'yes' === wcj_get_option( 'wcj_paypal_email_per_product_enabled', 'no' ) ) {
66
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
67
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
68
- add_filter( 'woocommerce_payment_gateways', array( $this, 'maybe_change_paypal_email' ) );
69
- }
70
 
71
- // Session expiration
72
- if ( 'yes' === wcj_get_option( 'wcj_session_expiration_section_enabled', 'no' ) ) {
73
- add_filter( 'wc_session_expiring', array( $this, 'change_session_expiring' ), PHP_INT_MAX );
74
- add_filter( 'wc_session_expiration', array( $this, 'change_session_expiration' ), PHP_INT_MAX );
75
- }
76
 
77
- // Booster role user changer
78
- if ( wcj_is_booster_role_changer_enabled() ) {
79
- add_action( 'admin_bar_menu', array( $this, 'add_user_role_changer' ), PHP_INT_MAX );
80
- add_action( 'init', array( $this, 'change_user_role_meta' ) );
81
- }
82
 
83
- // Try to overwrite WooCommerce IP detection
84
- if ( 'yes' === wcj_get_option( 'wcj_general_overwrite_wc_ip', 'no' ) ) {
85
- if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
86
- $_SERVER['HTTP_X_REAL_IP'] = wcj_get_the_ip();
 
87
  }
88
  }
89
-
90
  }
91
- }
92
 
93
- /**
94
- * change_user_role_meta.
95
- *
96
- * @version 2.9.0
97
- * @since 2.9.0
98
- * @todo [dev] (maybe) optionally via cookies
99
- */
100
- function change_user_role_meta() {
101
- if ( isset( $_GET['wcj_booster_user_role'] ) ) {
102
- $current_user_id = get_current_user_id();
103
- update_user_meta( $current_user_id, '_' . 'wcj_booster_user_role', $_GET['wcj_booster_user_role'] );
 
104
  }
105
- }
106
 
107
- /**
108
- * add_user_role_changer.
109
- *
110
- * @version 5.5.9
111
- * @since 2.9.0
112
- */
113
- function add_user_role_changer( $wp_admin_bar ) {
114
- $current_user_id = get_current_user_id();
115
- $user_roles = wcj_get_user_roles_options();
116
- if ( '' != ( $current_booster_user_role = get_user_meta( $current_user_id, '_' . 'wcj_booster_user_role', true ) ) ) {
117
- $current_booster_user_role = ( isset( $user_roles[ $current_booster_user_role ] ) ) ? $user_roles[ $current_booster_user_role ] : $current_booster_user_role;
118
- $current_booster_user_role = ' [' . $current_booster_user_role . ']';
119
- }
120
- $args = array(
121
- 'parent' => false,
122
- 'id' => 'booster-user-role-changer',
123
- 'title' => __( 'Booster User Role', 'woocommerce-jetpack' ) . $current_booster_user_role,
124
- 'href' => false,
125
- );
126
- $wp_admin_bar->add_node( $args );
127
- foreach ( $user_roles as $user_role_key => $user_role_name ) {
128
  $args = array(
129
- 'parent' => 'booster-user-role-changer',
130
- 'id' => 'booster-user-role-changer-role-' . $user_role_key,
131
- 'title' => $user_role_name,
132
- 'href' => esc_url(add_query_arg( 'wcj_booster_user_role', $user_role_key )),
133
  );
134
  $wp_admin_bar->add_node( $args );
 
 
 
 
 
 
 
 
 
135
  }
136
- }
137
 
138
- /**
139
- * fix_mini_cart.
140
- *
141
- * @version 2.5.2
142
- * @since 2.5.2
143
- * @todo [dev] this is only temporary solution!
144
- */
145
- function fix_mini_cart() {
146
- if ( wcj_is_frontend() ) {
147
- if ( null !== ( $wc = WC() ) ) {
148
- if ( isset( $wc->cart ) ) {
149
- $wc->cart->calculate_totals();
 
 
150
  }
151
  }
152
  }
153
- }
154
 
155
- /**
156
- * change_session_expiring.
157
- *
158
- * @version 2.5.7
159
- * @since 2.5.7
160
- */
161
- function change_session_expiring( $the_time ) {
162
- return wcj_get_option( 'wcj_session_expiring', 47 * 60 * 60 );
163
- }
 
164
 
165
- /**
166
- * change_session_expiration.
167
- *
168
- * @version 2.5.7
169
- * @since 2.5.7
170
- */
171
- function change_session_expiration( $the_time ) {
172
- return wcj_get_option( 'wcj_session_expiration', 48 * 60 * 60 );
173
- }
 
174
 
175
- /**
176
- * create_custom_roles_tool.
177
- *
178
- * @version 5.5.9
179
- * @since 2.5.3
180
- */
181
- function create_custom_roles_tool() {
182
- if ( isset( $_POST['wcj_add_new_role'] ) ) {
183
- if ( empty( $_POST['wcj_custom_role_id'] ) || empty( $_POST['wcj_custom_role_name'] ) || empty( $_POST['wcj_custom_role_caps'] ) ) {
184
- echo '<p style="color:red;font-weight:bold;">' . __( 'All fields are required!', 'woocommerce-jetpack') . '</p>';
185
- } else {
186
- $role_id = sanitize_key( $_POST['wcj_custom_role_id'] );
187
- if ( is_numeric( $role_id ) ) {
188
- echo '<p style="color:red;font-weight:bold;">' . __( 'Role ID must not be numbers only!', 'woocommerce-jetpack') . '</p>';
189
  } else {
190
- $caps_role = get_role( $_POST['wcj_custom_role_caps'] );
191
- $caps = ( ! empty( $caps_role->capabilities ) && is_array( $caps_role->capabilities ) ? $caps_role->capabilities : array() );
192
- $result = add_role( $role_id, $_POST['wcj_custom_role_name'], $caps );
193
- if ( null !== $result ) {
194
- $custom_roles = wcj_get_option( 'wcj_custom_roles', array() ); // `wcj_custom_roles` option added since Booster v4.0.0
195
- $custom_roles[ $role_id ] = array( 'display_name' => $_POST['wcj_custom_role_name'], 'caps_role' => $_POST['wcj_custom_role_caps'] );
196
- update_option( 'wcj_custom_roles', $custom_roles );
197
- echo '<p style="color:green;font-weight:bold;">' . __( 'Role successfully added!', 'woocommerce-jetpack') . '</p>';
198
  } else {
199
- echo '<p style="color:red;font-weight:bold;">' . __( 'Role already exists!', 'woocommerce-jetpack') . '</p>';
 
 
 
 
 
 
 
 
 
 
 
 
 
200
  }
201
  }
202
  }
203
- }
204
 
205
- if ( isset( $_GET['wcj_delete_role'] ) && '' != $_GET['wcj_delete_role'] ) {
206
- remove_role( $_GET['wcj_delete_role'] );
207
- $custom_roles = wcj_get_option( 'wcj_custom_roles', array() );
208
- if ( isset( $custom_roles[ $_GET['wcj_delete_role'] ] ) ) {
209
- unset( $custom_roles[ $_GET['wcj_delete_role'] ] );
210
- update_option( 'wcj_custom_roles', $custom_roles );
 
 
 
211
  }
212
- echo '<p style="color:green;font-weight:bold;">' . sprintf( __( 'Role %s successfully deleted!', 'woocommerce-jetpack'), sanitize_text_field($_GET['wcj_delete_role'] )) . '</p>';
213
- }
214
- echo '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
215
- echo $this->get_tool_header_html( 'custom_roles' );
216
 
217
- $table_data = array();
218
- $table_data[] = array( __( 'ID', 'woocommerce-jetpack'), __( 'Name', 'woocommerce-jetpack'), __( 'Capabilities', 'woocommerce-jetpack'), __( 'Actions', 'woocommerce-jetpack') );
219
- $existing_roles = wcj_get_user_roles();
220
- $default_wp_wc_roles = array( 'guest', 'administrator', 'editor', 'author', 'contributor', 'subscriber', 'customer', 'shop_manager' );
221
- $custom_roles = wcj_get_option( 'wcj_custom_roles', array() );
222
- foreach ( $existing_roles as $role_key => $role_data ) {
223
- $delete_html = ( in_array( $role_key, $default_wp_wc_roles ) )
224
  ? ''
225
- : '<a href="' . esc_url(add_query_arg( 'wcj_delete_role', $role_key )). '"' . wcj_get_js_confirmation() . '>' . __( 'Delete', 'woocommerce-jetpack') . '</a>';
226
- $caps = ( ! empty( $custom_roles[ $role_key ]['caps_role'] ) ? $custom_roles[ $role_key ]['caps_role'] : $role_key );
227
- $table_data[] = array( $role_key, $role_data['name'], $caps, $delete_html );
228
- }
229
- echo '<h3>' . __( 'Existing Roles', 'woocommerce-jetpack') . '</h3>';
230
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) );
231
 
232
- $table_data = array();
233
- $table_data[] = array( __( 'ID', 'woocommerce-jetpack'), '<input style="width:100%" required type="text" name="wcj_custom_role_id">' );
234
- $table_data[] = array( __( 'Name', 'woocommerce-jetpack'), '<input style="width:100%" required type="text" name="wcj_custom_role_name">' );
235
- $table_data[] = array( __( 'Capabilities', 'woocommerce-jetpack'), wcj_get_select_html( 'wcj_custom_role_caps', wcj_get_user_roles_options(), 'width:100%' ) );
236
- echo '<h3>' . __( 'Add New Role', 'woocommerce-jetpack') . '</h3>';
237
- echo '<form method="post" action="' . remove_query_arg( 'wcj_delete_role' ) . '">' .
238
- wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical', 'table_style' => 'width:20%;min-width:300px;', ) )
239
- . '<p>' . '<input type="submit" name="wcj_add_new_role" class="button-primary" value="' . __( 'Add', 'woocommerce-jetpack' ) . '">' . '</p>'
 
 
 
 
 
 
 
 
 
240
  . '</form>';
241
  echo '</div>';
242
- }
243
 
244
- /**
245
- * maybe_change_paypal_email.
246
- *
247
- * @version 2.5.2
248
- * @since 2.5.2
249
- */
250
- function maybe_change_paypal_email( $load_gateways ) {
251
- if ( isset( WC()->cart ) ) {
252
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
253
- if ( '' != ( $email = get_post_meta( $values['product_id'], '_' . 'wcj_paypal_per_product_email', true ) ) ) {
254
- foreach ( $load_gateways as $key => $gateway ) {
255
- if ( is_string( $gateway ) && 'WC_Gateway_Paypal' === $gateway ) {
256
- $load_gateway = new $gateway();
257
- $load_gateway->receiver_email = $load_gateway->email = $load_gateway->settings['receiver_email'] = $load_gateway->settings['email'] = $email;
258
- $load_gateways[ $key ] = $load_gateway;
 
 
 
 
 
 
259
  }
 
260
  }
261
- break;
262
  }
263
  }
 
264
  }
265
- return $load_gateways;
266
- }
267
 
268
- }
269
 
270
  endif;
271
 
4
  *
5
  * @version 5.5.9
6
  * @author Pluggabl LLC.
7
+ * @package Booster_For_WooCommerce/includes
8
  */
9
 
10
+ if ( ! defined( 'ABSPATH' ) ) {
11
+ exit; // Exit if accessed directly.
12
+ }
13
 
14
  if ( ! class_exists( 'WCJ_General' ) ) :
 
 
 
15
  /**
16
+ * WCJ_General.
 
 
 
17
  */
18
+ class WCJ_General extends WCJ_Module {
19
 
20
+ /**
21
+ * Constructor.
22
+ *
23
+ * @version 4.5.0
24
+ * @todo [dev] maybe expand `$this->desc` (e.g.: Custom roles tool, shortcodes in WordPress text widgets etc.)
25
+ */
26
+ public function __construct() {
27
 
28
+ $this->id = 'general';
29
+ $this->short_desc = __( 'General', 'woocommerce-jetpack' );
30
+ $this->desc = __( 'Booster for WooCommerce general front-end tools.', 'woocommerce-jetpack' );
31
+ $this->link_slug = 'woocommerce-booster-general-tools';
32
+ parent::__construct();
 
 
33
 
34
+ $this->add_tools(
35
+ array(
36
+ 'custom_roles' => array(
37
+ 'title' => __( 'Add/Manage Custom Roles', 'woocommerce-jetpack' ),
38
+ 'tab_title' => __( 'Custom Roles', 'woocommerce-jetpack' ),
39
+ 'desc' => __( 'Manage Custom Roles.', 'woocommerce-jetpack' ),
40
+ ),
41
+ )
42
+ );
43
 
44
+ $this->current_php_memory_limit = '';
45
+ $this->current_php_time_limit = '';
46
 
47
+ if ( $this->is_enabled() ) {
48
+ $php_memory_limit = wcj_get_option( 'wcj_admin_tools_php_memory_limit', '0' );
49
+ $php_time_limit = wcj_get_option( 'wcj_admin_tools_php_time_limit', '0' );
50
+ // PHP Memory Limit.
51
+ if ( '0' !== ( $php_memory_limit ) ) {
52
+ ini_set( 'memory_limit', $php_memory_limit . 'M' );
53
+ }
54
+ /* translators: %s: translation added */
55
+ $this->current_php_memory_limit = sprintf( ' ' . __( 'Current PHP memory limit: %s.', 'woocommerce-jetpack' ), ini_get( 'memory_limit' ) );
56
 
57
+ // PHP Time Limit.
58
+ if ( '0' !== ( $php_time_limit ) ) {
59
+ set_time_limit( $php_time_limit );
60
+ }
61
+ /* translators: %s: translation added */
62
+ $this->current_php_time_limit = sprintf( ' ' . __( 'Current PHP time limit: %s seconds.', 'woocommerce-jetpack' ), ini_get( 'max_execution_time' ) );
63
 
64
+ // Recalculate cart totals.
65
+ if ( 'yes' === wcj_get_option( 'wcj_general_advanced_recalculate_cart_totals', 'no' ) ) {
66
+ add_action( 'wp_loaded', array( $this, 'fix_mini_cart' ), PHP_INT_MAX );
67
+ }
68
 
69
+ // Shortcodes in text widgets.
70
+ if ( 'yes' === wcj_get_option( 'wcj_general_shortcodes_in_text_widgets_enabled' ) ) {
71
+ add_filter( 'widget_text', 'do_shortcode' );
72
+ }
73
 
74
+ // PayPal email per product.
75
+ if ( 'yes' === wcj_get_option( 'wcj_paypal_email_per_product_enabled', 'no' ) ) {
76
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
77
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
78
+ add_filter( 'woocommerce_payment_gateways', array( $this, 'maybe_change_paypal_email' ) );
79
+ }
80
 
81
+ // Session expiration.
82
+ if ( 'yes' === wcj_get_option( 'wcj_session_expiration_section_enabled', 'no' ) ) {
83
+ add_filter( 'wc_session_expiring', array( $this, 'change_session_expiring' ), PHP_INT_MAX );
84
+ add_filter( 'wc_session_expiration', array( $this, 'change_session_expiration' ), PHP_INT_MAX );
85
+ }
86
 
87
+ // Booster role user changer.
88
+ if ( wcj_is_booster_role_changer_enabled() ) {
89
+ add_action( 'admin_bar_menu', array( $this, 'add_user_role_changer' ), PHP_INT_MAX );
90
+ add_action( 'init', array( $this, 'change_user_role_meta' ) );
91
+ }
92
 
93
+ // Try to overwrite WooCommerce IP detection.
94
+ if ( 'yes' === wcj_get_option( 'wcj_general_overwrite_wc_ip', 'no' ) ) {
95
+ if ( isset( $_SERVER['REMOTE_ADDR'] ) ) {
96
+ $_SERVER['HTTP_X_REAL_IP'] = wcj_get_the_ip();
97
+ }
98
  }
99
  }
 
100
  }
 
101
 
102
+ /**
103
+ * Change_user_role_meta.
104
+ *
105
+ * @version 2.9.0
106
+ * @since 2.9.0
107
+ * @todo [dev] (maybe) optionally via cookies
108
+ */
109
+ public function change_user_role_meta() {
110
+ if ( isset( $_GET['wcj_booster_user_role'] ) ) {
111
+ $current_user_id = get_current_user_id();
112
+ update_user_meta( $current_user_id, '_wcj_booster_user_role', sanitize_text_field( wp_unslash( $_GET['wcj_booster_user_role'] ) ) );
113
+ }
114
  }
 
115
 
116
+ /**
117
+ * Add_user_role_changer.
118
+ *
119
+ * @version 5.5.9
120
+ * @since 2.9.0
121
+ * @param string | array $wp_admin_bar defines the wp_admin_bar.
122
+ */
123
+ public function add_user_role_changer( $wp_admin_bar ) {
124
+ $current_user_id = get_current_user_id();
125
+ $user_roles = wcj_get_user_roles_options();
126
+ $current_booster_user_role = get_user_meta( $current_user_id, '_wcj_booster_user_role', true );
127
+ if ( '' !== ( $current_booster_user_role ) ) {
128
+ $current_booster_user_role = ( isset( $user_roles[ $current_booster_user_role ] ) ) ? $user_roles[ $current_booster_user_role ] : $current_booster_user_role;
129
+ $current_booster_user_role = ' [' . $current_booster_user_role . ']';
130
+ }
 
 
 
 
 
 
131
  $args = array(
132
+ 'parent' => false,
133
+ 'id' => 'booster-user-role-changer',
134
+ 'title' => __( 'Booster User Role', 'woocommerce-jetpack' ) . $current_booster_user_role,
135
+ 'href' => false,
136
  );
137
  $wp_admin_bar->add_node( $args );
138
+ foreach ( $user_roles as $user_role_key => $user_role_name ) {
139
+ $args = array(
140
+ 'parent' => 'booster-user-role-changer',
141
+ 'id' => 'booster-user-role-changer-role-' . $user_role_key,
142
+ 'title' => $user_role_name,
143
+ 'href' => esc_url( add_query_arg( 'wcj_booster_user_role', $user_role_key ) ),
144
+ );
145
+ $wp_admin_bar->add_node( $args );
146
+ }
147
  }
 
148
 
149
+ /**
150
+ * Fix_mini_cart.
151
+ *
152
+ * @version 2.5.2
153
+ * @since 2.5.2
154
+ * @todo [dev] this is only temporary solution!
155
+ */
156
+ public function fix_mini_cart() {
157
+ if ( wcj_is_frontend() ) {
158
+ $wc = WC();
159
+ if ( null !== ( $wc ) ) {
160
+ if ( isset( $wc->cart ) ) {
161
+ $wc->cart->calculate_totals();
162
+ }
163
  }
164
  }
165
  }
 
166
 
167
+ /**
168
+ * Change_session_expiring.
169
+ *
170
+ * @version 2.5.7
171
+ * @since 2.5.7
172
+ * @param int $the_time defines the the_time.
173
+ */
174
+ public function change_session_expiring( $the_time ) {
175
+ return wcj_get_option( 'wcj_session_expiring', 47 * 60 * 60 );
176
+ }
177
 
178
+ /**
179
+ * Change_session_expiration.
180
+ *
181
+ * @version 2.5.7
182
+ * @since 2.5.7
183
+ * @param int $the_time defines the the_time.
184
+ */
185
+ public function change_session_expiration( $the_time ) {
186
+ return wcj_get_option( 'wcj_session_expiration', 48 * 60 * 60 );
187
+ }
188
 
189
+ /**
190
+ * Create_custom_roles_tool.
191
+ *
192
+ * @version 5.5.9
193
+ * @since 2.5.3
194
+ */
195
+ public function create_custom_roles_tool() {
196
+ if ( isset( $_POST['wcj_add_new_role'] ) ) {
197
+ if ( empty( $_POST['wcj_custom_role_id'] ) || empty( $_POST['wcj_custom_role_name'] ) || empty( $_POST['wcj_custom_role_caps'] ) ) {
198
+ echo '<p style="color:red;font-weight:bold;">' . wp_kses_post( 'All fields are required!', 'woocommerce-jetpack' ) . '</p>';
 
 
 
 
199
  } else {
200
+ $role_id = sanitize_key( $_POST['wcj_custom_role_id'] );
201
+ if ( is_numeric( $role_id ) ) {
202
+ echo '<p style="color:red;font-weight:bold;">' . wp_kses_post( 'Role ID must not be numbers only!', 'woocommerce-jetpack' ) . '</p>';
 
 
 
 
 
203
  } else {
204
+ $caps_role = get_role( sanitize_text_field( wp_unslash( $_POST['wcj_custom_role_caps'] ) ) );
205
+ $caps = ( ! empty( $caps_role->capabilities ) && is_array( $caps_role->capabilities ) ? $caps_role->capabilities : array() );
206
+ $result = add_role( $role_id, sanitize_text_field( wp_unslash( $_POST['wcj_custom_role_name'] ) ), $caps );
207
+ if ( null !== $result ) {
208
+ $custom_roles = wcj_get_option( 'wcj_custom_roles', array() ); // `wcj_custom_roles` option added since Booster v4.0.0
209
+ $custom_roles[ $role_id ] = array(
210
+ 'display_name' => sanitize_text_field( wp_unslash( $_POST['wcj_custom_role_name'] ) ),
211
+ 'caps_role' => sanitize_text_field( wp_unslash( $_POST['wcj_custom_role_caps'] ) ),
212
+ );
213
+ update_option( 'wcj_custom_roles', $custom_roles );
214
+ echo '<p style="color:green;font-weight:bold;">' . wp_kses_post( 'Role successfully added!', 'woocommerce-jetpack' ) . '</p>';
215
+ } else {
216
+ echo '<p style="color:red;font-weight:bold;">' . wp_kses_post( 'Role already exists!', 'woocommerce-jetpack' ) . '</p>';
217
+ }
218
  }
219
  }
220
  }
 
221
 
222
+ if ( isset( $_GET['wcj_delete_role'] ) && '' !== $_GET['wcj_delete_role'] ) {
223
+ remove_role( sanitize_text_field( wp_unslash( $_GET['wcj_delete_role'] ) ) );
224
+ $custom_roles = wcj_get_option( 'wcj_custom_roles', array() );
225
+ if ( isset( $custom_roles[ $_GET['wcj_delete_role'] ] ) ) {
226
+ unset( $custom_roles[ $_GET['wcj_delete_role'] ] );
227
+ update_option( 'wcj_custom_roles', $custom_roles );
228
+ }
229
+ /* translators: %s: translation added */
230
+ echo '<p style="color:green;font-weight:bold;">' . sprintf( wp_kses_post( 'Role %s successfully deleted!', 'woocommerce-jetpack' ), wp_kses_post( sanitize_text_field( wp_unslash( $_GET['wcj_delete_role'] ) ) ) ) . '</p>';
231
  }
232
+ echo '<div class="wcj-setting-jetpack-body wcj_tools_cnt_main">';
233
+ echo wp_kses_post( $this->get_tool_header_html( 'custom_roles' ) );
 
 
234
 
235
+ $table_data = array();
236
+ $table_data[] = array( __( 'ID', 'woocommerce-jetpack' ), __( 'Name', 'woocommerce-jetpack' ), __( 'Capabilities', 'woocommerce-jetpack' ), __( 'Actions', 'woocommerce-jetpack' ) );
237
+ $existing_roles = wcj_get_user_roles();
238
+ $default_wp_wc_roles = array( 'guest', 'administrator', 'editor', 'author', 'contributor', 'subscriber', 'customer', 'shop_manager' );
239
+ $custom_roles = wcj_get_option( 'wcj_custom_roles', array() );
240
+ foreach ( $existing_roles as $role_key => $role_data ) {
241
+ $delete_html = ( in_array( $role_key, $default_wp_wc_roles ) )
242
  ? ''
243
+ : '<a href="' . esc_url( add_query_arg( 'wcj_delete_role', $role_key ) ) . '"' . wcj_get_js_confirmation() . '>' . __( 'Delete', 'woocommerce-jetpack' ) . '</a>';
244
+ $caps = ( ! empty( $custom_roles[ $role_key ]['caps_role'] ) ? $custom_roles[ $role_key ]['caps_role'] : $role_key );
245
+ $table_data[] = array( $role_key, $role_data['name'], $caps, $delete_html );
246
+ }
247
+ echo '<h3>' . wp_kses_post( 'Existing Roles', 'woocommerce-jetpack' ) . '</h3>';
248
+ echo wp_kses_post( wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) ) );
249
 
250
+ $table_data = array();
251
+ $table_data[] = array( __( 'ID', 'woocommerce-jetpack' ), '<input style="width:100%" required type="text" name="wcj_custom_role_id">' );
252
+ $table_data[] = array( __( 'Name', 'woocommerce-jetpack' ), '<input style="width:100%" required type="text" name="wcj_custom_role_name">' );
253
+ $table_data[] = array( __( 'Capabilities', 'woocommerce-jetpack' ), wcj_get_select_html( 'wcj_custom_role_caps', wcj_get_user_roles_options(), 'width:100%' ) );
254
+ echo '<h3>' . wp_kses_post( 'Add New Role', 'woocommerce-jetpack' ) . '</h3>';
255
+ echo '<form method="post" action="' . wp_kses_post( esc_url( remove_query_arg( 'wcj_delete_role' ) ) ) . '">' .
256
+ wp_kses_post(
257
+ wcj_get_table_html(
258
+ $table_data,
259
+ array(
260
+ 'table_class' => 'widefat striped',
261
+ 'table_heading_type' => 'vertical',
262
+ 'table_style' => 'width:20%;min-width:300px;',
263
+ )
264
+ )
265
+ )
266
+ . '<p><input type="submit" name="wcj_add_new_role" class="button-primary" value="' . wp_kses_post( 'Add', 'woocommerce-jetpack' ) . '"></p>'
267
  . '</form>';
268
  echo '</div>';
269
+ }
270
 
271
+ /**
272
+ * Maybe_change_paypal_email.
273
+ *
274
+ * @version 2.5.2
275
+ * @since 2.5.2
276
+ * @param array $load_gateways defines the load_gateways.
277
+ */
278
+ public function maybe_change_paypal_email( $load_gateways ) {
279
+ if ( isset( WC()->cart ) ) {
280
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
281
+ $email = get_post_meta( $values['product_id'], '_wcj_paypal_per_product_email', true );
282
+ if ( '' !== ( $email ) ) {
283
+ foreach ( $load_gateways as $key => $gateway ) {
284
+ if ( is_string( $gateway ) && 'WC_Gateway_Paypal' === $gateway ) {
285
+ $load_gateway = new $gateway();
286
+ $load_gateway->settings['email'] = $email;
287
+ $load_gateway->settings['receiver_email'] = $load_gateway->settings['email'];
288
+ $$load_gateway->email = $load_gateway->settings['receiver_email'];
289
+ $load_gateway->receiver_email = $load_gateway->email;
290
+ $load_gateways[ $key ] = $load_gateway;
291
+ }
292
  }
293
+ break;
294
  }
 
295
  }
296
  }
297
+ return $load_gateways;
298
  }
 
 
299
 
300
+ }
301
 
302
  endif;
303
 
includes/class-wcj-global-discount.php CHANGED
@@ -5,429 +5,464 @@
5
  * @version 5.5.4
6
  * @since 2.5.7
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Global_Discount' ) ) :
13
-
14
- class WCJ_Global_Discount extends WCJ_Module {
15
-
16
- private $wcj_global_options = array();
17
-
18
  /**
19
- * Constructor.
20
- *
21
- * @version 5.2.0
22
- * @since 2.5.7
23
- * @todo fee instead of discount
24
- * @todo regular price coefficient
25
  */
26
- function __construct() {
27
-
28
- $this->id = 'global_discount';
29
- $this->short_desc = __( 'Global Discount', 'woocommerce-jetpack' );
30
- $this->desc = __( 'Add global discount to all products (1 discount group allowed in free version).', 'woocommerce-jetpack' );
31
- $this->desc_pro = __( 'Add global discount to all products.', 'woocommerce-jetpack' );
32
- $this->link_slug = 'woocommerce-shop-global-discount';
33
- parent::__construct();
34
-
35
- if ( $this->is_enabled() ) {
36
- $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'global_discount' );
37
- if ( 'yes' === wcj_get_option( 'wcj_global_discount_enabled_in_admin', 'no' ) || wcj_is_frontend() ) {
38
- wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  }
40
 
41
- add_action( 'admin_init', array( $this, 'regenerate_wcj_sale_products_in_cache' ) );
42
- add_filter( 'woocommerce_shortcode_products_query', array( $this, 'add_wcj_sale_ids_to_products_shortcode' ), 10, 3 );
43
  }
44
 
45
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
 
47
- /**
48
- * add_wcj_sale_ids_to_products_shortcode.
49
- *
50
- * @version 4.8.0
51
- * @since 4.8.0
52
- *
53
- * @param $args
54
- * @param $atts
55
- * @param $type
56
- *
57
- * @return mixed
58
- */
59
- function add_wcj_sale_ids_to_products_shortcode( $args, $atts, $type ) {
60
- if (
61
- 'sale_products' != $type ||
62
- 'yes' != wcj_get_option( 'wcj_global_discount_products_shortcode_compatibility', 'no' )
63
- ) {
64
  return $args;
65
  }
66
 
67
- $prev_post__in = isset( $args['post__in'] ) ? $args['post__in'] : array();
68
- $args['post__in'] = array_merge( $prev_post__in, $this->get_wcj_sale_products() );
69
- return $args;
70
- }
71
-
72
- /**
73
- * regenerate_wcj_sale_products_in_cache.
74
- *
75
- * @version 4.8.0
76
- * @since 4.8.0
77
- */
78
- function regenerate_wcj_sale_products_in_cache() {
79
- if (
80
- 'yes' != wcj_get_option( 'wcj_global_discount_products_shortcode_compatibility', 'no' ) ||
81
  ! isset( $_REQUEST['page'] ) || 'wc-settings' !== $_REQUEST['page'] ||
82
  ! isset( $_REQUEST['tab'] ) || 'jetpack' !== $_REQUEST['tab'] ||
83
  ! isset( $_REQUEST['wcj-cat'] ) || 'prices_and_currencies' !== $_REQUEST['wcj-cat'] ||
84
  ! isset( $_REQUEST['section'] ) || 'global_discount' !== $_REQUEST['section'] ||
85
  ! isset( $_POST['save'] )
86
- ) {
87
- return;
 
 
 
88
  }
89
- $this->clear_wcj_sale_products_from_cache();
90
- $this->get_wcj_sale_products();
91
- }
92
 
93
- /**
94
- * get_wcj_sale_products.
95
- *
96
- * @version 4.8.0
97
- * @since 4.8.0
98
- *
99
- * @return array|mixed
100
- */
101
- function get_wcj_sale_products() {
102
- $transient_name = 'wcj_global_discount_sale_products';
103
- $sale_products = get_transient( $transient_name );
104
- if ( false === $sale_products ) {
105
- $args = array(
106
- 'post_type' => 'product',
107
- 'posts_per_page' => - 1,
108
- 'fields' => 'ids',
109
- );
110
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_global_discount_groups_total_number', 1 ) );
111
- for ( $i = 1; $i <= $total_number; $i ++ ) {
112
- $enabled = wcj_get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
113
- if ( 'yes' !== $enabled ) {
114
- continue;
115
- }
116
-
117
- // Categories
118
- $include_cats = wcj_get_option( 'wcj_global_discount_sale_categories_incl_' . $i, array() );
119
- $exclude_cats = wcj_get_option( 'wcj_global_discount_sale_categories_excl_' . $i, array() );
120
- $cats = array();
121
- if ( ! empty( $include_cats ) || ! empty( $exclude_cats ) ) {
122
- $cats = array(
123
- 'relation' => 'AND',
124
- );
125
- if ( ! empty( $include_cats ) ) {
126
- $cats[] = array(
127
- 'taxonomy' => 'product_cat',
128
- 'field' => 'term_id',
129
- 'include_children' => false,
130
- 'terms' => $include_cats
131
- );
132
  }
133
- if ( ! empty( $exclude_cats ) ) {
134
- $cats[] = array(
135
- 'taxonomy' => 'product_cat',
136
- 'field' => 'term_id',
137
- 'include_children' => false,
138
- 'terms' => $exclude_cats,
139
- 'operator' => 'NOT IN'
 
140
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
  }
142
- }
143
 
144
- // Tags
145
- $include_tags = wcj_get_option( 'wcj_global_discount_sale_tags_incl_' . $i, array() );
146
- $exclude_tags = wcj_get_option( 'wcj_global_discount_sale_tags_excl_' . $i, array() );
147
- $tags = array();
148
- if ( ! empty( $include_tags ) || ! empty( $exclude_tags ) ) {
149
- $tags = array(
150
- 'relation' => 'AND',
151
- );
152
- if ( ! empty( $include_tags ) ) {
153
- $tags[] = array(
154
- 'taxonomy' => 'product_tag',
155
- 'field' => 'term_id',
156
- 'terms' => $include_tags
157
  );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
158
  }
159
- if ( ! empty( $exclude_tags ) ) {
160
- $tags[] = array(
161
- 'taxonomy' => 'product_tag',
162
- 'field' => 'term_id',
163
- 'terms' => $exclude_tags,
164
- 'operator' => 'NOT IN'
165
  );
 
 
 
 
 
 
166
  }
167
- }
168
 
169
- // Tax Query
170
- if ( ! empty( $cats ) || ! empty( $tags ) ) {
171
- $args['tax_query'] = array(
172
- 'relation' => 'AND'
173
- );
174
- if ( ! empty( $cats ) ) {
175
- $args['tax_query'][] = $cats;
176
- }
177
- if ( ! empty( $tags ) ) {
178
- $args['tax_query'][] = $tags;
179
  }
180
- }
181
 
182
- // Products
183
- $products_incl = wcj_get_option( 'wcj_global_discount_sale_products_incl_' . $i, array() );
184
- $products_excl = wcj_get_option( 'wcj_global_discount_sale_products_excl_' . $i, array() );
185
- if ( ! empty( $products_incl ) || ! empty( $products_excl ) ) {
186
- if ( ! empty( $products_incl ) ) {
187
- $args['post__in'] = $products_incl;
188
- }
189
- if ( ! empty( $products_excl ) ) {
190
- $args['post__not_in'] = $products_excl;
 
 
 
191
  }
192
- }
193
 
194
- // Scope
195
- $scope = wcj_get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
196
- if ( 'all' != $scope ) {
197
- $wc_sale_products = wc_get_product_ids_on_sale();
198
- if ( 'only_on_sale' == $scope ) {
199
- $args['post__in'] = $wc_sale_products;
200
- if ( empty( $wc_sale_products ) ) {
201
- $args['post_type'] = 'do_not_search';
202
- }
203
- } elseif ( 'only_not_on_sale' == $scope ) {
204
- $args['post__not_in'] = $wc_sale_products;
205
  }
206
- }
207
 
208
- $query = new WP_Query( $args );
209
- $sale_products = array_unique( $query->posts );
210
- $prev_group_sale_products = get_transient( $transient_name );
211
- if ( false !== $prev_group_sale_products ) {
212
- $sale_products = array_unique( array_merge( $prev_group_sale_products, $sale_products ) );
213
  }
214
-
215
- set_transient( $transient_name, $sale_products, YEAR_IN_SECONDS );
216
  }
 
217
  }
218
- return $sale_products;
219
- }
220
-
221
- /**
222
- * clear_wcj_sale_products_from_cache.
223
- *
224
- * @version 4.8.0
225
- * @since 4.8.0
226
- */
227
- function clear_wcj_sale_products_from_cache() {
228
- delete_transient( 'wcj_global_discount_sale_products' );
229
- }
230
-
231
- /**
232
- * change_price.
233
- *
234
- * @version 5.3.8
235
- * @since 3.1.0
236
- * @todo `WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER, 'woocommerce_variation_prices_regular_price', 'woocommerce_product_variation_get_regular_price'`
237
- */
238
- function change_price( $price, $_product ) {
239
- $_current_filter = current_filter();
240
- if ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_PRICE_FILTER, 'woocommerce_variation_prices_price', 'woocommerce_product_variation_get_price' ) ) ) {
241
- if(isset($_product->wcj_wholesale_price)){
242
 
243
- return $_product->wcj_wholesale_price;
244
- }
245
- return $this->add_global_discount( $price, $_product, 'price' );
246
- } elseif ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_SALE_PRICE_FILTER, 'woocommerce_variation_prices_sale_price', 'woocommerce_product_variation_get_sale_price' ) ) ) {
247
- return $this->add_global_discount( $price, $_product, 'sale_price' );
248
- } else {
249
- return $price;
 
250
  }
251
- }
252
 
253
- /**
254
- * change_price_grouped.
255
- *
256
- * @version 3.1.0
257
- * @since 2.5.7
258
- */
259
- function change_price_grouped( $price, $qty, $_product ) {
260
- if ( $_product->is_type( 'grouped' ) ) {
261
- foreach ( $_product->get_children() as $child_id ) {
262
- $the_price = get_post_meta( $child_id, '_price', true );
263
- $the_product = wc_get_product( $child_id );
264
- $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
265
- if ( $the_price == $price ) {
266
- return $this->add_global_discount( $price, $the_product, 'price' );
 
267
  }
 
 
 
 
 
268
  }
269
  }
270
- return $price;
271
- }
272
 
273
- /**
274
- * calculate_price.
275
- *
276
- * @version 3.8.0
277
- * @since 2.5.7
278
- */
279
- function calculate_price( $price, $coefficient, $group ) {
280
- if ( '' === $price ) {
 
 
 
 
 
 
 
 
 
 
 
 
281
  return $price;
282
  }
283
- $return_price = ( 'percent' === wcj_get_option( 'wcj_global_discount_sale_coefficient_type_' . $group, 'percent' ) ) ?
 
 
 
 
 
 
 
 
 
 
 
 
 
 
284
  ( $price + $price * ( $coefficient / 100 ) ) :
285
  ( $price + $coefficient );
286
- $return_price = ( $return_price >= 0 ? $return_price : 0 );
287
- if ( 'none' != ( $final_correction_function = wcj_get_option( 'wcj_global_discount_sale_final_correction_func_' . $group, 'none' ) ) ) {
288
- $final_correction_coef = wcj_get_option( 'wcj_global_discount_sale_final_correction_coef_' . $group, 1 );
289
- $return_price = $final_correction_function( $return_price / $final_correction_coef ) * $final_correction_coef;
 
 
 
290
  }
291
- return $return_price;
292
- }
293
 
294
- /**
295
- * check_if_applicable.
296
- *
297
- * @version 3.1.0
298
- * @since 2.5.7
299
- * @return bool
300
- */
301
- function check_if_applicable( $_product, $group ) {
302
- return ( 'yes' === wcj_get_option( 'wcj_global_discount_sale_enabled_' . $group, 'yes' ) && $this->is_enabled_for_product( $_product, $group ) );
303
- }
 
 
304
 
305
- /**
306
- * is_enabled_for_product.
307
- *
308
- * @version 3.1.0
309
- * @since 3.1.0
310
- */
311
- function is_enabled_for_product( $_product, $group ) {
312
- $product_id = wcj_get_product_id_or_variation_parent_id( $_product );
313
- return wcj_is_enabled_for_product( $product_id, array(
314
- 'include_products' => wcj_get_option( 'wcj_global_discount_sale_products_incl_' . $group, '' ),
315
- 'exclude_products' => wcj_get_option( 'wcj_global_discount_sale_products_excl_' . $group, '' ),
316
- 'include_categories' => wcj_get_option( 'wcj_global_discount_sale_categories_incl_' . $group, '' ),
317
- 'exclude_categories' => wcj_get_option( 'wcj_global_discount_sale_categories_excl_' . $group, '' ),
318
- 'include_tags' => wcj_get_option( 'wcj_global_discount_sale_tags_incl_' . $group, '' ),
319
- 'exclude_tags' => wcj_get_option( 'wcj_global_discount_sale_tags_excl_' . $group, '' ),
320
- ) );
321
- }
 
 
 
 
 
322
 
323
- /**
324
- * check_if_applicable_by_product_scope.
325
- *
326
- * @version 3.9.0
327
- * @since 3.1.0
328
- */
329
- function check_if_applicable_by_product_scope( $_product, $price, $price_type, $scope ) {
330
- $return = true;
331
- if ( 'sale_price' === $price_type ) {
332
- if ( 0 == $price ) {
333
- // The product is currently not on sale
334
- if ( 'only_on_sale' === $scope ) {
335
- $return = false;
 
 
 
 
 
 
 
 
 
 
336
  }
337
  } else {
338
- // The product is currently on sale
339
- if ( 'only_not_on_sale' === $scope ) {
 
 
340
  $return = false;
341
  }
 
342
  }
343
- } else { // if ( 'price' === $price_type )
344
- wcj_remove_change_price_hooks( $this, $this->price_hooks_priority, false );
345
- if ( 'only_on_sale' === $scope && 0 == $_product->get_sale_price() ) {
346
- $return = false;
347
- } elseif ( 'only_not_on_sale' === $scope && 0 != $_product->get_sale_price() ) {
348
- $return = false;
349
- }
350
- wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
351
  }
352
- return $return;
353
- }
354
 
355
- /**
356
- * add_global_discount.
357
- *
358
- * @version 3.1.0
359
- * @since 2.5.7
360
- */
361
- function add_global_discount( $price, $_product, $price_type ) {
362
-
363
- if ( 'price' === $price_type && '' === $price ) {
364
- return $price; // no changes
365
- }
366
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_global_discount_groups_total_number', 1 ) );
367
- for ( $i = 1; $i <= $total_number; $i++ ) {
368
- if ( ! $this->check_if_applicable( $_product, $i ) ) {
369
- continue; // no changes by current discount group
370
  }
371
- $coefficient = wcj_get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
372
- if ( 0 != $coefficient ) {
373
- if ( ! $this->check_if_applicable_by_product_scope( $_product, $price, $price_type, wcj_get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' ) ) ) {
374
- continue; // no changes by current discount group
375
  }
376
- if ( 'sale_price' === $price_type && 0 == (int)$price ) {
377
- $price = $_product->get_regular_price();
 
 
 
 
 
 
 
378
  }
379
- return $this->calculate_price( $price, $coefficient, $i ); // discount applied
380
  }
 
381
  }
382
- return $price; // no changes
383
- }
384
 
385
- /**
386
- * get_global_discount_options.
387
- *
388
- * @version 4.8.0
389
- * @since 4.8.0
390
- *
391
- * @return array
392
- */
393
- function get_global_discount_options() {
394
- $options = $this->wcj_global_options;
395
- if ( empty( $options ) ) {
396
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_global_discount_groups_total_number', 1 ) );
397
- $options['total_number'] = $total_number;
398
- for ( $i = 1; $i <= $total_number; $i ++ ) {
399
- $options['enabled'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
400
- $options['type'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_coefficient_type_' . $i, 'percent' );
401
- $options['value'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
402
- $options['scope'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
403
- $options['cats_in'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_categories_incl_' . $i, array() );
404
- $options['cats_ex'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_categories_excl_' . $i, array() );
405
- $options['tags_in'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_tags_incl_' . $i, array() );
406
- $options['tags_ex'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_tags_excl_' . $i, array() );
407
- $options['products_in'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_products_incl_' . $i, array() );
408
- $options['products_ex'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_products_excl_' . $i, array() );
 
 
409
  }
410
- $this->wcj_global_options = $options;
411
  }
412
- return $options;
413
- }
414
 
415
- /**
416
- * get_variation_prices_hash.
417
- *
418
- * @version 4.9.0
419
- * @since 2.5.7
420
- */
421
- function get_variation_prices_hash( $price_hash, $_product, $display ) {
422
- $options = $this->get_global_discount_options();
423
- if ( is_array( $price_hash ) ) {
424
- $price_hash['wcj_global_discount_price_hash'] = $options;
 
 
 
 
 
425
  }
426
- return $price_hash;
427
- }
428
 
429
- }
430
 
431
  endif;
432
 
433
- return new WCJ_Global_Discount();
5
  * @version 5.5.4
6
  * @since 2.5.7
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Global_Discount' ) ) :
 
 
 
 
 
16
  /**
17
+ * WCJ_Global_Discount.
 
 
 
 
 
18
  */
19
+ class WCJ_Global_Discount extends WCJ_Module {
20
+ /**
21
+ * Wcj_global_options.
22
+ *
23
+ * @var $wcj_global_options.
24
+ */
25
+ private $wcj_global_options = array();
26
+
27
+ /**
28
+ * Constructor.
29
+ *
30
+ * @version 5.2.0
31
+ * @since 2.5.7
32
+ * @todo fee instead of discount
33
+ * @todo regular price coefficient
34
+ */
35
+ public function __construct() {
36
+
37
+ $this->id = 'global_discount';
38
+ $this->short_desc = __( 'Global Discount', 'woocommerce-jetpack' );
39
+ $this->desc = __( 'Add global discount to all products (1 discount group allowed in free version).', 'woocommerce-jetpack' );
40
+ $this->desc_pro = __( 'Add global discount to all products.', 'woocommerce-jetpack' );
41
+ $this->link_slug = 'woocommerce-shop-global-discount';
42
+ parent::__construct();
43
+
44
+ if ( $this->is_enabled() ) {
45
+ $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'global_discount' );
46
+ if ( 'yes' === wcj_get_option( 'wcj_global_discount_enabled_in_admin', 'no' ) || wcj_is_frontend() ) {
47
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
48
+ }
49
+
50
+ add_action( 'admin_init', array( $this, 'regenerate_wcj_sale_products_in_cache' ) );
51
+ add_filter( 'woocommerce_shortcode_products_query', array( $this, 'add_wcj_sale_ids_to_products_shortcode' ), 10, 3 );
52
  }
53
 
 
 
54
  }
55
 
56
+ /**
57
+ * Add_wcj_sale_ids_to_products_shortcode.
58
+ *
59
+ * @version 4.8.0
60
+ * @since 4.8.0
61
+ *
62
+ * @param array $args defines the args.
63
+ * @param string | array $atts defines the atts.
64
+ * @param string $type defines the type.
65
+ *
66
+ * @return mixed
67
+ */
68
+ public function add_wcj_sale_ids_to_products_shortcode( $args, $atts, $type ) {
69
+ if (
70
+ 'sale_products' !== $type ||
71
+ 'yes' !== wcj_get_option( 'wcj_global_discount_products_shortcode_compatibility', 'no' )
72
+ ) {
73
+ return $args;
74
+ }
75
 
76
+ $prev_post__in = isset( $args['post__in'] ) ? $args['post__in'] : array();
77
+ $args['post__in'] = array_merge( $prev_post__in, $this->get_wcj_sale_products() );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  return $args;
79
  }
80
 
81
+ /**
82
+ * Regenerate_wcj_sale_products_in_cache.
83
+ *
84
+ * @version 4.8.0
85
+ * @since 4.8.0
86
+ */
87
+ public function regenerate_wcj_sale_products_in_cache() {
88
+ if (
89
+ 'yes' !== wcj_get_option( 'wcj_global_discount_products_shortcode_compatibility', 'no' ) ||
 
 
 
 
 
90
  ! isset( $_REQUEST['page'] ) || 'wc-settings' !== $_REQUEST['page'] ||
91
  ! isset( $_REQUEST['tab'] ) || 'jetpack' !== $_REQUEST['tab'] ||
92
  ! isset( $_REQUEST['wcj-cat'] ) || 'prices_and_currencies' !== $_REQUEST['wcj-cat'] ||
93
  ! isset( $_REQUEST['section'] ) || 'global_discount' !== $_REQUEST['section'] ||
94
  ! isset( $_POST['save'] )
95
+ ) {
96
+ return;
97
+ }
98
+ $this->clear_wcj_sale_products_from_cache();
99
+ $this->get_wcj_sale_products();
100
  }
 
 
 
101
 
102
+ /**
103
+ * Get_wcj_sale_products.
104
+ *
105
+ * @version 4.8.0
106
+ * @since 4.8.0
107
+ *
108
+ * @return array|mixed
109
+ */
110
+ public function get_wcj_sale_products() {
111
+ $transient_name = 'wcj_global_discount_sale_products';
112
+ $sale_products = get_transient( $transient_name );
113
+ if ( false === $sale_products ) {
114
+ $args = array(
115
+ 'post_type' => 'product',
116
+ 'posts_per_page' => - 1,
117
+ 'fields' => 'ids',
118
+ );
119
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_global_discount_groups_total_number', 1 ) );
120
+ for ( $i = 1; $i <= $total_number; $i ++ ) {
121
+ $enabled = wcj_get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
122
+ if ( 'yes' !== $enabled ) {
123
+ continue;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  }
125
+
126
+ // Categories.
127
+ $include_cats = wcj_get_option( 'wcj_global_discount_sale_categories_incl_' . $i, array() );
128
+ $exclude_cats = wcj_get_option( 'wcj_global_discount_sale_categories_excl_' . $i, array() );
129
+ $cats = array();
130
+ if ( ! empty( $include_cats ) || ! empty( $exclude_cats ) ) {
131
+ $cats = array(
132
+ 'relation' => 'AND',
133
  );
134
+ if ( ! empty( $include_cats ) ) {
135
+ $cats[] = array(
136
+ 'taxonomy' => 'product_cat',
137
+ 'field' => 'term_id',
138
+ 'include_children' => false,
139
+ 'terms' => $include_cats,
140
+ );
141
+ }
142
+ if ( ! empty( $exclude_cats ) ) {
143
+ $cats[] = array(
144
+ 'taxonomy' => 'product_cat',
145
+ 'field' => 'term_id',
146
+ 'include_children' => false,
147
+ 'terms' => $exclude_cats,
148
+ 'operator' => 'NOT IN',
149
+ );
150
+ }
151
  }
 
152
 
153
+ // Tags.
154
+ $include_tags = wcj_get_option( 'wcj_global_discount_sale_tags_incl_' . $i, array() );
155
+ $exclude_tags = wcj_get_option( 'wcj_global_discount_sale_tags_excl_' . $i, array() );
156
+ $tags = array();
157
+ if ( ! empty( $include_tags ) || ! empty( $exclude_tags ) ) {
158
+ $tags = array(
159
+ 'relation' => 'AND',
 
 
 
 
 
 
160
  );
161
+ if ( ! empty( $include_tags ) ) {
162
+ $tags[] = array(
163
+ 'taxonomy' => 'product_tag',
164
+ 'field' => 'term_id',
165
+ 'terms' => $include_tags,
166
+ );
167
+ }
168
+ if ( ! empty( $exclude_tags ) ) {
169
+ $tags[] = array(
170
+ 'taxonomy' => 'product_tag',
171
+ 'field' => 'term_id',
172
+ 'terms' => $exclude_tags,
173
+ 'operator' => 'NOT IN',
174
+ );
175
+ }
176
  }
177
+
178
+ // Tax Query.
179
+ if ( ! empty( $cats ) || ! empty( $tags ) ) {
180
+ $args['tax_query'] = array(
181
+ 'relation' => 'AND',
 
182
  );
183
+ if ( ! empty( $cats ) ) {
184
+ $args['tax_query'][] = $cats;
185
+ }
186
+ if ( ! empty( $tags ) ) {
187
+ $args['tax_query'][] = $tags;
188
+ }
189
  }
 
190
 
191
+ // Products.
192
+ $products_incl = wcj_get_option( 'wcj_global_discount_sale_products_incl_' . $i, array() );
193
+ $products_excl = wcj_get_option( 'wcj_global_discount_sale_products_excl_' . $i, array() );
194
+ if ( ! empty( $products_incl ) || ! empty( $products_excl ) ) {
195
+ if ( ! empty( $products_incl ) ) {
196
+ $args['post__in'] = $products_incl;
197
+ }
198
+ if ( ! empty( $products_excl ) ) {
199
+ $args['post__not_in'] = $products_excl;
200
+ }
201
  }
 
202
 
203
+ // Scope.
204
+ $scope = wcj_get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
205
+ if ( 'all' !== $scope ) {
206
+ $wc_sale_products = wc_get_product_ids_on_sale();
207
+ if ( 'only_on_sale' === $scope ) {
208
+ $args['post__in'] = $wc_sale_products;
209
+ if ( empty( $wc_sale_products ) ) {
210
+ $args['post_type'] = 'do_not_search';
211
+ }
212
+ } elseif ( 'only_not_on_sale' === $scope ) {
213
+ $args['post__not_in'] = $wc_sale_products;
214
+ }
215
  }
 
216
 
217
+ $query = new WP_Query( $args );
218
+ $sale_products = array_unique( $query->posts );
219
+ $prev_group_sale_products = get_transient( $transient_name );
220
+ if ( false !== $prev_group_sale_products ) {
221
+ $sale_products = array_unique( array_merge( $prev_group_sale_products, $sale_products ) );
 
 
 
 
 
 
222
  }
 
223
 
224
+ set_transient( $transient_name, $sale_products, YEAR_IN_SECONDS );
 
 
 
 
225
  }
 
 
226
  }
227
+ return $sale_products;
228
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
 
230
+ /**
231
+ * Clear_wcj_sale_products_from_cache.
232
+ *
233
+ * @version 4.8.0
234
+ * @since 4.8.0
235
+ */
236
+ public function clear_wcj_sale_products_from_cache() {
237
+ delete_transient( 'wcj_global_discount_sale_products' );
238
  }
 
239
 
240
+ /**
241
+ * Change_price.
242
+ *
243
+ * @version 5.3.8
244
+ * @since 3.1.0
245
+ * @todo `WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER, 'woocommerce_variation_prices_regular_price', 'woocommerce_product_variation_get_regular_price'`
246
+ * @param int $price defines the price.
247
+ * @param array | string $_product defines the _product.
248
+ */
249
+ public function change_price( $price, $_product ) {
250
+ $_current_filter = current_filter();
251
+ if ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_PRICE_FILTER, 'woocommerce_variation_prices_price', 'woocommerce_product_variation_get_price' ) ) ) {
252
+ if ( isset( $_product->wcj_wholesale_price ) ) {
253
+
254
+ return $_product->wcj_wholesale_price;
255
  }
256
+ return $this->add_global_discount( $price, $_product, 'price' );
257
+ } elseif ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_SALE_PRICE_FILTER, 'woocommerce_variation_prices_sale_price', 'woocommerce_product_variation_get_sale_price' ) ) ) {
258
+ return $this->add_global_discount( $price, $_product, 'sale_price' );
259
+ } else {
260
+ return $price;
261
  }
262
  }
 
 
263
 
264
+ /**
265
+ * Change_price_grouped.
266
+ *
267
+ * @version 3.1.0
268
+ * @since 2.5.7
269
+ * @param int $price defines the price.
270
+ * @param int $qty defines the qty.
271
+ * @param string | array $_product defines the _product.
272
+ */
273
+ public function change_price_grouped( $price, $qty, $_product ) {
274
+ if ( $_product->is_type( 'grouped' ) ) {
275
+ foreach ( $_product->get_children() as $child_id ) {
276
+ $the_price = get_post_meta( $child_id, '_price', true );
277
+ $the_product = wc_get_product( $child_id );
278
+ $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
279
+ if ( $the_price === $price ) {
280
+ return $this->add_global_discount( $price, $the_product, 'price' );
281
+ }
282
+ }
283
+ }
284
  return $price;
285
  }
286
+
287
+ /**
288
+ * Calculate_price.
289
+ *
290
+ * @version 3.8.0
291
+ * @since 2.5.7
292
+ * @param int $price defines the price.
293
+ * @param int $coefficient defines the coefficient.
294
+ * @param string | array $group defines the group.
295
+ */
296
+ public function calculate_price( $price, $coefficient, $group ) {
297
+ if ( '' === $price ) {
298
+ return $price;
299
+ }
300
+ $return_price = ( 'percent' === wcj_get_option( 'wcj_global_discount_sale_coefficient_type_' . $group, 'percent' ) ) ?
301
  ( $price + $price * ( $coefficient / 100 ) ) :
302
  ( $price + $coefficient );
303
+ $return_price = ( $return_price >= 0 ? $return_price : 0 );
304
+ $final_correction_function = wcj_get_option( 'wcj_global_discount_sale_final_correction_func_' . $group, 'none' );
305
+ if ( 'none' !== ( $final_correction_function ) ) {
306
+ $final_correction_coef = wcj_get_option( 'wcj_global_discount_sale_final_correction_coef_' . $group, 1 );
307
+ $return_price = $final_correction_function( $return_price / $final_correction_coef ) * $final_correction_coef;
308
+ }
309
+ return $return_price;
310
  }
 
 
311
 
312
+ /**
313
+ * Check_if_applicable.
314
+ *
315
+ * @version 3.1.0
316
+ * @since 2.5.7
317
+ * @return bool
318
+ * @param string | array $_product defines the _product.
319
+ * @param string | array $group defines the group.
320
+ */
321
+ public function check_if_applicable( $_product, $group ) {
322
+ return ( 'yes' === wcj_get_option( 'wcj_global_discount_sale_enabled_' . $group, 'yes' ) && $this->is_enabled_for_product( $_product, $group ) );
323
+ }
324
 
325
+ /**
326
+ * Is_enabled_for_product.
327
+ *
328
+ * @version 3.1.0
329
+ * @since 3.1.0
330
+ * @param string | array $_product defines the _product.
331
+ * @param string | array $group defines the group.
332
+ */
333
+ public function is_enabled_for_product( $_product, $group ) {
334
+ $product_id = wcj_get_product_id_or_variation_parent_id( $_product );
335
+ return wcj_is_enabled_for_product(
336
+ $product_id,
337
+ array(
338
+ 'include_products' => wcj_get_option( 'wcj_global_discount_sale_products_incl_' . $group, '' ),
339
+ 'exclude_products' => wcj_get_option( 'wcj_global_discount_sale_products_excl_' . $group, '' ),
340
+ 'include_categories' => wcj_get_option( 'wcj_global_discount_sale_categories_incl_' . $group, '' ),
341
+ 'exclude_categories' => wcj_get_option( 'wcj_global_discount_sale_categories_excl_' . $group, '' ),
342
+ 'include_tags' => wcj_get_option( 'wcj_global_discount_sale_tags_incl_' . $group, '' ),
343
+ 'exclude_tags' => wcj_get_option( 'wcj_global_discount_sale_tags_excl_' . $group, '' ),
344
+ )
345
+ );
346
+ }
347
 
348
+ /**
349
+ * Check_if_applicable_by_product_scope.
350
+ *
351
+ * @version 3.9.0
352
+ * @since 3.1.0
353
+ * @param string | array $_product defines the _product.
354
+ * @param int $price defines the price.
355
+ * @param string $price_type defines the price_type.
356
+ * @param string $scope defines the scope.
357
+ */
358
+ public function check_if_applicable_by_product_scope( $_product, $price, $price_type, $scope ) {
359
+ $return = true;
360
+ if ( 'sale_price' === $price_type ) {
361
+ if ( 0 === $price ) {
362
+ // The product is currently not on sale.
363
+ if ( 'only_on_sale' === $scope ) {
364
+ $return = false;
365
+ }
366
+ } else {
367
+ // The product is currently on sale.
368
+ if ( 'only_not_on_sale' === $scope ) {
369
+ $return = false;
370
+ }
371
  }
372
  } else {
373
+ wcj_remove_change_price_hooks( $this, $this->price_hooks_priority, false );
374
+ if ( 'only_on_sale' === $scope && 0 === $_product->get_sale_price() ) {
375
+ $return = false;
376
+ } elseif ( 'only_not_on_sale' === $scope && 0 !== $_product->get_sale_price() ) {
377
  $return = false;
378
  }
379
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
380
  }
381
+ return $return;
 
 
 
 
 
 
 
382
  }
 
 
383
 
384
+ /**
385
+ * Add_global_discount.
386
+ *
387
+ * @version 3.1.0
388
+ * @since 2.5.7
389
+ * @param int $price defines the price.
390
+ * @param string | array $_product defines the _product.
391
+ * @param string $price_type defines the price_type.
392
+ */
393
+ public function add_global_discount( $price, $_product, $price_type ) {
394
+
395
+ if ( 'price' === $price_type && '' === $price ) {
396
+ return $price; // no changes.
 
 
397
  }
398
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_global_discount_groups_total_number', 1 ) );
399
+ for ( $i = 1; $i <= $total_number; $i++ ) {
400
+ if ( ! $this->check_if_applicable( $_product, $i ) ) {
401
+ continue; // no changes by current discount group.
402
  }
403
+ $coefficient = wcj_get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
404
+ if ( 0 !== $coefficient ) {
405
+ if ( ! $this->check_if_applicable_by_product_scope( $_product, $price, $price_type, wcj_get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' ) ) ) {
406
+ continue; // no changes by current discount group.
407
+ }
408
+ if ( 'sale_price' === $price_type && 0 === (int) $price ) {
409
+ $price = $_product->get_regular_price();
410
+ }
411
+ return $this->calculate_price( $price, $coefficient, $i ); // discount applied.
412
  }
 
413
  }
414
+ return $price; // no changes.
415
  }
 
 
416
 
417
+ /**
418
+ * Get_global_discount_options.
419
+ *
420
+ * @version 4.8.0
421
+ * @since 4.8.0
422
+ *
423
+ * @return array
424
+ */
425
+ public function get_global_discount_options() {
426
+ $options = $this->wcj_global_options;
427
+ if ( empty( $options ) ) {
428
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_global_discount_groups_total_number', 1 ) );
429
+ $options['total_number'] = $total_number;
430
+ for ( $i = 1; $i <= $total_number; $i ++ ) {
431
+ $options['enabled'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
432
+ $options['type'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_coefficient_type_' . $i, 'percent' );
433
+ $options['value'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
434
+ $options['scope'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
435
+ $options['cats_in'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_categories_incl_' . $i, array() );
436
+ $options['cats_ex'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_categories_excl_' . $i, array() );
437
+ $options['tags_in'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_tags_incl_' . $i, array() );
438
+ $options['tags_ex'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_tags_excl_' . $i, array() );
439
+ $options['products_in'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_products_incl_' . $i, array() );
440
+ $options['products_ex'][ $i ] = wcj_get_option( 'wcj_global_discount_sale_products_excl_' . $i, array() );
441
+ }
442
+ $this->wcj_global_options = $options;
443
  }
444
+ return $options;
445
  }
 
 
446
 
447
+ /**
448
+ * Get_variation_prices_hash.
449
+ *
450
+ * @version 4.9.0
451
+ * @since 2.5.7
452
+ * @param array $price_hash defines the price_hash.
453
+ * @param string | array $_product defines the _product.
454
+ * @param string $display defines the display.
455
+ */
456
+ public function get_variation_prices_hash( $price_hash, $_product, $display ) {
457
+ $options = $this->get_global_discount_options();
458
+ if ( is_array( $price_hash ) ) {
459
+ $price_hash['wcj_global_discount_price_hash'] = $options;
460
+ }
461
+ return $price_hash;
462
  }
 
 
463
 
464
+ }
465
 
466
  endif;
467
 
468
+ return new WCJ_Global_Discount();
includes/class-wcj-left-to-free-shipping.php CHANGED
@@ -5,94 +5,100 @@
5
  * @version 2.8.0
6
  * @since 2.5.8
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Left_To_Free_Shipping' ) ) :
13
-
14
- class WCJ_Left_To_Free_Shipping extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 2.8.0
20
- * @since 2.5.8
21
  */
22
- function __construct() {
23
 
24
- $this->id = 'left_to_free_shipping';
25
- $this->short_desc = __( 'Left to Free Shipping', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Display "left to free shipping" info.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-left-to-free-shipping';
28
- parent::__construct();
 
 
29
 
30
- if ( $this->is_enabled() ) {
31
- if ( 'yes' === wcj_get_option( 'wcj_shipping_left_to_free_info_enabled_cart', 'no' ) ) {
32
- add_action(
33
- get_option( 'wcj_shipping_left_to_free_info_position_cart', 'woocommerce_after_cart_totals' ),
34
- array( $this, 'show_left_to_free_shipping_info_cart' ),
35
- get_option( 'wcj_shipping_left_to_free_info_priority_cart', 10 )
36
- );
37
- }
38
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_shipping_left_to_free_info_enabled_mini_cart', 'no' ) ) ) {
39
- add_action(
40
- get_option( 'wcj_shipping_left_to_free_info_position_mini_cart', 'woocommerce_after_mini_cart' ),
41
- array( $this, 'show_left_to_free_shipping_info_mini_cart' ),
42
- get_option( 'wcj_shipping_left_to_free_info_priority_mini_cart', 10 )
43
- );
44
- }
45
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_shipping_left_to_free_info_enabled_checkout', 'no' ) ) ) {
46
- add_action(
47
- get_option( 'wcj_shipping_left_to_free_info_position_checkout', 'woocommerce_checkout_after_order_review' ),
48
- array( $this, 'show_left_to_free_shipping_info_checkout' ),
49
- get_option( 'wcj_shipping_left_to_free_info_priority_checkout', 10 )
50
- );
 
 
 
 
 
 
 
51
  }
52
  }
53
- }
54
 
55
- /**
56
- * show_left_to_free_shipping_info_checkout.
57
- *
58
- * @version 2.5.2
59
- * @since 2.4.4
60
- */
61
- function show_left_to_free_shipping_info_checkout() {
62
- $this->show_left_to_free_shipping_info( do_shortcode( wcj_get_option( 'wcj_shipping_left_to_free_info_content_checkout', __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' ) ) ) );
63
- }
64
 
65
- /**
66
- * show_left_to_free_shipping_info_mini_cart.
67
- *
68
- * @version 2.5.2
69
- * @since 2.4.4
70
- */
71
- function show_left_to_free_shipping_info_mini_cart() {
72
- $this->show_left_to_free_shipping_info( do_shortcode( wcj_get_option( 'wcj_shipping_left_to_free_info_content_mini_cart', __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' ) ) ) );
73
- }
74
 
75
- /**
76
- * show_left_to_free_shipping_info_cart.
77
- *
78
- * @version 2.5.2
79
- * @since 2.4.4
80
- */
81
- function show_left_to_free_shipping_info_cart() {
82
- $this->show_left_to_free_shipping_info( do_shortcode( wcj_get_option( 'wcj_shipping_left_to_free_info_content_cart', __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' ) ) ) );
83
- }
84
 
85
- /**
86
- * show_left_to_free_shipping_info.
87
- *
88
- * @version 2.4.4
89
- * @since 2.4.4
90
- */
91
- function show_left_to_free_shipping_info( $content ) {
92
- echo wcj_get_left_to_free_shipping( $content );
93
- }
 
94
 
95
- }
96
 
97
  endif;
98
 
5
  * @version 2.8.0
6
  * @since 2.5.8
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Left_To_Free_Shipping' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Left_To_Free_Shipping.
 
 
 
18
  */
19
+ class WCJ_Left_To_Free_Shipping extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 2.8.0
25
+ * @since 2.5.8
26
+ */
27
+ public function __construct() {
28
 
29
+ $this->id = 'left_to_free_shipping';
30
+ $this->short_desc = __( 'Left to Free Shipping', 'woocommerce-jetpack' );
31
+ $this->desc = __( 'Display "left to free shipping" info.', 'woocommerce-jetpack' );
32
+ $this->link_slug = 'woocommerce-left-to-free-shipping';
33
+ parent::__construct();
34
+
35
+ if ( $this->is_enabled() ) {
36
+ if ( 'yes' === wcj_get_option( 'wcj_shipping_left_to_free_info_enabled_cart', 'no' ) ) {
37
+ add_action(
38
+ get_option( 'wcj_shipping_left_to_free_info_position_cart', 'woocommerce_after_cart_totals' ),
39
+ array( $this, 'show_left_to_free_shipping_info_cart' ),
40
+ get_option( 'wcj_shipping_left_to_free_info_priority_cart', 10 )
41
+ );
42
+ }
43
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_shipping_left_to_free_info_enabled_mini_cart', 'no' ) ) ) {
44
+ add_action(
45
+ get_option( 'wcj_shipping_left_to_free_info_position_mini_cart', 'woocommerce_after_mini_cart' ),
46
+ array( $this, 'show_left_to_free_shipping_info_mini_cart' ),
47
+ get_option( 'wcj_shipping_left_to_free_info_priority_mini_cart', 10 )
48
+ );
49
+ }
50
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_shipping_left_to_free_info_enabled_checkout', 'no' ) ) ) {
51
+ add_action(
52
+ get_option( 'wcj_shipping_left_to_free_info_position_checkout', 'woocommerce_checkout_after_order_review' ),
53
+ array( $this, 'show_left_to_free_shipping_info_checkout' ),
54
+ get_option( 'wcj_shipping_left_to_free_info_priority_checkout', 10 )
55
+ );
56
+ }
57
  }
58
  }
 
59
 
60
+ /**
61
+ * Show_left_to_free_shipping_info_checkout.
62
+ *
63
+ * @version 2.5.2
64
+ * @since 2.4.4
65
+ */
66
+ public function show_left_to_free_shipping_info_checkout() {
67
+ $this->show_left_to_free_shipping_info( do_shortcode( wcj_get_option( 'wcj_shipping_left_to_free_info_content_checkout', __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' ) ) ) );
68
+ }
69
 
70
+ /**
71
+ * Show_left_to_free_shipping_info_mini_cart.
72
+ *
73
+ * @version 2.5.2
74
+ * @since 2.4.4
75
+ */
76
+ public function show_left_to_free_shipping_info_mini_cart() {
77
+ $this->show_left_to_free_shipping_info( do_shortcode( wcj_get_option( 'wcj_shipping_left_to_free_info_content_mini_cart', __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' ) ) ) );
78
+ }
79
 
80
+ /**
81
+ * Show_left_to_free_shipping_info_cart.
82
+ *
83
+ * @version 2.5.2
84
+ * @since 2.4.4
85
+ */
86
+ public function show_left_to_free_shipping_info_cart() {
87
+ $this->show_left_to_free_shipping_info( do_shortcode( wcj_get_option( 'wcj_shipping_left_to_free_info_content_cart', __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' ) ) ) );
88
+ }
89
 
90
+ /**
91
+ * Show_left_to_free_shipping_info.
92
+ *
93
+ * @version 2.4.4
94
+ * @since 2.4.4
95
+ * @param string | array $content defines the content.
96
+ */
97
+ public function show_left_to_free_shipping_info( $content ) {
98
+ echo wp_kses_post( wcj_get_left_to_free_shipping( $content ) );
99
+ }
100
 
101
+ }
102
 
103
  endif;
104
 
includes/class-wcj-max-products-per-user.php CHANGED
@@ -5,347 +5,387 @@
5
  * @version 5.5.9
6
  * @since 3.5.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Max_products_Per_User' ) ) :
13
-
14
- class WCJ_Max_products_Per_User extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.2.0
20
- * @since 3.5.0
21
- * @todo (maybe) JS
22
- * @todo (maybe) zero quantity for "Guest"
23
- * @todo (maybe) editable sales data (i.e. change "Qty Bought" for product for user)
24
- * @todo (maybe) `wcj_max_products_per_user_order_status` - add "Any" option
25
- * @todo (maybe) `wcj_max_products_per_user_order_status` - add "Manually" option
26
  */
27
- function __construct() {
28
 
29
- $this->id = 'max_products_per_user';
30
- $this->short_desc = __( 'Maximum Products per User', 'woocommerce-jetpack' );
31
- $this->desc = __( 'Limit number of items your (logged) customers can buy (Free version allows to limit globally).', 'woocommerce-jetpack' );
32
- $this->desc_pro = __( 'Limit number of items your (logged) customers can buy.', 'woocommerce-jetpack' );
33
- $this->extra_desc = __( 'Please note, that there is no maximum quantity set for not-logged (i.e. guest) users. Product quantities are updated, when order status is changed to status listed in module\'s "Order Status" option.', 'woocommerce-jetpack' );
34
- $this->link_slug = 'woocommerce-maximum-products-per-user';
35
- parent::__construct();
 
 
 
 
 
36
 
37
- if ( $this->is_enabled() ) {
38
- if ( 'yes' === wcj_get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) || 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
39
- add_action( 'woocommerce_checkout_process', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
40
- add_action( 'woocommerce_before_cart', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
41
- if ( 'yes' === wcj_get_option( 'wcj_max_products_per_user_stop_from_adding_to_cart', 'no' ) ) {
42
- add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_on_add_to_cart' ), PHP_INT_MAX, 3 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
43
  }
44
- if ( 'yes' === wcj_get_option( 'wcj_max_products_per_user_stop_from_seeing_checkout', 'no' ) ) {
45
- add_action( 'wp', array( $this, 'stop_from_seeing_checkout' ), PHP_INT_MAX );
 
46
  }
47
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
48
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
49
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
50
  }
 
 
 
51
  }
52
- $this->order_status = wcj_get_option( 'wcj_max_products_per_user_order_status', array( 'wc-completed' ) );
53
- if ( empty( $this->order_status ) ) {
54
- $this->order_status = array( 'wc-completed' );
55
- }
56
- foreach ( $this->order_status as $status ) {
57
- $status = substr( $status, 3 );
58
- add_action( 'woocommerce_order_status_' . $status, array( $this, 'save_quantities' ), PHP_INT_MAX );
59
- }
60
- add_action( 'add_meta_boxes', array( $this, 'add_report_meta_box' ) );
61
- add_action( 'admin_init', array( $this, 'calculate_data' ) );
62
- add_action( 'admin_notices', array( $this, 'calculate_data_notice' ) );
63
  }
64
- }
65
 
66
- /**
67
- * validate_on_add_to_cart.
68
- *
69
- * @version 4.2.0
70
- * @since 4.2.0
71
- * @todo [dev] code refactoring (this function is very similar to `$this->check_quantities()`)
72
- * @todo [dev] (maybe) recheck `wc_add_notice()` or `wc_print_notice()`
73
- * @todo [feature] add two additional (i.e. not `wcj_max_products_per_user_message`) separate messages: 1) `( 0 == $currently_in_cart )` and 2) '( 0 != $currently_in_cart )`
74
- * @todo [feature] add replaced value `%qty_already_in_cart%` (same in `$this->check_quantities()`)
75
- * @todo [feature] add replaced value `%current_add_to_cart_qty%`
76
- * @todo [feature] (maybe) add replaced value `%remaining_qty_incl_qty_already_in_cart%`
77
- * @todo [feature] (maybe) option to choose `wc_add_notice( $message, 'error' );` or `wc_add_notice( $message, 'notice' );`
78
- */
79
- function validate_on_add_to_cart( $passed, $product_id, $quantity ) {
80
- // Get max quantity (for current product)
81
- if ( 0 == ( $max_qty = $this->get_max_qty( $product_id ) ) ) {
82
- return $passed; // no max qty set for current product
83
- }
84
- // Get quantity already bought (for current user / current product)
85
- if ( 0 == ( $current_user_id = wcj_get_current_user_id() ) ) {
86
- return $passed; // unlogged (i.e. guest) user
87
- }
88
- $user_already_bought = 0;
89
- if ( ( $users_quantities = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', true ) ) && isset( $users_quantities[ $current_user_id ] ) ) {
90
- $user_already_bought = $users_quantities[ $current_user_id ];
91
- }
92
- // Get quantity in cart (for current product)
93
- $currently_in_cart = 0;
94
- if ( isset( WC()->cart ) ) {
95
- $cart_item_quantities = WC()->cart->get_cart_item_quantities();
96
- if ( ! empty( $cart_item_quantities ) && is_array( $cart_item_quantities ) ) {
97
- foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
98
- if ( $_product_id == $product_id ) {
99
- $currently_in_cart += $cart_item_quantity;
 
 
 
 
 
 
 
100
  }
101
  }
102
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  }
104
- // Validate
105
- if ( ( $currently_in_cart + $user_already_bought + $quantity ) > $max_qty ) {
106
- $product = wc_get_product( $product_id );
107
- $replaced_values = array(
108
- '%max_qty%' => $max_qty,
109
- '%product_title%' => $product->get_title(),
110
- '%qty_already_bought%' => $user_already_bought,
111
- '%remaining_qty%' => max( ( $max_qty - $user_already_bought ), 0 ),
112
- );
113
- $message = wcj_get_option( 'wcj_max_products_per_user_message',
114
- __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' ) );
115
- $message = str_replace( array_keys( $replaced_values ), $replaced_values, $message );
116
- wc_add_notice( $message, 'error' );
117
- return false;
118
- }
119
- // Passed
120
- return $passed;
121
- }
122
 
123
- /**
124
- * calculate_data_notice.
125
- *
126
- * @version 3.5.0
127
- * @since 3.5.0
128
- */
129
- function calculate_data_notice() {
130
- if ( isset( $_GET['wcj_max_products_per_user_calculate_data_finished'] ) ) {
131
- $class = 'notice notice-info';
132
- $message = __( 'Data re-calculated.', 'woocommerce-jetpack' ) . ' ' .
 
133
  sprintf( __( '%s order(s) processed.', 'woocommerce-jetpack' ), $_GET['wcj_max_products_per_user_calculate_data_finished'] );
134
- printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
 
135
  }
136
- }
137
 
138
- /**
139
- * calculate_data.
140
- *
141
- * @version 5.5.9
142
- * @since 3.5.0
143
- * @todo reset `wcj_max_products_per_user_report` and `wcj_max_products_per_user_saved` meta
144
- */
145
- function calculate_data() {
146
- if ( isset( $_GET['wcj_max_products_per_user_calculate_data'] ) ) {
147
- $offset = 0;
148
- $block_size = 512;
149
- $total_orders = 0;
150
- while( true ) {
151
- $args = array(
152
- 'post_type' => 'shop_order',
153
- 'post_status' => $this->order_status,
154
- 'posts_per_page' => $block_size,
155
- 'orderby' => 'ID',
156
- 'order' => 'DESC',
157
- 'offset' => $offset,
158
- 'fields' => 'ids',
159
- );
160
- $loop = new WP_Query( $args );
161
- if ( ! $loop->have_posts() ) {
162
- break;
163
- }
164
- foreach ( $loop->posts as $_order_id ) {
165
- $this->save_quantities( $_order_id );
166
- $total_orders++;
 
 
167
  }
168
- $offset += $block_size;
 
 
 
 
 
 
 
169
  }
170
- wp_safe_redirect( add_query_arg( 'wcj_max_products_per_user_calculate_data_finished', $total_orders,
171
- remove_query_arg( 'wcj_max_products_per_user_calculate_data' ) ) );
172
- exit;
173
  }
174
- }
175
 
176
- /**
177
- * add_report_meta_box.
178
- *
179
- * @version 3.5.0
180
- * @since 3.5.0
181
- */
182
- function add_report_meta_box() {
183
- add_meta_box(
184
- 'wc-jetpack-' . $this->id . '-report',
185
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Maximum Products per User: Sales Data', 'woocommerce-jetpack' ),
186
- array( $this, 'create_report_meta_box' ),
187
- 'product',
188
- 'normal',
189
- 'high'
190
- );
191
- }
192
 
193
- /**
194
- * create_report_meta_box.
195
- *
196
- * @version 3.5.0
197
- * @since 3.5.0
198
- */
199
- function create_report_meta_box() {
200
- if ( $users_quantities = get_post_meta( get_the_ID(), '_' . 'wcj_max_products_per_user_report', true ) ) {
201
- $table_data = array();
202
- $table_data[] = array( __( 'User ID', 'woocommerce-jetpack' ), __( 'User Name', 'woocommerce-jetpack' ), __( 'Qty Bought', 'woocommerce-jetpack' ) );
203
- foreach ( $users_quantities as $user_id => $qty_bought ) {
204
- if ( 0 == $user_id ) {
205
- $user = __( 'Guest', 'woocommerce-jetpack' );
206
- } else {
207
- $user = get_user_by( 'id', $user_id );
208
- $user = ( isset( $user->data->user_nicename ) ? $user->data->user_nicename : '-' );
 
 
 
209
  }
210
- $table_data[] = array( $user_id, $user, $qty_bought );
 
 
 
 
 
 
 
 
 
 
211
  }
212
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal' ) );
213
- } else {
214
- echo '<em>' . __( 'No data yet.', 'woocommerce-jetpack' ) . '</em>';
215
  }
216
- }
217
 
218
- /**
219
- * save_quantities.
220
- *
221
- * @version 3.5.0
222
- * @since 3.5.0
223
- */
224
- function save_quantities( $order_id ) {
225
- if ( $order = wc_get_order( $order_id ) ) {
226
- if ( 'yes' !== get_post_meta( $order_id, '_' . 'wcj_max_products_per_user_saved', true ) ) {
227
- if ( sizeof( $order->get_items() ) > 0 ) {
228
- $user_id = ( WCJ_IS_WC_VERSION_BELOW_3 ? $order->customer_user : $order->get_customer_id() );
229
- foreach ( $order->get_items() as $item ) {
230
- if ( $item->is_type( 'line_item' ) && ( $product = $item->get_product() ) ) {
231
- $product_id = wcj_get_product_id_or_variation_parent_id( $product );
232
- $product_qty = $item->get_quantity();
233
- if ( '' == ( $users_quantities = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', true ) ) ) {
234
- $users_quantities = array();
 
 
 
 
 
 
 
 
 
 
235
  }
236
- if ( isset( $users_quantities[ $user_id ] ) ) {
237
- $product_qty += $users_quantities[ $user_id ];
238
- }
239
- $users_quantities[ $user_id ] = $product_qty;
240
- update_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', $users_quantities );
241
  }
242
  }
 
243
  }
244
- update_post_meta( $order_id, '_' . 'wcj_max_products_per_user_saved', 'yes' );
245
  }
246
  }
247
- }
248
 
249
- /**
250
- * get_max_qty.
251
- *
252
- * @version 3.5.0
253
- * @since 3.5.0
254
- * @todo (maybe) local - add "enabled/disabled" option
255
- * @todo (maybe) global - apply only to selected products (i.e. include/exclude products, cats, tags)
256
- * @todo (maybe) per user and/or per user role (both global and local)
257
- */
258
- function get_max_qty( $product_id ) {
259
- if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) && 0 != ( $qty = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_qty', true ) ) ) {
260
- return $qty;
261
- } elseif ( 'yes' === wcj_get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) ) {
262
- return wcj_get_option( 'wcj_max_products_per_user_global_max_qty', 1 );
263
- } else {
264
- return 0;
 
 
 
265
  }
266
- }
267
 
268
- /**
269
- * stop_from_seeing_checkout.
270
- *
271
- * @version 3.5.0
272
- * @since 3.5.0
273
- */
274
- function stop_from_seeing_checkout() {
275
- if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
276
- return;
277
- }
278
- if ( ! $this->check_quantities( false ) ) {
279
- wp_safe_redirect( wc_get_cart_url() );
280
- exit;
 
281
  }
282
- }
283
 
284
- /**
285
- * check_cart_quantities.
286
- *
287
- * @version 3.5.0
288
- * @since 3.5.0
289
- */
290
- function check_cart_quantities() {
291
- $this->check_quantities();
292
- }
293
-
294
- /**
295
- * check_quantities.
296
- *
297
- * @version 3.5.0
298
- * @since 3.5.0
299
- * @todo [dev] recheck `$cart_item_quantity` (maybe should be calculated same as `$currently_in_cart` in `$this->validate_on_add_to_cart()`)
300
- */
301
- function check_quantities( $add_notices = true ) {
302
- $result = true;
303
- if ( ! isset( WC()->cart ) ) {
304
- return $result;
305
  }
306
- if ( 0 == ( $current_user_id = wcj_get_current_user_id() ) ) {
307
- return $result;
308
- }
309
- $cart_item_quantities = WC()->cart->get_cart_item_quantities();
310
- if ( empty( $cart_item_quantities ) || ! is_array( $cart_item_quantities ) ) {
311
- return $result;
312
- }
313
- $is_cart = ( function_exists( 'is_cart' ) && is_cart() );
314
- foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
315
- if ( 0 == ( $max_qty = $this->get_max_qty( $_product_id ) ) ) {
316
- continue;
 
 
317
  }
318
- $user_already_bought = 0;
319
- if ( ( $users_quantities = get_post_meta( $_product_id, '_' . 'wcj_max_products_per_user_report', true ) ) && isset( $users_quantities[ $current_user_id ] ) ) {
320
- $user_already_bought = $users_quantities[ $current_user_id ];
321
  }
322
- if ( ( $user_already_bought + $cart_item_quantity ) > $max_qty ) {
323
- if ( $add_notices ) {
324
- $result = false;
325
- $product = wc_get_product( $_product_id );
326
- $replaced_values = array(
327
- '%max_qty%' => $max_qty,
328
- '%product_title%' => $product->get_title(),
329
- '%qty_already_bought%' => $user_already_bought,
330
- '%remaining_qty%' => max( ( $max_qty - $user_already_bought ), 0 ),
331
- );
332
- $message = wcj_get_option( 'wcj_max_products_per_user_message',
333
- __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' ) );
334
- $message = str_replace( array_keys( $replaced_values ), $replaced_values, $message );
335
- if ( $is_cart ) {
336
- wc_print_notice( $message, 'notice' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  } else {
338
- wc_add_notice( $message, 'error' );
339
  }
340
- } else {
341
- return false;
342
  }
343
  }
 
344
  }
345
- return $result;
346
- }
347
 
348
- }
349
 
350
  endif;
351
 
5
  * @version 5.5.9
6
  * @since 3.5.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Max_products_Per_User' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Max_products_Per_User.
 
 
 
 
 
 
 
 
18
  */
19
+ class WCJ_Max_products_Per_User extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.2.0
25
+ * @since 3.5.0
26
+ * @todo (maybe) JS
27
+ * @todo (maybe) zero quantity for "Guest"
28
+ * @todo (maybe) editable sales data (i.e. change "Qty Bought" for product for user)
29
+ * @todo (maybe) `wcj_max_products_per_user_order_status` - add "Any" option
30
+ * @todo (maybe) `wcj_max_products_per_user_order_status` - add "Manually" option
31
+ */
32
+ public function __construct() {
33
 
34
+ $this->id = 'max_products_per_user';
35
+ $this->short_desc = __( 'Maximum Products per User', 'woocommerce-jetpack' );
36
+ $this->desc = __( 'Limit number of items your (logged) customers can buy (Free version allows to limit globally).', 'woocommerce-jetpack' );
37
+ $this->desc_pro = __( 'Limit number of items your (logged) customers can buy.', 'woocommerce-jetpack' );
38
+ $this->extra_desc = __( 'Please note, that there is no maximum quantity set for not-logged (i.e. guest) users. Product quantities are updated, when order status is changed to status listed in module\'s "Order Status" option.', 'woocommerce-jetpack' );
39
+ $this->link_slug = 'woocommerce-maximum-products-per-user';
40
+ parent::__construct();
41
+
42
+ if ( $this->is_enabled() ) {
43
+ if ( 'yes' === wcj_get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) || 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
44
+ add_action( 'woocommerce_checkout_process', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
45
+ add_action( 'woocommerce_before_cart', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
46
+ if ( 'yes' === wcj_get_option( 'wcj_max_products_per_user_stop_from_adding_to_cart', 'no' ) ) {
47
+ add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_on_add_to_cart' ), PHP_INT_MAX, 3 );
48
+ }
49
+ if ( 'yes' === wcj_get_option( 'wcj_max_products_per_user_stop_from_seeing_checkout', 'no' ) ) {
50
+ add_action( 'wp', array( $this, 'stop_from_seeing_checkout' ), PHP_INT_MAX );
51
+ }
52
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
53
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
54
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
55
+ }
56
  }
57
+ $this->order_status = wcj_get_option( 'wcj_max_products_per_user_order_status', array( 'wc-completed' ) );
58
+ if ( empty( $this->order_status ) ) {
59
+ $this->order_status = array( 'wc-completed' );
60
  }
61
+ foreach ( $this->order_status as $status ) {
62
+ $status = substr( $status, 3 );
63
+ add_action( 'woocommerce_order_status_' . $status, array( $this, 'save_quantities' ), PHP_INT_MAX );
64
  }
65
+ add_action( 'add_meta_boxes', array( $this, 'add_report_meta_box' ) );
66
+ add_action( 'admin_init', array( $this, 'calculate_data' ) );
67
+ add_action( 'admin_notices', array( $this, 'calculate_data_notice' ) );
68
  }
 
 
 
 
 
 
 
 
 
 
 
69
  }
 
70
 
71
+ /**
72
+ * Validate_on_add_to_cart.
73
+ *
74
+ * @version 4.2.0
75
+ * @since 4.2.0
76
+ * @todo [dev] code refactoring (this function is very similar to `$this->check_quantities()`)
77
+ * @todo [dev] (maybe) recheck `wc_add_notice()` or `wc_print_notice()`
78
+ * @todo [feature] add two additional (i.e. not `wcj_max_products_per_user_message`) separate messages: 1) `( 0 == $currently_in_cart )` and 2) '( 0 != $currently_in_cart )`
79
+ * @todo [feature] add replaced value `%qty_already_in_cart%` (same in `$this->check_quantities()`)
80
+ * @todo [feature] add replaced value `%current_add_to_cart_qty%`
81
+ * @todo [feature] (maybe) add replaced value `%remaining_qty_incl_qty_already_in_cart%`
82
+ * @todo [feature] (maybe) option to choose `wc_add_notice( $message, 'error' );` or `wc_add_notice( $message, 'notice' );`
83
+ * @param string $passed defines the passed.
84
+ * @param int $product_id defines the product_id.
85
+ * @param int $quantity defines the quantity.
86
+ */
87
+ public function validate_on_add_to_cart( $passed, $product_id, $quantity ) {
88
+ // Get max quantity (for current product).
89
+ $max_qty = $this->get_max_qty( $product_id );
90
+ if ( 0 === ( $max_qty ) ) {
91
+ return $passed; // no max qty set for current product.
92
+ }
93
+ // Get quantity already bought (for current user / current product).
94
+ $current_user_id = wcj_get_current_user_id();
95
+ if ( 0 === ( $current_user_id ) ) {
96
+ return $passed; // unlogged (i.e. guest) user.
97
+ }
98
+ $user_already_bought = 0;
99
+ $users_quantities = get_post_meta( $product_id, '_wcj_max_products_per_user_report', true );
100
+ if ( ( $users_quantities ) && isset( $users_quantities[ $current_user_id ] ) ) {
101
+ $user_already_bought = $users_quantities[ $current_user_id ];
102
+ }
103
+ // Get quantity in cart (for current product).
104
+ $currently_in_cart = 0;
105
+ if ( isset( WC()->cart ) ) {
106
+ $cart_item_quantities = WC()->cart->get_cart_item_quantities();
107
+ if ( ! empty( $cart_item_quantities ) && is_array( $cart_item_quantities ) ) {
108
+ foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
109
+ if ( $_product_id === $product_id ) {
110
+ $currently_in_cart += $cart_item_quantity;
111
+ }
112
  }
113
  }
114
  }
115
+ // Validate.
116
+ if ( ( $currently_in_cart + $user_already_bought + $quantity ) > $max_qty ) {
117
+ $product = wc_get_product( $product_id );
118
+ $replaced_values = array(
119
+ '%max_qty%' => $max_qty,
120
+ '%product_title%' => $product->get_title(),
121
+ '%qty_already_bought%' => $user_already_bought,
122
+ '%remaining_qty%' => max( ( $max_qty - $user_already_bought ), 0 ),
123
+ );
124
+ $message = wcj_get_option(
125
+ 'wcj_max_products_per_user_message',
126
+ __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' )
127
+ );
128
+ $message = str_replace( array_keys( $replaced_values ), $replaced_values, $message );
129
+ wc_add_notice( $message, 'error' );
130
+ return false;
131
+ }
132
+ // Passed.
133
+ return $passed;
134
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
135
 
136
+ /**
137
+ * Calculate_data_notice.
138
+ *
139
+ * @version 3.5.0
140
+ * @since 3.5.0
141
+ */
142
+ public function calculate_data_notice() {
143
+ if ( isset( $_GET['wcj_max_products_per_user_calculate_data_finished'] ) ) {
144
+ $class = 'notice notice-info';
145
+ $message = __( 'Data re-calculated.', 'woocommerce-jetpack' ) . ' ' .
146
+ /* translators: %s: translation added */
147
  sprintf( __( '%s order(s) processed.', 'woocommerce-jetpack' ), $_GET['wcj_max_products_per_user_calculate_data_finished'] );
148
+ printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
149
+ }
150
  }
 
151
 
152
+ /**
153
+ * Calculate_data.
154
+ *
155
+ * @version 5.5.9
156
+ * @since 3.5.0
157
+ * @todo reset `wcj_max_products_per_user_report` and `wcj_max_products_per_user_saved` meta
158
+ */
159
+ public function calculate_data() {
160
+ if ( isset( $_GET['wcj_max_products_per_user_calculate_data'] ) ) {
161
+ $offset = 0;
162
+ $block_size = 512;
163
+ $total_orders = 0;
164
+ while ( true ) {
165
+ $args = array(
166
+ 'post_type' => 'shop_order',
167
+ 'post_status' => $this->order_status,
168
+ 'posts_per_page' => $block_size,
169
+ 'orderby' => 'ID',
170
+ 'order' => 'DESC',
171
+ 'offset' => $offset,
172
+ 'fields' => 'ids',
173
+ );
174
+ $loop = new WP_Query( $args );
175
+ if ( ! $loop->have_posts() ) {
176
+ break;
177
+ }
178
+ foreach ( $loop->posts as $_order_id ) {
179
+ $this->save_quantities( $_order_id );
180
+ $total_orders++;
181
+ }
182
+ $offset += $block_size;
183
  }
184
+ wp_safe_redirect(
185
+ add_query_arg(
186
+ 'wcj_max_products_per_user_calculate_data_finished',
187
+ $total_orders,
188
+ esc_url( remove_query_arg( 'wcj_max_products_per_user_calculate_data' ) )
189
+ )
190
+ );
191
+ exit;
192
  }
 
 
 
193
  }
 
194
 
195
+ /**
196
+ * Add_report_meta_box.
197
+ *
198
+ * @version 3.5.0
199
+ * @since 3.5.0
200
+ */
201
+ public function add_report_meta_box() {
202
+ add_meta_box(
203
+ 'wc-jetpack-' . $this->id . '-report',
204
+ __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Maximum Products per User: Sales Data', 'woocommerce-jetpack' ),
205
+ array( $this, 'create_report_meta_box' ),
206
+ 'product',
207
+ 'normal',
208
+ 'high'
209
+ );
210
+ }
211
 
212
+ /**
213
+ * Create_report_meta_box.
214
+ *
215
+ * @version 3.5.0
216
+ * @since 3.5.0
217
+ */
218
+ public function create_report_meta_box() {
219
+ $users_quantities = get_post_meta( get_the_ID(), '_wcj_max_products_per_user_report', true );
220
+ if ( $users_quantities ) {
221
+ $table_data = array();
222
+ $table_data[] = array( __( 'User ID', 'woocommerce-jetpack' ), __( 'User Name', 'woocommerce-jetpack' ), __( 'Qty Bought', 'woocommerce-jetpack' ) );
223
+ foreach ( $users_quantities as $user_id => $qty_bought ) {
224
+ if ( 0 === $user_id ) {
225
+ $user = __( 'Guest', 'woocommerce-jetpack' );
226
+ } else {
227
+ $user = get_user_by( 'id', $user_id );
228
+ $user = ( isset( $user->data->user_nicename ) ? $user->data->user_nicename : '-' );
229
+ }
230
+ $table_data[] = array( $user_id, $user, $qty_bought );
231
  }
232
+ echo wp_kses_post(
233
+ wcj_get_table_html(
234
+ $table_data,
235
+ array(
236
+ 'table_class' => 'widefat striped',
237
+ 'table_heading_type' => 'horizontal',
238
+ )
239
+ )
240
+ );
241
+ } else {
242
+ echo '<em>' . wp_kses_post( 'No data yet.', 'woocommerce-jetpack' ) . '</em>';
243
  }
 
 
 
244
  }
 
245
 
246
+ /**
247
+ * Save_quantities.
248
+ *
249
+ * @version 3.5.0
250
+ * @since 3.5.0
251
+ * @param int $order_id defines the order_id.
252
+ */
253
+ public function save_quantities( $order_id ) {
254
+ $order = wc_get_order( $order_id );
255
+ if ( $order ) {
256
+ if ( 'yes' !== get_post_meta( $order_id, '_wcj_max_products_per_user_saved', true ) ) {
257
+ if ( count( $order->get_items() ) > 0 ) {
258
+ $user_id = ( WCJ_IS_WC_VERSION_BELOW_3 ? $order->customer_user : $order->get_customer_id() );
259
+ foreach ( $order->get_items() as $item ) {
260
+ $product = $item->get_product();
261
+ if ( $item->is_type( 'line_item' ) && ( $product ) ) {
262
+ $product_id = wcj_get_product_id_or_variation_parent_id( $product );
263
+ $product_qty = $item->get_quantity();
264
+ $users_quantities = get_post_meta( $product_id, '_wcj_max_products_per_user_report', true );
265
+ if ( '' === ( $users_quantities ) ) {
266
+ $users_quantities = array();
267
+ }
268
+ if ( isset( $users_quantities[ $user_id ] ) ) {
269
+ $product_qty += $users_quantities[ $user_id ];
270
+ }
271
+ $users_quantities[ $user_id ] = $product_qty;
272
+ update_post_meta( $product_id, '_wcj_max_products_per_user_report', $users_quantities );
273
  }
 
 
 
 
 
274
  }
275
  }
276
+ update_post_meta( $order_id, '_wcj_max_products_per_user_saved', 'yes' );
277
  }
 
278
  }
279
  }
 
280
 
281
+ /**
282
+ * Get_max_qty.
283
+ *
284
+ * @version 3.5.0
285
+ * @since 3.5.0
286
+ * @todo (maybe) local - add "enabled/disabled" option
287
+ * @todo (maybe) global - apply only to selected products (i.e. include/exclude products, cats, tags)
288
+ * @todo (maybe) per user and/or per user role (both global and local)
289
+ * @param int $product_id defines the product_id.
290
+ */
291
+ public function get_max_qty( $product_id ) {
292
+ $qty = get_post_meta( $product_id, '_wcj_max_products_per_user_qty', true );
293
+ if ( 'yes' === apply_filters( 'booster_option', 'no', wcj_get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) && 0 !== ( $qty ) ) {
294
+ return $qty;
295
+ } elseif ( 'yes' === wcj_get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) ) {
296
+ return wcj_get_option( 'wcj_max_products_per_user_global_max_qty', 1 );
297
+ } else {
298
+ return 0;
299
+ }
300
  }
 
301
 
302
+ /**
303
+ * Stop_from_seeing_checkout.
304
+ *
305
+ * @version 3.5.0
306
+ * @since 3.5.0
307
+ */
308
+ public function stop_from_seeing_checkout() {
309
+ if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
310
+ return;
311
+ }
312
+ if ( ! $this->check_quantities( false ) ) {
313
+ wp_safe_redirect( wc_get_cart_url() );
314
+ exit;
315
+ }
316
  }
 
317
 
318
+ /**
319
+ * Check_cart_quantities.
320
+ *
321
+ * @version 3.5.0
322
+ * @since 3.5.0
323
+ */
324
+ public function check_cart_quantities() {
325
+ $this->check_quantities();
 
 
 
 
 
 
 
 
 
 
 
 
 
326
  }
327
+
328
+ /**
329
+ * Check_quantities.
330
+ *
331
+ * @version 3.5.0
332
+ * @since 3.5.0
333
+ * @todo [dev] recheck `$cart_item_quantity` (maybe should be calculated same as `$currently_in_cart` in `$this->validate_on_add_to_cart()`)
334
+ * @param bool $add_notices defines the add_notices.
335
+ */
336
+ public function check_quantities( $add_notices = true ) {
337
+ $result = true;
338
+ if ( ! isset( WC()->cart ) ) {
339
+ return $result;
340
  }
341
+ $current_user_id = wcj_get_current_user_id();
342
+ if ( 0 === ( $current_user_id ) ) {
343
+ return $result;
344
  }
345
+ $cart_item_quantities = WC()->cart->get_cart_item_quantities();
346
+ if ( empty( $cart_item_quantities ) || ! is_array( $cart_item_quantities ) ) {
347
+ return $result;
348
+ }
349
+ $is_cart = ( function_exists( 'is_cart' ) && is_cart() );
350
+ foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
351
+ $max_qty = $this->get_max_qty( $_product_id );
352
+ if ( 0 === ( $max_qty ) ) {
353
+ continue;
354
+ }
355
+ $user_already_bought = 0;
356
+ $users_quantities = get_post_meta( $_product_id, '_wcj_max_products_per_user_report', true );
357
+ if ( ( $users_quantities ) && isset( $users_quantities[ $current_user_id ] ) ) {
358
+ $user_already_bought = $users_quantities[ $current_user_id ];
359
+ }
360
+ if ( ( $user_already_bought + $cart_item_quantity ) > $max_qty ) {
361
+ if ( $add_notices ) {
362
+ $result = false;
363
+ $product = wc_get_product( $_product_id );
364
+ $replaced_values = array(
365
+ '%max_qty%' => $max_qty,
366
+ '%product_title%' => $product->get_title(),
367
+ '%qty_already_bought%' => $user_already_bought,
368
+ '%remaining_qty%' => max( ( $max_qty - $user_already_bought ), 0 ),
369
+ );
370
+ $message = wcj_get_option(
371
+ 'wcj_max_products_per_user_message',
372
+ __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' )
373
+ );
374
+ $message = str_replace( array_keys( $replaced_values ), $replaced_values, $message );
375
+ if ( $is_cart ) {
376
+ wc_print_notice( $message, 'notice' );
377
+ } else {
378
+ wc_add_notice( $message, 'error' );
379
+ }
380
  } else {
381
+ return false;
382
  }
 
 
383
  }
384
  }
385
+ return $result;
386
  }
 
 
387
 
388
+ }
389
 
390
  endif;
391
 
includes/class-wcj-mini-cart.php CHANGED
@@ -5,61 +5,66 @@
5
  * @version 5.2.0
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Mini_Cart' ) ) :
13
-
14
- class WCJ_Mini_Cart extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 5.2.0
20
  */
21
- function __construct() {
22
 
23
- $this->id = 'mini_cart';
24
- $this->short_desc = __( 'Mini Cart Custom Info', 'woocommerce-jetpack' );
25
- $this->desc = __( 'Add custom info to the mini cart widget (1 block allowed in free version).', 'woocommerce-jetpack' );
26
- $this->desc_pro = __( 'Add custom info to the mini cart widget.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-mini-cart';
28
- parent::__construct();
29
 
30
- if ( $this->is_enabled() ) {
31
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_mini_cart_custom_info_total_number', 1 ) );
32
- for ( $i = 1; $i <= $total_number; $i++ ) {
33
- add_action(
34
- get_option( 'wcj_mini_cart_custom_info_hook_' . $i, 'woocommerce_after_mini_cart' ),
35
- array( $this, 'add_mini_cart_custom_info' ),
36
- get_option( 'wcj_mini_cart_custom_info_priority_' . $i, 10 )
37
- );
 
 
 
 
 
 
 
 
38
  }
39
  }
40
- }
41
 
42
- /**
43
- * add_mini_cart_custom_info.
44
- *
45
- * @version 2.4.6
46
- */
47
- function add_mini_cart_custom_info() {
48
- $current_filter = current_filter();
49
- $current_filter_priority = wcj_current_filter_priority();
50
- $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_mini_cart_custom_info_total_number', 1 ) );
51
- for ( $i = 1; $i <= $total_number; $i++ ) {
52
- if (
53
- '' != wcj_get_option( 'wcj_mini_cart_custom_info_content_' . $i ) &&
54
- $current_filter === wcj_get_option( 'wcj_mini_cart_custom_info_hook_' . $i, 'woocommerce_after_mini_cart' ) &&
55
- $current_filter_priority == wcj_get_option( 'wcj_mini_cart_custom_info_priority_' . $i, 10 )
56
- ) {
57
- echo do_shortcode( wcj_get_option( 'wcj_mini_cart_custom_info_content_' . $i ) );
 
58
  }
59
  }
60
- }
61
 
62
- }
63
 
64
  endif;
65
 
5
  * @version 5.2.0
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Mini_Cart' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Mini_Cart.
 
 
18
  */
19
+ class WCJ_Mini_Cart extends WCJ_Module {
20
 
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 5.2.0
25
+ */
26
+ public function __construct() {
27
 
28
+ $this->id = 'mini_cart';
29
+ $this->short_desc = __( 'Mini Cart Custom Info', 'woocommerce-jetpack' );
30
+ $this->desc = __( 'Add custom info to the mini cart widget (1 block allowed in free version).', 'woocommerce-jetpack' );
31
+ $this->desc_pro = __( 'Add custom info to the mini cart widget.', 'woocommerce-jetpack' );
32
+ $this->link_slug = 'woocommerce-mini-cart';
33
+ parent::__construct();
34
+
35
+ if ( $this->is_enabled() ) {
36
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_mini_cart_custom_info_total_number', 1 ) );
37
+ for ( $i = 1; $i <= $total_number; $i++ ) {
38
+ add_action(
39
+ get_option( 'wcj_mini_cart_custom_info_hook_' . $i, 'woocommerce_after_mini_cart' ),
40
+ array( $this, 'add_mini_cart_custom_info' ),
41
+ get_option( 'wcj_mini_cart_custom_info_priority_' . $i, 10 )
42
+ );
43
+ }
44
  }
45
  }
 
46
 
47
+ /**
48
+ * Add_mini_cart_custom_info.
49
+ *
50
+ * @version 2.4.6
51
+ */
52
+ public function add_mini_cart_custom_info() {
53
+ $current_filter = current_filter();
54
+ $current_filter_priority = wcj_current_filter_priority();
55
+ $total_number = apply_filters( 'booster_option', 1, wcj_get_option( 'wcj_mini_cart_custom_info_total_number', 1 ) );
56
+ for ( $i = 1; $i <= $total_number; $i++ ) {
57
+ if (
58
+ '' !== wcj_get_option( 'wcj_mini_cart_custom_info_content_' . $i ) &&
59
+ wcj_get_option( 'wcj_mini_cart_custom_info_hook_' . $i, 'woocommerce_after_mini_cart' ) === $current_filter &&
60
+ wcj_get_option( 'wcj_mini_cart_custom_info_priority_' . $i, 10 ) === $current_filter_priority
61
+ ) {
62
+ echo do_shortcode( wcj_get_option( 'wcj_mini_cart_custom_info_content_' . $i ) );
63
+ }
64
  }
65
  }
 
66
 
67
+ }
68
 
69
  endif;
70
 
includes/class-wcj-modules-by-user-roles.php CHANGED
@@ -5,30 +5,35 @@
5
  * @version 3.3.0
6
  * @since 3.3.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Modules_By_User_Roles' ) ) :
13
-
14
- class WCJ_Modules_By_User_Roles extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 3.3.0
20
- * @since 3.3.0
21
  */
22
- function __construct() {
23
-
24
- $this->id = 'modules_by_user_roles';
25
- $this->short_desc = __( 'Modules By User Roles', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Enable/disable Booster for WooCommerce modules by user roles.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-booster-modules-by-user-roles';
28
- parent::__construct();
29
-
 
 
 
 
 
 
 
 
 
30
  }
31
- }
32
 
33
  endif;
34
 
5
  * @version 3.3.0
6
  * @since 3.3.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit; // Exit if accessed directly.
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Modules_By_User_Roles' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Modules_By_User_Roles.
 
 
 
18
  */
19
+ class WCJ_Modules_By_User_Roles extends WCJ_Module {
20
+
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 3.3.0
25
+ * @since 3.3.0
26
+ */
27
+ public function __construct() {
28
+
29
+ $this->id = 'modules_by_user_roles';
30
+ $this->short_desc = __( 'Modules By User Roles', 'woocommerce-jetpack' );
31
+ $this->desc = __( 'Enable/disable Booster for WooCommerce modules by user roles.', 'woocommerce-jetpack' );
32
+ $this->link_slug = 'woocommerce-booster-modules-by-user-roles';
33
+ parent::__construct();
34
+
35
+ }
36
  }
 
37
 
38
  endif;
39
 
includes/class-wcj-more-button-labels.php CHANGED
@@ -5,59 +5,66 @@
5
  * @version 3.3.0
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_More_Button_Labels' ) ) :
13
-
14
- class WCJ_More_Button_Labels extends WCJ_Module {
15
-
16
  /**
17
- * Constructor.
18
- *
19
- * @version 3.3.0
20
  */
21
- function __construct() {
 
 
 
 
 
 
 
22
 
23
- $this->id = 'more_button_labels';
24
- $this->short_desc = __( 'More Button Labels', 'woocommerce-jetpack' );
25
- $this->desc = __( 'Set "Place order" button label.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-more-button-labels';
27
- parent::__construct();
28
 
29
- if ( $this->is_enabled() ) {
30
- add_filter( 'woocommerce_order_button_text', array( $this, 'set_order_button_text' ), PHP_INT_MAX );
31
- if ( 'yes' === wcj_get_option( 'wcj_checkout_place_order_button_override', 'no' ) ) {
32
- add_action( 'init', array( $this, 'override_order_button_text' ), PHP_INT_MAX );
 
33
  }
34
  }
35
- }
36
 
37
- /**
38
- * override_order_button_text.
39
- *
40
- * @version 3.3.0
41
- * @since 3.3.0
42
- */
43
- function override_order_button_text() {
44
- if ( function_exists( 'WC' ) && method_exists( WC(), 'payment_gateways' ) && isset( WC()->payment_gateways()->payment_gateways ) ) {
45
- foreach ( WC()->payment_gateways()->payment_gateways as &$payment_gateway ) {
46
- $payment_gateway->order_button_text = '';
 
47
  }
48
  }
49
- }
50
 
51
- /**
52
- * set_order_button_text.
53
- *
54
- * @version 2.8.0
55
- */
56
- function set_order_button_text( $current_text ) {
57
- return ( '' != ( $new_text = wcj_get_option( 'wcj_checkout_place_order_button_text', '' ) ) ) ? $new_text : $current_text;
58
- }
 
 
59
 
60
- }
61
 
62
  endif;
63
 
5
  * @version 3.3.0
6
  * @since 2.2.0
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_More_Button_Labels' ) ) :
 
 
 
16
  /**
17
+ * WCJ_More_Button_Labels.
 
 
18
  */
19
+ class WCJ_More_Button_Labels extends WCJ_Module {
20
+
21
+ /**
22
+ * Constructor.
23
+ *
24
+ * @version 3.3.0
25
+ */
26
+ public function __construct() {
27
 
28
+ $this->id = 'more_button_labels';
29
+ $this->short_desc = __( 'More Button Labels', 'woocommerce-jetpack' );
30
+ $this->desc = __( 'Set "Place order" button label.', 'woocommerce-jetpack' );
31
+ $this->link_slug = 'woocommerce-more-button-labels';
32
+ parent::__construct();
33
 
34
+ if ( $this->is_enabled() ) {
35
+ add_filter( 'woocommerce_order_button_text', array( $this, 'set_order_button_text' ), PHP_INT_MAX );
36
+ if ( 'yes' === wcj_get_option( 'wcj_checkout_place_order_button_override', 'no' ) ) {
37
+ add_action( 'init', array( $this, 'override_order_button_text' ), PHP_INT_MAX );
38
+ }
39
  }
40
  }
 
41
 
42
+ /**
43
+ * Override_order_button_text.
44
+ *
45
+ * @version 3.3.0
46
+ * @since 3.3.0
47
+ */
48
+ public function override_order_button_text() {
49
+ if ( function_exists( 'WC' ) && method_exists( WC(), 'payment_gateways' ) && isset( WC()->payment_gateways()->payment_gateways ) ) {
50
+ foreach ( WC()->payment_gateways()->payment_gateways as &$payment_gateway ) {
51
+ $payment_gateway->order_button_text = '';
52
+ }
53
  }
54
  }
 
55
 
56
+ /**
57
+ * Set_order_button_text.
58
+ *
59
+ * @version 2.8.0
60
+ * @param string $current_text defines the current_text.
61
+ */
62
+ public function set_order_button_text( $current_text ) {
63
+ $new_text = wcj_get_option( 'wcj_checkout_place_order_button_text', '' );
64
+ return ( '' !== ( $new_text ) ) ? $new_text : $current_text;
65
+ }
66
 
67
+ }
68
 
69
  endif;
70
 
includes/class-wcj-multicurrency-product-base-price.php CHANGED
@@ -5,12 +5,17 @@
5
  * @version 5.2.0
6
  * @since 2.4.8
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
13
-
 
 
14
  class WCJ_Multicurrency_Base_Price extends WCJ_Module {
15
 
16
  /**
@@ -19,7 +24,7 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
19
  * @version 5.2.0
20
  * @since 2.4.8
21
  */
22
- function __construct() {
23
 
24
  $this->id = 'multicurrency_base_price';
25
  $this->short_desc = __( 'Multicurrency Product Base Price', 'woocommerce-jetpack' );
@@ -30,7 +35,7 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
30
 
31
  if ( $this->is_enabled() ) {
32
 
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
  add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
36
 
@@ -41,40 +46,48 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
41
  wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
42
  }
43
 
44
- // Compatibility with WooCommerce Price Filter Widget
45
  $this->handle_price_filter_widget_compatibility();
46
 
47
- // Compatibility with WooCommerce Ordering
48
  $this->handle_wc_price_sorting();
49
  }
50
  }
51
 
52
  /**
53
- * handle_wc_ordering.
54
  *
55
  * @version 5.0.0
56
  * @since 5.0.0
57
  */
58
- function handle_wc_price_sorting() {
59
- add_filter( 'woocommerce_get_catalog_ordering_args', function ( $args, $orderby, $order ) {
60
- if (
 
 
61
  'no' === wcj_get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ||
62
  is_admin()
63
- ) {
64
- return $args;
65
- }
66
- add_filter( 'posts_clauses', function ( $args ) use ( $order ) {
67
- if ( false === strpos( $args['orderby'], 'wc_product_meta_lookup' ) ) {
68
  return $args;
69
  }
70
- $order_sql = 'DESC' === $order ? 'DESC' : 'ASC';
71
- global $wpdb;
72
- $args['join'] .= " LEFT JOIN {$wpdb->postmeta} AS pm ON ({$wpdb->posts}.ID = pm.post_id and pm.meta_key='_wcj_multicurrency_base_price')";
73
- $args['orderby'] = " pm.meta_value + 0 {$order_sql}, wc_product_meta_lookup.product_id {$order_sql} ";
 
 
 
 
 
 
 
 
 
74
  return $args;
75
- } );
76
- return $args;
77
- }, 10, 3 );
 
78
  }
79
 
80
  /**
@@ -83,7 +96,7 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
83
  * @version 4.8.0
84
  * @since 4.3.1
85
  */
86
- function handle_price_filter_widget_compatibility() {
87
  add_action( 'updated_post_meta', array( $this, 'update_base_price_meta_on_price_update' ), 10, 3 );
88
  add_action( 'updated_post_meta', array( $this, 'update_base_price_meta_on_base_price_currency_update' ), 10, 3 );
89
  add_action( 'added_post_meta', array( $this, 'update_base_price_meta_on_base_price_currency_update' ), 10, 3 );
@@ -95,16 +108,16 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
95
  }
96
 
97
  /**
98
- * modify_default_price_filter_hook.
99
  *
100
  * @version 4.8.0
101
  * @since 4.8.0
102
  *
103
- * @param $query
104
  *
105
  * @return mixed
106
  */
107
- function modify_default_price_filter_hook( $query ) {
108
  if (
109
  'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
110
  ! isset( $_GET['min_price'] ) ||
@@ -113,7 +126,7 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
113
  return $query;
114
  }
115
 
116
- // Remove Price Filter Meta Query
117
  $meta_query = $query->get( 'meta_query' );
118
  $meta_query = empty( $meta_query ) ? array() : $meta_query;
119
  foreach ( $meta_query as $key => $value ) {
@@ -125,38 +138,38 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
125
  }
126
  $query->set( 'meta_query', $meta_query );
127
 
128
- // Remove Price Filter Hooks
129
  wcj_remove_class_filter( 'posts_clauses', 'WC_Query', 'price_filter_post_clauses' );
130
 
131
- // Remove Price Filter hooks from "Product Filter for WooCommerce" plugin
132
  if ( class_exists( 'XforWC_Product_Filters_Frontend' ) ) {
133
  remove_filter( 'posts_clauses', 'XforWC_Product_Filters_Frontend::price_filter_post_clauses', 10, 2 );
134
  }
135
 
136
- // Add Price Filter Hook
137
  add_filter( 'posts_clauses', array( $this, 'price_filter_post_clauses' ), 10, 2 );
138
  }
139
 
140
  /**
141
- * price_filter_post_clauses.
142
  *
143
  * @version 4.8.0
144
  * @since 4.8.0
145
  *
146
  * @see WC_Query::price_filter_post_clauses
147
  *
148
- * @param $args
149
- * @param $wp_query
150
  *
151
  * @return mixed
152
  */
153
- function price_filter_post_clauses( $args, $wp_query ) {
154
  global $wpdb;
155
  if ( ! $wp_query->is_main_query() || ( ! isset( $_GET['max_price'] ) && ! isset( $_GET['min_price'] ) ) ) {
156
  return $args;
157
  }
158
- $current_min_price = isset( $_GET['min_price'] ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0; // WPCS: input var ok, CSRF ok.
159
- $current_max_price = isset( $_GET['max_price'] ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : PHP_INT_MAX; // WPCS: input var ok, CSRF ok.
160
  if ( wc_tax_enabled() && 'incl' === wcj_get_option( 'woocommerce_tax_display_shop' ) && ! wc_prices_include_tax() ) {
161
  $tax_class = apply_filters( 'woocommerce_price_filter_widget_tax_class', '' ); // Uses standard tax class.
162
  $tax_rates = WC_Tax::get_rates( $tax_class );
@@ -194,11 +207,11 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
194
  * @since 4.3.1
195
  *
196
  * @see WC_Widget_Price_Filter::get_filtered_price()
197
- * @param $sql
198
  *
199
  * @return string
200
  */
201
- function change_woocommerce_price_filter_sql($sql){
202
  if (
203
  is_admin() ||
204
  ( ! is_shop() && ! is_product_taxonomy() ) ||
@@ -223,20 +236,20 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
223
  unset( $meta_query[ $key ] );
224
  }
225
  }
226
- $meta_query = new WP_Meta_Query( $meta_query );
227
- $tax_query = new WP_Tax_Query( $tax_query );
228
  $meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
229
  $tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' );
230
- $sql = "SELECT MIN(FLOOR(IF(pm2.meta_value=1, pm3.meta_value, pm.meta_value))) AS min_price, MAX(CEILING(IF(pm2.meta_value=1, pm3.meta_value, pm.meta_value))) AS max_price FROM {$wpdb->posts}";
231
- $sql .= " JOIN {$wpdb->postmeta} as pm ON {$wpdb->posts}.ID = pm.post_id " . $tax_query_sql['join'] . $meta_query_sql['join'];
232
- $sql .= " LEFT JOIN {$wpdb->postmeta} as pm2 ON {$wpdb->posts}.ID = pm2.post_id AND pm2.meta_key = '_wcj_multicurrency_base_price_comp_pf' ";
233
- $sql .= " LEFT JOIN {$wpdb->postmeta} as pm3 ON {$wpdb->posts}.ID = pm3.post_id AND pm3.meta_key = '_wcj_multicurrency_base_price' ";
234
- $sql .= " WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_post_type', array( 'product' ) ) ) ) . "')
235
  AND {$wpdb->posts}.post_status = 'publish'
236
  AND pm.meta_key IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_meta_keys', array( '_price' ) ) ) ) . "')
237
  AND pm.meta_value > '' ";
238
- $sql .= $tax_query_sql['where'] . $meta_query_sql['where'];
239
- $search = WC_Query::get_main_search_query_sql();
240
  if ( $search ) {
241
  $sql .= ' AND ' . $search;
242
  }
@@ -249,16 +262,17 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
249
  * @version 5.0.0
250
  * @since 4.3.1
251
  *
252
- * @param $meta_id
253
- * @param $object_id
254
- * @param $meta_key
255
  */
256
- function update_base_price_meta_on_base_price_currency_update( $meta_id, $object_id, $meta_key ) {
 
257
  if (
258
  ( 'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp' ) && 'no' === wcj_get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ) ||
259
  ! function_exists( 'wc_get_product' ) ||
260
  '_wcj_multicurrency_base_price_currency' !== $meta_key ||
261
- ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
262
  ) {
263
  return;
264
  }
@@ -271,16 +285,17 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
271
  * @version 5.0.0
272
  * @since 4.3.1
273
  *
274
- * @param $meta_id
275
- * @param $object_id
276
- * @param $meta_key
277
  */
278
- function update_base_price_meta_on_price_update( $meta_id, $object_id, $meta_key ){
 
279
  if (
280
  ( 'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp' ) && 'no' === wcj_get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ) ||
281
  ! function_exists( 'wc_get_product' ) ||
282
  '_price' !== $meta_key ||
283
- ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
284
  ) {
285
  return;
286
  }
@@ -293,11 +308,11 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
293
  * @version 5.0.0
294
  * @since 4.3.1
295
  *
296
- * @param $option_name
297
- * @param $old_value
298
- * @param $option_value
299
  */
300
- function update_products_base_price_on_exchange_rate_change( $option_name, $old_value, $option_value ){
301
  if (
302
  ( 'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp' ) && 'no' === wcj_get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ) ||
303
  false === strpos( $option_name, 'wcj_multicurrency_base_price_exchange_rate_' )
@@ -321,21 +336,22 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
321
  * @version 4.3.1
322
  * @since 4.3.1
323
  *
324
- * @param $meta_id
325
- * @param $object_id
326
- * @param $meta_key
327
- * @param $meta_value
328
  */
329
- function handle_price_filter_compatibility_flag_on_base_price_currency_update( $meta_id, $object_id, $meta_key, $meta_value ) {
 
330
  if (
331
  'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
332
  ! function_exists( 'wc_get_product' ) ||
333
  '_wcj_multicurrency_base_price_currency' !== $meta_key ||
334
- ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
335
  ) {
336
  return;
337
  }
338
- if ( $meta_value === wcj_get_option( 'woocommerce_currency' ) ) {
339
  delete_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf' );
340
  } else {
341
  update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf', true );
@@ -348,21 +364,22 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
348
  * @version 4.3.1
349
  * @since 4.3.1
350
  *
351
- * @param $meta_id
352
- * @param $object_id
353
- * @param $meta_key
354
- * @param $meta_value
355
  */
356
- function handle_price_filter_compatibility_flag_on_base_price_update( $meta_id, $object_id, $meta_key, $meta_value ) {
 
357
  if (
358
  'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
359
  ! function_exists( 'wc_get_product' ) ||
360
  '_wcj_multicurrency_base_price' !== $meta_key ||
361
- ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
362
  ) {
363
  return;
364
  }
365
- if ( $meta_value === get_post_meta( $product->get_id(), '_price', true ) ) {
366
  delete_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf' );
367
  } else {
368
  update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf', true );
@@ -375,12 +392,12 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
375
  * @version 4.3.1
376
  * @since 4.3.1
377
  *
378
- * @param string $compare
379
- * @param string $currency
380
  *
381
  * @return WP_Query
382
  */
383
- function get_products_by_base_price_currency( $compare = '=', $currency = '' ) {
384
  if ( empty( $currency ) ) {
385
  $currency = wcj_get_option( 'woocommerce_currency' );
386
  }
@@ -395,9 +412,9 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
395
  array(
396
  'key' => '_wcj_multicurrency_base_price_currency',
397
  'value' => $currency,
398
- 'compare' => $compare
399
- )
400
- )
401
  );
402
  $query = new WP_Query( $args );
403
  return $query;
@@ -409,12 +426,12 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
409
  * @version 4.4.0
410
  * @since 4.3.1
411
  *
412
- * @param $product
413
- * @param null $price
414
  *
415
  * @return bool
416
  */
417
- function update_wcj_multicurrency_base_price_meta( $product, $price = null ) {
418
  if ( filter_var( $product, FILTER_VALIDATE_INT ) ) {
419
  $product = wc_get_product( $product );
420
  }
@@ -429,18 +446,21 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
429
  }
430
 
431
  /**
432
- * change_price_grouped.
433
  *
434
  * @version 2.7.0
435
  * @since 2.5.0
 
 
 
436
  */
437
- function change_price_grouped( $price, $qty, $_product ) {
438
  if ( $_product->is_type( 'grouped' ) ) {
439
  foreach ( $_product->get_children() as $child_id ) {
440
- $the_price = get_post_meta( $child_id, '_price', true );
441
  $the_product = wc_get_product( $child_id );
442
- $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
443
- if ( $the_price == $price ) {
444
  return $this->change_price( $price, $the_product );
445
  }
446
  }
@@ -449,23 +469,28 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
449
  }
450
 
451
  /**
452
- * change_price.
453
  *
454
  * @version 2.7.0
455
  * @since 2.4.8
 
 
456
  */
457
- function change_price( $price, $_product ) {
458
  return wcj_price_by_product_base_currency( $price, wcj_get_product_id_or_variation_parent_id( $_product ) );
459
  }
460
 
461
  /**
462
- * get_variation_prices_hash.
463
  *
464
  * @version 3.5.0
465
  * @since 2.4.8
 
 
 
466
  */
467
- function get_variation_prices_hash( $price_hash, $_product, $display ) {
468
- $multicurrency_base_price_currency = get_post_meta( wcj_get_product_id_or_variation_parent_id( $_product, true ), '_' . 'wcj_multicurrency_base_price_currency', true );
469
  $price_hash['wcj_multicurrency_base_price'] = array(
470
  'currency' => $multicurrency_base_price_currency,
471
  'exchange_rate' => wcj_get_currency_exchange_rate_product_base_currency( $multicurrency_base_price_currency ),
@@ -477,23 +502,27 @@ if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
477
  }
478
 
479
  /**
480
- * change_currency_symbol_on_product_edit.
481
  *
482
  * @version 3.9.0
483
  * @since 2.4.8
 
 
484
  */
485
- function change_currency_symbol_on_product_edit( $currency_symbol, $currency ) {
 
486
  if ( is_admin() ) {
487
  global $pagenow;
488
  if (
489
- ( 'post.php' === $pagenow && isset( $_GET['action'] ) && 'edit' === $_GET['action'] ) || // admin product edit page
490
- ( ! $this->do_convert_in_back_end && 'edit.php' === $pagenow && isset( $_GET['post_type'] ) && 'product' === $_GET['post_type'] ) // admin products list
 
491
  ) {
492
- $multicurrency_base_price_currency = get_post_meta( get_the_ID(), '_' . 'wcj_multicurrency_base_price_currency', true );
493
- if ( '' != $multicurrency_base_price_currency ) {
494
  remove_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
495
  $return = get_woocommerce_currency_symbol( $multicurrency_base_price_currency );
496
- add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
497
  return $return;
498
  }
499
  }
5
  * @version 5.2.0
6
  * @since 2.4.8
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Multicurrency_Base_Price' ) ) :
16
+ /**
17
+ * WCJ_Multicurrency_Base_Price.
18
+ */
19
  class WCJ_Multicurrency_Base_Price extends WCJ_Module {
20
 
21
  /**
24
  * @version 5.2.0
25
  * @since 2.4.8
26
  */
27
+ public function __construct() {
28
 
29
  $this->id = 'multicurrency_base_price';
30
  $this->short_desc = __( 'Multicurrency Product Base Price', 'woocommerce-jetpack' );
35
 
36
  if ( $this->is_enabled() ) {
37
 
38
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
39
  add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
40
  add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
41
 
46
  wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
47
  }
48
 
49
+ // Compatibility with WooCommerce Price Filter Widget.
50
  $this->handle_price_filter_widget_compatibility();
51
 
52
+ // Compatibility with WooCommerce Ordering.
53
  $this->handle_wc_price_sorting();
54
  }
55
  }
56
 
57
  /**
58
+ * Handle_wc_ordering.
59
  *
60
  * @version 5.0.0
61
  * @since 5.0.0
62
  */
63
+ public function handle_wc_price_sorting() {
64
+ add_filter(
65
+ 'woocommerce_get_catalog_ordering_args',
66
+ function ( $args, $orderby, $order ) {
67
+ if (
68
  'no' === wcj_get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ||
69
  is_admin()
70
+ ) {
 
 
 
 
71
  return $args;
72
  }
73
+ add_filter(
74
+ 'posts_clauses',
75
+ function ( $args ) use ( $order ) {
76
+ if ( false === strpos( $args['orderby'], 'wc_product_meta_lookup' ) ) {
77
+ return $args;
78
+ }
79
+ $order_sql = 'DESC' === $order ? 'DESC' : 'ASC';
80
+ global $wpdb;
81
+ $args['join'] .= " LEFT JOIN {$wpdb->postmeta} AS pm ON ({$wpdb->posts}.ID = pm.post_id and pm.meta_key='_wcj_multicurrency_base_price')";
82
+ $args['orderby'] = " pm.meta_value + 0 {$order_sql}, wc_product_meta_lookup.product_id {$order_sql} ";
83
+ return $args;
84
+ }
85
+ );
86
  return $args;
87
+ },
88
+ 10,
89
+ 3
90
+ );
91
  }
92
 
93
  /**
96
  * @version 4.8.0
97
  * @since 4.3.1
98
  */
99
+ public function handle_price_filter_widget_compatibility() {
100
  add_action( 'updated_post_meta', array( $this, 'update_base_price_meta_on_price_update' ), 10, 3 );
101
  add_action( 'updated_post_meta', array( $this, 'update_base_price_meta_on_base_price_currency_update' ), 10, 3 );
102
  add_action( 'added_post_meta', array( $this, 'update_base_price_meta_on_base_price_currency_update' ), 10, 3 );
108
  }
109
 
110
  /**
111
+ * Modify_default_price_filter_hook.
112
  *
113
  * @version 4.8.0
114
  * @since 4.8.0
115
  *
116
+ * @param string $query defines the query.
117
  *
118
  * @return mixed
119
  */
120
+ public function modify_default_price_filter_hook( $query ) {
121
  if (
122
  'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
123
  ! isset( $_GET['min_price'] ) ||
126
  return $query;
127
  }
128
 
129
+ // Remove Price Filter Meta Query.
130
  $meta_query = $query->get( 'meta_query' );
131
  $meta_query = empty( $meta_query ) ? array() : $meta_query;
132
  foreach ( $meta_query as $key => $value ) {
138
  }
139
  $query->set( 'meta_query', $meta_query );
140
 
141
+ // Remove Price Filter Hooks.
142
  wcj_remove_class_filter( 'posts_clauses', 'WC_Query', 'price_filter_post_clauses' );
143
 
144
+ // Remove Price Filter hooks from "Product Filter for WooCommerce" plugin.
145
  if ( class_exists( 'XforWC_Product_Filters_Frontend' ) ) {
146
  remove_filter( 'posts_clauses', 'XforWC_Product_Filters_Frontend::price_filter_post_clauses', 10, 2 );
147
  }
148
 
149
+ // Add Price Filter Hook.
150
  add_filter( 'posts_clauses', array( $this, 'price_filter_post_clauses' ), 10, 2 );
151
  }
152
 
153
  /**
154
+ * Price_filter_post_clauses.
155
  *
156
  * @version 4.8.0
157
  * @since 4.8.0
158
  *
159
  * @see WC_Query::price_filter_post_clauses
160
  *
161
+ * @param array $args defines the args.
162
+ * @param string $wp_query defines the wp_query.
163
  *
164
  * @return mixed
165
  */
166
+ public function price_filter_post_clauses( $args, $wp_query ) {
167
  global $wpdb;
168
  if ( ! $wp_query->is_main_query() || ( ! isset( $_GET['max_price'] ) && ! isset( $_GET['min_price'] ) ) ) {
169
  return $args;
170
  }
171
+ $current_min_price = isset( $_GET['min_price'] ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0;
172
+ $current_max_price = isset( $_GET['max_price'] ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : PHP_INT_MAX;
173
  if ( wc_tax_enabled() && 'incl' === wcj_get_option( 'woocommerce_tax_display_shop' ) && ! wc_prices_include_tax() ) {
174
  $tax_class = apply_filters( 'woocommerce_price_filter_widget_tax_class', '' ); // Uses standard tax class.
175
  $tax_rates = WC_Tax::get_rates( $tax_class );
207
  * @since 4.3.1
208
  *
209
  * @see WC_Widget_Price_Filter::get_filtered_price()
210
+ * @param string $sql defines the sql.
211
  *
212
  * @return string
213
  */
214
+ public function change_woocommerce_price_filter_sql( $sql ) {
215
  if (
216
  is_admin() ||
217
  ( ! is_shop() && ! is_product_taxonomy() ) ||
236
  unset( $meta_query[ $key ] );
237
  }
238
  }
239
+ $meta_query = new WP_Meta_Query( $meta_query );
240
+ $tax_query = new WP_Tax_Query( $tax_query );
241
  $meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
242
  $tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' );
243
+ $sql = "SELECT MIN(FLOOR(IF(pm2.meta_value=1, pm3.meta_value, pm.meta_value))) AS min_price, MAX(CEILING(IF(pm2.meta_value=1, pm3.meta_value, pm.meta_value))) AS max_price FROM {$wpdb->posts}";
244
+ $sql .= " JOIN {$wpdb->postmeta} as pm ON {$wpdb->posts}.ID = pm.post_id " . $tax_query_sql['join'] . $meta_query_sql['join'];
245
+ $sql .= " LEFT JOIN {$wpdb->postmeta} as pm2 ON {$wpdb->posts}.ID = pm2.post_id AND pm2.meta_key = '_wcj_multicurrency_base_price_comp_pf' ";
246
+ $sql .= " LEFT JOIN {$wpdb->postmeta} as pm3 ON {$wpdb->posts}.ID = pm3.post_id AND pm3.meta_key = '_wcj_multicurrency_base_price' ";
247
+ $sql .= " WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_post_type', array( 'product' ) ) ) ) . "')
248
  AND {$wpdb->posts}.post_status = 'publish'
249
  AND pm.meta_key IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_meta_keys', array( '_price' ) ) ) ) . "')
250
  AND pm.meta_value > '' ";
251
+ $sql .= $tax_query_sql['where'] . $meta_query_sql['where'];
252
+ $search = WC_Query::get_main_search_query_sql();
253
  if ( $search ) {
254
  $sql .= ' AND ' . $search;
255
  }
262
  * @version 5.0.0
263
  * @since 4.3.1
264
  *
265
+ * @param int $meta_id defines the meta_id.
266
+ * @param int $object_id defines the object_id.
267
+ * @param string $meta_key defines the meta_key.
268
  */
269
+ public function update_base_price_meta_on_base_price_currency_update( $meta_id, $object_id, $meta_key ) {
270
+ $product = wc_get_product( $object_id );
271
  if (
272
  ( 'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp' ) && 'no' === wcj_get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ) ||
273
  ! function_exists( 'wc_get_product' ) ||
274
  '_wcj_multicurrency_base_price_currency' !== $meta_key ||
275
+ ! is_a( $product, 'WC_Product' )
276
  ) {
277
  return;
278
  }
285
  * @version 5.0.0
286
  * @since 4.3.1
287
  *
288
+ * @param int $meta_id defines the meta_id.
289
+ * @param int $object_id defines the object_id.
290
+ * @param string $meta_key defines the meta_key.
291
  */
292
+ public function update_base_price_meta_on_price_update( $meta_id, $object_id, $meta_key ) {
293
+ $product = wc_get_product( $object_id );
294
  if (
295
  ( 'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp' ) && 'no' === wcj_get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ) ||
296
  ! function_exists( 'wc_get_product' ) ||
297
  '_price' !== $meta_key ||
298
+ ! is_a( $product, 'WC_Product' )
299
  ) {
300
  return;
301
  }
308
  * @version 5.0.0
309
  * @since 4.3.1
310
  *
311
+ * @param string $option_name defines the option_name.
312
+ * @param string $old_value defines the old_value.
313
+ * @param string $option_value defines the option_value.
314
  */
315
+ public function update_products_base_price_on_exchange_rate_change( $option_name, $old_value, $option_value ) {
316
  if (
317
  ( 'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp' ) && 'no' === wcj_get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ) ||
318
  false === strpos( $option_name, 'wcj_multicurrency_base_price_exchange_rate_' )
336
  * @version 4.3.1
337
  * @since 4.3.1
338
  *
339
+ * @param int $meta_id defines the meta_id.
340
+ * @param int $object_id defines the object_id.
341
+ * @param string $meta_key defines the meta_key.
342
+ * @param string $meta_value defines the meta_value.
343
  */
344
+ public function handle_price_filter_compatibility_flag_on_base_price_currency_update( $meta_id, $object_id, $meta_key, $meta_value ) {
345
+ $product = wc_get_product( $object_id );
346
  if (
347
  'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
348
  ! function_exists( 'wc_get_product' ) ||
349
  '_wcj_multicurrency_base_price_currency' !== $meta_key ||
350
+ ! is_a( $product, 'WC_Product' )
351
  ) {
352
  return;
353
  }
354
+ if ( wcj_get_option( 'woocommerce_currency' ) === $meta_value ) {
355
  delete_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf' );
356
  } else {
357
  update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf', true );
364
  * @version 4.3.1
365
  * @since 4.3.1
366
  *
367
+ * @param int $meta_id defines the meta_id.
368
+ * @param int $object_id defines the object_id.
369
+ * @param string $meta_key defines the meta_key.
370
+ * @param string $meta_value defines the meta_value.
371
  */
372
+ public function handle_price_filter_compatibility_flag_on_base_price_update( $meta_id, $object_id, $meta_key, $meta_value ) {
373
+ $product = wc_get_product( $object_id );
374
  if (
375
  'no' === wcj_get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
376
  ! function_exists( 'wc_get_product' ) ||
377
  '_wcj_multicurrency_base_price' !== $meta_key ||
378
+ ! is_a( $product, 'WC_Product' )
379
  ) {
380
  return;
381
  }
382
+ if ( get_post_meta( $product->get_id(), '_price', true ) === $meta_value ) {
383
  delete_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf' );
384
  } else {
385
  update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf', true );
392
  * @version 4.3.1
393
  * @since 4.3.1
394
  *
395
+ * @param string $compare defines the compare.
396
+ * @param string $currency defines the currency.
397
  *
398
  * @return WP_Query
399
  */
400
+ public function get_products_by_base_price_currency( $compare = '=', $currency = '' ) {
401
  if ( empty( $currency ) ) {
402
  $currency = wcj_get_option( 'woocommerce_currency' );
403
  }
412
  array(
413
  'key' => '_wcj_multicurrency_base_price_currency',
414
  'value' => $currency,
415
+ 'compare' => $compare,
416
+ ),
417
+ ),
418
  );
419
  $query = new WP_Query( $args );
420
  return $query;
426
  * @version 4.4.0
427
  * @since 4.3.1
428
  *
429
+ * @param string | array $product defines the product.
430
+ * @param null $price defines the price.
431
  *
432
  * @return bool
433
  */
434
+ public function update_wcj_multicurrency_base_price_meta( $product, $price = null ) {
435
  if ( filter_var( $product, FILTER_VALIDATE_INT ) ) {
436
  $product = wc_get_product( $product );
437
  }
446
  }
447
 
448
  /**
449
+ * Change_price_grouped.
450
  *
451
  * @version 2.7.0
452
  * @since 2.5.0
453
+ * @param int $price defines the price.
454
+ * @param int $qty defines the qty.
455
+ * @param array $_product defines the _product.
456
  */
457
+ public function change_price_grouped( $price, $qty, $_product ) {
458
  if ( $_product->is_type( 'grouped' ) ) {
459
  foreach ( $_product->get_children() as $child_id ) {
460
+ $the_price = get_post_meta( $child_id, '_price', true );
461
  $the_product = wc_get_product( $child_id );
462
+ $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
463
+ if ( $the_price === $price ) {
464
  return $this->change_price( $price, $the_product );
465
  }
466
  }
469
  }
470
 
471
  /**
472
+ * Change_price.
473
  *
474
  * @version 2.7.0
475
  * @since 2.4.8
476
+ * @param int $price defines the price.
477
+ * @param array $_product defines the _product.
478
  */
479
+ public function change_price( $price, $_product ) {
480
  return wcj_price_by_product_base_currency( $price, wcj_get_product_id_or_variation_parent_id( $_product ) );
481
  }
482
 
483
  /**
484
+ * Get_variation_prices_hash.
485
  *
486
  * @version 3.5.0
487
  * @since 2.4.8
488
+ * @param int $price_hash defines the price_hash.
489
+ * @param array $_product defines the _product.
490
+ * @param string $display defines the display.
491
  */
492
+ public function get_variation_prices_hash( $price_hash, $_product, $display ) {
493
+ $multicurrency_base_price_currency = get_post_meta( wcj_get_product_id_or_variation_parent_id( $_product, true ), '_wcj_multicurrency_base_price_currency', true );
494
  $price_hash['wcj_multicurrency_base_price'] = array(
495
  'currency' => $multicurrency_base_price_currency,
496
  'exchange_rate' => wcj_get_currency_exchange_rate_product_base_currency( $multicurrency_base_price_currency ),
502
  }
503
 
504
  /**
505
+ * Change_currency_symbol_on_product_edit.
506
  *
507
  * @version 3.9.0
508
  * @since 2.4.8
509
+ * @param string $currency_symbol defines the currency_symbol.
510
+ * @param string | int $currency defines the currency.
511
  */
512
+ public function change_currency_symbol_on_product_edit( $currency_symbol, $currency ) {
513
+ $nonce = wp_create_nonce();
514
  if ( is_admin() ) {
515
  global $pagenow;
516
  if (
517
+ ( 'post.php' === $pagenow && isset( $_GET['action'] ) && 'edit' === $_GET['action'] ) || // admin product edit page.
518
+ ( ! $this->do_convert_in_back_end && 'edit.php' === $pagenow && isset( $_GET['post_type'] ) && 'product' === $_GET['post_type'] ) // admin products list.
519
+ && wp_verify_nonce( $nonce )
520
  ) {
521
+ $multicurrency_base_price_currency = get_post_meta( get_the_ID(), '_wcj_multicurrency_base_price_currency', true );
522
+ if ( '' !== $multicurrency_base_price_currency ) {
523
  remove_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
524
  $return = get_woocommerce_currency_symbol( $multicurrency_base_price_currency );
525
+ add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
526
  return $return;
527
  }
528
  }
includes/class-wcj-multicurrency.php CHANGED
@@ -5,520 +5,545 @@
5
  * @version 5.4.3
6
  * @since 2.4.3
7
  * @author Pluggabl LLC.
 
8
  */
9
 
10
- if ( ! defined( 'ABSPATH' ) ) exit;
 
 
11
 
12
  if ( ! class_exists( 'WCJ_Multicurrency' ) ) :
13
-
14
- class WCJ_Multicurrency extends WCJ_Module {
15
-
16
  /**
17
- * @var WCJ_Multicurrency_Price_Updater
18
  */
19
- protected $bkg_process_price_updater;
20
-
21
- /**
22
- * Constructor.
23
- *
24
- * @version 5.2.0
25
- * @todo check if we can just always execute `init()` on `init` hook
26
- */
27
- function __construct() {
28
-
29
- $this->id = 'multicurrency';
30
- $this->short_desc = __( 'Multicurrency (Currency Switcher)', 'woocommerce-jetpack' );
31
- $this->desc = __( 'Add multiple currencies (currency switcher) to WooCommerce (2 currencies allowed in free version).', 'woocommerce-jetpack' );
32
- $this->desc_pro = __( 'Add multiple currencies (currency switcher) to WooCommerce.', 'woocommerce-jetpack' );
33
- $this->link_slug = 'woocommerce-multicurrency-currency-switcher';
34
- $this->extra_desc = sprintf( __( 'After setting currencies in the Currencies Options section below, you can add switcher to the frontend with: %s', 'woocommerce-jetpack' ),
35
- '<ol>' .
36
- '<li>' . sprintf( __( '<strong>Widget:</strong> "%s"', 'woocommerce-jetpack' ),
37
- __( 'Booster - Multicurrency Switcher', 'woocommerce-jetpack' ) ) .
 
 
 
 
 
 
 
 
 
 
 
 
38
  '</li>' .
39
- '<li>' . sprintf( __( '<strong>Shortcodes:</strong> %s', 'woocommerce-jetpack' ),
40
- '<code>[wcj_currency_select_drop_down_list]</code>, <code>[wcj_currency_select_radio_list]</code>, <code>[wcj_currency_select_link_list]</code>' ) .
 
 
 
41
  '</li>' .
42
- '<li>' . sprintf( __( '<strong>PHP code:</strong> by using %s function, e.g.: %s', 'woocommerce-jetpack' ),
 
 
43
  '<code>do_shortcode()</code>',
44
- '<code>echo&nbsp;do_shortcode(&nbsp;\'[wcj_currency_select_drop_down_list]\'&nbsp;);</code>' ) .
 
45
  '</li>' .
46
- '</ol>' );
47
- parent::__construct();
 
48
 
49
- if ( $this->is_enabled() ) {
50
- $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'multicurrency' );
51
 
52
- // Session
53
- if ( 'wc' === WCJ_SESSION_TYPE ) {
54
- // `init()` executed on `init` hook because we need to use `WC()->session`
55
- add_action( 'init', array( $this, 'init' ) );
56
- } else {
57
- $this->init();
58
- }
59
 
60
- $this->add_hooks();
61
 
62
- if ( 'yes' === wcj_get_option( 'wcj_multicurrency_per_product_enabled' , 'yes' ) ) {
63
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
64
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
65
- }
66
 
67
- if ( is_admin() ) {
68
- include_once( 'reports/class-wcj-currency-reports.php' );
69
- }
70
 
71
- if ( 'init' === current_filter() ) {
72
- $this->init_bkg_process_class();
73
- } else {
74
- add_action( 'plugins_loaded', array( $this, 'init_bkg_process_class' ) );
 
75
  }
76
  }
77
- }
78
-
79
- /**
80
- * init_bkg_process_class.
81
- *
82
- * @version 4.5.0
83
- * @since 4.5.0
84
- */
85
- function init_bkg_process_class() {
86
- if ( 'yes' === wcj_get_option( 'wcj_multicurrency_update_prices_on_exch_update', 'no' ) ) {
87
- require_once( wcj_plugin_path() . '/includes/background-process/class-wcj-multicurrency-price-updater.php' );
88
- $this->bkg_process_price_updater = new WCJ_Multicurrency_Price_Updater();
89
- }
90
- }
91
 
92
- /**
93
- * Handles third party compatibility.
94
- *
95
- * @version 5.4.3
96
- * @since 4.3.0
97
- */
98
- function handle_compatibility(){
99
- // "WooCommerce Smart Coupons" Compatibility
100
- if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_smart_coupons' , 'yes' ) ) {
101
- add_filter( 'woocommerce_coupon_get_amount', array( $this, 'smart_coupons_get_amount' ), 10, 2 );
 
102
  }
103
 
104
- // WooCommerce Coupons
105
- add_filter( 'woocommerce_coupon_is_valid', array( $this, 'check_woocommerce_coupon_min_max_amount' ), 10, 3 );
106
- add_filter( 'woocommerce_get_shop_coupon_data', array( $this, 'fix_wc_coupon_discount_amount' ), 10, 3 );
 
 
 
 
 
 
 
 
107
 
108
- // WooCommerce Attribute Swatches by Iconic Plugin
109
- if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_attribute_swatches_premium_variable_cart_item_price' , 'no' ) ) {
110
- add_filter( 'woocommerce_cart_item_price', array( $this, 'fix_wc_attribute_swatches_premium_variable_cart_item_price' ), 20, 3 );
111
- }
112
 
113
- // WooCommerce Price Filter Widget
114
- if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_price_filter' , 'no' ) ) {
115
- add_action( 'wp_footer', array( $this, 'add_compatibility_with_price_filter_widget' ) );
116
- add_action( 'wp_footer', array( $this, 'fix_price_filter_widget_currency_format' ) );
117
- add_filter( 'woocommerce_price_filter_sql', array( $this, 'get_price_filter_sql_compatible' ), 10, 3 );
118
- add_filter( 'posts_clauses', array( $this, 'posts_clauses_price_filter_compatible' ), 11, 2 );
119
- add_filter( 'woocommerce_price_filter_widget_step', function ( $step ) {
120
- $step = 1;
121
- return $step;
122
- } );
123
- }
124
 
125
- // Sort by Price
126
- if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_price_sorting_per_product', 'no' ) ) {
127
- add_filter( 'woocommerce_get_catalog_ordering_args', array( $this, 'handle_per_product_opt_with_sort_by_price' ), 29, 3 );
128
- }
 
 
 
 
 
 
 
 
 
 
129
 
130
- // Fix WooCommerce Import
131
- if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_import' , 'no' ) ) {
132
- add_filter( 'woocommerce_product_importer_parsed_data', array( $this, 'fix_wc_product_import' ), 10, 2 );
133
- }
134
 
135
- // WPC Product Bundles plugin
136
- add_action( 'woocommerce_init', function () {
137
- if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wpc_product_bundle', 'no' ) ) {
138
- wcj_remove_class_filter( 'woocommerce_add_to_cart', 'WPcleverWoosb', 'woosb_add_to_cart' );
139
  }
140
- }, 99 );
141
 
142
- // WooCommerce Tree Table Rate Shipping (https://tablerateshipping.com/)
143
- $this->wc_tree_table_rate_shipping_compatibility();
 
 
 
 
 
 
 
 
 
 
 
144
 
145
- // Flexible Shipping plugin https://flexibleshipping.com/
146
- add_filter( 'flexible_shipping_value_in_currency', array( $this, 'flexible_shipping_compatibility' ) );
147
 
148
- // Compatibility with Price by Country module
149
- add_action( 'wcj_price_by_country_set_country', array( $this, 'change_currency_by_country' ), 10, 2 );
150
 
151
- // Compatibility with Pricing Deals
152
- add_filter( 'option_' . 'vtprd_rules_set', array( $this, 'convert_pricing_deals_settings' ) );
153
 
154
- // "WooCommerce Product Add-ons" plugin
155
- add_filter( 'woocommerce_get_item_data', array( $this, 'get_addons_item_data' ), 20, 2 );
156
- add_filter( 'woocommerce_product_addons_option_price_raw', array( $this, 'product_addons_option_price_raw' ), 10, 2 );
157
- add_filter( 'woocommerce_product_addons_price_raw', array( $this, 'product_addons_price_raw' ), 10, 2 );
158
 
159
- // Free Shipping
160
- add_filter( 'woocommerce_shipping_free_shipping_instance_option', array( $this, 'convert_free_shipping_min_amount' ), 10, 3 );
161
- add_filter( 'woocommerce_shipping_free_shipping_option', array( $this, 'convert_free_shipping_min_amount' ), 10, 3 );
162
 
163
- //add_filter( 'wdp_get_product_price', array( $this, 'wdp_get_product_price' ) );
164
- }
165
 
166
- /**
167
- * convert_free_shipping_min_amount.
168
- *
169
- * @version 5.3.3
170
- * @since 5.3.3
171
- *
172
- * @param $option
173
- * @param $key
174
- * @param $method
175
- *
176
- * @return mixed
177
- */
178
- function convert_free_shipping_min_amount( $option, $key, $method ) {
179
- if (
180
  'no' === wcj_get_option( 'wcj_multicurrency_compatibility_free_shipping', 'no' )
181
  || 'min_amount' !== $key
182
  || ! is_numeric( $option )
183
  || 0 === (float) $option
184
- ) {
 
 
 
185
  return $option;
186
  }
187
- $option = $this->change_price( $option, null );
188
- return $option;
189
- }
190
 
191
- /*function wdp_get_product_price( $price, $product, $price_mode, $item_meta ) {
192
- error_log('asd');
193
- if ( $product->is_on_sale( 'edit' ) ) {
194
- if ( 'sale_price' === $price_mode ) {
195
- $price = $product->get_sale_price( '' );
196
- } elseif ( 'discount_sale' === $price_mode ) {
197
- $price = $product->get_sale_price( '' );
198
- } else {
199
- $price = $product->get_regular_price( '' );
200
- }
201
- } else {
202
- $price = $product->get_price( '' );
203
- }
204
- return $price;
205
- }*/
206
 
207
- /**
208
- * product_addons_price_raw.
209
- *
210
- * @version 5.1.1
211
- * @since 5.1.1
212
- *
213
- * @param $price
214
- * @param $addon
215
- *
216
- * @return mixed|string
217
- */
218
- function product_addons_price_raw( $price, $addon ) {
219
- if (
 
220
  'no' === wcj_get_option( 'wcj_multicurrency_compatibility_product_addons', 'no' )
221
- || ( 'quantity_based' != $addon['price_type'] && 'flat_fee' != $addon['price_type'] )
222
- ) {
 
 
 
223
  return $price;
224
  }
225
- $price = $this->change_price( $price, null );
226
- return $price;
227
- }
228
 
229
- /**
230
- * convert_pricing_deals_settings.
231
- *
232
- * @version 5.0.0
233
- * @since 5.0.0
234
- *
235
- * @param $option
236
- *
237
- * @return mixed
238
- */
239
- function convert_pricing_deals_settings( $option ) {
240
- if ( 'no' === wcj_get_option( 'wcj_multicurrency_compatibility_pricing_deals', 'no' ) ) {
241
- return $option;
242
- }
243
- foreach ( $option as $key => $value ) {
244
- foreach ( $value->rule_deal_info as $deal_info_key => $deal_info_value ) {
245
- if ( 'currency' === $deal_info_value['buy_amt_type'] ) {
246
- $option[ $key ]->rule_deal_info[ $deal_info_key ]['buy_amt_count'] *= $this->get_currency_exchange_rate( $this->get_current_currency_code() );
 
247
  }
248
  }
 
249
  }
250
- return $option;
251
- }
252
 
253
- /**
254
- * change_currency_by_country.
255
- *
256
- * @version 5.0.0
257
- * @since 5.0.0
258
- *
259
- * @param $country
260
- * @param $currency
261
- */
262
- function change_currency_by_country( $country, $currency ) {
263
- if (
264
  empty( $currency ) ||
265
  'no' === wcj_get_option( 'wcj_multicurrency_compatibility_price_by_country_module', 'no' )
266
- ) {
267
- return;
 
 
268
  }
269
- wcj_session_set( 'wcj-currency', $currency );
270
- }
271
 
272
- /**
273
- * wcj_multicurrency_compatibility_flexible_shipping.
274
- *
275
- * @see https://flexibleshipping.com
276
- *
277
- * @version 4.9.0
278
- * @since 4.9.0
279
- *
280
- */
281
- function flexible_shipping_compatibility( $value ) {
282
- if ( 'yes' !== wcj_get_option( 'wcj_multicurrency_compatibility_flexible_shipping', 'no' ) ) {
 
 
 
283
  return $value;
284
  }
285
- $value *= $this->get_currency_exchange_rate( $this->get_current_currency_code() );
286
- return $value;
287
- }
288
 
289
- /**
290
- * wc_tree_table_rate_shipping_compatibility.
291
- *
292
- * @see https://tablerateshipping.com/
293
- *
294
- * @version 4.9.0
295
- * @since 4.9.0
296
- */
297
- function wc_tree_table_rate_shipping_compatibility() {
298
- $shipping_instance_max = apply_filters( 'wcj_multicurrency_compatibility_wc_ttrs_instances', 90 );
299
- for ( $i = 1; $i <= $shipping_instance_max; $i ++ ) {
300
- add_filter( 'option_' . 'woocommerce_tree_table_rate_' . $i . '_settings', array( $this, 'convert_wc_tree_table_rate_settings' ) );
 
301
  }
302
- }
303
 
304
- /**
305
- * get_wc_tree_table_rate_settings.
306
- *
307
- * @version 5.1.0
308
- * @since 4.9.0
309
- *
310
- * @param $option
311
- *
312
- * @return mixed
313
- */
314
- function convert_wc_tree_table_rate_settings( $option ) {
315
- if ( 'no' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_ttrs', 'no' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
316
  return $option;
317
  }
318
- $transition_name = 'wcj_wc_tree_table_opt_' . md5( current_filter() );
319
- if ( false === ( $modified_rule_result = get_transient( $transition_name ) ) ) {
320
- $rule = json_decode( $option['rule'] );
321
- $modified_rule = $this->recursively_convert_wc_tree_settings( $rule, array(
322
- 'change_keys' => array( 'value', 'min', 'max' ),
323
- 'exchange_rate' => $this->get_currency_exchange_rate( $this->get_current_currency_code() )
324
- ) );
325
- set_transient( $transition_name, json_encode( $modified_rule ), 5 * MINUTE_IN_SECONDS );
326
- }
327
- $option['rule'] = $modified_rule_result;
328
- remove_filter( current_filter(), array( $this, 'convert_wc_tree_table_rate_settings' ) );
329
- return $option;
330
- }
331
 
332
- /**
333
- * recursively_convert_wc_tree_settings.
334
- *
335
- * @version 5.1.0
336
- * @since 4.9.0
337
- *
338
- * @param $array
339
- * @param null $args
340
- *
341
- * @return array
342
- */
343
- function recursively_convert_wc_tree_settings( $array, $args = null ) {
344
- $args = wp_parse_args( $args, array(
345
- 'change_keys' => array(),
346
- 'exchange_rate' => 1,
347
- ) );
348
- $change_keys = $args['change_keys'];
349
- $exchange_rate = $args['exchange_rate'];
350
- foreach ( $array as $key => $value ) {
351
- if ( in_array( $key, $change_keys ) ) {
352
- if (
353
- is_array( $array ) &&
354
- isset( $array['condition'] ) &&
355
- 'price' == $array['condition'] &&
356
- ! empty( $value ) &&
357
- is_numeric( $value )
358
- ) {
359
- $array[ $key ] = $value * $exchange_rate;
360
- } elseif (
 
 
 
361
  is_a( $array, 'stdClass' ) &&
362
  property_exists( $array, 'condition' ) &&
363
  'price' === $array->condition &&
364
  ! empty( $value ) &&
365
  is_numeric( $value )
366
- ) {
367
- $array->$key = $value * $exchange_rate;
 
 
 
 
368
  }
369
  }
370
- if ( is_array( $value ) || is_a( $value, 'stdClass' ) ) {
371
- $this->recursively_convert_wc_tree_settings( $value, $args );
372
- }
373
  }
374
- return $array;
375
- }
376
 
377
- /**
378
- * @version 4.9.0
379
- * @since 4.9.0
380
- *
381
- * @param $valid
382
- * @param WC_Coupon $coupon
383
- * @param WC_Discounts $wc_discounts
384
- *
385
- * @return bool
386
- * @throws Exception
387
- */
388
- function check_woocommerce_coupon_min_max_amount( $valid, WC_Coupon $coupon, WC_Discounts $wc_discounts ) {
389
- if ( 'yes' !== wcj_get_option( 'wcj_multicurrency_compatibility_wc_coupons', 'no' ) ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
390
  return $valid;
391
  }
392
- remove_filter( 'woocommerce_coupon_is_valid', array( $this, 'check_woocommerce_coupon_min_max_amount' ), 10 );
393
- if ( ! empty( $minimum_amount = $coupon->get_minimum_amount() ) ) {
394
- $coupon->set_minimum_amount( $this->change_price( $minimum_amount, null ) );
395
- }
396
- if ( ! empty( $maximum_amount = $coupon->get_maximum_amount() ) ) {
397
- $coupon->set_maximum_amount( $this->change_price( $maximum_amount, null ) );
398
- }
399
- $is_coupon_valid = $wc_discounts->is_coupon_valid( $coupon );
400
- if ( is_wp_error( $is_coupon_valid ) ) {
401
- return false;
402
- }
403
- return $valid;
404
- }
405
 
406
- /**
407
- * fix_wc_coupon_discount_amount.
408
- *
409
- * @version 5.2.0
410
- * @since 5.2.0
411
- *
412
- * @param $false
413
- * @param $data
414
- * @param $coupon
415
- *
416
- * @return mixed
417
- */
418
- function fix_wc_coupon_discount_amount( $false, $data, $coupon ) {
419
- if (
 
420
  'yes' !== wcj_get_option( 'wcj_multicurrency_compatibility_wc_coupons', 'no' ) ||
421
  is_admin() ||
422
- empty( $coupon_id = wc_get_coupon_id_by_code( $data ) ) ||
423
- 'fixed_cart' != get_post_meta( $coupon_id, 'discount_type', true )
424
- ) {
425
- return $false;
 
 
 
 
426
  }
427
- $current_coupon_amount = get_post_meta( $coupon_id, 'coupon_amount', true );
428
- $coupon->set_amount( $this->change_price( $current_coupon_amount, null ) );
429
- return $coupon;
430
- }
431
 
432
- /**
433
- * fix_wc_attribute_swatches_premium_variable_cart_item_price.
434
- *
435
- * @version 5.4.3
436
- * @since 5.4.3
437
- *
438
- * @param $price_html
439
- * @param $cart_item
440
- * @param $cart_item_key
441
- *
442
- * @return mixed
443
- */
444
- function fix_wc_attribute_swatches_premium_variable_cart_item_price( $price_html, $cart_item, $cart_item_key ) {
445
- if ( empty( $cart_item['iconic_was_fee'] ) ) {
446
- return $price_html;
 
 
 
447
  }
448
- $price = $this->change_price( $cart_item['iconic_was_fee'], null );
449
- return wc_price( $price );
450
- }
451
 
452
- /**
453
- * Fixes sort by price when `wcj_multicurrency_per_product_enabled` is enabled.
454
- *
455
- * @version 4.6.0
456
- * @since 4.5.0
457
- *
458
- * @param $args
459
- * @param $orderby
460
- * @param $order
461
- *
462
- * @return mixed
463
- */
464
- function handle_per_product_opt_with_sort_by_price( $args, $orderby, $order ) {
465
- if (
466
- $orderby != 'price' ||
467
  is_admin() ||
468
  ! is_main_query() ||
469
  'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
470
  get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
471
- 1 === $this->get_currency_exchange_rate( $this->get_current_currency_code()
 
472
  )
473
- ) {
474
- return $args;
475
- }
476
- $order = 'DESC' === $order ? $order : 'ASC';
477
- add_filter( 'posts_clauses', function ( $clauses ) use ( $order ) {
478
- global $wpdb;
479
- if (
480
- false === strpos( $clauses['orderby'], 'wc_product_meta_lookup.max_price DESC' ) &&
481
- false === strpos( $clauses['orderby'], 'wc_product_meta_lookup.min_price ASC' )
482
  ) {
483
- return $clauses;
484
  }
485
- $current_currency_code = $this->get_current_currency_code();
486
- $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
 
 
 
 
 
 
 
 
 
 
 
487
 
488
- $min_max_join = "LEFT JOIN {$wpdb->postmeta} AS pm on pm.post_id = {$wpdb->posts}.ID AND (pm.meta_key IN ('_wcj_multicurrency_per_product_min_price_{$current_currency_code}','_wcj_multicurrency_per_product_max_price_{$current_currency_code}') and pm.meta_value!='')";
489
- if ( false === strpos( $clauses['join'], $min_max_join ) ) {
490
- $clauses['join'] .= " {$min_max_join} ";
491
- }
492
- if ( 'DESC' === $order ) {
493
- $clauses['fields'] .= ", (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) +0) AS wcj_price ";
494
- } else {
495
- $clauses['fields'] .= ", (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_price ";
496
- }
497
- $clauses['orderby'] = " wcj_price {$order}, wc_product_meta_lookup.product_id {$order} ";
498
 
499
- return $clauses;
500
- }, 99 );
501
- return $args;
502
- }
 
 
503
 
504
- /**
505
- * Makes Price Filter Widget filter correct products if Per product option `wcj_multicurrency_per_product_enabled` is enabled.
506
- *
507
- * First it removes products witch `_wcj_multicurrency_per_product_regular_price_{$current_currency_code}` meta don't match min and max.
508
- * Then it adds products witch `_wcj_multicurrency_per_product_regular_price_{$current_currency_code}` meta match min and max.
509
- *
510
- * @version 4.6.0
511
- * @since 4.5.0
512
- *
513
- * @see WC_Query::price_filter_post_clauses()
514
- *
515
- * @param $args
516
- * @param $query
517
- *
518
- * @return mixed
519
- */
520
- function posts_clauses_price_filter_compatible( $args, $query ) {
521
- if (
522
  is_admin() ||
523
  'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
524
  get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
@@ -528,76 +553,77 @@ class WCJ_Multicurrency extends WCJ_Module {
528
  false === strpos( $args['where'], 'wc_product_meta_lookup.min_price >=' ) &&
529
  false === strpos( $args['where'], 'wc_product_meta_lookup.max_price <=' )
530
  )
531
- ) {
532
- return $args;
533
- }
534
-
535
- global $wpdb;
536
- $current_currency_code = $this->get_current_currency_code();
537
- $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
538
 
539
- $min_price = isset( $_GET['min_price'] ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0;
540
- $max_price = isset( $_GET['max_price'] ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : PHP_INT_MAX;
541
- $min_max_join = "LEFT JOIN {$wpdb->postmeta} AS pm on pm.post_id = {$wpdb->posts}.ID AND (pm.meta_key IN ('_wcj_multicurrency_per_product_min_price_{$current_currency_code}','_wcj_multicurrency_per_product_max_price_{$current_currency_code}') and pm.meta_value!='')";
542
- if ( false === strpos( $args['join'], $min_max_join ) ) {
543
- $args['join'] .= " {$min_max_join} ";
 
 
 
 
 
 
 
 
 
544
  }
545
- $args['fields'] .= ", (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_min_price ";
546
- $args['fields'] .= ", (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) +0) AS wcj_max_price ";
547
- $args['where'] = preg_replace( '/and wc_product_meta_lookup.min_price >= \d.* and wc_product_meta_lookup.max_price <= \d.*\s/i', '', $args['where'] );
548
- $args['groupby'] .= " having wcj_min_price >= $min_price AND wcj_min_price <= $max_price ";
549
- return $args;
550
- }
551
 
552
- /**
553
- * Makes Price Filter Widget show correct min and max values if Per product option `wcj_multicurrency_per_product_enabled` is enabled.
554
- *
555
- * It works comparing min and max values from "_wcj_multicurrency_per_product_regular_price_{currency_code}" meta as well as min and max price from wc_product_meta_lookup
556
- *
557
- * @version 4.6.0
558
- * @since 4.5.0
559
- *
560
- * @see WC_Widget_Price_Filter::get_filtered_price()
561
- *
562
- * @param $sql
563
- *
564
- * @return mixed
565
- */
566
- function get_price_filter_sql_compatible( $sql, $meta_query_sql, $tax_query_sql ) {
567
- if (
 
 
568
  is_admin() ||
569
  'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
570
  get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
571
  1 === $this->get_currency_exchange_rate( $this->get_current_currency_code() )
572
- ) {
573
- return $sql;
574
- }
575
 
576
- global $wpdb;
577
- $current_currency_code = $this->get_current_currency_code();
578
- $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
579
- $args = WC()->query->get_main_query()->query_vars;
580
- $tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
581
- $meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
582
-
583
- if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
584
- $tax_query[] = array(
585
- 'taxonomy' => $args['taxonomy'],
586
- 'terms' => array( $args['term'] ),
587
- 'field' => 'slug',
588
- );
589
- }
590
 
591
- foreach ( $meta_query + $tax_query as $key => $query ) {
592
- if ( ! empty( $query['price_filter'] ) || ! empty( $query['rating_filter'] ) ) {
593
- unset( $meta_query[ $key ] );
 
594
  }
595
- }
596
 
597
- $search = WC_Query::get_main_search_query_sql();
598
- $search_query_sql = $search ? ' AND ' . $search : '';
599
 
600
- $sql = "
601
  SELECT FLOOR(min(wcj_min_price)) as min_price, CEILING(max(wcj_max_price)) as max_price
602
  FROM(
603
  SELECT (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_min_price, (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) + 0) AS wcj_max_price
@@ -613,66 +639,72 @@ class WCJ_Multicurrency extends WCJ_Module {
613
  group by product_id
614
  ) as wcj_min_max_price
615
  ';
616
- return $sql;
617
- }
618
 
619
- /**
620
- * Fixes WooCommerce import.
621
- *
622
- * For now it converts '_wcj_%price%_{currency}' meta with lowercase currency to uppercase.
623
- *
624
- * @version 4.4.0
625
- * @since 4.4.0
626
- *
627
- * @param $parsed_data
628
- * @param $raw_data
629
- *
630
- * @return mixed
631
- */
632
- function fix_wc_product_import( $parsed_data, $raw_data ) {
633
- // Gets values
634
- $multicurrency_values = array_filter( $parsed_data['meta_data'], function ( $value ) {
635
- return preg_match( '/^_wcj_.+price.*_[a-z]{2,3}$/', $value['key'] );
636
- } );
637
-
638
- // Changes lowercase currency to uppercase
639
- $modified_values = array_map( function ( $value ) {
640
- $str = $value['key'];
641
- $last_underscore = strrpos( $str, '_' );
642
- $before = substr( $str, 0, $last_underscore );
643
- $currency = substr( $str, $last_underscore + 1 );
644
- $value['key'] = $before . '_' . strtoupper( $currency );
645
- return $value;
646
- }, $multicurrency_values );
647
 
648
- // Applies changes to the main data
649
- foreach ( $modified_values as $i => $value ) {
650
- $parsed_data['meta_data'][ $i ]['key'] = $value['key'];
651
- }
 
 
 
 
 
 
 
 
652
 
653
- return $parsed_data;
654
- }
 
 
655
 
656
- /**
657
- * Adds compatibility with WooCommerce Price Filter widget.
658
- *
659
- * @see price-slider.js, init_price_filter()
660
- *
661
- * @version 5.2.0
662
- * @since 4.3.0
663
- */
664
- function add_compatibility_with_price_filter_widget() {
665
- if ( ! is_active_widget( false, false, 'woocommerce_price_filter' ) ) {
666
- return;
667
  }
668
- ?>
669
- <?php
670
- $exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() );
671
- if ( $exchange_rate == 1 ) {
672
- return;
673
- }
674
- ?>
675
- <input type="hidden" id="wcj_mc_exchange_rate" value="<?php echo esc_html( $exchange_rate ) ?>"/>
 
 
 
 
 
 
 
 
 
 
 
 
 
676
  <script>
677
  var wcj_mc_pf_slider = {
678
  slider: null,
@@ -757,131 +789,145 @@ class WCJ_Multicurrency extends WCJ_Module {
757
  }
758
  });
759
  </script>
760
- <?php
761
- }
762
-
763
- /**
764
- * Fixes price filter widget currency format
765
- *
766
- * @version 4.3.0
767
- * @since 4.3.0
768
- */
769
- function fix_price_filter_widget_currency_format() {
770
- $price_args = apply_filters( 'wc_price_args', array(
771
- 'ex_tax_label' => false,
772
- 'currency' => '',
773
- 'decimal_separator' => wc_get_price_decimal_separator(),
774
- 'thousand_separator' => wc_get_price_thousand_separator(),
775
- 'decimals' => wc_get_price_decimals(),
776
- 'price_format' => get_woocommerce_price_format(),
777
- ) );
778
- $symbol = apply_filters( 'woocommerce_currency_symbol', get_woocommerce_currency_symbol(), get_woocommerce_currency() );
779
- wp_localize_script(
780
- 'wc-price-slider', 'woocommerce_price_slider_params', array(
781
- 'currency_format_num_decimals' => $price_args['decimals'],
782
- 'currency_format_symbol' => $symbol,
783
- 'currency_format_decimal_sep' => esc_attr( $price_args['decimal_separator'] ),
784
- 'currency_format_thousand_sep' => esc_attr( $price_args['thousand_separator'] ),
785
- 'currency_format' => esc_attr( str_replace( array( '%1$s', '%2$s' ), array( '%s', '%v' ), $price_args['price_format'] ) ),
786
- )
787
- );
788
- }
789
-
790
- /**
791
- * add_hooks.
792
- *
793
- * @version 5.0.0
794
- */
795
- function add_hooks() {
796
- if ( wcj_is_frontend() ) {
797
-
798
- // Prices - Compatibility - "WooCommerce TM Extra Product Options" plugin
799
- add_filter( 'woocommerce_tm_epo_price_on_cart', array( $this, 'change_price_by_currency_tm_extra_product_options_plugin_cart' ), $this->price_hooks_priority, 1 );
800
- add_filter( 'wc_epo_price', array( $this, 'change_price_by_currency_tm_extra_product_options_plugin' ), $this->price_hooks_priority, 3 );
801
-
802
- // Currency hooks
803
- add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), $this->price_hooks_priority, 1 );
804
-
805
- // Add "Change Price" hooks
806
- wcj_add_change_price_hooks( $this, $this->price_hooks_priority );
807
 
808
- // Handle Compatibility
809
- $this->handle_compatibility();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
810
 
811
- // Additional Price Filters
812
- $this->additional_price_filters = wcj_get_option( 'wcj_multicurrency_switcher_additional_price_filters', '' );
813
- if ( ! empty( $this->additional_price_filters ) ) {
814
- $this->additional_price_filters = array_map( 'trim', explode( PHP_EOL, $this->additional_price_filters ) );
815
- foreach ( $this->additional_price_filters as $additional_price_filter ) {
816
- add_filter( $additional_price_filter, array( $this, 'change_price' ), $this->price_hooks_priority, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
817
  }
818
  } else {
819
- $this->additional_price_filters = array();
820
- }
821
-
822
- } else {
823
- // Saves min and max price when product is updated
824
- add_action( 'woocommerce_update_product', function ( $post_id ) {
825
- if ( 'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ) ) {
826
- return;
827
- }
828
- $this->save_min_max_prices_per_product( $post_id );
829
- }, 99 );
830
 
831
- // Saves min and max price when exchange rate changes
832
- add_action( 'updated_option', array( $this, 'update_min_max_prices_on_exchange_rate_change' ), 10, 3 );
 
833
  }
834
- }
835
 
836
- /**
837
- * Updates min and max prices on exchange rate change.
838
- *
839
- * The update is done with background process.
840
- *
841
- * @version 4.5.0
842
- * @since 4.5.0
843
- *
844
- * @param $option_name
845
- * @param $old_value
846
- * @param $option_value
847
- */
848
- function update_min_max_prices_on_exchange_rate_change( $option_name, $old_value, $option_value ) {
849
- if (
850
  'no' === wcj_get_option( 'wcj_multicurrency_update_prices_on_exch_update', 'no' ) ||
851
  'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ) ||
852
  false === strpos( $option_name, 'wcj_multicurrency_exchange_rate_' )
853
- ) {
854
- return;
855
- }
856
- $currency_number = substr( $option_name, strrpos( $option_name, '_' ) + 1 );
857
- $currency = wcj_get_option( 'wcj_multicurrency_currency_' . $currency_number );
858
- $product_ids = $this->get_products_by_per_product_currency( $currency );
859
- if ( is_array( $product_ids ) && count( $product_ids ) > 0 ) {
860
- $this->bkg_process_price_updater->cancel_process();
861
- foreach ( $product_ids as $post_id ) {
862
- $this->bkg_process_price_updater->push_to_queue( array( 'id' => $post_id, 'currency' => $currency ) );
 
 
 
 
 
 
 
863
  }
864
- $this->bkg_process_price_updater->save()->dispatch();
865
  }
866
- }
867
 
868
- /**
869
- * Gets all products, or products with variations containing meta '_wcj_multicurrency_per_product_regular_price_{currency}' or '_wcj_multicurrency_per_product_sale_price_{currency}'.
870
- *
871
- * @version 4.6.0
872
- * @since 4.5.0
873
- *
874
- * @param $currency
875
- *
876
- * @return array
877
- */
878
- function get_products_by_per_product_currency( $currency ) {
879
- if ( empty( $currency ) ) {
880
- $currency = wcj_get_option( 'woocommerce_currency' );
881
- }
882
 
883
- global $wpdb;
884
- $product_ids = $wpdb->get_col( "
 
885
  SELECT p.ID
886
  FROM {$wpdb->posts} AS p
887
  LEFT JOIN {$wpdb->posts} AS p2 ON p.ID = p2.ID OR (p2.post_parent = p.ID AND p2.post_type='product_variation')
@@ -889,462 +935,490 @@ class WCJ_Multicurrency extends WCJ_Module {
889
  WHERE p.post_status = 'publish' AND p.post_type IN ('product')
890
  AND pm.meta_value != 'null'
891
  GROUP BY p.ID
892
- " );
 
893
 
894
- return $product_ids;
895
- }
896
 
897
- /**
898
- * Updates min and max prices.
899
- *
900
- * @version 4.5.0
901
- * @since 4.5.0
902
- *
903
- * @param $post_id
904
- * @param string $currency_code_param
905
- */
906
- function save_min_max_prices_per_product( $post_id, $currency_code_param = '' ) {
907
- $product = wc_get_product( $post_id );
908
- $products = array();
909
- if ( $product->is_type( 'variable' ) ) {
910
- $available_variations = $product->get_variation_prices()['price'];
911
- foreach ( $available_variations as $variation_id => $price ) {
912
- $products[ $variation_id ] = $price;
 
 
 
 
 
 
 
 
913
  }
914
- } else {
915
- $products[ $post_id ] = $product->get_price();
916
- }
917
- if ( empty( $currency_code_param ) ) {
918
- $total_number = apply_filters( 'booster_option', 2, wcj_get_option( 'wcj_multicurrency_total_number', 2 ) );
919
- } else {
920
- $total_number = 1;
921
- }
922
 
923
- $per_product_prices = array();
924
- for ( $i = 1; $i <= $total_number; $i ++ ) {
925
- $currency_code = empty( $currency_code_param ) ? wcj_get_option( 'wcj_multicurrency_currency_' . $i ) : $currency_code_param;
926
- $exchange_rate = $this->get_currency_exchange_rate( $currency_code );
927
- foreach ( $products as $product_id => $original_price ) {
928
- // Regular Price
929
- if ( isset( $_POST["wcj_multicurrency_per_product_regular_price_{$currency_code}_{$product_id}"] ) ) {
930
- $regular_price = $_POST["wcj_multicurrency_per_product_regular_price_{$currency_code}_{$product_id}"];
931
- } else {
932
- $regular_price = get_post_meta( $product_id, '_wcj_multicurrency_per_product_regular_price_' . $currency_code, true );
933
- }
934
-
935
- // Sale Price
936
- if ( isset( $_POST["wcj_multicurrency_per_product_sale_price_{$currency_code}_{$product_id}"] ) ) {
937
- $sale_price = $_POST["wcj_multicurrency_per_product_sale_price_{$currency_code}_{$product_id}"];
938
- } else {
939
- $sale_price = get_post_meta( $product_id, '_wcj_multicurrency_per_product_sale_price_' . $currency_code, true );
 
 
 
 
 
940
  }
941
- $prices = array_filter( ar
5
  * @version 5.4.3
6
  * @since 2.4.3
7
  * @author Pluggabl LLC.
8
+ * @package Booster_For_WooCommerce/includes
9
  */
10
 
11
+ if ( ! defined( 'ABSPATH' ) ) {
12
+ exit;
13
+ }
14
 
15
  if ( ! class_exists( 'WCJ_Multicurrency' ) ) :
 
 
 
16
  /**
17
+ * WCJ_Multicurrency.
18
  */
19
+ class WCJ_Multicurrency extends WCJ_Module {
20
+
21
+ /**
22
+ Bkg_process_price_updater
23
+ *
24
+ * @var bkg_process_price_updater
25
+ */
26
+ protected $bkg_process_price_updater;
27
+
28
+ /**
29
+ * Constructor.
30
+ *
31
+ * @version 5.2.0
32
+ * @todo check if we can just always execute `init()` on `init` hook
33
+ */
34
+ public function __construct() {
35
+
36
+ $this->id = 'multicurrency';
37
+ $this->short_desc = __( 'Multicurrency (Currency Switcher)', 'woocommerce-jetpack' );
38
+ $this->desc = __( 'Add multiple currencies (currency switcher) to WooCommerce (2 currencies allowed in free version).', 'woocommerce-jetpack' );
39
+ $this->desc_pro = __( 'Add multiple currencies (currency switcher) to WooCommerce.', 'woocommerce-jetpack' );
40
+ $this->link_slug = 'woocommerce-multicurrency-currency-switcher';
41
+ $this->extra_desc = sprintf(
42
+ /* translators: %s: translation added */
43
+ __( 'After setting currencies in the Currencies Options section below, you can add switcher to the frontend with: %s', 'woocommerce-jetpack' ),
44
+ '<ol>' .
45
+ '<li>' . sprintf(
46
+ /* translators: %s: translation added */
47
+ __( '<strong>Widget:</strong> "%s"', 'woocommerce-jetpack' ),
48
+ __( 'Booster - Multicurrency Switcher', 'woocommerce-jetpack' )
49
+ ) .
50
  '</li>' .
51
+ '<li>' . sprintf(
52
+ /* translators: %s: translation added */
53
+ __( '<strong>Shortcodes:</strong> %s', 'woocommerce-jetpack' ),
54
+ '<code>[wcj_currency_select_drop_down_list]</code>, <code>[wcj_currency_select_radio_list]</code>, <code>[wcj_currency_select_link_list]</code>'
55
+ ) .
56
  '</li>' .
57
+ '<li>' . sprintf(
58
+ /* translators: %s: translation added */
59
+ __( '<strong>PHP code:</strong> by using %1$s function, e.g.: %2$s', 'woocommerce-jetpack' ),
60
  '<code>do_shortcode()</code>',
61
+ '<code>echo&nbsp;do_shortcode(&nbsp;\'[wcj_currency_select_drop_down_list]\'&nbsp;);</code>'
62
+ ) .
63
  '</li>' .
64
+ '</ol>'
65
+ );
66
+ parent::__construct();
67
 
68
+ if ( $this->is_enabled() ) {
69
+ $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'multicurrency' );
70
 
71
+ // Session.
72
+ if ( 'wc' === WCJ_SESSION_TYPE ) {
73
+ // `init()` executed on `init` hook because we need to use `WC()->session`.
74
+ add_action( 'init', array( $this, 'init' ) );
75
+ } else {
76
+ $this->init();
77
+ }
78
 
79
+ $this->add_hooks();
80
 
81
+ if ( 'yes' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ) ) {
82
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
83
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
84
+ }
85
 
86
+ if ( is_admin() ) {
87
+ include_once 'reports/class-wcj-currency-reports.php';
88
+ }
89
 
90
+ if ( 'init' === current_filter() ) {
91
+ $this->init_bkg_process_class();
92
+ } else {
93
+ add_action( 'plugins_loaded', array( $this, 'init_bkg_process_class' ) );
94
+ }
95
  }
96
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
97
 
98
+ /**
99
+ * Init_bkg_process_class.
100
+ *
101
+ * @version 4.5.0
102
+ * @since 4.5.0
103
+ */
104
+ public function init_bkg_process_class() {
105
+ if ( 'yes' === wcj_get_option( 'wcj_multicurrency_update_prices_on_exch_update', 'no' ) ) {
106
+ require_once wcj_plugin_path() . '/includes/background-process/class-wcj-multicurrency-price-updater.php';
107
+ $this->bkg_process_price_updater = new WCJ_Multicurrency_Price_Updater();
108
+ }
109
  }
110
 
111
+ /**
112
+ * Handles third party compatibility.
113
+ *
114
+ * @version 5.4.3
115
+ * @since 4.3.0
116
+ */
117
+ public function handle_compatibility() {
118
+ // "WooCommerce Smart Coupons" Compatibility.
119
+ if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_smart_coupons', 'yes' ) ) {
120
+ add_filter( 'woocommerce_coupon_get_amount', array( $this, 'smart_coupons_get_amount' ), 10, 2 );
121
+ }
122
 
123
+ // WooCommerce Coupons.
124
+ add_filter( 'woocommerce_coupon_is_valid', array( $this, 'check_woocommerce_coupon_min_max_amount' ), 10, 3 );
125
+ add_filter( 'woocommerce_get_shop_coupon_data', array( $this, 'fix_wc_coupon_discount_amount' ), 10, 3 );
 
126
 
127
+ // WooCommerce Attribute Swatches by Iconic Plugin.
128
+ if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_attribute_swatches_premium_variable_cart_item_price', 'no' ) ) {
129
+ add_filter( 'woocommerce_cart_item_price', array( $this, 'fix_wc_attribute_swatches_premium_variable_cart_item_price' ), 20, 3 );
130
+ }
 
 
 
 
 
 
 
131
 
132
+ // WooCommerce Price Filter Widget.
133
+ if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_price_filter', 'no' ) ) {
134
+ add_action( 'wp_footer', array( $this, 'add_compatibility_with_price_filter_widget' ) );
135
+ add_action( 'wp_footer', array( $this, 'fix_price_filter_widget_currency_format' ) );
136
+ add_filter( 'woocommerce_price_filter_sql', array( $this, 'get_price_filter_sql_compatible' ), 10, 3 );
137
+ add_filter( 'posts_clauses', array( $this, 'posts_clauses_price_filter_compatible' ), 11, 2 );
138
+ add_filter(
139
+ 'woocommerce_price_filter_widget_step',
140
+ function ( $step ) {
141
+ $step = 1;
142
+ return $step;
143
+ }
144
+ );
145
+ }
146
 
147
+ // Sort by Price.
148
+ if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_price_sorting_per_product', 'no' ) ) {
149
+ add_filter( 'woocommerce_get_catalog_ordering_args', array( $this, 'handle_per_product_opt_with_sort_by_price' ), 29, 3 );
150
+ }
151
 
152
+ // Fix WooCommerce Import.
153
+ if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_import', 'no' ) ) {
154
+ add_filter( 'woocommerce_product_importer_parsed_data', array( $this, 'fix_wc_product_import' ), 10, 2 );
 
155
  }
 
156
 
157
+ // WPC Product Bundles plugin.
158
+ add_action(
159
+ 'woocommerce_init',
160
+ function () {
161
+ if ( 'yes' === wcj_get_option( 'wcj_multicurrency_compatibility_wpc_product_bundle', 'no' ) ) {
162
+ wcj_remove_class_filter( 'woocommerce_add_to_cart', 'WPcleverWoosb', 'woosb_add_to_cart' );
163
+ }
164
+ },
165
+ 99
166
+ );
167
+
168
+ // WooCommerce Tree Table Rate Shipping (https://tablerateshipping.com/).
169
+ $this->wc_tree_table_rate_shipping_compatibility();
170
 
171
+ // Flexible Shipping plugin https://flexibleshipping.com/.
172
+ add_filter( 'flexible_shipping_value_in_currency', array( $this, 'flexible_shipping_compatibility' ) );
173
 
174
+ // Compatibility with Price by Country module.
175
+ add_action( 'wcj_price_by_country_set_country', array( $this, 'change_currency_by_country' ), 10, 2 );
176
 
177
+ // Compatibility with Pricing Deals.
178
+ add_filter( 'option_vtprd_rules_set', array( $this, 'convert_pricing_deals_settings' ) );
179
 
180
+ // "WooCommerce Product Add-ons" plugin.
181
+ add_filter( 'woocommerce_get_item_data', array( $this, 'get_addons_item_data' ), 20, 2 );
182
+ add_filter( 'woocommerce_product_addons_option_price_raw', array( $this, 'product_addons_option_price_raw' ), 10, 2 );
183
+ add_filter( 'woocommerce_product_addons_price_raw', array( $this, 'product_addons_price_raw' ), 10, 2 );
184
 
185
+ // Free Shipping.
186
+ add_filter( 'woocommerce_shipping_free_shipping_instance_option', array( $this, 'convert_free_shipping_min_amount' ), 10, 3 );
187
+ add_filter( 'woocommerce_shipping_free_shipping_option', array( $this, 'convert_free_shipping_min_amount' ), 10, 3 );
188
 
189
+ }
 
190
 
191
+ /**
192
+ * Convert_free_shipping_min_amount.
193
+ *
194
+ * @version 5.3.3
195
+ * @since 5.3.3
196
+ *
197
+ * @param string | int $option defines the option.
198
+ * @param string $key defines the key.
199
+ * @param string $method defines the method.
200
+ *
201
+ * @return mixed
202
+ */
203
+ public function convert_free_shipping_min_amount( $option, $key, $method ) {
204
+ if (
205
  'no' === wcj_get_option( 'wcj_multicurrency_compatibility_free_shipping', 'no' )
206
  || 'min_amount' !== $key
207
  || ! is_numeric( $option )
208
  || 0 === (float) $option
209
+ ) {
210
+ return $option;
211
+ }
212
+ $option = $this->change_price( $option, null );
213
  return $option;
214
  }
 
 
 
215
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
216
 
217
+
218
+ /**
219
+ * Product_addons_price_raw.
220
+ *
221
+ * @version 5.1.1
222
+ * @since 5.1.1
223
+ *
224
+ * @param int $price defines the price.
225
+ * @param array $addon defines the addon.
226
+ *
227
+ * @return mixed|string
228
+ */
229
+ public function product_addons_price_raw( $price, $addon ) {
230
+ if (
231
  'no' === wcj_get_option( 'wcj_multicurrency_compatibility_product_addons', 'no' )
232
+ || ( 'quantity_based' !== $addon['price_type'] && 'flat_fee' !== $addon['price_type'] )
233
+ ) {
234
+ return $price;
235
+ }
236
+ $price = $this->change_price( $price, null );
237
  return $price;
238
  }
 
 
 
239
 
240
+ /**
241
+ * Convert_pricing_deals_settings.
242
+ *
243
+ * @version 5.0.0
244
+ * @since 5.0.0
245
+ *
246
+ * @param array $option defines the option.
247
+ *
248
+ * @return mixed
249
+ */
250
+ public function convert_pricing_deals_settings( $option ) {
251
+ if ( 'no' === wcj_get_option( 'wcj_multicurrency_compatibility_pricing_deals', 'no' ) ) {
252
+ return $option;
253
+ }
254
+ foreach ( $option as $key => $value ) {
255
+ foreach ( $value->rule_deal_info as $deal_info_key => $deal_info_value ) {
256
+ if ( 'currency' === $deal_info_value['buy_amt_type'] ) {
257
+ $option[ $key ]->rule_deal_info[ $deal_info_key ]['buy_amt_count'] *= $this->get_currency_exchange_rate( $this->get_current_currency_code() );
258
+ }
259
  }
260
  }
261
+ return $option;
262
  }
 
 
263
 
264
+ /**
265
+ * Change_currency_by_country.
266
+ *
267
+ * @version 5.0.0
268
+ * @since 5.0.0
269
+ *
270
+ * @param string $country defines the country.
271
+ * @param int | string $currency defines the currency.
272
+ */
273
+ public function change_currency_by_country( $country, $currency ) {
274
+ if (
275
  empty( $currency ) ||
276
  'no' === wcj_get_option( 'wcj_multicurrency_compatibility_price_by_country_module', 'no' )
277
+ ) {
278
+ return;
279
+ }
280
+ wcj_session_set( 'wcj-currency', $currency );
281
  }
 
 
282
 
283
+ /**
284
+ * Wcj_multicurrency_compatibility_flexible_shipping.
285
+ *
286
+ * @see https://flexibleshipping.com
287
+ *
288
+ * @version 4.9.0
289
+ * @since 4.9.0
290
+ * @param int | string $value defines the value.
291
+ */
292
+ public function flexible_shipping_compatibility( $value ) {
293
+ if ( 'yes' !== wcj_get_option( 'wcj_multicurrency_compatibility_flexible_shipping', 'no' ) ) {
294
+ return $value;
295
+ }
296
+ $value *= $this->get_currency_exchange_rate( $this->get_current_currency_code() );
297
  return $value;
298
  }
 
 
 
299
 
300
+ /**
301
+ * Wc_tree_table_rate_shipping_compatibility.
302
+ *
303
+ * @see https://tablerateshipping.com/
304
+ *
305
+ * @version 4.9.0
306
+ * @since 4.9.0
307
+ */
308
+ public function wc_tree_table_rate_shipping_compatibility() {
309
+ $shipping_instance_max = apply_filters( 'wcj_multicurrency_compatibility_wc_ttrs_instances', 90 );
310
+ for ( $i = 1; $i <= $shipping_instance_max; $i ++ ) {
311
+ add_filter( 'option_woocommerce_tree_table_rate_' . $i . '_settings', array( $this, 'convert_wc_tree_table_rate_settings' ) );
312
+ }
313
  }
 
314
 
315
+ /**
316
+ * Get_wc_tree_table_rate_settings.
317
+ *
318
+ * @version 5.1.0
319
+ * @since 4.9.0
320
+ * @param array $option defines the option.
321
+ *
322
+ * @return mixed
323
+ */
324
+ public function convert_wc_tree_table_rate_settings( $option ) {
325
+ if ( 'no' === wcj_get_option( 'wcj_multicurrency_compatibility_wc_ttrs', 'no' ) ) {
326
+ return $option;
327
+ }
328
+ $transition_name = 'wcj_wc_tree_table_opt_' . md5( current_filter() );
329
+ $modified_rule_result = get_transient( $transition_name );
330
+ if ( false === ( $modified_rule_result ) ) {
331
+ $rule = json_decode( $option['rule'] );
332
+ $modified_rule = $this->recursively_convert_wc_tree_settings(
333
+ $rule,
334
+ array(
335
+ 'change_keys' => array( 'value', 'min', 'max' ),
336
+ 'exchange_rate' => $this->get_currency_exchange_rate( $this->get_current_currency_code() ),
337
+ )
338
+ );
339
+ set_transient( $transition_name, wp_json_encode( $modified_rule ), 5 * MINUTE_IN_SECONDS );
340
+ }
341
+ $option['rule'] = $modified_rule_result;
342
+ remove_filter( current_filter(), array( $this, 'convert_wc_tree_table_rate_settings' ) );
343
  return $option;
344
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
345
 
346
+ /**
347
+ * Recursively_convert_wc_tree_settings.
348
+ *
349
+ * @version 5.1.0
350
+ * @since 4.9.0
351
+ *
352
+ * @param array $array defines the array.
353
+ * @param null $args defines the args.
354
+ *
355
+ * @return array
356
+ */
357
+ public function recursively_convert_wc_tree_settings( $array, $args = null ) {
358
+ $args = wp_parse_args(
359
+ $args,
360
+ array(
361
+ 'change_keys' => array(),
362
+ 'exchange_rate' => 1,
363
+ )
364
+ );
365
+ $change_keys = $args['change_keys'];
366
+ $exchange_rate = $args['exchange_rate'];
367
+ foreach ( $array as $key => $value ) {
368
+ if ( in_array( $key, $change_keys ) ) {
369
+ if (
370
+ is_array( $array ) &&
371
+ isset( $array['condition'] ) &&
372
+ 'price' === $array['condition'] &&
373
+ ! empty( $value ) &&
374
+ is_numeric( $value )
375
+ ) {
376
+ $array[ $key ] = $value * $exchange_rate;
377
+ } elseif (
378
  is_a( $array, 'stdClass' ) &&
379
  property_exists( $array, 'condition' ) &&
380
  'price' === $array->condition &&
381
  ! empty( $value ) &&
382
  is_numeric( $value )
383
+ ) {
384
+ $array->$key = $value * $exchange_rate;
385
+ }
386
+ }
387
+ if ( is_array( $value ) || is_a( $value, 'stdClass' ) ) {
388
+ $this->recursively_convert_wc_tree_settings( $value, $args );
389
  }
390
  }
391
+ return $array;
 
 
392
  }
 
 
393
 
394
+ /**
395
+ * @version 4.9.0
396
+ * @since 4.9.0
397
+ *
398
+ * @param string $valid defines the valid.
399
+ * @param string $coupon defines the $coupon.
400
+ * @param string $wc_discounts defines the wc_discounts.
401
+ *
402
+ * @return bool
403
+ * @throws Exception
404
+ */
405
+ public function check_woocommerce_coupon_min_max_amount( $valid, WC_Coupon $coupon, WC_Discounts $wc_discounts ) {
406
+ if ( 'yes' !== wcj_get_option( 'wcj_multicurrency_compatibility_wc_coupons', 'no' ) ) {
407
+ return $valid;
408
+ }
409
+ remove_filter( 'woocommerce_coupon_is_valid', array( $this, 'check_woocommerce_coupon_min_max_amount' ), 10 );
410
+ $minimum_amount = $coupon->get_minimum_amount();
411
+ if ( ! empty( $minimum_amount ) ) {
412
+ $coupon->set_minimum_amount( $this->change_price( $minimum_amount, null ) );
413
+ }
414
+ $maximum_amount = $coupon->get_maximum_amount();
415
+ if ( ! empty( $maximum_amount ) ) {
416
+ $coupon->set_maximum_amount( $this->change_price( $maximum_amount, null ) );
417
+ }
418
+ $is_coupon_valid = $wc_discounts->is_coupon_valid( $coupon );
419
+ if ( is_wp_error( $is_coupon_valid ) ) {
420
+ return false;
421
+ }
422
  return $valid;
423
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
424
 
425
+ /**
426
+ * Fix_wc_coupon_discount_amount.
427
+ *
428
+ * @version 5.2.0
429
+ * @since 5.2.0
430
+ *
431
+ * @param bool $false defines the false.
432
+ * @param string | array $data defines the data.
433
+ * @param string | array $coupon defines the coupon.
434
+ *
435
+ * @return mixed
436
+ */
437
+ public function fix_wc_coupon_discount_amount( $false, $data, $coupon ) {
438
+ $coupon_id = wc_get_coupon_id_by_code( $data );
439
+ if (
440
  'yes' !== wcj_get_option( 'wcj_multicurrency_compatibility_wc_coupons', 'no' ) ||
441
  is_admin() ||
442
+ empty( $coupon_id ) ||
443
+ 'fixed_cart' !== get_post_meta( $coupon_id, 'discount_type', true )
444
+ ) {
445
+ return $false;
446
+ }
447
+ $current_coupon_amount = get_post_meta( $coupon_id, 'coupon_amount', true );
448
+ $coupon->set_amount( $this->change_price( $current_coupon_amount, null ) );
449
+ return $coupon;
450
  }
 
 
 
 
451
 
452
+ /**
453
+ * Fix_wc_attribute_swatches_premium_variable_cart_item_price.
454
+ *
455
+ * @version 5.4.3
456
+ * @since 5.4.3
457
+ *
458
+ * @param int $price_html defines the price_html.
459
+ * @param array $cart_item defines the cart_item.
460
+ * @param string $cart_item_key defines the cart_item_key.
461
+ *
462
+ * @return mixed
463
+ */
464
+ public function fix_wc_attribute_swatches_premium_variable_cart_item_price( $price_html, $cart_item, $cart_item_key ) {
465
+ if ( empty( $cart_item['iconic_was_fee'] ) ) {
466
+ return $price_html;
467
+ }
468
+ $price = $this->change_price( $cart_item['iconic_was_fee'], null );
469
+ return wc_price( $price );
470
  }
 
 
 
471
 
472
+ /**
473
+ * Fixes sort by price when `wcj_multicurrency_per_product_enabled` is enabled.
474
+ *
475
+ * @version 4.6.0
476
+ * @since 4.5.0
477
+ *
478
+ * @param string | array $args defines the args.
479
+ * @param string $orderby defines the orderby.
480
+ * @param string | array $order defines the order.
481
+ *
482
+ * @return mixed
483
+ */
484
+ public function handle_per_product_opt_with_sort_by_price( $args, $orderby, $order ) {
485
+ if (
486
+ 'price' !== $orderby ||
487
  is_admin() ||
488
  ! is_main_query() ||
489
  'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
490
  get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
491
+ 1 === $this->get_currency_exchange_rate(
492
+ $this->get_current_currency_code()
493
  )
 
 
 
 
 
 
 
 
 
494
  ) {
495
+ return $args;
496
  }
497
+ $order = 'DESC' === $order ? $order : 'ASC';
498
+ add_filter(
499
+ 'posts_clauses',
500
+ function ( $clauses ) use ( $order ) {
501
+ global $wpdb;
502
+ if (
503
+ false === strpos( $clauses['orderby'], 'wc_product_meta_lookup.max_price DESC' ) &&
504
+ false === strpos( $clauses['orderby'], 'wc_product_meta_lookup.min_price ASC' )
505
+ ) {
506
+ return $clauses;
507
+ }
508
+ $current_currency_code = $this->get_current_currency_code();
509
+ $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
510
 
511
+ $min_max_join = "LEFT JOIN {$wpdb->postmeta} AS pm on pm.post_id = {$wpdb->posts}.ID AND (pm.meta_key IN ('_wcj_multicurrency_per_product_min_price_{$current_currency_code}','_wcj_multicurrency_per_product_max_price_{$current_currency_code}') and pm.meta_value!='')";
512
+ if ( false === strpos( $clauses['join'], $min_max_join ) ) {
513
+ $clauses['join'] .= " {$min_max_join} ";
514
+ }
515
+ if ( 'DESC' === $order ) {
516
+ $clauses['fields'] .= ", (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) +0) AS wcj_price ";
517
+ } else {
518
+ $clauses['fields'] .= ", (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_price ";
519
+ }
520
+ $clauses['orderby'] = " wcj_price {$order}, wc_product_meta_lookup.product_id {$order} ";
521
 
522
+ return $clauses;
523
+ },
524
+ 99
525
+ );
526
+ return $args;
527
+ }
528
 
529
+ /**
530
+ * Makes Price Filter Widget filter correct products if Per product option `wcj_multicurrency_per_product_enabled` is enabled.
531
+ *
532
+ * First it removes products witch `_wcj_multicurrency_per_product_regular_price_{$current_currency_code}` meta don't match min and max.
533
+ * Then it adds products witch `_wcj_multicurrency_per_product_regular_price_{$current_currency_code}` meta match min and max.
534
+ *
535
+ * @version 4.6.0
536
+ * @since 4.5.0
537
+ *
538
+ * @see WC_Query::price_filter_post_clauses()
539
+ *
540
+ * @param array $args defines the args.
541
+ * @param string $query defines the query.
542
+ *
543
+ * @return mixed
544
+ */
545
+ public function posts_clauses_price_filter_compatible( $args, $query ) {
546
+ if (
547
  is_admin() ||
548
  'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
549
  get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
553
  false === strpos( $args['where'], 'wc_product_meta_lookup.min_price >=' ) &&
554
  false === strpos( $args['where'], 'wc_product_meta_lookup.max_price <=' )
555
  )
556
+ ) {
557
+ return $args;
558
+ }
 
 
 
 
559
 
560
+ global $wpdb;
561
+ $current_currency_code = $this->get_current_currency_code();
562
+ $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
563
+ $min_price = ( isset( $_GET['min_price'] ) ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0;
564
+ $max_price = ( isset( $_GET['max_price'] ) ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : PHP_INT_MAX;
565
+ $min_max_join = "LEFT JOIN {$wpdb->postmeta} AS pm on pm.post_id = {$wpdb->posts}.ID AND (pm.meta_key IN ('_wcj_multicurrency_per_product_min_price_{$current_currency_code}','_wcj_multicurrency_per_product_max_price_{$current_currency_code}') and pm.meta_value!='')";
566
+ if ( false === strpos( $args['join'], $min_max_join ) ) {
567
+ $args['join'] .= " {$min_max_join} ";
568
+ }
569
+ $args['fields'] .= ", (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_min_price ";
570
+ $args['fields'] .= ", (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) +0) AS wcj_max_price ";
571
+ $args['where'] = preg_replace( '/and wc_product_meta_lookup.min_price >= \d.* and wc_product_meta_lookup.max_price <= \d.*\s/i', '', $args['where'] );
572
+ $args['groupby'] .= " having wcj_min_price >= $min_price AND wcj_min_price <= $max_price ";
573
+ return $args;
574
  }
 
 
 
 
 
 
575
 
576
+ /**
577
+ * Makes Price Filter Widget show correct min and max values if Per product option `wcj_multicurrency_per_product_enabled` is enabled.
578
+ *
579
+ * It works comparing min and max values from "_wcj_multicurrency_per_product_regular_price_{currency_code}" meta as well as min and max price from wc_product_meta_lookup
580
+ *
581
+ * @version 4.6.0
582
+ * @since 4.5.0
583
+ *
584
+ * @see WC_Widget_Price_Filter::get_filtered_price()
585
+ *
586
+ * @param string $sql defines the sql.
587
+ * @param string $meta_query_sql defines the meta_query_sql.
588
+ * @param string $tax_query_sql defines the tax_query_sql.
589
+ *
590
+ * @return mixed
591
+ */
592
+ public function get_price_filter_sql_compatible( $sql, $meta_query_sql, $tax_query_sql ) {
593
+ if (
594
  is_admin() ||
595
  'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
596
  get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
597
  1 === $this->get_currency_exchange_rate( $this->get_current_currency_code() )
598
+ ) {
599
+ return $sql;
600
+ }
601
 
602
+ global $wpdb;
603
+ $current_currency_code = $this->get_current_currency_code();
604
+ $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
605
+ $args = WC()->query->get_main_query()->query_vars;
606
+ $tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
607
+ $meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
608
+
609
+ if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
610
+ $tax_query[] = array(
611
+ 'taxonomy' => $args['taxonomy'],
612
+ 'terms' => array( $args['term'] ),
613
+ 'field' => 'slug',
614
+ );
615
+ }
616
 
617
+ foreach ( $meta_query + $tax_query as $key => $query ) {
618
+ if ( ! empty( $query['price_filter'] ) || ! empty( $query['rating_filter'] ) ) {
619
+ unset( $meta_query[ $key ] );
620
+ }
621
  }
 
622
 
623
+ $search = WC_Query::get_main_search_query_sql();
624
+ $search_query_sql = $search ? ' AND ' . $search : '';
625
 
626
+ $sql = "
627
  SELECT FLOOR(min(wcj_min_price)) as min_price, CEILING(max(wcj_max_price)) as max_price
628
  FROM(
629
  SELECT (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_min_price, (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) + 0) AS wcj_max_price
639
  group by product_id
640
  ) as wcj_min_max_price
641
  ';
642
+ return $sql;
643
+ }
644
 
645
+ /**
646
+ * Fixes WooCommerce import.
647
+ *
648
+ * For now it converts '_wcj_%price%_{currency}' meta with lowercase currency to uppercase.
649
+ *
650
+ * @version 4.4.0
651
+ * @since 4.4.0
652
+ *
653
+ * @param array $parsed_data defines the parsed_data.
654
+ * @param string | array $raw_data defines the raw_data.
655
+ *
656
+ * @return mixed
657
+ */
658
+ public function fix_wc_product_import( $parsed_data, $raw_data ) {
659
+ // Gets values.
660
+ $multicurrency_values = array_filter(
661
+ $parsed_data['meta_data'],
662
+ function ( $value ) {
663
+ return preg_match( '/^_wcj_.+price.*_[a-z]{2,3}$/', $value['key'] );
664
+ }
665
+ );
 
 
 
 
 
 
 
666
 
667
+ // Changes lowercase currency to uppercase.
668
+ $modified_values = array_map(
669
+ function ( $value ) {
670
+ $str = $value['key'];
671
+ $last_underscore = strrpos( $str, '_' );
672
+ $before = substr( $str, 0, $last_underscore );
673
+ $currency = substr( $str, $last_underscore + 1 );
674
+ $value['key'] = $before . '_' . strtoupper( $currency );
675
+ return $value;
676
+ },
677
+ $multicurrency_values
678
+ );
679
 
680
+ // Applies changes to the main data.
681
+ foreach ( $modified_values as $i => $value ) {
682
+ $parsed_data['meta_data'][ $i ]['key'] = $value['key'];
683
+ }
684
 
685
+ return $parsed_data;
 
 
 
 
 
 
 
 
 
 
686
  }
687
+
688
+ /**
689
+ * Adds compatibility with WooCommerce Price Filter widget.
690
+ *
691
+ * @see price-slider.js, init_price_filter()
692
+ *
693
+ * @version 5.2.0
694
+ * @since 4.3.0
695
+ */
696
+ public function add_compatibility_with_price_filter_widget() {
697
+ if ( ! is_active_widget( false, false, 'woocommerce_price_filter' ) ) {
698
+ return;
699
+ }
700
+ ?>
701
+ <?php
702
+ $exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() );
703
+ if ( 1 === $exchange_rate ) {
704
+ return;
705
+ }
706
+ ?>
707
+ <input type="hidden" id="wcj_mc_exchange_rate" value="<?php echo esc_html( $exchange_rate ); ?>"/>
708
  <script>
709
  var wcj_mc_pf_slider = {
710
  slider: null,
789
  }
790
  });
791
  </script>
792
+ <?php
793
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
794
 
795
+ /**
796
+ * Fixes price filter widget currency format.
797
+ *
798
+ * @version 4.3.0
799
+ * @since 4.3.0
800
+ */
801
+ public function fix_price_filter_widget_currency_format() {
802
+ $price_args = apply_filters(
803
+ 'wc_price_args',
804
+ array(
805
+ 'ex_tax_label' => false,
806
+ 'currency' => '',
807
+ 'decimal_separator' => wc_get_price_decimal_separator(),
808
+ 'thousand_separator' => wc_get_price_thousand_separator(),
809
+ 'decimals' => wc_get_price_decimals(),
810
+ 'price_format' => get_woocommerce_price_format(),
811
+ )
812
+ );
813
+ $symbol = apply_filters( 'woocommerce_currency_symbol', get_woocommerce_currency_symbol(), get_woocommerce_currency() );
814
+ wp_localize_script(
815
+ 'wc-price-slider',
816
+ 'woocommerce_price_slider_params',
817
+ array(
818
+ 'currency_format_num_decimals' => $price_args['decimals'],
819
+ 'currency_format_symbol' => $symbol,
820
+ 'currency_format_decimal_sep' => esc_attr( $price_args['decimal_separator'] ),
821
+ 'currency_format_thousand_sep' => esc_attr( $price_args['thousand_separator'] ),
822
+ 'currency_format' => esc_attr( str_replace( array( '%1$s', '%2$s' ), array( '%s', '%v' ), $price_args['price_format'] ) ),
823
+ )
824
+ );
825
+ }
826
 
827
+ /**
828
+ * Add_hooks.
829
+ *
830
+ * @version 5.0.0
831
+ */
832
+ public function add_hooks() {
833
+ if ( wcj_is_frontend() ) {
834
+
835
+ // Prices - Compatibility - "WooCommerce TM Extra Product Options" plugin.
836
+ add_filter( 'woocommerce_tm_epo_price_on_cart', array( $this, 'change_price_by_currency_tm_extra_product_options_plugin_cart' ), $this->price_hooks_priority, 1 );
837
+ add_filter( 'wc_epo_price', array( $this, 'change_price_by_currency_tm_extra_product_options_plugin' ), $this->price_hooks_priority, 3 );
838
+
839
+ // Currency hooks.
840
+ add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), $this->price_hooks_priority, 1 );
841
+
842
+ // Add "Change Price" hooks.
843
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority );
844
+
845
+ // Handle Compatibility.
846
+ $this->handle_compatibility();
847
+
848
+ // Additional Price Filters.
849
+ $this->additional_price_filters = wcj_get_option( 'wcj_multicurrency_switcher_additional_price_filters', '' );
850
+ if ( ! empty( $this->additional_price_filters ) ) {
851
+ $this->additional_price_filters = array_map( 'trim', explode( PHP_EOL, $this->additional_price_filters ) );
852
+ foreach ( $this->additional_price_filters as $additional_price_filter ) {
853
+ add_filter( $additional_price_filter, array( $this, 'change_price' ), $this->price_hooks_priority, 2 );
854
+ }
855
+ } else {
856
+ $this->additional_price_filters = array();
857
  }
858
  } else {
859
+ // Saves min and max price when product is updated.
860
+ add_action(
861
+ 'woocommerce_update_product',
862
+ function ( $post_id ) {
863
+ if ( 'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ) ) {
864
+ return;
865
+ }
866
+ $this->save_min_max_prices_per_product( $post_id );
867
+ },
868
+ 99
869
+ );
870
 
871
+ // Saves min and max price when exchange rate changes.
872
+ add_action( 'updated_option', array( $this, 'update_min_max_prices_on_exchange_rate_change' ), 10, 3 );
873
+ }
874
  }
 
875
 
876
+ /**
877
+ * Updates min and max prices on exchange rate change.
878
+ *
879
+ * The update is done with background process.
880
+ *
881
+ * @version 4.5.0
882
+ * @since 4.5.0
883
+ *
884
+ * @param string | array $option_name defines the option_name.
885
+ * @param string | array $old_value defines the old_value.
886
+ * @param string $option_value defines the option_value.
887
+ */
888
+ public function update_min_max_prices_on_exchange_rate_change( $option_name, $old_value, $option_value ) {
889
+ if (
890
  'no' === wcj_get_option( 'wcj_multicurrency_update_prices_on_exch_update', 'no' ) ||
891
  'no' === wcj_get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ) ||
892
  false === strpos( $option_name, 'wcj_multicurrency_exchange_rate_' )
893
+ ) {
894
+ return;
895
+ }
896
+ $currency_number = substr( $option_name, strrpos( $option_name, '_' ) + 1 );
897
+ $currency = wcj_get_option( 'wcj_multicurrency_currency_' . $currency_number );
898
+ $product_ids = $this->get_products_by_per_product_currency( $currency );
899
+ if ( is_array( $product_ids ) && count( $product_ids ) > 0 ) {
900
+ $this->bkg_process_price_updater->cancel_process();
901
+ foreach ( $product_ids as $post_id ) {
902
+ $this->bkg_process_price_updater->push_to_queue(
903
+ array(
904
+ 'id' => $post_id,
905
+ 'currency' => $currency,
906
+ )
907
+ );
908
+ }
909
+ $this->bkg_process_price_updater->save()->dispatch();
910
  }
 
911
  }
 
912
 
913
+ /**
914
+ * Gets all products, or products with variations containing meta '_wcj_multicurrency_per_product_regular_price_{currency}' or '_wcj_multicurrency_per_product_sale_price_{currency}'.
915
+ *
916
+ * @version 4.6.0
917
+ * @since 4.5.0
918
+ *
919
+ * @param int | string $currency defines the currency.
920
+ *
921
+ * @return array
922
+ */
923
+ public function get_products_by_per_product_currency( $currency ) {
924
+ if ( empty( $currency ) ) {
925
+ $currency = wcj_get_option( 'woocommerce_currency' );
926
+ }
927
 
928
+ global $wpdb;
929
+ $product_ids = $wpdb->get_col(
930
+ "
931
  SELECT p.ID
932
  FROM {$wpdb->posts} AS p
933
  LEFT JOIN {$wpdb->posts} AS p2 ON p.ID = p2.ID OR (p2.post_parent = p.ID AND p2.post_type='product_variation')
935
  WHERE p.post_status = 'publish' AND p.post_type IN ('product')
936
  AND pm.meta_value != 'null'
937
  GROUP BY p.ID
938
+ "
939
+ );
940
 
941
+ return $product_ids;
942
+ }
943
 
944
+ /**
945
+ * Updates min and max prices.
946
+ *
947
+ * @version 4.5.0
948
+ * @since 4.5.0
949
+ *
950
+ * @param int $post_id defines the post_id.
951
+ * @param int | string $currency_code_param defines the currency_code_param.
952
+ */
953
+ public function save_min_max_prices_per_product( $post_id, $currency_code_param = '' ) {
954
+ $product = wc_get_product( $post_id );
955
+ $products = array();
956
+ if ( $product->is_type( 'variable' ) ) {
957
+ $available_variations = $product->get_variation_prices()['price'];
958
+ foreach ( $available_variations as $variation_id => $price ) {
959
+ $products[ $variation_id ] = $price;
960
+ }
961
+ } else {
962
+ $products[ $post_id ] = $product->get_price();
963
+ }
964
+ if ( empty( $currency_code_param ) ) {
965
+ $total_number = apply_filters( 'booster_option', 2, wcj_get_option( 'wcj_multicurrency_total_number', 2 ) );
966
+ } else {
967
+ $total_number = 1;
968
  }
 
 
 
 
 
 
 
 
969
 
970
+ $per_product_prices = array();
971
+ for ( $i = 1; $i <= $total_number; $i ++ ) {
972
+ $currency_code = empty( $currency_code_param ) ? wcj_get_option( 'wcj_multicurrency_currency_' . $i ) : $currency_code_param;
973
+ $exchange_rate = $this->get_currency_exchange_rate( $currency_code );
974
+ foreach ( $products as $product_id => $original_price ) {
975
+ // Regular Price.
976
+
977
+ if ( isset( $_POST[ "wcj_multicurrency_per_product_regular_price_{$currency_code}_{$product_id}" ] ) ) {
978
+ $regular_price = $_POST[ "wcj_multicurrency_per_product_regular_price_{$currency_code}_{$product_id}" ];
979
+ } else {
980
+ $regular_price = get_post_meta( $product_id, '_wcj_multicurrency_per_product_regular_price_' . $currency_code, true );
981
+ }
982
+
983
+ // Sale Price.
984
+ if ( isset( $_POST[ "wcj_multicurrency_per_product_sale_price_{$currency_code}_{$product_id}" ] ) ) {
985
+ $sale_price = $_POST[ "wcj_multicurrency_per_product_sale_price_{$currency_code}_{$product_id}" ];
986
+ } else {
987
+ $sale_price = get_post_meta( $product_id, '_wcj_multicurrency_per_product_sale_price_' . $currency_code, true );
988
+ }
989
+ $prices = array_filter( array( $regular_price, $sale_price ) );
990
+ $price = count( $prices ) > 0 ? min( $prices ) : $original_price * $exchange_rate;
991
+ $per_product_prices[ $currency_code ][ $product_id ] = $price;
992
  }