Booster for WooCommerce - Version 5.0.0

Version Description

  • 01/06/2020 =
  • Fix - PRICES & CURRENCIES - Wholesale Price - Consider heading_format param from [wcj_product_wholesale_price_table] on Heading Format option.
  • Fix - PRICES & CURRENCIES - Wholesale Price - Change 'Price Table Format' option to 'Table Heading Format'
  • Dev - PDF INVOICING & PACKING SLIPS - TCPDF library updated (from v6.2.26 to v6.3.0).
  • Dev - PRICES & CURRENCIES - Multicurrency Product Base Price - Add 'WooCommerce Price Sorting' compatibility option.
  • Dev - PRICES & CURRENCIES - Wholesale Price - Add 'Discount Value - Price Directly Totals' option allowing to define how the %discount_value% will calculate the totals when the 'price directly' is in use.
  • Dev - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - Add compatibility with 'Prices and Currencies by Country' module.
  • Dev - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - Add compatibility with 'Pricing Deals' plugin.
Download this release

Release Info

Developer pluggabl
Plugin Icon 128x128 Booster for WooCommerce
Version 5.0.0
Comparing to
See all releases

Code changes from version 4.9.0 to 5.0.0

Files changed (56) hide show
  1. includes/add-to-cart/class-wcj-add-to-cart-per-category.php +65 -65
  2. includes/add-to-cart/class-wcj-add-to-cart-per-product-type.php +91 -91
  3. includes/add-to-cart/class-wcj-add-to-cart-per-product.php +136 -136
  4. includes/admin/class-wc-settings-jetpack.php +570 -570
  5. includes/admin/class-wcj-settings-custom-fields.php +332 -332
  6. includes/admin/class-wcj-settings-manager.php +165 -165
  7. includes/admin/class-wcj-tools.php +90 -90
  8. includes/admin/wcj-modules-cats.php +205 -205
  9. includes/background-process/class-wcj-multicurrency-price-updater.php +33 -33
  10. includes/class-wcj-add-to-cart-button-visibility.php +220 -220
  11. includes/class-wcj-add-to-cart.php +39 -39
  12. includes/class-wcj-address-formats.php +117 -117
  13. includes/class-wcj-admin-bar.php +655 -655
  14. includes/class-wcj-admin-orders-list.php +419 -419
  15. includes/class-wcj-admin-products-list.php +127 -127
  16. includes/class-wcj-admin-tools.php +335 -335
  17. includes/class-wcj-breadcrumbs.php +92 -92
  18. includes/class-wcj-call-for-price.php +173 -173
  19. includes/class-wcj-cart-customization.php +118 -118
  20. includes/class-wcj-cart.php +87 -87
  21. includes/class-wcj-checkout-core-fields.php +265 -265
  22. includes/class-wcj-checkout-custom-fields.php +631 -631
  23. includes/class-wcj-checkout-custom-info.php +64 -64
  24. includes/class-wcj-checkout-customization.php +308 -308
  25. includes/class-wcj-checkout-fees.php +280 -280
  26. includes/class-wcj-checkout-files-upload.php +829 -829
  27. includes/class-wcj-coupon-by-user-role.php +104 -104
  28. includes/class-wcj-coupon-code-generator.php +142 -142
  29. includes/class-wcj-cross-sells.php +215 -215
  30. includes/class-wcj-crowdfunding.php +80 -80
  31. includes/class-wcj-currency-exchange-rates.php +262 -262
  32. includes/class-wcj-currency-external-products.php +53 -53
  33. includes/class-wcj-currency-per-product.php +489 -489
  34. includes/class-wcj-currency.php +192 -192
  35. includes/class-wcj-custom-css.php +91 -91
  36. includes/class-wcj-custom-js.php +66 -66
  37. includes/class-wcj-custom-php.php +90 -90
  38. includes/class-wcj-debug-tools.php +107 -107
  39. includes/class-wcj-email-options.php +169 -169
  40. includes/class-wcj-emails-verification.php +212 -212
  41. includes/class-wcj-emails.php +135 -135
  42. includes/class-wcj-empty-cart-button.php +80 -80
  43. includes/class-wcj-eu-vat-number.php +600 -600
  44. includes/class-wcj-export-import.php +339 -339
  45. includes/class-wcj-free-price.php +171 -171
  46. includes/class-wcj-general.php +271 -271
  47. includes/class-wcj-global-discount.php +427 -427
  48. includes/class-wcj-left-to-free-shipping.php +99 -99
  49. includes/class-wcj-max-products-per-user.php +351 -351
  50. includes/class-wcj-mini-cart.php +65 -65
  51. includes/class-wcj-modules-by-user-roles.php +35 -35
  52. includes/class-wcj-more-button-labels.php +64 -64
  53. includes/class-wcj-multicurrency-product-base-price.php +507 -476
  54. includes/class-wcj-multicurrency.php +1203 -1154
  55. includes/class-wcj-my-account.php +532 -532
  56. includes/class-wcj-offer-price.php +0 -493
includes/add-to-cart/class-wcj-add-to-cart-per-category.php CHANGED
@@ -1,65 +1,65 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce Add to Cart per Category
4
- *
5
- * @version 2.2.6
6
- * @author Algoritmika Ltd.
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' === 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, get_option( 'wcj_add_to_cart_per_category_total_groups_number', 1 ) ); $i++ ) {
48
- if ( 'yes' !== get_option( 'wcj_add_to_cart_per_category_enabled_group_' . $i ) ) continue;
49
- $categories = 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 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
-
65
- return new WCJ_Add_To_Cart_Per_Category();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce Add to Cart per Category
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' === 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, get_option( 'wcj_add_to_cart_per_category_total_groups_number', 1 ) ); $i++ ) {
48
+ if ( 'yes' !== get_option( 'wcj_add_to_cart_per_category_enabled_group_' . $i ) ) continue;
49
+ $categories = 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 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
+
65
+ return new WCJ_Add_To_Cart_Per_Category();
includes/add-to-cart/class-wcj-add-to-cart-per-product-type.php CHANGED
@@ -1,91 +1,91 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Add to Cart Button Labels - Per Product Type
4
- *
5
- * @version 4.2.0
6
- * @author Algoritmika Ltd.
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' === 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 = 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 = 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 = 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 = 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 = 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 = 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
-
91
- return new WCJ_Add_To_Cart_Per_Product_Type();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Add to Cart Button Labels - Per Product Type
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' === 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 = 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 = 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 = 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 = 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 = 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 = 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
+
91
+ return new WCJ_Add_To_Cart_Per_Product_Type();
includes/add-to-cart/class-wcj-add-to-cart-per-product.php CHANGED
@@ -1,136 +1,136 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce Add to Cart per Product
4
- *
5
- * @version 2.7.0
6
- * @author Algoritmika Ltd.
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' === 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
-
136
- return new WCJ_Add_To_Cart_Per_Product();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce Add to Cart per Product
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' === 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
+
136
+ return new WCJ_Add_To_Cart_Per_Product();
includes/admin/class-wc-settings-jetpack.php CHANGED
@@ -1,570 +1,570 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Settings
4
- *
5
- * @version 4.4.0
6
- * @since 1.0.0
7
- * @author Algoritmika Ltd.
8
- */
9
-
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
-
12
- if ( ! class_exists( 'WC_Settings_Jetpack' ) ) :
13
-
14
- class WC_Settings_Jetpack extends WC_Settings_Page {
15
-
16
- /**
17
- * Constructor.
18
- *
19
- * @version 3.0.0
20
- */
21
- function __construct() {
22
-
23
- $this->id = 'jetpack';
24
- $this->label = __( 'Booster', 'woocommerce-jetpack' );
25
-
26
- $this->cats = include( 'wcj-modules-cats.php' );
27
-
28
- $this->custom_dashboard_modules = apply_filters( 'wcj_custom_dashboard_modules', array() );
29
-
30
- add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
31
- add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
32
- add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
33
- add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_cats_submenu' ) );
34
- add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_sections_submenu' ) );
35
-
36
- require_once( 'class-wcj-settings-custom-fields.php' );
37
- }
38
-
39
- /**
40
- * Output cats
41
- *
42
- * @version 2.7.0
43
- */
44
- function output_cats_submenu() {
45
- $current_cat = empty( $_REQUEST['wcj-cat'] ) ? 'dashboard' : sanitize_title( $_REQUEST['wcj-cat'] );
46
- if ( empty( $this->cats ) ) {
47
- return;
48
- }
49
- echo '<ul class="subsubsub" style="text-transform: uppercase !important; font-weight: bold; margin-bottom: 10px !important;">';
50
- $array_keys = array_keys( $this->cats );
51
- foreach ( $this->cats as $id => $label_info ) {
52
- echo '<li><a href="' . admin_url( 'admin.php?page=wc-settings&tab=' . $this->id . '&wcj-cat=' . sanitize_title( $id ) ) . '" class="' . ( $current_cat == $id ? 'current' : '' ) . '">' . $label_info['label'] . '</a> ' . ( end( $array_keys ) == $id ? '' : '|' ) . ' </li>';
53
- }
54
- echo '</ul>' . '<br class="clear" />';
55
- }
56
-
57
- /**
58
- * Output sections (modules) sub menu
59
- *
60
- * @version 3.4.0
61
- * @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)
62
- */
63
- function output_sections_submenu() {
64
- global $current_section;
65
- $sections = $this->get_sections();
66
- $current_cat = empty( $_REQUEST['wcj-cat'] ) ? 'dashboard' : sanitize_title( $_REQUEST['wcj-cat'] );
67
- if ( 'dashboard' === $current_cat ) {
68
-
69
- // Counting modules
70
- $all = 0;
71
- $active = 0;
72
- foreach ( $this->module_statuses as $module_status ) {
73
- if ( isset( $module_status['id'] ) && isset( $module_status['default'] ) ) {
74
- if ( 'yes' === get_option( $module_status['id'], $module_status['default'] ) ) {
75
- $active++;
76
- } elseif ( wcj_is_module_deprecated( $module_status['id'], true ) ) {
77
- continue;
78
- }
79
- $all++;
80
- }
81
- }
82
-
83
- $sections['alphabetically'] = __( 'Alphabetically', 'woocommerce-jetpack' ) . ' <span class="count">(' . $all . ')</span>';
84
- $sections['by_category'] = __( 'By Category', 'woocommerce-jetpack' ) . ' <span class="count">(' . $all . ')</span>';
85
- $sections['active'] = __( 'Active', 'woocommerce-jetpack' ) . ' <span class="count">(' . $active . ')</span>';
86
- $sections['manager'] = __( 'Manage Settings', 'woocommerce-jetpack' );
87
- if ( ! empty( $this->custom_dashboard_modules ) ) {
88
- foreach ( $this->custom_dashboard_modules as $custom_dashboard_module_id => $custom_dashboard_module_data ) {
89
- $sections[ $custom_dashboard_module_id ] = $custom_dashboard_module_data['title'];
90
- }
91
- }
92
- if ( '' == $current_section ) {
93
- $current_section = 'by_category';
94
- }
95
- }
96
- if ( ! empty( $this->cats[ $current_cat ]['all_cat_ids'] ) ) {
97
- foreach ( $sections as $id => $label ) {
98
- if ( ! in_array( $id, $this->cats[ $current_cat ]['all_cat_ids'] ) ) {
99
- unset( $sections[ $id ] );
100
- }
101
- }
102
- }
103
- if ( empty( $sections ) || 1 === count( $sections ) ) {
104
- return;
105
- }
106
- foreach ( $this->cats[ $current_cat ]['all_cat_ids'] as $key => $id ) {
107
- if ( wcj_is_module_deprecated( $id, false, true ) ) {
108
- unset( $this->cats[ $current_cat ]['all_cat_ids'][ $key ] );
109
- }
110
- }
111
- $menu = array();
112
- foreach ( $this->cats[ $current_cat ]['all_cat_ids'] as $id ) {
113
- $menu[ $id ] = $sections[ $id ];
114
- }
115
- if ( 'dashboard' !== $current_cat && 'pdf_invoicing' !== $current_cat ) {
116
- asort( $menu );
117
- }
118
- $menu_links = array();
119
- foreach ( $menu as $id => $label ) {
120
- $url = admin_url( 'admin.php?page=wc-settings&tab=' . $this->id . '&wcj-cat=' . $current_cat . '&section=' . sanitize_title( $id ) );
121
- $menu_links[] = '<a href="' . $url . '" class="' . ( $current_section == $id ? 'current' : '' ) . '">' . $label . '</a>';
122
- }
123
- echo '<ul class="subsubsub">' . '<li>' . implode( '</li> | <li>', $menu_links ) . '</li>' . '</ul>' . '<br class="clear" />';
124
- }
125
-
126
- /**
127
- * get_cat_by_section
128
- */
129
- function get_cat_by_section( $section ) {
130
- foreach ( $this->cats as $id => $label_info ) {
131
- if ( ! empty( $label_info['all_cat_ids'] ) ) {
132
- if ( in_array( $section, $label_info['all_cat_ids'] ) ) {
133
- return $id;
134
- }
135
- }
136
- }
137
- return '';
138
- }
139
-
140
- /**
141
- * Get sections (modules)
142
- *
143
- * @return array
144
- */
145
- function get_sections() {
146
- return apply_filters( 'wcj_settings_sections', array( '' => __( 'Dashboard', 'woocommerce-jetpack' ) ) );
147
- }
148
-
149
- /**
150
- * active.
151
- *
152
- * @version 2.8.0
153
- */
154
- function active( $active ) {
155
- return ( 'yes' === $active ) ? 'active' : 'inactive';
156
- }
157
-
158
- /**
159
- * is_dashboard_section.
160
- *
161
- * @version 3.0.0
162
- * @since 3.0.0
163
- */
164
- function is_dashboard_section( $current_section ) {
165
- return in_array( $current_section, array_merge( array( '', 'alphabetically', 'by_category', 'active', 'manager' ), array_keys( $this->custom_dashboard_modules ) ) );
166
- }
167
-
168
- /**
169
- * Output the settings.
170
- *
171
- * @version 4.1.0
172
- * @todo (maybe) admin_notices
173
- */
174
- function output() {
175
-
176
- global $current_section, $wcj_notice;
177
-
178
- if ( '' != $wcj_notice ) {
179
- echo '<div id="wcj_message" class="updated"><p><strong>' . $wcj_notice . '</strong></p></div>';
180
- }
181
-
182
- $is_dashboard = $this->is_dashboard_section( $current_section );
183
-
184
- // Deprecated message
185
- if ( $replacement_module = wcj_is_module_deprecated( $current_section ) ) {
186
- echo '<div id="wcj_message" class="error">';
187
- echo '<p>';
188
- echo '<strong>';
189
- echo sprintf(
190
- __( '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' ),
191
- WCJ()->modules[ $current_section ]->short_desc,
192
- '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $replacement_module['cat'] . '&section=' . $replacement_module['module'] ) . '">' .
193
- $replacement_module['title'] . '</a>'
194
- );
195
- echo ' <span style="color:red;">' . __( 'Module will be removed from the module\'s list as soon as you disable it.', 'woocommerce-jetpack' ) . '</span>';
196
- echo '</strong>';
197
- echo '</p>';
198
- echo '</div>';
199
- }
200
-
201
- // "Under development" message
202
- if ( isset( WCJ()->modules[ $current_section ]->dev ) && true === WCJ()->modules[ $current_section ]->dev ) {
203
- echo '<div id="wcj_message" class="error">';
204
- echo '<p>';
205
- echo '<strong>';
206
- 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 );
207
- echo '</strong>';
208
- echo '</p>';
209
- echo '</div>';
210
- }
211
-
212
- if ( 'yes' === get_option( 'wcj_debug_tools_enabled', 'no' ) && 'yes' === get_option( 'wcj_debuging_enabled', 'no' ) ) {
213
- // Breadcrumbs
214
- $breadcrumbs_html = '';
215
- $breadcrumbs_html .= '<p>';
216
- $breadcrumbs_html .= '<code>';
217
- $breadcrumbs_html .= __( 'WooCommerce', 'woocommerce-jetpack' );
218
- $breadcrumbs_html .= ' > ';
219
- $breadcrumbs_html .= __( 'Settings', 'woocommerce-jetpack' );
220
- $breadcrumbs_html .= ' > ';
221
- $breadcrumbs_html .= __( 'Booster', 'woocommerce-jetpack' );
222
- $breadcrumbs_html .= ' > ';
223
- foreach ( $this->cats as $id => $label_info ) {
224
- if ( $this->get_cat_by_section( $current_section ) === $id ) {
225
- $breadcrumbs_html .= $label_info['label'];
226
- break;
227
- }
228
- }
229
- if ( $is_dashboard && isset( $_GET['wcj-cat'] ) && 'dashboard' != $_GET['wcj-cat'] ) {
230
- $breadcrumbs_html .= $this->cats[ $_GET['wcj-cat'] ]['label'];
231
- }
232
- if ( ! $is_dashboard ) {
233
- $breadcrumbs_html .= ' > ';
234
- $sections = $this->get_sections();
235
- $breadcrumbs_html .= $sections[ $current_section ];
236
- }
237
- $breadcrumbs_html .= '</code>';
238
- $breadcrumbs_html .= '</p>';
239
- echo $breadcrumbs_html;
240
- }
241
-
242
- $settings = $this->get_settings( $current_section );
243
-
244
- if ( ! $is_dashboard ) {
245
- WC_Admin_Settings::output_fields( $settings );
246
- } else {
247
- $this->output_dashboard( $current_section );
248
- }
249
- }
250
-
251
- /**
252
- * output_dashboard.
253
- *
254
- * @version 3.4.0
255
- */
256
- function output_dashboard( $current_section ) {
257
-
258
- if ( '' == $current_section ) {
259
- $current_section = 'by_category';
260
- }
261
-
262
- $the_settings = $this->get_settings();
263
-
264
- echo '<h3>' . $the_settings[0]['title'] . '</h3>';
265
- if ( isset( $this->custom_dashboard_modules[ $current_section ] ) ) {
266
- echo '<p>' . $this->custom_dashboard_modules[ $current_section ]['desc'] . '</p>';
267
- } elseif ( 'manager' != $current_section ) {
268
- echo '<p>' . $the_settings[0]['desc'] . '</p>';
269
- } else {
270
- echo '<p>' . __( 'This section lets you export, import or reset all Booster\'s modules settings.', 'woocommerce-jetpack' ) . '</p>';
271
- }
272
-
273
- if ( 'alphabetically' === $current_section ) {
274
- $this->output_dashboard_modules( $the_settings );
275
- } elseif ( 'by_category' === $current_section ) {
276
- foreach ( $this->cats as $cat_id => $cat_label_info ) {
277
- if ( 'dashboard' === $cat_id ) {
278
- continue;
279
- }
280
- if ( isset( $_GET['wcj-cat'] ) && 'dashboard' != $_GET['wcj-cat'] ) {
281
- if ( $cat_id != $_GET['wcj-cat'] ) {
282
- continue;
283
- }
284
- } else {
285
- echo '<h4>' . $cat_label_info['label'] . '</h4>';
286
- }
287
- $this->output_dashboard_modules( $the_settings, $cat_id );
288
- }
289
- } elseif ( 'active' === $current_section ) {
290
- $this->output_dashboard_modules( $the_settings, 'active_modules_only' );
291
- } elseif ( 'manager' === $current_section ) {
292
- $table_data = array(
293
- array(
294
- '<button style="width:100px;" class="button-primary" type="submit" name="booster_export_settings">' . __( 'Export', 'woocommerce-jetpack' ) . '</button>',
295
- '<em>' . __( 'Export all Booster\'s options to a file.', 'woocommerce-jetpack' ) . '</em>',
296
- ),
297
- array(
298
- '<button style="width:100px;" class="button-primary" type="submit" name="booster_import_settings">' . __( 'Import', 'woocommerce-jetpack' ) . '</button>' .
299
- ' ' . '<input type="file" name="booster_import_settings_file">',
300
- '<em>' . __( 'Import all Booster\'s options from a file.', 'woocommerce-jetpack' ) . '</em>',
301
- ),
302
- array(
303
- '<button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings"' .
304
- wcj_get_js_confirmation( __( 'This will reset settings to defaults for all Booster modules. Are you sure?', 'woocommerce-jetpack' ) ) . '>' .
305
- __( 'Reset', 'woocommerce-jetpack' ) . '</button>',
306
- '<em>' . __( 'Reset all Booster\'s options.', 'woocommerce-jetpack' ) . '</em>',
307
- ),
308
- array(
309
- '<button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings_meta"' .
310
- wcj_get_js_confirmation( __( 'This will delete all Booster meta. Are you sure?', 'woocommerce-jetpack' ) ) . '>' .
311
- __( 'Reset meta', 'woocommerce-jetpack' ) . '</button>',
312
- '<em>' . __( 'Reset all Booster\'s meta.', 'woocommerce-jetpack' ) . '</em>',
313
- ),
314
- );
315
- $manager_settings = $this->get_manager_settings();
316
- foreach ( $manager_settings as $manager_settings_field ) {
317
- $table_data[] = array(
318
- '<label for="' . $manager_settings_field['id'] . '">' .
319
- '<input name="' . $manager_settings_field['id'] . '" id="' . $manager_settings_field['id'] . '" type="' . $manager_settings_field['type'] . '"' .
320
- ' class="" value="1" ' . checked( get_option( $manager_settings_field['id'], $manager_settings_field['default'] ), 'yes', false ) . '>' .
321
- ' ' . '<strong>' . $manager_settings_field['title'] . '</strong>' .
322
- '</label>',
323
- '<em>' . $manager_settings_field['desc'] . '</em>',
324
- );
325
- }
326
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'none' ) );
327
- }
328
-
329
- if ( isset( $this->custom_dashboard_modules[ $current_section ] ) ) {
330
- $table_data = array();
331
- foreach ( $this->custom_dashboard_modules[ $current_section ]['settings'] as $_settings ) {
332
- $table_data[] = array(
333
- $_settings['title'],
334
- '<label for="' . $_settings['id'] . '">' .
335
- '<input name="' . $_settings['id'] .
336
- '" id="' . $_settings['id'] .
337
- '" type="' . $_settings['type'] .
338
- '" class="' . $_settings['class'] .
339
- '" value="' . get_option( $_settings['id'], $_settings['default'] )
340
- . '">' . ' ' . '<em>' . $_settings['desc'] . '</em>' .
341
- '</label>',
342
- );
343
- }
344
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
345
- }
346
-
347
- $plugin_data = get_plugin_data( WCJ_PLUGIN_FILE );
348
- $plugin_title = ( isset( $plugin_data['Name'] ) ? '[' . $plugin_data['Name'] . '] ' : '' );
349
- echo '<p style="text-align:right;color:gray;font-size:x-small;font-style:italic;">' . $plugin_title .
350
- __( 'Version', 'woocommerce-jetpack' ) . ': ' . get_option( WCJ_VERSION_OPTION, 'N/A' ) . '</p>';
351
-
352
- }
353
-
354
- /**
355
- * compare_for_usort.
356
- */
357
- private function compare_for_usort( $a, $b ) {
358
- return strcmp( $a['title'], $b['title'] );
359
- }
360
-
361
- /**
362
- * output_dashboard_modules.
363
- *
364
- * @version 3.3.0
365
- */
366
- function output_dashboard_modules( $settings, $cat_id = '' ) {
367
- ?>
368
- <table class="wp-list-table widefat plugins">
369
- <thead>
370
- <tr>
371
- <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>
372
- <th scope="col" id="name" class="manage-column column-name" style=""><?php _e( 'Module', 'woocommerce-jetpack' ); ?></th>
373
- <th scope="col" id="description" class="manage-column column-description" style=""><?php _e( 'Description', 'woocommerce-jetpack' ); ?></th>
374
- </tr>
375
- </thead>
376
- <tfoot>
377
- <tr>
378
- <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>
379
- <th scope="col" class="manage-column column-name" style=""><?php _e( 'Module', 'woocommerce-jetpack' ); ?></th>
380
- <th scope="col" class="manage-column column-description" style=""><?php _e( 'Description', 'woocommerce-jetpack' ); ?></th>
381
- </tr>
382
- </tfoot>
383
- <tbody id="the-list"><?php
384
- $html = '';
385
- usort( $settings, array( $this, 'compare_for_usort' ) );
386
- $total_modules = 0;
387
- foreach ( $settings as $the_feature ) {
388
- if ( 'checkbox' !== $the_feature['type'] ) {
389
- continue;
390
- }
391
- $section = $the_feature['id'];
392
- $section = str_replace( 'wcj_', '', $section );
393
- $section = str_replace( '_enabled', '', $section );
394
- if ( wcj_is_module_deprecated( $section, false, true ) ) {
395
- continue;
396
- }
397
- if ( '' != $cat_id ) {
398
- if ( 'active_modules_only' === $cat_id ) {
399
- if ( 'no' === get_option( $the_feature['id'], 'no' ) ) {
400
- continue;
401
- }
402
- } elseif ( $cat_id != $this->get_cat_by_section( $section ) ) {
403
- continue;
404
- }
405
- }
406
- $total_modules++;
407
- $html .= '<tr id="' . $the_feature['id'] . '" ' . 'class="' . $this->active( get_option( $the_feature['id'] ) ) . '">';
408
- $html .= '<th scope="row" class="check-column">';
409
- $html .= '<label class="screen-reader-text" for="' . $the_feature['id'] . '">' . $the_feature['desc'] . '</label>';
410
- $html .= '<input type="checkbox" name="' . $the_feature['id'] . '" value="1" id="' . $the_feature['id'] . '" ' . checked( get_option( $the_feature['id'] ), 'yes', false ) . '>';
411
- $html .= '</th>';
412
- $html .= '<td class="plugin-title">' . '<strong>' . $the_feature['title'] . '</strong>';
413
- $html .= '<div class="row-actions visible">';
414
- $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>';
415
- if ( isset( $the_feature['wcj_link'] ) && '' != $the_feature['wcj_link'] ) {
416
- $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>';
417
- }
418
- $html .= '</div>';
419
- $html .= '</td>';
420
- $html .= '<td class="column-description desc">';
421
- $html .= '<div class="plugin-description"><p>' . ( ( isset( $the_feature['wcj_desc'] ) ) ? $the_feature['wcj_desc'] : $the_feature['desc_tip'] ) . '</p></div>';
422
- $html .= '</td>';
423
- $html .= '</tr>';
424
- }
425
- echo $html;
426
- if ( 0 == $total_modules && 'active_modules_only' === $cat_id ) {
427
- echo '<tr><td colspan="3">' . '<em>' . __( 'No active modules found.', 'woocommerce-jetpack' ) . '</em>' . '</td></tr>';
428
- }
429
- ?></tbody>
430
- </table><p style="color:gray;font-size:x-small;font-style:italic;"><?php echo __( 'Total Modules:' ) . ' ' . $total_modules; ?></p><?php
431
- }
432
-
433
- /**
434
- * Save settings.
435
- *
436
- * @version 3.6.0
437
- */
438
- function save() {
439
- global $current_section;
440
- $settings = $this->get_settings( $current_section );
441
- WC_Admin_Settings::save_fields( $settings );
442
- add_action( 'admin_notices', array( $this, 'booster_message_global' ) );
443
- do_action( 'woojetpack_after_settings_save', $this->get_sections(), $current_section );
444
- }
445
-
446
- /**
447
- * booster_message_global.
448
- *
449
- * @version 3.6.0
450
- * @since 3.6.0
451
- */
452
- function booster_message_global() {
453
- if ( '' != ( $message = apply_filters( 'booster_message', '', 'global' ) ) ) {
454
- echo $message;
455
- }
456
- }
457
-
458
- /**
459
- * get_manager_settings.
460
- *
461
- * @version 3.5.0
462
- * @since 2.6.0
463
- * @return array
464
- */
465
- function get_manager_settings() {
466
- return array(
467
- array(
468
- 'title' => __( 'Autoload Booster\'s Options', 'woocommerce-jetpack' ),
469
- 'type' => 'checkbox',
470
- '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' ),
471
- 'id' => 'wcj_autoload_options',
472
- 'default' => 'yes',
473
- ),
474
- array(
475
- 'title' => __( 'Load Modules on Init Hook', 'woocommerce-jetpack' ),
476
- 'type' => 'checkbox',
477
- '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' ),
478
- 'id' => 'wcj_load_modules_on_init',
479
- 'default' => 'no',
480
- ),
481
- array(
482
- 'title' => __( 'Use List Instead of Comma Separated Text for Products in Settings', 'woocommerce-jetpack' ),
483
- 'type' => 'checkbox',
484
- 'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
485
- __( 'Gateways per Product or Category', 'woocommerce-jetpack' ),
486
- __( 'Global Discount', 'woocommerce-jetpack' ),
487
- __( 'Product Info', 'woocommerce-jetpack' ),
488
- __( 'Product Input Fields', 'woocommerce-jetpack' ),
489
- __( 'Products XML', 'woocommerce-jetpack' ),
490
- __( 'Related Products', 'woocommerce-jetpack' ),
491
- ) ) ),
492
- 'id' => 'wcj_list_for_products',
493
- 'default' => 'yes',
494
- ),
495
- array(
496
- 'title' => __( 'Use List Instead of Comma Separated Text for Products Categories in Settings', 'woocommerce-jetpack' ),
497
- 'type' => 'checkbox',
498
- 'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
499
- __( 'Product Info', 'woocommerce-jetpack' ),
500
- ) ) ),
501
- 'id' => 'wcj_list_for_products_cats',
502
- 'default' => 'yes',
503
- ),
504
- array(
505
- 'title' => __( 'Use List Instead of Comma Separated Text for Products Tags in Settings', 'woocommerce-jetpack' ),
506
- 'type' => 'checkbox',
507
- 'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
508
- __( 'Product Info', 'woocommerce-jetpack' ),
509
- ) ) ),
510
- 'id' => 'wcj_list_for_products_tags',
511
- 'default' => 'yes',
512
- ),
513
- );
514
- }
515
-
516
- /**
517
- * Get settings array
518
- *
519
- * @version 3.0.0
520
- * @return array
521
- */
522
- function get_settings( $current_section = '' ) {
523
- if ( ! $this->is_dashboard_section( $current_section ) ) {
524
- return apply_filters( 'wcj_settings_' . $current_section, array() );
525
- } elseif ( 'manager' === $current_section ) {
526
- return $this->get_manager_settings();
527
- } elseif ( isset( $this->custom_dashboard_modules[ $current_section ] ) ) {
528
- return $this->custom_dashboard_modules[ $current_section ]['settings'];
529
- } else {
530
- $cat_id = ( isset( $_GET['wcj-cat'] ) && '' != $_GET['wcj-cat'] ) ? $_GET['wcj-cat'] : 'dashboard';
531
- $settings[] = array(
532
- 'title' => __( 'Booster for WooCommerce', 'woocommerce-jetpack' ) . ' - ' . $this->cats[ $cat_id ]['label'],
533
- 'type' => 'title',
534
- 'desc' => $this->cats[ $cat_id ]['desc'],
535
- 'id' => 'wcj_' . $cat_id . '_options',
536
- );
537
- if ( 'dashboard' === $cat_id ) {
538
- $settings = array_merge( $settings, $this->module_statuses );
539
- } else {
540
- $cat_module_statuses = array();
541
- foreach ( $this->module_statuses as $module_status ) {
542
- $section = $module_status['id'];
543
- $section = str_replace( 'wcj_', '', $section );
544
- $section = str_replace( '_enabled', '', $section );
545
- if ( $cat_id === $this->get_cat_by_section( $section ) ) {
546
- $cat_module_statuses[] = $module_status;
547
- }
548
- }
549
- $settings = array_merge( $settings, $cat_module_statuses );
550
- }
551
- $settings[] = array(
552
- 'type' => 'sectionend',
553
- 'id' => 'wcj_' . $cat_id . '_options',
554
- 'title' => '', // for usort
555
- );
556
- return $settings;
557
- }
558
- }
559
-
560
- /**
561
- * add_module_statuses
562
- */
563
- function add_module_statuses( $statuses ) {
564
- $this->module_statuses = $statuses;
565
- }
566
- }
567
-
568
- endif;
569
-
570
- return new WC_Settings_Jetpack();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings
4
+ *
5
+ * @version 4.4.0
6
+ * @since 1.0.0
7
+ * @author Pluggabl LLC.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ if ( ! class_exists( 'WC_Settings_Jetpack' ) ) :
13
+
14
+ class WC_Settings_Jetpack extends WC_Settings_Page {
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 3.0.0
20
+ */
21
+ function __construct() {
22
+
23
+ $this->id = 'jetpack';
24
+ $this->label = __( 'Booster', 'woocommerce-jetpack' );
25
+
26
+ $this->cats = include( 'wcj-modules-cats.php' );
27
+
28
+ $this->custom_dashboard_modules = apply_filters( 'wcj_custom_dashboard_modules', array() );
29
+
30
+ add_filter( 'woocommerce_settings_tabs_array', array( $this, 'add_settings_page' ), 20 );
31
+ add_action( 'woocommerce_settings_' . $this->id, array( $this, 'output' ) );
32
+ add_action( 'woocommerce_settings_save_' . $this->id, array( $this, 'save' ) );
33
+ add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_cats_submenu' ) );
34
+ add_action( 'woocommerce_sections_' . $this->id, array( $this, 'output_sections_submenu' ) );
35
+
36
+ require_once( 'class-wcj-settings-custom-fields.php' );
37
+ }
38
+
39
+ /**
40
+ * Output cats
41
+ *
42
+ * @version 2.7.0
43
+ */
44
+ function output_cats_submenu() {
45
+ $current_cat = empty( $_REQUEST['wcj-cat'] ) ? 'dashboard' : sanitize_title( $_REQUEST['wcj-cat'] );
46
+ if ( empty( $this->cats ) ) {
47
+ return;
48
+ }
49
+ echo '<ul class="subsubsub" style="text-transform: uppercase !important; font-weight: bold; margin-bottom: 10px !important;">';
50
+ $array_keys = array_keys( $this->cats );
51
+ foreach ( $this->cats as $id => $label_info ) {
52
+ echo '<li><a href="' . admin_url( 'admin.php?page=wc-settings&tab=' . $this->id . '&wcj-cat=' . sanitize_title( $id ) ) . '" class="' . ( $current_cat == $id ? 'current' : '' ) . '">' . $label_info['label'] . '</a> ' . ( end( $array_keys ) == $id ? '' : '|' ) . ' </li>';
53
+ }
54
+ echo '</ul>' . '<br class="clear" />';
55
+ }
56
+
57
+ /**
58
+ * Output sections (modules) sub menu
59
+ *
60
+ * @version 3.4.0
61
+ * @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)
62
+ */
63
+ function output_sections_submenu() {
64
+ global $current_section;
65
+ $sections = $this->get_sections();
66
+ $current_cat = empty( $_REQUEST['wcj-cat'] ) ? 'dashboard' : sanitize_title( $_REQUEST['wcj-cat'] );
67
+ if ( 'dashboard' === $current_cat ) {
68
+
69
+ // Counting modules
70
+ $all = 0;
71
+ $active = 0;
72
+ foreach ( $this->module_statuses as $module_status ) {
73
+ if ( isset( $module_status['id'] ) && isset( $module_status['default'] ) ) {
74
+ if ( 'yes' === get_option( $module_status['id'], $module_status['default'] ) ) {
75
+ $active++;
76
+ } elseif ( wcj_is_module_deprecated( $module_status['id'], true ) ) {
77
+ continue;
78
+ }
79
+ $all++;
80
+ }
81
+ }
82
+
83
+ $sections['alphabetically'] = __( 'Alphabetically', 'woocommerce-jetpack' ) . ' <span class="count">(' . $all . ')</span>';
84
+ $sections['by_category'] = __( 'By Category', 'woocommerce-jetpack' ) . ' <span class="count">(' . $all . ')</span>';
85
+ $sections['active'] = __( 'Active', 'woocommerce-jetpack' ) . ' <span class="count">(' . $active . ')</span>';
86
+ $sections['manager'] = __( 'Manage Settings', 'woocommerce-jetpack' );
87
+ if ( ! empty( $this->custom_dashboard_modules ) ) {
88
+ foreach ( $this->custom_dashboard_modules as $custom_dashboard_module_id => $custom_dashboard_module_data ) {
89
+ $sections[ $custom_dashboard_module_id ] = $custom_dashboard_module_data['title'];
90
+ }
91
+ }
92
+ if ( '' == $current_section ) {
93
+ $current_section = 'by_category';
94
+ }
95
+ }
96
+ if ( ! empty( $this->cats[ $current_cat ]['all_cat_ids'] ) ) {
97
+ foreach ( $sections as $id => $label ) {
98
+ if ( ! in_array( $id, $this->cats[ $current_cat ]['all_cat_ids'] ) ) {
99
+ unset( $sections[ $id ] );
100
+ }
101
+ }
102
+ }
103
+ if ( empty( $sections ) || 1 === count( $sections ) ) {
104
+ return;
105
+ }
106
+ foreach ( $this->cats[ $current_cat ]['all_cat_ids'] as $key => $id ) {
107
+ if ( wcj_is_module_deprecated( $id, false, true ) ) {
108
+ unset( $this->cats[ $current_cat ]['all_cat_ids'][ $key ] );
109
+ }
110
+ }
111
+ $menu = array();
112
+ foreach ( $this->cats[ $current_cat ]['all_cat_ids'] as $id ) {
113
+ $menu[ $id ] = $sections[ $id ];
114
+ }
115
+ if ( 'dashboard' !== $current_cat && 'pdf_invoicing' !== $current_cat ) {
116
+ asort( $menu );
117
+ }
118
+ $menu_links = array();
119
+ foreach ( $menu as $id => $label ) {
120
+ $url = admin_url( 'admin.php?page=wc-settings&tab=' . $this->id . '&wcj-cat=' . $current_cat . '&section=' . sanitize_title( $id ) );
121
+ $menu_links[] = '<a href="' . $url . '" class="' . ( $current_section == $id ? 'current' : '' ) . '">' . $label . '</a>';
122
+ }
123
+ echo '<ul class="subsubsub">' . '<li>' . implode( '</li> | <li>', $menu_links ) . '</li>' . '</ul>' . '<br class="clear" />';
124
+ }
125
+
126
+ /**
127
+ * get_cat_by_section
128
+ */
129
+ function get_cat_by_section( $section ) {
130
+ foreach ( $this->cats as $id => $label_info ) {
131
+ if ( ! empty( $label_info['all_cat_ids'] ) ) {
132
+ if ( in_array( $section, $label_info['all_cat_ids'] ) ) {
133
+ return $id;
134
+ }
135
+ }
136
+ }
137
+ return '';
138
+ }
139
+
140
+ /**
141
+ * Get sections (modules)
142
+ *
143
+ * @return array
144
+ */
145
+ function get_sections() {
146
+ return apply_filters( 'wcj_settings_sections', array( '' => __( 'Dashboard', 'woocommerce-jetpack' ) ) );
147
+ }
148
+
149
+ /**
150
+ * active.
151
+ *
152
+ * @version 2.8.0
153
+ */
154
+ function active( $active ) {
155
+ return ( 'yes' === $active ) ? 'active' : 'inactive';
156
+ }
157
+
158
+ /**
159
+ * is_dashboard_section.
160
+ *
161
+ * @version 3.0.0
162
+ * @since 3.0.0
163
+ */
164
+ function is_dashboard_section( $current_section ) {
165
+ return in_array( $current_section, array_merge( array( '', 'alphabetically', 'by_category', 'active', 'manager' ), array_keys( $this->custom_dashboard_modules ) ) );
166
+ }
167
+
168
+ /**
169
+ * Output the settings.
170
+ *
171
+ * @version 4.1.0
172
+ * @todo (maybe) admin_notices
173
+ */
174
+ function output() {
175
+
176
+ global $current_section, $wcj_notice;
177
+
178
+ if ( '' != $wcj_notice ) {
179
+ echo '<div id="wcj_message" class="updated"><p><strong>' . $wcj_notice . '</strong></p></div>';
180
+ }
181
+
182
+ $is_dashboard = $this->is_dashboard_section( $current_section );
183
+
184
+ // Deprecated message
185
+ if ( $replacement_module = wcj_is_module_deprecated( $current_section ) ) {
186
+ echo '<div id="wcj_message" class="error">';
187
+ echo '<p>';
188
+ echo '<strong>';
189
+ echo sprintf(
190
+ __( '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' ),
191
+ WCJ()->modules[ $current_section ]->short_desc,
192
+ '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=' . $replacement_module['cat'] . '&section=' . $replacement_module['module'] ) . '">' .
193
+ $replacement_module['title'] . '</a>'
194
+ );
195
+ echo ' <span style="color:red;">' . __( 'Module will be removed from the module\'s list as soon as you disable it.', 'woocommerce-jetpack' ) . '</span>';
196
+ echo '</strong>';
197
+ echo '</p>';
198
+ echo '</div>';
199
+ }
200
+
201
+ // "Under development" message
202
+ if ( isset( WCJ()->modules[ $current_section ]->dev ) && true === WCJ()->modules[ $current_section ]->dev ) {
203
+ echo '<div id="wcj_message" class="error">';
204
+ echo '<p>';
205
+ echo '<strong>';
206
+ 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 );
207
+ echo '</strong>';
208
+ echo '</p>';
209
+ echo '</div>';
210
+ }
211
+
212
+ if ( 'yes' === get_option( 'wcj_debug_tools_enabled', 'no' ) && 'yes' === get_option( 'wcj_debuging_enabled', 'no' ) ) {
213
+ // Breadcrumbs
214
+ $breadcrumbs_html = '';
215
+ $breadcrumbs_html .= '<p>';
216
+ $breadcrumbs_html .= '<code>';
217
+ $breadcrumbs_html .= __( 'WooCommerce', 'woocommerce-jetpack' );
218
+ $breadcrumbs_html .= ' > ';
219
+ $breadcrumbs_html .= __( 'Settings', 'woocommerce-jetpack' );
220
+ $breadcrumbs_html .= ' > ';
221
+ $breadcrumbs_html .= __( 'Booster', 'woocommerce-jetpack' );
222
+ $breadcrumbs_html .= ' > ';
223
+ foreach ( $this->cats as $id => $label_info ) {
224
+ if ( $this->get_cat_by_section( $current_section ) === $id ) {
225
+ $breadcrumbs_html .= $label_info['label'];
226
+ break;
227
+ }
228
+ }
229
+ if ( $is_dashboard && isset( $_GET['wcj-cat'] ) && 'dashboard' != $_GET['wcj-cat'] ) {
230
+ $breadcrumbs_html .= $this->cats[ $_GET['wcj-cat'] ]['label'];
231
+ }
232
+ if ( ! $is_dashboard ) {
233
+ $breadcrumbs_html .= ' > ';
234
+ $sections = $this->get_sections();
235
+ $breadcrumbs_html .= $sections[ $current_section ];
236
+ }
237
+ $breadcrumbs_html .= '</code>';
238
+ $breadcrumbs_html .= '</p>';
239
+ echo $breadcrumbs_html;
240
+ }
241
+
242
+ $settings = $this->get_settings( $current_section );
243
+
244
+ if ( ! $is_dashboard ) {
245
+ WC_Admin_Settings::output_fields( $settings );
246
+ } else {
247
+ $this->output_dashboard( $current_section );
248
+ }
249
+ }
250
+
251
+ /**
252
+ * output_dashboard.
253
+ *
254
+ * @version 3.4.0
255
+ */
256
+ function output_dashboard( $current_section ) {
257
+
258
+ if ( '' == $current_section ) {
259
+ $current_section = 'by_category';
260
+ }
261
+
262
+ $the_settings = $this->get_settings();
263
+
264
+ echo '<h3>' . $the_settings[0]['title'] . '</h3>';
265
+ if ( isset( $this->custom_dashboard_modules[ $current_section ] ) ) {
266
+ echo '<p>' . $this->custom_dashboard_modules[ $current_section ]['desc'] . '</p>';
267
+ } elseif ( 'manager' != $current_section ) {
268
+ echo '<p>' . $the_settings[0]['desc'] . '</p>';
269
+ } else {
270
+ echo '<p>' . __( 'This section lets you export, import or reset all Booster\'s modules settings.', 'woocommerce-jetpack' ) . '</p>';
271
+ }
272
+
273
+ if ( 'alphabetically' === $current_section ) {
274
+ $this->output_dashboard_modules( $the_settings );
275
+ } elseif ( 'by_category' === $current_section ) {
276
+ foreach ( $this->cats as $cat_id => $cat_label_info ) {
277
+ if ( 'dashboard' === $cat_id ) {
278
+ continue;
279
+ }
280
+ if ( isset( $_GET['wcj-cat'] ) && 'dashboard' != $_GET['wcj-cat'] ) {
281
+ if ( $cat_id != $_GET['wcj-cat'] ) {
282
+ continue;
283
+ }
284
+ } else {
285
+ echo '<h4>' . $cat_label_info['label'] . '</h4>';
286
+ }
287
+ $this->output_dashboard_modules( $the_settings, $cat_id );
288
+ }
289
+ } elseif ( 'active' === $current_section ) {
290
+ $this->output_dashboard_modules( $the_settings, 'active_modules_only' );
291
+ } elseif ( 'manager' === $current_section ) {
292
+ $table_data = array(
293
+ array(
294
+ '<button style="width:100px;" class="button-primary" type="submit" name="booster_export_settings">' . __( 'Export', 'woocommerce-jetpack' ) . '</button>',
295
+ '<em>' . __( 'Export all Booster\'s options to a file.', 'woocommerce-jetpack' ) . '</em>',
296
+ ),
297
+ array(
298
+ '<button style="width:100px;" class="button-primary" type="submit" name="booster_import_settings">' . __( 'Import', 'woocommerce-jetpack' ) . '</button>' .
299
+ ' ' . '<input type="file" name="booster_import_settings_file">',
300
+ '<em>' . __( 'Import all Booster\'s options from a file.', 'woocommerce-jetpack' ) . '</em>',
301
+ ),
302
+ array(
303
+ '<button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings"' .
304
+ wcj_get_js_confirmation( __( 'This will reset settings to defaults for all Booster modules. Are you sure?', 'woocommerce-jetpack' ) ) . '>' .
305
+ __( 'Reset', 'woocommerce-jetpack' ) . '</button>',
306
+ '<em>' . __( 'Reset all Booster\'s options.', 'woocommerce-jetpack' ) . '</em>',
307
+ ),
308
+ array(
309
+ '<button style="width:100px;" class="button-primary" type="submit" name="booster_reset_settings_meta"' .
310
+ wcj_get_js_confirmation( __( 'This will delete all Booster meta. Are you sure?', 'woocommerce-jetpack' ) ) . '>' .
311
+ __( 'Reset meta', 'woocommerce-jetpack' ) . '</button>',
312
+ '<em>' . __( 'Reset all Booster\'s meta.', 'woocommerce-jetpack' ) . '</em>',
313
+ ),
314
+ );
315
+ $manager_settings = $this->get_manager_settings();
316
+ foreach ( $manager_settings as $manager_settings_field ) {
317
+ $table_data[] = array(
318
+ '<label for="' . $manager_settings_field['id'] . '">' .
319
+ '<input name="' . $manager_settings_field['id'] . '" id="' . $manager_settings_field['id'] . '" type="' . $manager_settings_field['type'] . '"' .
320
+ ' class="" value="1" ' . checked( get_option( $manager_settings_field['id'], $manager_settings_field['default'] ), 'yes', false ) . '>' .
321
+ ' ' . '<strong>' . $manager_settings_field['title'] . '</strong>' .
322
+ '</label>',
323
+ '<em>' . $manager_settings_field['desc'] . '</em>',
324
+ );
325
+ }
326
+ echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'none' ) );
327
+ }
328
+
329
+ if ( isset( $this->custom_dashboard_modules[ $current_section ] ) ) {
330
+ $table_data = array();
331
+ foreach ( $this->custom_dashboard_modules[ $current_section ]['settings'] as $_settings ) {
332
+ $table_data[] = array(
333
+ $_settings['title'],
334
+ '<label for="' . $_settings['id'] . '">' .
335
+ '<input name="' . $_settings['id'] .
336
+ '" id="' . $_settings['id'] .
337
+ '" type="' . $_settings['type'] .
338
+ '" class="' . $_settings['class'] .
339
+ '" value="' . get_option( $_settings['id'], $_settings['default'] )
340
+ . '">' . ' ' . '<em>' . $_settings['desc'] . '</em>' .
341
+ '</label>',
342
+ );
343
+ }
344
+ echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
345
+ }
346
+
347
+ $plugin_data = get_plugin_data( WCJ_PLUGIN_FILE );
348
+ $plugin_title = ( isset( $plugin_data['Name'] ) ? '[' . $plugin_data['Name'] . '] ' : '' );
349
+ echo '<p style="text-align:right;color:gray;font-size:x-small;font-style:italic;">' . $plugin_title .
350
+ __( 'Version', 'woocommerce-jetpack' ) . ': ' . get_option( WCJ_VERSION_OPTION, 'N/A' ) . '</p>';
351
+
352
+ }
353
+
354
+ /**
355
+ * compare_for_usort.
356
+ */
357
+ private function compare_for_usort( $a, $b ) {
358
+ return strcmp( $a['title'], $b['title'] );
359
+ }
360
+
361
+ /**
362
+ * output_dashboard_modules.
363
+ *
364
+ * @version 3.3.0
365
+ */
366
+ function output_dashboard_modules( $settings, $cat_id = '' ) {
367
+ ?>
368
+ <table class="wp-list-table widefat plugins">
369
+ <thead>
370
+ <tr>
371
+ <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>
372
+ <th scope="col" id="name" class="manage-column column-name" style=""><?php _e( 'Module', 'woocommerce-jetpack' ); ?></th>
373
+ <th scope="col" id="description" class="manage-column column-description" style=""><?php _e( 'Description', 'woocommerce-jetpack' ); ?></th>
374
+ </tr>
375
+ </thead>
376
+ <tfoot>
377
+ <tr>
378
+ <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>
379
+ <th scope="col" class="manage-column column-name" style=""><?php _e( 'Module', 'woocommerce-jetpack' ); ?></th>
380
+ <th scope="col" class="manage-column column-description" style=""><?php _e( 'Description', 'woocommerce-jetpack' ); ?></th>
381
+ </tr>
382
+ </tfoot>
383
+ <tbody id="the-list"><?php
384
+ $html = '';
385
+ usort( $settings, array( $this, 'compare_for_usort' ) );
386
+ $total_modules = 0;
387
+ foreach ( $settings as $the_feature ) {
388
+ if ( 'checkbox' !== $the_feature['type'] ) {
389
+ continue;
390
+ }
391
+ $section = $the_feature['id'];
392
+ $section = str_replace( 'wcj_', '', $section );
393
+ $section = str_replace( '_enabled', '', $section );
394
+ if ( wcj_is_module_deprecated( $section, false, true ) ) {
395
+ continue;
396
+ }
397
+ if ( '' != $cat_id ) {
398
+ if ( 'active_modules_only' === $cat_id ) {
399
+ if ( 'no' === get_option( $the_feature['id'], 'no' ) ) {
400
+ continue;
401
+ }
402
+ } elseif ( $cat_id != $this->get_cat_by_section( $section ) ) {
403
+ continue;
404
+ }
405
+ }
406
+ $total_modules++;
407
+ $html .= '<tr id="' . $the_feature['id'] . '" ' . 'class="' . $this->active( get_option( $the_feature['id'] ) ) . '">';
408
+ $html .= '<th scope="row" class="check-column">';
409
+ $html .= '<label class="screen-reader-text" for="' . $the_feature['id'] . '">' . $the_feature['desc'] . '</label>';
410
+ $html .= '<input type="checkbox" name="' . $the_feature['id'] . '" value="1" id="' . $the_feature['id'] . '" ' . checked( get_option( $the_feature['id'] ), 'yes', false ) . '>';
411
+ $html .= '</th>';
412
+ $html .= '<td class="plugin-title">' . '<strong>' . $the_feature['title'] . '</strong>';
413
+ $html .= '<div class="row-actions visible">';
414
+ $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>';
415
+ if ( isset( $the_feature['wcj_link'] ) && '' != $the_feature['wcj_link'] ) {
416
+ $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>';
417
+ }
418
+ $html .= '</div>';
419
+ $html .= '</td>';
420
+ $html .= '<td class="column-description desc">';
421
+ $html .= '<div class="plugin-description"><p>' . ( ( isset( $the_feature['wcj_desc'] ) ) ? $the_feature['wcj_desc'] : $the_feature['desc_tip'] ) . '</p></div>';
422
+ $html .= '</td>';
423
+ $html .= '</tr>';
424
+ }
425
+ echo $html;
426
+ if ( 0 == $total_modules && 'active_modules_only' === $cat_id ) {
427
+ echo '<tr><td colspan="3">' . '<em>' . __( 'No active modules found.', 'woocommerce-jetpack' ) . '</em>' . '</td></tr>';
428
+ }
429
+ ?></tbody>
430
+ </table><p style="color:gray;font-size:x-small;font-style:italic;"><?php echo __( 'Total Modules:' ) . ' ' . $total_modules; ?></p><?php
431
+ }
432
+
433
+ /**
434
+ * Save settings.
435
+ *
436
+ * @version 3.6.0
437
+ */
438
+ function save() {
439
+ global $current_section;
440
+ $settings = $this->get_settings( $current_section );
441
+ WC_Admin_Settings::save_fields( $settings );
442
+ add_action( 'admin_notices', array( $this, 'booster_message_global' ) );
443
+ do_action( 'woojetpack_after_settings_save', $this->get_sections(), $current_section );
444
+ }
445
+
446
+ /**
447
+ * booster_message_global.
448
+ *
449
+ * @version 3.6.0
450
+ * @since 3.6.0
451
+ */
452
+ function booster_message_global() {
453
+ if ( '' != ( $message = apply_filters( 'booster_message', '', 'global' ) ) ) {
454
+ echo $message;
455
+ }
456
+ }
457
+
458
+ /**
459
+ * get_manager_settings.
460
+ *
461
+ * @version 3.5.0
462
+ * @since 2.6.0
463
+ * @return array
464
+ */
465
+ function get_manager_settings() {
466
+ return array(
467
+ array(
468
+ 'title' => __( 'Autoload Booster\'s Options', 'woocommerce-jetpack' ),
469
+ 'type' => 'checkbox',
470
+ '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' ),
471
+ 'id' => 'wcj_autoload_options',
472
+ 'default' => 'yes',
473
+ ),
474
+ array(
475
+ 'title' => __( 'Load Modules on Init Hook', 'woocommerce-jetpack' ),
476
+ 'type' => 'checkbox',
477
+ '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' ),
478
+ 'id' => 'wcj_load_modules_on_init',
479
+ 'default' => 'no',
480
+ ),
481
+ array(
482
+ 'title' => __( 'Use List Instead of Comma Separated Text for Products in Settings', 'woocommerce-jetpack' ),
483
+ 'type' => 'checkbox',
484
+ 'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
485
+ __( 'Gateways per Product or Category', 'woocommerce-jetpack' ),
486
+ __( 'Global Discount', 'woocommerce-jetpack' ),
487
+ __( 'Product Info', 'woocommerce-jetpack' ),
488
+ __( 'Product Input Fields', 'woocommerce-jetpack' ),
489
+ __( 'Products XML', 'woocommerce-jetpack' ),
490
+ __( 'Related Products', 'woocommerce-jetpack' ),
491
+ ) ) ),
492
+ 'id' => 'wcj_list_for_products',
493
+ 'default' => 'yes',
494
+ ),
495
+ array(
496
+ 'title' => __( 'Use List Instead of Comma Separated Text for Products Categories in Settings', 'woocommerce-jetpack' ),
497
+ 'type' => 'checkbox',
498
+ 'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
499
+ __( 'Product Info', 'woocommerce-jetpack' ),
500
+ ) ) ),
501
+ 'id' => 'wcj_list_for_products_cats',
502
+ 'default' => 'yes',
503
+ ),
504
+ array(
505
+ 'title' => __( 'Use List Instead of Comma Separated Text for Products Tags in Settings', 'woocommerce-jetpack' ),
506
+ 'type' => 'checkbox',
507
+ 'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
508
+ __( 'Product Info', 'woocommerce-jetpack' ),
509
+ ) ) ),
510
+ 'id' => 'wcj_list_for_products_tags',
511
+ 'default' => 'yes',
512
+ ),
513
+ );
514
+ }
515
+
516
+ /**
517
+ * Get settings array
518
+ *
519
+ * @version 3.0.0
520
+ * @return array
521
+ */
522
+ function get_settings( $current_section = '' ) {
523
+ if ( ! $this->is_dashboard_section( $current_section ) ) {
524
+ return apply_filters( 'wcj_settings_' . $current_section, array() );
525
+ } elseif ( 'manager' === $current_section ) {
526
+ return $this->get_manager_settings();
527
+ } elseif ( isset( $this->custom_dashboard_modules[ $current_section ] ) ) {
528
+ return $this->custom_dashboard_modules[ $current_section ]['settings'];
529
+ } else {
530
+ $cat_id = ( isset( $_GET['wcj-cat'] ) && '' != $_GET['wcj-cat'] ) ? $_GET['wcj-cat'] : 'dashboard';
531
+ $settings[] = array(
532
+ 'title' => __( 'Booster for WooCommerce', 'woocommerce-jetpack' ) . ' - ' . $this->cats[ $cat_id ]['label'],
533
+ 'type' => 'title',
534
+ 'desc' => $this->cats[ $cat_id ]['desc'],
535
+ 'id' => 'wcj_' . $cat_id . '_options',
536
+ );
537
+ if ( 'dashboard' === $cat_id ) {
538
+ $settings = array_merge( $settings, $this->module_statuses );
539
+ } else {
540
+ $cat_module_statuses = array();
541
+ foreach ( $this->module_statuses as $module_status ) {
542
+ $section = $module_status['id'];
543
+ $section = str_replace( 'wcj_', '', $section );
544
+ $section = str_replace( '_enabled', '', $section );
545
+ if ( $cat_id === $this->get_cat_by_section( $section ) ) {
546
+ $cat_module_statuses[] = $module_status;
547
+ }
548
+ }
549
+ $settings = array_merge( $settings, $cat_module_statuses );
550
+ }
551
+ $settings[] = array(
552
+ 'type' => 'sectionend',
553
+ 'id' => 'wcj_' . $cat_id . '_options',
554
+ 'title' => '', // for usort
555
+ );
556
+ return $settings;
557
+ }
558
+ }
559
+
560
+ /**
561
+ * add_module_statuses
562
+ */
563
+ function add_module_statuses( $statuses ) {
564
+ $this->module_statuses = $statuses;
565
+ }
566
+ }
567
+
568
+ endif;
569
+
570
+ return new WC_Settings_Jetpack();
includes/admin/class-wcj-settings-custom-fields.php CHANGED
@@ -1,332 +1,332 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Settings Custom Fields
4
- *
5
- * @version 3.4.5
6
- * @since 2.8.0
7
- * @author Algoritmika Ltd.
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 3.4.5
40
- */
41
- function output_exchange_rate_settings_button( $value ) {
42
-
43
- $value['type'] = 'number';
44
-
45
- $option_value = 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
- $custom_attributes = array( 'step="' . sprintf( "%.12f", 1 / pow( 10, 12 ) ) . '"', 'min="0"' );
55
- }
56
- $custom_attributes_button = array();
57
- if ( ! empty( $value['custom_attributes_button'] ) && is_array( $value['custom_attributes_button'] ) ) {
58
- foreach ( $value['custom_attributes_button'] as $attribute => $attribute_value ) {
59
- $custom_attributes_button[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
60
- }
61
- }
62
- $tip = '';
63
- $description = '';
64
- $exchange_rate_server = wcj_get_currency_exchange_rate_server_name( $value['custom_attributes_button']['currency_from'], $value['custom_attributes_button']['currency_to'] );
65
- $value_title = sprintf( __( 'Grab raw %s rate from %s.', 'woocommerce-jetpack' ), $value['value'], $exchange_rate_server ) .
66
- ' ' . __( 'Doesn\'t apply rounding, offset etc.', 'woocommerce-jetpack' );
67
- ?>
68
- <tr valign="top">
69
- <th scope="row" class="titledesc">
70
- <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
71
- <?php echo $tip; ?>
72
- </th>
73
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
74
- <input
75
- name="<?php echo esc_attr( $value['id'] ); ?>"
76
- id="<?php echo esc_attr( $value['id'] ); ?>"
77
- type="<?php echo esc_attr( $value['type'] ); ?>"
78
- style="<?php echo esc_attr( $value['css'] ); ?>"
79
- value="<?php echo esc_attr( $option_value ); ?>"
80
- class="<?php echo esc_attr( $value['class'] ); ?>"
81
- <?php echo implode( ' ', $custom_attributes ); ?>
82
- />
83
- <input
84
- name="<?php echo esc_attr( $value['id'] . '_button' ); ?>"
85
- id="<?php echo esc_attr( $value['id'] . '_button' ); ?>"
86
- type="button"
87
- value="<?php echo esc_attr( $value['value'] ); ?>"
88
- title="<?php echo esc_attr( $value_title ); ?>"
89
- class="exchage_rate_button"
90
- <?php echo implode( ' ', $custom_attributes_button ); ?>
91
- />
92
- </td>
93
- </tr>
94
- <?php
95
- }
96
-
97
- /**
98
- * maybe_unclean_field.
99
- *
100
- * @version 3.1.3
101
- * @since 3.1.3
102
- */
103
- function maybe_unclean_field( $value, $option, $raw_value ) {
104
- return ( isset( $option['wcj_raw'] ) && $option['wcj_raw'] ? $raw_value : $value );
105
- }
106
-
107
- /**
108
- * output_wcj_save_settings_button.
109
- *
110
- * @version 2.9.0
111
- * @since 2.9.0
112
- */
113
- function output_wcj_save_settings_button( $value ) {
114
- // Output
115
- ?><tr valign="top">
116
- <th scope="row" class="titledesc"></th>
117
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
118
- <input name="save" class="button-primary woocommerce-save-button" type="submit" value="<?php echo esc_html( $value['title'] ); ?>">
119
- </td>
120
- </tr><?php
121
- }
122
-
123
- /**
124
- * format_wcj_number_plus_checkbox_end.
125
- *
126
- * @version 2.8.0
127
- * @since 2.8.0
128
- */
129
- function format_wcj_number_plus_checkbox_end( $value, $option, $raw_value ) {
130
- return ( 'wcj_number_plus_checkbox_end' === $option['type'] ) ? ( '1' === $raw_value || 'yes' === $raw_value ? 'yes' : 'no' ) : $value;
131
- }
132
-
133
- /**
134
- * output_wcj_number_plus_checkbox_start.
135
- *
136
- * @version 2.8.0
137
- * @since 2.8.0
138
- */
139
- function output_wcj_number_plus_checkbox_start( $value ) {
140
- // Custom attribute handling
141
- $custom_attributes = array();
142
- if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
143
- foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
144
- $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
145
- }
146
- }
147
- // Description handling
148
- $field_description = WC_Admin_Settings::get_field_description( $value );
149
- extract( $field_description );
150
- // Option value
151
- $option_value = WC_Admin_Settings::get_option( $value['id'], $value['default'] );
152
- // Output
153
- ?><tr valign="top">
154
- <th scope="row" class="titledesc">
155
- <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
156
- <?php echo $tooltip_html; ?>
157
- </th>
158
- <td class="forminp forminp-number-checkbox">
159
- <input
160
- name="<?php echo esc_attr( $value['id'] ); ?>"
161
- id="<?php echo esc_attr( $value['id'] ); ?>"
162
- type="number"
163
- style="<?php echo esc_attr( $value['css'] ); ?>"
164
- value="<?php echo esc_attr( $option_value ); ?>"
165
- class="<?php echo esc_attr( $value['class'] ); ?>"
166
- placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
167
- <?php echo implode( ' ', $custom_attributes ); ?>
168
- /> <?php echo $description . ' ';
169
- }
170
-
171
- /**
172
- * output_wcj_number_plus_checkbox_end.
173
- *
174
- * @version 2.8.0
175
- * @since 2.8.0
176
- */
177
- function output_wcj_number_plus_checkbox_end( $value ) {
178
- // Custom attribute handling
179
- $custom_attributes = array();
180
- if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
181
- foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
182
- $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
183
- }
184
- }
185
- // Description handling
186
- $field_description = WC_Admin_Settings::get_field_description( $value );
187
- extract( $field_description );
188
- // Option value
189
- $option_value = WC_Admin_Settings::get_option( $value['id'], $value['default'] );
190
- // Output
191
- ?><label for="<?php echo $value['id'] ?>">
192
- <input
193
- name="<?php echo esc_attr( $value['id'] ); ?>"
194
- id="<?php echo esc_attr( $value['id'] ); ?>"
195
- type="checkbox"
196
- class="<?php echo esc_attr( isset( $value['class'] ) ? $value['class'] : '' ); ?>"
197
- value="1"
198
- <?php checked( $option_value, 'yes' ); ?>
199
- <?php echo implode( ' ', $custom_attributes ); ?>
200
- /> <?php echo $description ?>
201
- </label> <?php echo $tooltip_html; ?>
202
- </td>
203
- </tr><?php
204
- }
205
-
206
- /**
207
- * unclean_custom_textarea.
208
- *
209
- * @version 2.5.7
210
- * @since 2.5.7
211
- */
212
- function unclean_custom_textarea( $value, $option, $raw_value ) {
213
- return ( 'custom_textarea' === $option['type'] ) ? $raw_value : $value;
214
- }
215
-
216
- /**
217
- * output_custom_textarea.
218
- *
219
- * @version 2.6.0
220
- * @since 2.2.6
221
- */
222
- function output_custom_textarea( $value ) {
223
- $option_value = get_option( $value['id'], $value['default'] );
224
- $custom_attributes = ( isset( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) ?
225
- $value['custom_attributes'] : array();
226
- $description = ' <p class="description">' . $value['desc'] . '</p>';
227
- $tooltip_html = ( isset( $value['desc_tip'] ) && '' != $value['desc_tip'] ) ?
228
- '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
229
- // Output
230
- ?><tr valign="top">
231
- <th scope="row" class="titledesc">
232
- <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
233
- <?php echo $tooltip_html; ?>
234
- </th>
235
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
236
- <?php echo $description; ?>
237
-
238
- <textarea
239
- name="<?php echo esc_attr( $value['id'] ); ?>"
240
- id="<?php echo esc_attr( $value['id'] ); ?>"
241
- style="<?php echo esc_attr( $value['css'] ); ?>"
242
- class="<?php echo esc_attr( $value['class'] ); ?>"
243
- placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
244
- <?php echo implode( ' ', $custom_attributes ); ?>
245
- ><?php echo esc_textarea( $option_value ); ?></textarea>
246
- </td>
247
- </tr><?php
248
- }
249
-
250
- /**
251
- * output_module_tools.
252
- *
253
- * @version 2.7.0
254
- * @since 2.2.3
255
- */
256
- function output_module_tools( $value ) {
257
- ?><tr valign="top">
258
- <th scope="row" class="titledesc">
259
- <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
260
- <span class="woocommerce-help-tip" data-tip="<?php echo __( 'To use tools, module must be enabled.', 'woocommerce-jetpack' ); ?>"></span>
261
- </th>
262
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
263
- <?php if ( isset( $_GET['section'] ) ) do_action( 'wcj_module_tools_' . $_GET['section'] ); ?>
264
- </td>
265
- </tr><?php
266
- }
267
-
268
- /**
269
- * output_custom_link.
270
- *
271
- * @version 2.7.0
272
- * @since 2.2.8
273
- */
274
- function output_custom_link( $value ) {
275
- $tooltip_html = ( isset( $value['desc_tip'] ) && '' != $value['desc_tip'] ) ?
276
- '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
277
- ?><tr valign="top">
278
- <th scope="row" class="titledesc">
279
- <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label><?php echo $tooltip_html; ?>
280
- </th>
281
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
282
- <?php echo $value['link']; ?>
283
- </td>
284
- </tr><?php
285
- }
286
-
287
- /**
288
- * output_custom_number.
289
- *
290
- * @version 2.5.5
291
- */
292
- function output_custom_number( $value ) {
293
- $type = 'number';
294
- $option_value = get_option( $value['id'], $value['default'] );
295
- $tooltip_html = ( isset( $value['desc_tip'] ) && '' != $value['desc_tip'] ) ?
296
- '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
297
- $description = ' <span class="description">' . $value['desc'] . '</span>';
298
- $save_button = apply_filters( 'booster_option', '',
299
- ' <input name="save" class="button-primary" type="submit" value="' . __( 'Save changes', 'woocommerce' ) . '">' );
300
- // Custom attribute handling
301
- $custom_attributes = array();
302
- if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
303
- foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
304
- $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
305
- }
306
- }
307
- // Output
308
- ?><tr valign="top">
309
- <th scope="row" class="titledesc">
310
- <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
311
- <?php echo $tooltip_html; ?>
312
- </th>
313
- <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
314
- <input
315
- name="<?php echo esc_attr( $value['id'] ); ?>"
316
- id="<?php echo esc_attr( $value['id'] ); ?>"
317
- type="<?php echo esc_attr( $type ); ?>"
318
- style="<?php echo esc_attr( $value['css'] ); ?>"
319
- value="<?php echo esc_attr( $option_value ); ?>"
320
- class="<?php echo esc_attr( $value['class'] ); ?>"
321
- placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
322
- <?php echo implode( ' ', $custom_attributes ); ?>
323
- /><?php echo $save_button; ?><?php echo $description; ?>
324
- </td>
325
- </tr><?php
326
- }
327
-
328
- }
329
-
330
- endif;
331
-
332
- return new WCJ_Settings_Custom_Fields();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings Custom Fields
4
+ *
5
+ * @version 3.4.5
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 3.4.5
40
+ */
41
+ function output_exchange_rate_settings_button( $value ) {
42
+
43
+ $value['type'] = 'number';
44
+
45
+ $option_value = 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
+ $custom_attributes = array( 'step="' . sprintf( "%.12f", 1 / pow( 10, 12 ) ) . '"', 'min="0"' );
55
+ }
56
+ $custom_attributes_button = array();
57
+ if ( ! empty( $value['custom_attributes_button'] ) && is_array( $value['custom_attributes_button'] ) ) {
58
+ foreach ( $value['custom_attributes_button'] as $attribute => $attribute_value ) {
59
+ $custom_attributes_button[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
60
+ }
61
+ }
62
+ $tip = '';
63
+ $description = '';
64
+ $exchange_rate_server = wcj_get_currency_exchange_rate_server_name( $value['custom_attributes_button']['currency_from'], $value['custom_attributes_button']['currency_to'] );
65
+ $value_title = sprintf( __( 'Grab raw %s rate from %s.', 'woocommerce-jetpack' ), $value['value'], $exchange_rate_server ) .
66
+ ' ' . __( 'Doesn\'t apply rounding, offset etc.', 'woocommerce-jetpack' );
67
+ ?>
68
+ <tr valign="top">
69
+ <th scope="row" class="titledesc">
70
+ <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
71
+ <?php echo $tip; ?>
72
+ </th>
73
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
74
+ <input
75
+ name="<?php echo esc_attr( $value['id'] ); ?>"
76
+ id="<?php echo esc_attr( $value['id'] ); ?>"
77
+ type="<?php echo esc_attr( $value['type'] ); ?>"
78
+ style="<?php echo esc_attr( $value['css'] ); ?>"
79
+ value="<?php echo esc_attr( $option_value ); ?>"
80
+ class="<?php echo esc_attr( $value['class'] ); ?>"
81
+ <?php echo implode( ' ', $custom_attributes ); ?>
82
+ />
83
+ <input
84
+ name="<?php echo esc_attr( $value['id'] . '_button' ); ?>"
85
+ id="<?php echo esc_attr( $value['id'] . '_button' ); ?>"
86
+ type="button"
87
+ value="<?php echo esc_attr( $value['value'] ); ?>"
88
+ title="<?php echo esc_attr( $value_title ); ?>"
89
+ class="exchage_rate_button"
90
+ <?php echo implode( ' ', $custom_attributes_button ); ?>
91
+ />
92
+ </td>
93
+ </tr>
94
+ <?php
95
+ }
96
+
97
+ /**
98
+ * maybe_unclean_field.
99
+ *
100
+ * @version 3.1.3
101
+ * @since 3.1.3
102
+ */
103
+ function maybe_unclean_field( $value, $option, $raw_value ) {
104
+ return ( isset( $option['wcj_raw'] ) && $option['wcj_raw'] ? $raw_value : $value );
105
+ }
106
+
107
+ /**
108
+ * output_wcj_save_settings_button.
109
+ *
110
+ * @version 2.9.0
111
+ * @since 2.9.0
112
+ */
113
+ function output_wcj_save_settings_button( $value ) {
114
+ // Output
115
+ ?><tr valign="top">
116
+ <th scope="row" class="titledesc"></th>
117
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
118
+ <input name="save" class="button-primary woocommerce-save-button" type="submit" value="<?php echo esc_html( $value['title'] ); ?>">
119
+ </td>
120
+ </tr><?php
121
+ }
122
+
123
+ /**
124
+ * format_wcj_number_plus_checkbox_end.
125
+ *
126
+ * @version 2.8.0
127
+ * @since 2.8.0
128
+ */
129
+ function format_wcj_number_plus_checkbox_end( $value, $option, $raw_value ) {
130
+ return ( 'wcj_number_plus_checkbox_end' === $option['type'] ) ? ( '1' === $raw_value || 'yes' === $raw_value ? 'yes' : 'no' ) : $value;
131
+ }
132
+
133
+ /**
134
+ * output_wcj_number_plus_checkbox_start.
135
+ *
136
+ * @version 2.8.0
137
+ * @since 2.8.0
138
+ */
139
+ function output_wcj_number_plus_checkbox_start( $value ) {
140
+ // Custom attribute handling
141
+ $custom_attributes = array();
142
+ if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
143
+ foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
144
+ $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
145
+ }
146
+ }
147
+ // Description handling
148
+ $field_description = WC_Admin_Settings::get_field_description( $value );
149
+ extract( $field_description );
150
+ // Option value
151
+ $option_value = WC_Admin_Settings::get_option( $value['id'], $value['default'] );
152
+ // Output
153
+ ?><tr valign="top">
154
+ <th scope="row" class="titledesc">
155
+ <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
156
+ <?php echo $tooltip_html; ?>
157
+ </th>
158
+ <td class="forminp forminp-number-checkbox">
159
+ <input
160
+ name="<?php echo esc_attr( $value['id'] ); ?>"
161
+ id="<?php echo esc_attr( $value['id'] ); ?>"
162
+ type="number"
163
+ style="<?php echo esc_attr( $value['css'] ); ?>"
164
+ value="<?php echo esc_attr( $option_value ); ?>"
165
+ class="<?php echo esc_attr( $value['class'] ); ?>"
166
+ placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
167
+ <?php echo implode( ' ', $custom_attributes ); ?>
168
+ /> <?php echo $description . ' ';
169
+ }
170
+
171
+ /**
172
+ * output_wcj_number_plus_checkbox_end.
173
+ *
174
+ * @version 2.8.0
175
+ * @since 2.8.0
176
+ */
177
+ function output_wcj_number_plus_checkbox_end( $value ) {
178
+ // Custom attribute handling
179
+ $custom_attributes = array();
180
+ if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
181
+ foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
182
+ $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
183
+ }
184
+ }
185
+ // Description handling
186
+ $field_description = WC_Admin_Settings::get_field_description( $value );
187
+ extract( $field_description );
188
+ // Option value
189
+ $option_value = WC_Admin_Settings::get_option( $value['id'], $value['default'] );
190
+ // Output
191
+ ?><label for="<?php echo $value['id'] ?>">
192
+ <input
193
+ name="<?php echo esc_attr( $value['id'] ); ?>"
194
+ id="<?php echo esc_attr( $value['id'] ); ?>"
195
+ type="checkbox"
196
+ class="<?php echo esc_attr( isset( $value['class'] ) ? $value['class'] : '' ); ?>"
197
+ value="1"
198
+ <?php checked( $option_value, 'yes' ); ?>
199
+ <?php echo implode( ' ', $custom_attributes ); ?>
200
+ /> <?php echo $description ?>
201
+ </label> <?php echo $tooltip_html; ?>
202
+ </td>
203
+ </tr><?php
204
+ }
205
+
206
+ /**
207
+ * unclean_custom_textarea.
208
+ *
209
+ * @version 2.5.7
210
+ * @since 2.5.7
211
+ */
212
+ function unclean_custom_textarea( $value, $option, $raw_value ) {
213
+ return ( 'custom_textarea' === $option['type'] ) ? $raw_value : $value;
214
+ }
215
+
216
+ /**
217
+ * output_custom_textarea.
218
+ *
219
+ * @version 2.6.0
220
+ * @since 2.2.6
221
+ */
222
+ function output_custom_textarea( $value ) {
223
+ $option_value = get_option( $value['id'], $value['default'] );
224
+ $custom_attributes = ( isset( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) ?
225
+ $value['custom_attributes'] : array();
226
+ $description = ' <p class="description">' . $value['desc'] . '</p>';
227
+ $tooltip_html = ( isset( $value['desc_tip'] ) && '' != $value['desc_tip'] ) ?
228
+ '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
229
+ // Output
230
+ ?><tr valign="top">
231
+ <th scope="row" class="titledesc">
232
+ <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
233
+ <?php echo $tooltip_html; ?>
234
+ </th>
235
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
236
+ <?php echo $description; ?>
237
+
238
+ <textarea
239
+ name="<?php echo esc_attr( $value['id'] ); ?>"
240
+ id="<?php echo esc_attr( $value['id'] ); ?>"
241
+ style="<?php echo esc_attr( $value['css'] ); ?>"
242
+ class="<?php echo esc_attr( $value['class'] ); ?>"
243
+ placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
244
+ <?php echo implode( ' ', $custom_attributes ); ?>
245
+ ><?php echo esc_textarea( $option_value ); ?></textarea>
246
+ </td>
247
+ </tr><?php
248
+ }
249
+
250
+ /**
251
+ * output_module_tools.
252
+ *
253
+ * @version 2.7.0
254
+ * @since 2.2.3
255
+ */
256
+ function output_module_tools( $value ) {
257
+ ?><tr valign="top">
258
+ <th scope="row" class="titledesc">
259
+ <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
260
+ <span class="woocommerce-help-tip" data-tip="<?php echo __( 'To use tools, module must be enabled.', 'woocommerce-jetpack' ); ?>"></span>
261
+ </th>
262
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
263
+ <?php if ( isset( $_GET['section'] ) ) do_action( 'wcj_module_tools_' . $_GET['section'] ); ?>
264
+ </td>
265
+ </tr><?php
266
+ }
267
+
268
+ /**
269
+ * output_custom_link.
270
+ *
271
+ * @version 2.7.0
272
+ * @since 2.2.8
273
+ */
274
+ function output_custom_link( $value ) {
275
+ $tooltip_html = ( isset( $value['desc_tip'] ) && '' != $value['desc_tip'] ) ?
276
+ '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
277
+ ?><tr valign="top">
278
+ <th scope="row" class="titledesc">
279
+ <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label><?php echo $tooltip_html; ?>
280
+ </th>
281
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
282
+ <?php echo $value['link']; ?>
283
+ </td>
284
+ </tr><?php
285
+ }
286
+
287
+ /**
288
+ * output_custom_number.
289
+ *
290
+ * @version 2.5.5
291
+ */
292
+ function output_custom_number( $value ) {
293
+ $type = 'number';
294
+ $option_value = get_option( $value['id'], $value['default'] );
295
+ $tooltip_html = ( isset( $value['desc_tip'] ) && '' != $value['desc_tip'] ) ?
296
+ '<span class="woocommerce-help-tip" data-tip="' . $value['desc_tip'] . '"></span>' : '';
297
+ $description = ' <span class="description">' . $value['desc'] . '</span>';
298
+ $save_button = apply_filters( 'booster_option', '',
299
+ ' <input name="save" class="button-primary" type="submit" value="' . __( 'Save changes', 'woocommerce' ) . '">' );
300
+ // Custom attribute handling
301
+ $custom_attributes = array();
302
+ if ( ! empty( $value['custom_attributes'] ) && is_array( $value['custom_attributes'] ) ) {
303
+ foreach ( $value['custom_attributes'] as $attribute => $attribute_value ) {
304
+ $custom_attributes[] = esc_attr( $attribute ) . '="' . esc_attr( $attribute_value ) . '"';
305
+ }
306
+ }
307
+ // Output
308
+ ?><tr valign="top">
309
+ <th scope="row" class="titledesc">
310
+ <label for="<?php echo esc_attr( $value['id'] ); ?>"><?php echo esc_html( $value['title'] ); ?></label>
311
+ <?php echo $tooltip_html; ?>
312
+ </th>
313
+ <td class="forminp forminp-<?php echo sanitize_title( $value['type'] ) ?>">
314
+ <input
315
+ name="<?php echo esc_attr( $value['id'] ); ?>"
316
+ id="<?php echo esc_attr( $value['id'] ); ?>"
317
+ type="<?php echo esc_attr( $type ); ?>"
318
+ style="<?php echo esc_attr( $value['css'] ); ?>"
319
+ value="<?php echo esc_attr( $option_value ); ?>"
320
+ class="<?php echo esc_attr( $value['class'] ); ?>"
321
+ placeholder="<?php echo esc_attr( $value['placeholder'] ); ?>"
322
+ <?php echo implode( ' ', $custom_attributes ); ?>
323
+ /><?php echo $save_button; ?><?php echo $description; ?>
324
+ </td>
325
+ </tr><?php
326
+ }
327
+
328
+ }
329
+
330
+ endif;
331
+
332
+ return new WCJ_Settings_Custom_Fields();
includes/admin/class-wcj-settings-manager.php CHANGED
@@ -1,165 +1,165 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Settings Manager - Import / Export / Reset Booster's settings
4
- *
5
- * @version 3.8.0
6
- * @since 2.9.0
7
- * @author Algoritmika Ltd.
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'] ] = 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' . 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
-
165
- return new WCJ_Settings_Manager();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings Manager - Import / Export / Reset Booster's settings
4
+ *
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'] ] = 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' . 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
+
165
+ return new WCJ_Settings_Manager();
includes/admin/class-wcj-tools.php CHANGED
@@ -1,90 +1,90 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce Tools
4
- *
5
- * @version 4.8.0
6
- * @author Algoritmika Ltd.
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
- }
23
- }
24
- }
25
-
26
- /**
27
- * add_wcj_tools.
28
- *
29
- * @version 4.8.0
30
- */
31
- function add_wcj_tools() {
32
- if ( apply_filters( 'wcj_can_create_admin_interface', true ) ) {
33
- add_submenu_page(
34
- 'woocommerce',
35
- __( 'Booster for WooCommerce Tools', 'woocommerce-jetpack' ),
36
- __( 'Booster Tools', 'woocommerce-jetpack' ),
37
- ( 'yes' === get_option( 'wcj_' . 'admin_tools' . '_enabled', 'no' ) && 'yes' === get_option( 'wcj_admin_tools_show_menus_to_admin_only', 'no' ) ? 'manage_options' : 'manage_woocommerce' ),
38
- 'wcj-tools',
39
- array( $this, 'create_tools_page' )
40
- );
41
- }
42
- }
43
-
44
- /**
45
- * create_tools_page.
46
- *
47
- * @version 2.3.10
48
- */
49
- function create_tools_page() {
50
-
51
- // Tabs
52
- $tabs = apply_filters( 'wcj_tools_tabs', array(
53
- array(
54
- 'id' => 'dashboard',
55
- 'title' => __( 'Tools Dashboard', 'woocommerce-jetpack' ),
56
- ),
57
- ) );
58
- $html = '<h2 class="nav-tab-wrapper woo-nav-tab-wrapper">';
59
- $active_tab = ( isset( $_GET['tab'] ) ) ? $_GET['tab'] : 'dashboard';
60
- foreach ( $tabs as $tab ) {
61
- $is_active = ( $active_tab === $tab['id'] ) ? 'nav-tab-active' : '';
62
- $html .= '<a href="' . add_query_arg( array( 'page' => 'wcj-tools', 'tab' => $tab['id'] ), get_admin_url() . 'admin.php' ) . '" class="nav-tab ' . $is_active . '">' . $tab['title'] . '</a>';
63
- }
64
- $html .= '</h2>';
65
- echo $html;
66
-
67
- // Content
68
- if ( 'dashboard' === $active_tab ) {
69
- $title = __( 'Booster for WooCommerce Tools - Dashboard', 'woocommerce-jetpack' );
70
- $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' );
71
- echo '<h3>' . $title . '</h3>';
72
- echo '<p>' . $desc . '</p>';
73
- echo '<table class="widefat" style="width:90%;">';
74
- echo '<tr>';
75
- echo '<th style="width:20%;">' . __( 'Tool', 'woocommerce-jetpack' ) . '</th>';
76
- echo '<th style="width:20%;">' . __( 'Module', 'woocommerce-jetpack' ) . '</th>';
77
- echo '<th style="width:50%;">' . __( 'Description', 'woocommerce-jetpack' ) . '</th>';
78
- echo '<th style="width:10%;">' . __( 'Status', 'woocommerce-jetpack' ) . '</th>';
79
- echo '</tr>';
80
- do_action( 'wcj_tools_' . 'dashboard' );
81
- echo '</table>';
82
- } else {
83
- do_action( 'wcj_tools_' . $active_tab );
84
- }
85
- }
86
- }
87
-
88
- endif;
89
-
90
- return new WCJ_Tools();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce Tools
4
+ *
5
+ * @version 4.8.0
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
+ }
23
+ }
24
+ }
25
+
26
+ /**
27
+ * add_wcj_tools.
28
+ *
29
+ * @version 4.8.0
30
+ */
31
+ function add_wcj_tools() {
32
+ if ( apply_filters( 'wcj_can_create_admin_interface', true ) ) {
33
+ add_submenu_page(
34
+ 'woocommerce',
35
+ __( 'Booster for WooCommerce Tools', 'woocommerce-jetpack' ),
36
+ __( 'Booster Tools', 'woocommerce-jetpack' ),
37
+ ( 'yes' === get_option( 'wcj_' . 'admin_tools' . '_enabled', 'no' ) && 'yes' === get_option( 'wcj_admin_tools_show_menus_to_admin_only', 'no' ) ? 'manage_options' : 'manage_woocommerce' ),
38
+ 'wcj-tools',
39
+ array( $this, 'create_tools_page' )
40
+ );
41
+ }
42
+ }
43
+
44
+ /**
45
+ * create_tools_page.
46
+ *
47
+ * @version 2.3.10
48
+ */
49
+ function create_tools_page() {
50
+
51
+ // Tabs
52
+ $tabs = apply_filters( 'wcj_tools_tabs', array(
53
+ array(
54
+ 'id' => 'dashboard',
55
+ 'title' => __( 'Tools Dashboard', 'woocommerce-jetpack' ),
56
+ ),
57
+ ) );
58
+ $html = '<h2 class="nav-tab-wrapper woo-nav-tab-wrapper">';
59
+ $active_tab = ( isset( $_GET['tab'] ) ) ? $_GET['tab'] : 'dashboard';
60
+ foreach ( $tabs as $tab ) {
61
+ $is_active = ( $active_tab === $tab['id'] ) ? 'nav-tab-active' : '';
62
+ $html .= '<a href="' . add_query_arg( array( 'page' => 'wcj-tools', 'tab' => $tab['id'] ), get_admin_url() . 'admin.php' ) . '" class="nav-tab ' . $is_active . '">' . $tab['title'] . '</a>';
63
+ }
64
+ $html .= '</h2>';
65
+ echo $html;
66
+
67
+ // Content
68
+ if ( 'dashboard' === $active_tab ) {
69
+ $title = __( 'Booster for WooCommerce Tools - Dashboard', 'woocommerce-jetpack' );
70
+ $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' );
71
+ echo '<h3>' . $title . '</h3>';
72
+ echo '<p>' . $desc . '</p>';
73
+ echo '<table class="widefat" style="width:90%;">';
74
+ echo '<tr>';
75
+ echo '<th style="width:20%;">' . __( 'Tool', 'woocommerce-jetpack' ) . '</th>';
76
+ echo '<th style="width:20%;">' . __( 'Module', 'woocommerce-jetpack' ) . '</th>';
77
+ echo '<th style="width:50%;">' . __( 'Description', 'woocommerce-jetpack' ) . '</th>';
78
+ echo '<th style="width:10%;">' . __( 'Status', 'woocommerce-jetpack' ) . '</th>';
79
+ echo '</tr>';
80
+ do_action( 'wcj_tools_' . 'dashboard' );
81
+ echo '</table>';
82
+ } else {
83
+ do_action( 'wcj_tools_' . $active_tab );
84
+ }
85
+ }
86
+ }
87
+
88
+ endif;
89
+
90
+ return new WCJ_Tools();
includes/admin/wcj-modules-cats.php CHANGED
@@ -1,205 +1,205 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Modules Array
4
- *
5
- * @version 4.3.0
6
- * @since 2.2.0
7
- * @author Algoritmika Ltd.
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
- 'alphabetically',
18
- 'by_category',
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
-
46
- 'labels' => array(
47
- 'label' => __( 'Button & Price Labels', 'woocommerce-jetpack' ),
48
- 'desc' => __( 'Add to Cart Labels, Call for Price, Custom Price Labels and more.', 'woocommerce-jetpack' ),
49
- 'all_cat_ids' => array(
50
- 'price_labels',
51
- 'call_for_price',
52
- 'free_price',
53
- 'add_to_cart',
54
- 'more_button_labels',
55
- ),
56
- ),
57
-
58
- 'products' => array(
59
- 'label' => __( 'Products', 'woocommerce-jetpack' ),
60
- 'desc' => __( 'Bookings, Crowdfunding Products, Product Addons and Input Fields, Product Listings, Product Tabs and more.', 'woocommerce-jetpack' ),
61
- 'all_cat_ids' => array(
62
- 'product_listings',
63
- 'tax_display',
64
- 'admin_products_list',
65
- 'products_per_page',
66
- 'product_tabs',
67
- 'product_custom_info',
68
- 'related_products',
69
- 'cross_sells',
70
- 'upsells',
71
- 'sorting',
72
- 'sku',
73
- 'stock',
74
- 'product_input_fields',
75
- 'product_add_to_cart',
76
- 'add_to_cart_button_visibility',
77
- 'purchase_data',
78
- 'product_bookings',
79
- 'crowdfunding',
80
- 'product_addons',
81
- 'product_images',
82
- 'sale_flash',
83
- 'product_by_country',
84
- 'product_by_user_role',
85
- 'product_custom_visibility',
86
- 'product_by_time',
87
- 'product_by_date',
88
- 'product_by_user',
89
- 'products_xml',
90
- 'product_bulk_meta_editor',
91
- 'product_msrp',
92
- ),
93
- ),
94
-
95
- 'cart_and_checkout' => array(
96
- 'label' => __( 'Cart & Checkout', 'woocommerce-jetpack' ),
97
- 'desc' => __( 'Cart and Checkout Customization, Empty Cart Button, Mini Cart, Coupons and more.', 'woocommerce-jetpack' ),
98
- 'all_cat_ids' => array(
99
- 'cart',
100
- 'cart_customization',
101
- 'empty_cart',
102
- 'mini_cart',
103
- 'url_coupons',
104
- 'coupon_code_generator',
105
- 'coupon_by_user_role',
106
- 'checkout_core_fields',
107
- 'checkout_custom_fields',
108
- 'checkout_files_upload',
109
- 'checkout_custom_info',
110
- 'checkout_customization',
111
- 'checkout_fees',
112
- 'eu_vat_number',
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
- ) );
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Modules Array
4
+ *
5
+ * @version 4.3.0
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
+ 'alphabetically',
18
+ 'by_category',
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
+
46
+ 'labels' => array(
47
+ 'label' => __( 'Button & Price Labels', 'woocommerce-jetpack' ),
48
+ 'desc' => __( 'Add to Cart Labels, Call for Price, Custom Price Labels and more.', 'woocommerce-jetpack' ),
49
+ 'all_cat_ids' => array(
50
+ 'price_labels',
51
+ 'call_for_price',
52
+ 'free_price',
53
+ 'add_to_cart',
54
+ 'more_button_labels',
55
+ ),
56
+ ),
57
+
58
+ 'products' => array(
59
+ 'label' => __( 'Products', 'woocommerce-jetpack' ),
60
+ 'desc' => __( 'Bookings, Crowdfunding Products, Product Addons and Input Fields, Product Listings, Product Tabs and more.', 'woocommerce-jetpack' ),
61
+ 'all_cat_ids' => array(
62
+ 'product_listings',
63
+ 'tax_display',
64
+ 'admin_products_list',
65
+ 'products_per_page',
66
+ 'product_tabs',
67
+ 'product_custom_info',
68
+ 'related_products',
69
+ 'cross_sells',
70
+ 'upsells',
71
+ 'sorting',
72
+ 'sku',
73
+ 'stock',
74
+ 'product_input_fields',
75
+ 'product_add_to_cart',
76
+ 'add_to_cart_button_visibility',
77
+ 'purchase_data',
78
+ 'product_bookings',
79
+ 'crowdfunding',
80
+ 'product_addons',
81
+ 'product_images',
82
+ 'sale_flash',
83
+ 'product_by_country',
84
+ 'product_by_user_role',
85
+ 'product_custom_visibility',
86
+ 'product_by_time',
87
+ 'product_by_date',
88
+ 'product_by_user',
89
+ 'products_xml',
90
+ 'product_bulk_meta_editor',
91
+ 'product_msrp',
92
+ ),
93
+ ),
94
+
95
+ 'cart_and_checkout' => array(
96
+ 'label' => __( 'Cart & Checkout', 'woocommerce-jetpack' ),
97
+ 'desc' => __( 'Cart and Checkout Customization, Empty Cart Button, Mini Cart, Coupons and more.', 'woocommerce-jetpack' ),
98
+ 'all_cat_ids' => array(
99
+ 'cart',
100
+ 'cart_customization',
101
+ 'empty_cart',
102
+ 'mini_cart',
103
+ 'url_coupons',
104
+ 'coupon_code_generator',
105
+ 'coupon_by_user_role',
106
+ 'checkout_core_fields',
107
+ 'checkout_custom_fields',
108
+ 'checkout_files_upload',
109
+ 'checkout_custom_info',
110
+ 'checkout_customization',
111
+ 'checkout_fees',
112
+ 'eu_vat_number',
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
+ ) );
includes/background-process/class-wcj-multicurrency-price-updater.php CHANGED
@@ -1,34 +1,34 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Background Process - Multicurrency Price Updater
4
- *
5
- * Updates min and max prices
6
- *
7
- * @version 4.5.0
8
- * @since 4.5.0
9
- * @author Algoritmika Ltd.
10
- */
11
-
12
- if ( ! defined( 'ABSPATH' ) ) {
13
- exit;
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;
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Background Process - Multicurrency Price Updater
4
+ *
5
+ * Updates min and max prices
6
+ *
7
+ * @version 4.5.0
8
+ * @since 4.5.0
9
+ * @author Pluggabl LLC.
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) {
13
+ exit;
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;
includes/class-wcj-add-to-cart-button-visibility.php CHANGED
@@ -1,220 +1,220 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Add to Cart Button Visibility
4
- *
5
- * @version 3.9.0
6
- * @since 3.3.0
7
- * @author Algoritmika Ltd.
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' === get_option( 'wcj_add_to_cart_button_global_enabled', 'no' ) ) {
39
- // Archives
40
- if ( 'yes' === get_option( 'wcj_add_to_cart_button_disable_archives', 'no' ) ) {
41
- if ( 'remove_action' === 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' === get_option( 'wcj_add_to_cart_button_disable_single', 'no' ) ) {
50
- if ( 'remove_action' === 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' === 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' === 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( 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 = 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 = 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 = 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( 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 = 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 = 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( 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
-
220
- return new WCJ_Add_To_Cart_Button_Visibility();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Add to Cart Button Visibility
4
+ *
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' === get_option( 'wcj_add_to_cart_button_global_enabled', 'no' ) ) {
39
+ // Archives
40
+ if ( 'yes' === get_option( 'wcj_add_to_cart_button_disable_archives', 'no' ) ) {
41
+ if ( 'remove_action' === 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' === get_option( 'wcj_add_to_cart_button_disable_single', 'no' ) ) {
50
+ if ( 'remove_action' === 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' === 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' === 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( 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 = 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 = 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 = 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( 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 = 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 = 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( 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
+
220
+ return new WCJ_Add_To_Cart_Button_Visibility();
includes/class-wcj-add-to-cart.php CHANGED
@@ -1,39 +1,39 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Add to Cart
4
- *
5
- * @version 3.3.0
6
- * @author Algoritmika Ltd.
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 3.3.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.', 'woocommerce-jetpack' );
25
- $this->link_slug = 'woocommerce-add-to-cart-labels';
26
- parent::__construct();
27
-
28
- if ( $this->is_enabled() ) {
29
- include_once( 'add-to-cart/class-wcj-add-to-cart-per-category.php' );
30
- include_once( 'add-to-cart/class-wcj-add-to-cart-per-product.php' );
31
- include_once( 'add-to-cart/class-wcj-add-to-cart-per-product-type.php' );
32
- }
33
- }
34
-
35
- }
36
-
37
- endif;
38
-
39
- return new WCJ_Add_To_Cart();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Add to Cart
4
+ *
5
+ * @version 3.3.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 3.3.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.', 'woocommerce-jetpack' );
25
+ $this->link_slug = 'woocommerce-add-to-cart-labels';
26
+ parent::__construct();
27
+
28
+ if ( $this->is_enabled() ) {
29
+ include_once( 'add-to-cart/class-wcj-add-to-cart-per-category.php' );
30
+ include_once( 'add-to-cart/class-wcj-add-to-cart-per-product.php' );
31
+ include_once( 'add-to-cart/class-wcj-add-to-cart-per-product-type.php' );
32
+ }
33
+ }
34
+
35
+ }
36
+
37
+ endif;
38
+
39
+ return new WCJ_Add_To_Cart();
includes/class-wcj-address-formats.php CHANGED
@@ -1,117 +1,117 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Address Formats
4
- *
5
- * @version 2.8.0
6
- * @since 2.2.0
7
- * @author Algoritmika Ltd.
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' === 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 = 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();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Address Formats
4
+ *
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' === 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 = 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();
includes/class-wcj-admin-bar.php CHANGED
@@ -1,655 +1,655 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Admin Bar
4
- *
5
- * @version 4.1.0
6
- * @since 2.9.0
7
- * @author Algoritmika Ltd.
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' === 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' === get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) || 'yes' === get_option( 'wcj_admin_bar_booster_active_enabled', 'yes' ) ) {
42
- if ( 'yes' === 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' === 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' === 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' === 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' === 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
-
655
- return new WCJ_Admin_Bar();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Admin Bar
4
+ *
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' === 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' === get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) || 'yes' === get_option( 'wcj_admin_bar_booster_active_enabled', 'yes' ) ) {
42
+ if ( 'yes' === 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' === 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' === 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' === 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' === 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
+
655
+ return new WCJ_Admin_Bar();
includes/class-wcj-admin-orders-list.php CHANGED
@@ -1,419 +1,419 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Admin Orders List
4
- *
5
- * @version 3.9.0
6
- * @since 3.2.4
7
- * @author Algoritmika Ltd.
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 3.7.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; add multiple status filtering.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-admin-orders-list';
28
- parent::__construct();
29
-
30
- if ( $this->is_enabled() ) {
31
-
32
- // Custom columns
33
- if ( 'yes' === get_option( 'wcj_order_admin_list_custom_columns_enabled', 'no' ) ) {
34
- add_filter( 'manage_edit-shop_order_columns', array( $this, 'add_order_columns' ), PHP_INT_MAX - 1 );
35
- add_action( 'manage_shop_order_posts_custom_column', array( $this, 'render_order_column' ), PHP_INT_MAX );
36
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) || 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
37
- // Billing country or Currency filtering
38
- add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );
39
- add_filter( 'parse_query', array( $this, 'parse_query' ) );
40
- }
41
- // Maybe make sortable custom columns
42
- add_filter( 'manage_edit-shop_order_sortable_columns', array( $this, 'shop_order_sortable_columns' ) );
43
- add_action( 'pre_get_posts', array( $this, 'shop_order_pre_get_posts_order_by_column' ) );
44
- }
45
-
46
- // Multiple status
47
- if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_enabled', 'no' ) ) {
48
- if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_not_completed_link', 'no' ) ) {
49
- add_filter( 'views_edit-shop_order', array( $this, 'add_shop_order_multiple_statuses_not_completed_link' ) );
50
- add_action( 'pre_get_posts', array( $this, 'filter_shop_order_multiple_statuses_not_completed_link' ), PHP_INT_MAX, 1 );
51
- }
52
- if ( 'no' != get_option( 'wcj_order_admin_list_multiple_status_filter', 'no' ) ) {
53
- add_action( 'restrict_manage_posts', array( $this, 'add_shop_order_multiple_statuses' ), PHP_INT_MAX, 2 );
54
- add_action( 'pre_get_posts', array( $this, 'filter_shop_order_multiple_statuses' ), PHP_INT_MAX, 1 );
55
- }
56
- if ( 'yes' === get_option( 'wcj_order_admin_list_hide_default_statuses_menu', 'no' ) ) {
57
- add_action( 'admin_head', array( $this, 'hide_default_statuses_menu' ), PHP_INT_MAX );
58
- }
59
- if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_admin_menu', 'no' ) ) {
60
- add_action( 'admin_menu', array( $this, 'admin_menu_multiple_status' ) );
61
- }
62
- }
63
-
64
- // Columns Order
65
- if ( 'yes' === get_option( 'wcj_order_admin_list_columns_order_enabled', 'no' ) ) {
66
- add_filter( 'manage_edit-shop_order_columns', array( $this, 'rearange_order_columns' ), PHP_INT_MAX - 1 );
67
- }
68
-
69
- }
70
- }
71
-
72
- /**
73
- * admin_menu_multiple_status.
74
- *
75
- * @version 3.7.0
76
- * @since 3.7.0
77
- * @todo add presets as links (same as "Not completed" link)
78
- * @todo fix: custom (i.e. presets) menus are not highlighted
79
- */
80
- function admin_menu_multiple_status() {
81
- // Remove "Coupons" menu (to get "Orders" menus on top)
82
- $coupons_menu = remove_submenu_page( 'woocommerce', 'edit.php?post_type=shop_coupon' );
83
- // Maybe remove original "Orders" menu
84
- if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_admin_menu_remove_original', 'no' ) ) {
85
- remove_submenu_page( 'woocommerce', 'edit.php?post_type=shop_order' );
86
- }
87
- // Add presets
88
- $titles = get_option( 'wcj_order_admin_list_multiple_status_presets_titles', array() );
89
- $statuses = get_option( 'wcj_order_admin_list_multiple_status_presets_statuses', array() );
90
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_order_admin_list_multiple_status_presets_total_number', 1 ) );
91
- for ( $i = 1; $i <= $total_number; $i++ ) {
92
- if ( ! empty( $titles[ $i ] ) && ! empty( $statuses[ $i ] ) ) {
93
- $menu_slug = 'edit.php?post_type=shop_order';
94
- foreach ( $statuses[ $i ] as $x => $status ) {
95
- $menu_slug .= "&wcj_admin_filter_statuses[{$x}]={$status}";
96
- }
97
- $orders_count_html = '';
98
- if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_admin_menu_counter', 'no' ) ) {
99
- $order_count = 0;
100
- foreach ( $statuses[ $i ] as $x => $status ) {
101
- $order_count += wc_orders_count( substr( $status, 3 ) );
102
- }
103
- $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.
104
- }
105
- add_submenu_page( 'woocommerce', $titles[ $i ], $titles[ $i ] . $orders_count_html, 'edit_shop_orders', $menu_slug );
106
- }
107
- }
108
- // Re-add "Coupons" menu
109
- add_submenu_page( 'woocommerce', $coupons_menu[0], $coupons_menu[3], $coupons_menu[1], $coupons_menu[2] );
110
- }
111
-
112
- /**
113
- * shop_order_pre_get_posts_order_by_column.
114
- *
115
- * @version 2.9.0
116
- * @since 2.9.0
117
- * @todo add sortable to "Billing Country" and "Currency Code"
118
- * @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
119
- * @todo (maybe) add filtering to custom columns (as it's done for "Billing Country" and "Currency Code")
120
- */
121
- function shop_order_pre_get_posts_order_by_column( $query ) {
122
- if (
123
- $query->is_main_query() &&
124
- ( $orderby = $query->get( 'orderby' ) ) &&
125
- isset( $query->query['post_type'] ) && 'shop_order' === $query->query['post_type'] &&
126
- isset( $query->is_admin ) && 1 == $query->is_admin
127
- ) {
128
- if ( 'wcj_orders_custom_column_' === substr( $orderby, 0, 25 ) ) {
129
- $index = substr( $orderby, 25 );
130
- $query->set( 'orderby', get_option( 'wcj_orders_list_custom_columns_sortable_' . $index, 'no' ) ); // 'meta_value' or 'meta_value_num'
131
- $query->set( 'meta_key', get_option( 'wcj_orders_list_custom_columns_sortable_key_' . $index, '' ) );
132
- }
133
- }
134
- }
135
-
136
- /**
137
- * Make columns sortable.
138
- *
139
- * @version 2.9.0
140
- * @since 2.9.0
141
- * @param array $columns
142
- * @return array
143
- */
144
- function shop_order_sortable_columns( $columns ) {
145
- $custom = array();
146
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
147
- for ( $i = 1; $i <= $total_number; $i++ ) {
148
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
149
- if ( 'no' != get_option( 'wcj_orders_list_custom_columns_sortable_' . $i, 'no' ) && '' != get_option( 'wcj_orders_list_custom_columns_sortable_key_' . $i, '' ) ) {
150
- $custom[ 'wcj_orders_custom_column_' . $i ] = 'wcj_orders_custom_column_' . $i;
151
- }
152
- }
153
- }
154
- return ( ! empty( $custom ) ? wp_parse_args( $custom, $columns ) : $columns );
155
- }
156
-
157
- /**
158
- * hide_default_statuses_menu.
159
- *
160
- * @version 2.5.7
161
- * @since 2.5.7
162
- */
163
- function hide_default_statuses_menu() {
164
- echo '<style>body.post-type-shop_order ul.subsubsub {display: none !important;}</style>';
165
- }
166
-
167
- /**
168
- * get_orders_default_columns_in_order.
169
- *
170
- * @version 2.5.7
171
- * @since 2.5.7
172
- */
173
- function get_orders_default_columns_in_order() {
174
- $columns = array(
175
- 'cb',
176
- 'order_status',
177
- 'order_title',
178
- 'order_items',
179
- 'billing_address',
180
- 'shipping_address',
181
- 'customer_message',
182
- 'order_notes',
183
- 'order_date',
184
- 'order_total',
185
- 'order_actions',
186
- );
187
- return implode( PHP_EOL, $columns );
188
- }
189
-
190
- /**
191
- * add_shop_order_multiple_statuses_not_completed_link.
192
- *
193
- * @version 3.9.0
194
- * @since 2.5.7
195
- */
196
- function add_shop_order_multiple_statuses_not_completed_link( $views ) {
197
- global $wp_query;
198
- if ( ! wcj_current_user_can( 'edit_others_pages' ) ) {
199
- return $views;
200
- }
201
- $all_not_completed_statuses = wc_get_order_statuses();
202
- unset( $all_not_completed_statuses['wc-completed'] );
203
- $all_not_completed_statuses = array_keys( $all_not_completed_statuses );
204
- $all_not_completed_statuses_param = urlencode( implode( ',', $all_not_completed_statuses ) );
205
- $class = ( isset( $wp_query->query['post_status'] ) && is_array( $wp_query->query['post_status'] ) && $all_not_completed_statuses === $wp_query->query['post_status'] ) ? 'current' : '';
206
- $query_string = remove_query_arg( array( 'post_status', 'wcj_admin_filter_statuses' ) );
207
- $query_string = add_query_arg( 'post_status', $all_not_completed_statuses_param, $query_string );
208
- $views['wcj_statuses_not_completed'] = '<a href="' . esc_url( $query_string ) . '" class="' . esc_attr( $class ) . '">' . __( 'Not Completed', 'woocommerce-jetpack' ) . '</a>';
209
- return $views;
210
- }
211
-
212
- /**
213
- * filter_shop_order_multiple_statuses_not_completed_link.
214
- *
215
- * @version 3.9.0
216
- * @since 2.5.7
217
- */
218
- function filter_shop_order_multiple_statuses_not_completed_link( $query ) {
219
- if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/edit.php' ) && isset( $_GET['post_type'] ) && 'shop_order' === $_GET['post_type'] ) {
220
- if ( wcj_current_user_can( 'edit_others_pages' ) ) {
221
- if ( isset( $_GET['post_status'] ) && false !== strpos( $_GET['post_status'], ',' ) ) {
222
- $post_statuses = explode( ',', $_GET['post_status'] );
223
- $query->query['post_status'] = $post_statuses;
224
- $query->query_vars['post_status'] = $post_statuses;
225
- }
226
- }
227
- }
228
- }
229
-
230
- /**
231
- * multiple_shop_order_statuses.
232
- *
233
- * @version 3.7.0
234
- * @since 2.5.7
235
- */
236
- function multiple_shop_order_statuses( $type ) {
237
- $checked_post_statuses = isset( $_GET['wcj_admin_filter_statuses'] ) ? $_GET['wcj_admin_filter_statuses'] : array();
238
- $html = '';
239
- $html .= ( 'checkboxes' === $type ) ?
240
- '<span id="wcj_admin_filter_shop_order_statuses">' :
241
- '<select multiple name="wcj_admin_filter_statuses[]" id="wcj_admin_filter_shop_order_statuses" class="chosen_select">';
242
- $num_posts = wp_count_posts( 'shop_order', 'readable' );
243
- foreach ( array_merge( wc_get_order_statuses(), array( 'trash' => __( 'Trash', 'woocommerce-jetpack' ) ) ) as $status_id => $status_title ) {
244
- $total_number = ( isset( $num_posts->{$status_id} ) ) ? $num_posts->{$status_id} : 0;
245
- if ( $total_number > 0 ) {
246
- $html .= ( 'checkboxes' === $type ) ?
247
- '<input type="checkbox" name="wcj_admin_filter_statuses[]" style="width:16px;height:16px;" value="' . $status_id . '"' .
248
- checked( in_array( $status_id, $checked_post_statuses ), true, false ) . '>' . $status_title . ' (' . $total_number . ') ' :
249
- '<option value="' . $status_id . '"' . selected( in_array( $status_id, $checked_post_statuses ), true, false ) . '>' .
250
- $status_title . ' (' . $total_number . ') ' . '</option>';
251
- }
252
- }
253
- $html .= ( 'checkboxes' === $type ) ?
254
- '</span>' :
255
- '</select>';
256
- return $html;
257
- }
258
-
259
- /**
260
- * add_shop_order_multiple_statuses.
261
- *
262
- * @version 2.5.7
263
- * @since 2.5.7
264
- */
265
- function add_shop_order_multiple_statuses( $post_type, $which ) {
266
- if ( 'shop_order' === $post_type ) {
267
- echo $this->multiple_shop_order_statuses( get_option( 'wcj_order_admin_list_multiple_status_filter', 'no' ) );
268
- }
269
- }
270
-
271
- /**
272
- * filter_shop_order_multiple_statuses.
273
- *
274
- * @version 3.9.0
275
- * @since 2.5.7
276
- */
277
- function filter_shop_order_multiple_statuses( $query ) {
278
- if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/edit.php' ) && isset( $_GET['post_type'] ) && 'shop_order' === $_GET['post_type'] ) {
279
- if ( wcj_current_user_can( 'edit_others_pages' ) ) {
280
- if ( isset( $_GET['wcj_admin_filter_statuses'] ) ) {
281
- $post_statuses = $_GET['wcj_admin_filter_statuses'];
282
- $query->query['post_status'] = $post_statuses;
283
- $query->query_vars['post_status'] = $post_statuses;
284
- }
285
- }
286
- }
287
- }
288
-
289
- /**
290
- * Filter the orders in admin based on options.
291
- *
292
- * @version 2.8.0
293
- * @access public
294
- * @param mixed $query
295
- * @return void
296
- */
297
- function parse_query( $query ) {
298
- global $typenow, $wp_query;
299
- if ( $typenow != 'shop_order' ) {
300
- return;
301
- }
302
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) && isset( $_GET['country'] ) && 'all' != $_GET['country'] ) {
303
- $query->query_vars['meta_query'][] = array(
304
- 'key' => '_billing_country',
305
- 'value' => $_GET['country'],
306
- );
307
- }
308
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) && isset( $_GET['currency'] ) && 'all' != $_GET['currency'] ) {
309
- $query->query_vars['meta_query'][] = array(
310
- 'key' => '_order_currency',
311
- 'value' => $_GET['currency'],
312
- );
313
- }
314
- }
315
-
316
- /**
317
- * Filters for post types.
318
- *
319
- * @version 3.9.0
320
- */
321
- function restrict_manage_posts() {
322
- global $typenow, $wp_query;
323
- if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ) ) ) {
324
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
325
- $selected_coutry = isset( $_GET['country'] ) ? $_GET['country'] : 'all';
326
- $countries = array_merge( array( 'all' => __( 'All countries', 'woocommerce-jetpack' ) ), wcj_get_countries() );
327
- echo '<select id="country" name="country">';
328
- foreach ( $countries as $code => $name ) {
329
- echo '<option value="' . $code . '" ' . selected( $code, $selected_coutry, false ) . '>' . $name . '</option>';
330
- }
331
- echo '</select>';
332
- }
333
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
334
- $selected_currency = isset( $_GET['currency'] ) ? $_GET['currency'] : 'all';
335
- $currencies = array_merge( array( 'all' => __( 'All currencies', 'woocommerce-jetpack' ) ), wcj_get_woocommerce_currencies_and_symbols() );
336
- echo '<select id="currency" name="currency">';
337
- foreach ( $currencies as $code => $name ) {
338
- echo '<option value="' . $code . '" ' . selected( $code, $selected_currency, false ) . '>' . $name . '</option>';
339
- }
340
- echo '</select>';
341
- }
342
- }
343
- }
344
-
345
- /**
346
- * rearange_order_columns.
347
- *
348
- * @version 2.5.7
349
- * @version 2.5.7
350
- */
351
- function rearange_order_columns( $columns ) {
352
- $reordered_columns = get_option( 'wcj_order_admin_list_columns_order', $this->get_orders_default_columns_in_order() );
353
- $reordered_columns = explode( PHP_EOL, $reordered_columns );
354
- $reordered_columns_result = array();
355
- if ( ! empty( $reordered_columns ) ) {
356
- foreach ( $reordered_columns as $column_id ) {
357
- $column_id = str_replace( "\n", '', $column_id );
358
- $column_id = str_replace( "\r", '', $column_id );
359
- if ( '' != $column_id && isset( $columns[ $column_id ] ) ) {
360
- $reordered_columns_result[ $column_id ] = $columns[ $column_id ];
361
- unset( $columns[ $column_id ] );
362
- }
363
- }
364
- }
365
- return array_merge( $reordered_columns_result, $columns );
366
- }
367
-
368
- /**
369
- * add_order_columns.
370
- *
371
- * @version 2.8.0
372
- */
373
- function add_order_columns( $columns ) {
374
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
375
- $columns['country'] = __( 'Billing Country', 'woocommerce-jetpack' );
376
- }
377
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
378
- $columns['currency'] = __( 'Currency Code', 'woocommerce-jetpack' );
379
- }
380
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
381
- for ( $i = 1; $i <= $total_number; $i++ ) {
382
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
383
- $columns[ 'wcj_orders_custom_column_' . $i ] = get_option( 'wcj_orders_list_custom_columns_label_' . $i, '' );
384
- }
385
- }
386
- return $columns;
387
- }
388
-
389
- /**
390
- * Output custom columns for orders
391
- *
392
- * @version 2.8.0
393
- * @param string $column
394
- */
395
- function render_order_column( $column ) {
396
- if ( 'country' === $column && 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
397
- $country_code = do_shortcode( '[wcj_order_checkout_field field_id="billing_country"]' );
398
- echo ( 2 == strlen( $country_code ) )
399
- ? wcj_get_country_flag_by_code( $country_code ) . ' ' . wcj_get_country_name_by_code( $country_code )
400
- : wcj_get_country_name_by_code( $country_code );
401
- } elseif ( 'currency' === $column && 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
402
- echo do_shortcode( '[wcj_order_currency]' );
403
- } else {
404
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
405
- for ( $i = 1; $i <= $total_number; $i++ ) {
406
- if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
407
- if ( 'wcj_orders_custom_column_' . $i === $column ) {
408
- echo do_shortcode( get_option( 'wcj_orders_list_custom_columns_value_' . $i, '' ) );
409
- }
410
- }
411
- }
412
- }
413
- }
414
-
415
- }
416
-
417
- endif;
418
-
419
- return new WCJ_Admin_Orders_List();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Admin Orders List
4
+ *
5
+ * @version 3.9.0
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 3.7.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; add multiple status filtering.', 'woocommerce-jetpack' );
27
+ $this->link_slug = 'woocommerce-admin-orders-list';
28
+ parent::__construct();
29
+
30
+ if ( $this->is_enabled() ) {
31
+
32
+ // Custom columns
33
+ if ( 'yes' === get_option( 'wcj_order_admin_list_custom_columns_enabled', 'no' ) ) {
34
+ add_filter( 'manage_edit-shop_order_columns', array( $this, 'add_order_columns' ), PHP_INT_MAX - 1 );
35
+ add_action( 'manage_shop_order_posts_custom_column', array( $this, 'render_order_column' ), PHP_INT_MAX );
36
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) || 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
37
+ // Billing country or Currency filtering
38
+ add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );
39
+ add_filter( 'parse_query', array( $this, 'parse_query' ) );
40
+ }
41
+ // Maybe make sortable custom columns
42
+ add_filter( 'manage_edit-shop_order_sortable_columns', array( $this, 'shop_order_sortable_columns' ) );
43
+ add_action( 'pre_get_posts', array( $this, 'shop_order_pre_get_posts_order_by_column' ) );
44
+ }
45
+
46
+ // Multiple status
47
+ if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_enabled', 'no' ) ) {
48
+ if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_not_completed_link', 'no' ) ) {
49
+ add_filter( 'views_edit-shop_order', array( $this, 'add_shop_order_multiple_statuses_not_completed_link' ) );
50
+ add_action( 'pre_get_posts', array( $this, 'filter_shop_order_multiple_statuses_not_completed_link' ), PHP_INT_MAX, 1 );
51
+ }
52
+ if ( 'no' != get_option( 'wcj_order_admin_list_multiple_status_filter', 'no' ) ) {
53
+ add_action( 'restrict_manage_posts', array( $this, 'add_shop_order_multiple_statuses' ), PHP_INT_MAX, 2 );
54
+ add_action( 'pre_get_posts', array( $this, 'filter_shop_order_multiple_statuses' ), PHP_INT_MAX, 1 );
55
+ }
56
+ if ( 'yes' === get_option( 'wcj_order_admin_list_hide_default_statuses_menu', 'no' ) ) {
57
+ add_action( 'admin_head', array( $this, 'hide_default_statuses_menu' ), PHP_INT_MAX );
58
+ }
59
+ if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_admin_menu', 'no' ) ) {
60
+ add_action( 'admin_menu', array( $this, 'admin_menu_multiple_status' ) );
61
+ }
62
+ }
63
+
64
+ // Columns Order
65
+ if ( 'yes' === get_option( 'wcj_order_admin_list_columns_order_enabled', 'no' ) ) {
66
+ add_filter( 'manage_edit-shop_order_columns', array( $this, 'rearange_order_columns' ), PHP_INT_MAX - 1 );
67
+ }
68
+
69
+ }
70
+ }
71
+
72
+ /**
73
+ * admin_menu_multiple_status.
74
+ *
75
+ * @version 3.7.0
76
+ * @since 3.7.0
77
+ * @todo add presets as links (same as "Not completed" link)
78
+ * @todo fix: custom (i.e. presets) menus are not highlighted
79
+ */
80
+ function admin_menu_multiple_status() {
81
+ // Remove "Coupons" menu (to get "Orders" menus on top)
82
+ $coupons_menu = remove_submenu_page( 'woocommerce', 'edit.php?post_type=shop_coupon' );
83
+ // Maybe remove original "Orders" menu
84
+ if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_admin_menu_remove_original', 'no' ) ) {
85
+ remove_submenu_page( 'woocommerce', 'edit.php?post_type=shop_order' );
86
+ }
87
+ // Add presets
88
+ $titles = get_option( 'wcj_order_admin_list_multiple_status_presets_titles', array() );
89
+ $statuses = get_option( 'wcj_order_admin_list_multiple_status_presets_statuses', array() );
90
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_order_admin_list_multiple_status_presets_total_number', 1 ) );
91
+ for ( $i = 1; $i <= $total_number; $i++ ) {
92
+ if ( ! empty( $titles[ $i ] ) && ! empty( $statuses[ $i ] ) ) {
93
+ $menu_slug = 'edit.php?post_type=shop_order';
94
+ foreach ( $statuses[ $i ] as $x => $status ) {
95
+ $menu_slug .= "&wcj_admin_filter_statuses[{$x}]={$status}";
96
+ }
97
+ $orders_count_html = '';
98
+ if ( 'yes' === get_option( 'wcj_order_admin_list_multiple_status_admin_menu_counter', 'no' ) ) {
99
+ $order_count = 0;
100
+ foreach ( $statuses[ $i ] as $x => $status ) {
101
+ $order_count += wc_orders_count( substr( $status, 3 ) );
102
+ }
103
+ $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.
104
+ }
105
+ add_submenu_page( 'woocommerce', $titles[ $i ], $titles[ $i ] . $orders_count_html, 'edit_shop_orders', $menu_slug );
106
+ }
107
+ }
108
+ // Re-add "Coupons" menu
109
+ add_submenu_page( 'woocommerce', $coupons_menu[0], $coupons_menu[3], $coupons_menu[1], $coupons_menu[2] );
110
+ }
111
+
112
+ /**
113
+ * shop_order_pre_get_posts_order_by_column.
114
+ *
115
+ * @version 2.9.0
116
+ * @since 2.9.0
117
+ * @todo add sortable to "Billing Country" and "Currency Code"
118
+ * @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
119
+ * @todo (maybe) add filtering to custom columns (as it's done for "Billing Country" and "Currency Code")
120
+ */
121
+ function shop_order_pre_get_posts_order_by_column( $query ) {
122
+ if (
123
+ $query->is_main_query() &&
124
+ ( $orderby = $query->get( 'orderby' ) ) &&
125
+ isset( $query->query['post_type'] ) && 'shop_order' === $query->query['post_type'] &&
126
+ isset( $query->is_admin ) && 1 == $query->is_admin
127
+ ) {
128
+ if ( 'wcj_orders_custom_column_' === substr( $orderby, 0, 25 ) ) {
129
+ $index = substr( $orderby, 25 );
130
+ $query->set( 'orderby', get_option( 'wcj_orders_list_custom_columns_sortable_' . $index, 'no' ) ); // 'meta_value' or 'meta_value_num'
131
+ $query->set( 'meta_key', get_option( 'wcj_orders_list_custom_columns_sortable_key_' . $index, '' ) );
132
+ }
133
+ }
134
+ }
135
+
136
+ /**
137
+ * Make columns sortable.
138
+ *
139
+ * @version 2.9.0
140
+ * @since 2.9.0
141
+ * @param array $columns
142
+ * @return array
143
+ */
144
+ function shop_order_sortable_columns( $columns ) {
145
+ $custom = array();
146
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
147
+ for ( $i = 1; $i <= $total_number; $i++ ) {
148
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
149
+ if ( 'no' != get_option( 'wcj_orders_list_custom_columns_sortable_' . $i, 'no' ) && '' != get_option( 'wcj_orders_list_custom_columns_sortable_key_' . $i, '' ) ) {
150
+ $custom[ 'wcj_orders_custom_column_' . $i ] = 'wcj_orders_custom_column_' . $i;
151
+ }
152
+ }
153
+ }
154
+ return ( ! empty( $custom ) ? wp_parse_args( $custom, $columns ) : $columns );
155
+ }
156
+
157
+ /**
158
+ * hide_default_statuses_menu.
159
+ *
160
+ * @version 2.5.7
161
+ * @since 2.5.7
162
+ */
163
+ function hide_default_statuses_menu() {
164
+ echo '<style>body.post-type-shop_order ul.subsubsub {display: none !important;}</style>';
165
+ }
166
+
167
+ /**
168
+ * get_orders_default_columns_in_order.
169
+ *
170
+ * @version 2.5.7
171
+ * @since 2.5.7
172
+ */
173
+ function get_orders_default_columns_in_order() {
174
+ $columns = array(
175
+ 'cb',
176
+ 'order_status',
177
+ 'order_title',
178
+ 'order_items',
179
+ 'billing_address',
180
+ 'shipping_address',
181
+ 'customer_message',
182
+ 'order_notes',
183
+ 'order_date',
184
+ 'order_total',
185
+ 'order_actions',
186
+ );
187
+ return implode( PHP_EOL, $columns );
188
+ }
189
+
190
+ /**
191
+ * add_shop_order_multiple_statuses_not_completed_link.
192
+ *
193
+ * @version 3.9.0
194
+ * @since 2.5.7
195
+ */
196
+ function add_shop_order_multiple_statuses_not_completed_link( $views ) {
197
+ global $wp_query;
198
+ if ( ! wcj_current_user_can( 'edit_others_pages' ) ) {
199
+ return $views;
200
+ }
201
+ $all_not_completed_statuses = wc_get_order_statuses();
202
+ unset( $all_not_completed_statuses['wc-completed'] );
203
+ $all_not_completed_statuses = array_keys( $all_not_completed_statuses );
204
+ $all_not_completed_statuses_param = urlencode( implode( ',', $all_not_completed_statuses ) );
205
+ $class = ( isset( $wp_query->query['post_status'] ) && is_array( $wp_query->query['post_status'] ) && $all_not_completed_statuses === $wp_query->query['post_status'] ) ? 'current' : '';
206
+ $query_string = remove_query_arg( array( 'post_status', 'wcj_admin_filter_statuses' ) );
207
+ $query_string = add_query_arg( 'post_status', $all_not_completed_statuses_param, $query_string );
208
+ $views['wcj_statuses_not_completed'] = '<a href="' . esc_url( $query_string ) . '" class="' . esc_attr( $class ) . '">' . __( 'Not Completed', 'woocommerce-jetpack' ) . '</a>';
209
+ return $views;
210
+ }
211
+
212
+ /**
213
+ * filter_shop_order_multiple_statuses_not_completed_link.
214
+ *
215
+ * @version 3.9.0
216
+ * @since 2.5.7
217
+ */
218
+ function filter_shop_order_multiple_statuses_not_completed_link( $query ) {
219
+ if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/edit.php' ) && isset( $_GET['post_type'] ) && 'shop_order' === $_GET['post_type'] ) {
220
+ if ( wcj_current_user_can( 'edit_others_pages' ) ) {
221
+ if ( isset( $_GET['post_status'] ) && false !== strpos( $_GET['post_status'], ',' ) ) {
222
+ $post_statuses = explode( ',', $_GET['post_status'] );
223
+ $query->query['post_status'] = $post_statuses;
224
+ $query->query_vars['post_status'] = $post_statuses;
225
+ }
226
+ }
227
+ }
228
+ }
229
+
230
+ /**
231
+ * multiple_shop_order_statuses.
232
+ *
233
+ * @version 3.7.0
234
+ * @since 2.5.7
235
+ */
236
+ function multiple_shop_order_statuses( $type ) {
237
+ $checked_post_statuses = isset( $_GET['wcj_admin_filter_statuses'] ) ? $_GET['wcj_admin_filter_statuses'] : array();
238
+ $html = '';
239
+ $html .= ( 'checkboxes' === $type ) ?
240
+ '<span id="wcj_admin_filter_shop_order_statuses">' :
241
+ '<select multiple name="wcj_admin_filter_statuses[]" id="wcj_admin_filter_shop_order_statuses" class="chosen_select">';
242
+ $num_posts = wp_count_posts( 'shop_order', 'readable' );
243
+ foreach ( array_merge( wc_get_order_statuses(), array( 'trash' => __( 'Trash', 'woocommerce-jetpack' ) ) ) as $status_id => $status_title ) {
244
+ $total_number = ( isset( $num_posts->{$status_id} ) ) ? $num_posts->{$status_id} : 0;
245
+ if ( $total_number > 0 ) {
246
+ $html .= ( 'checkboxes' === $type ) ?
247
+ '<input type="checkbox" name="wcj_admin_filter_statuses[]" style="width:16px;height:16px;" value="' . $status_id . '"' .
248
+ checked( in_array( $status_id, $checked_post_statuses ), true, false ) . '>' . $status_title . ' (' . $total_number . ') ' :
249
+ '<option value="' . $status_id . '"' . selected( in_array( $status_id, $checked_post_statuses ), true, false ) . '>' .
250
+ $status_title . ' (' . $total_number . ') ' . '</option>';
251
+ }
252
+ }
253
+ $html .= ( 'checkboxes' === $type ) ?
254
+ '</span>' :
255
+ '</select>';
256
+ return $html;
257
+ }
258
+
259
+ /**
260
+ * add_shop_order_multiple_statuses.
261
+ *
262
+ * @version 2.5.7
263
+ * @since 2.5.7
264
+ */
265
+ function add_shop_order_multiple_statuses( $post_type, $which ) {
266
+ if ( 'shop_order' === $post_type ) {
267
+ echo $this->multiple_shop_order_statuses( get_option( 'wcj_order_admin_list_multiple_status_filter', 'no' ) );
268
+ }
269
+ }
270
+
271
+ /**
272
+ * filter_shop_order_multiple_statuses.
273
+ *
274
+ * @version 3.9.0
275
+ * @since 2.5.7
276
+ */
277
+ function filter_shop_order_multiple_statuses( $query ) {
278
+ if ( false !== strpos( $_SERVER['REQUEST_URI'], '/wp-admin/edit.php' ) && isset( $_GET['post_type'] ) && 'shop_order' === $_GET['post_type'] ) {
279
+ if ( wcj_current_user_can( 'edit_others_pages' ) ) {
280
+ if ( isset( $_GET['wcj_admin_filter_statuses'] ) ) {
281
+ $post_statuses = $_GET['wcj_admin_filter_statuses'];
282
+ $query->query['post_status'] = $post_statuses;
283
+ $query->query_vars['post_status'] = $post_statuses;
284
+ }
285
+ }
286
+ }
287
+ }
288
+
289
+ /**
290
+ * Filter the orders in admin based on options.
291
+ *
292
+ * @version 2.8.0
293
+ * @access public
294
+ * @param mixed $query
295
+ * @return void
296
+ */
297
+ function parse_query( $query ) {
298
+ global $typenow, $wp_query;
299
+ if ( $typenow != 'shop_order' ) {
300
+ return;
301
+ }
302
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) && isset( $_GET['country'] ) && 'all' != $_GET['country'] ) {
303
+ $query->query_vars['meta_query'][] = array(
304
+ 'key' => '_billing_country',
305
+ 'value' => $_GET['country'],
306
+ );
307
+ }
308
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) && isset( $_GET['currency'] ) && 'all' != $_GET['currency'] ) {
309
+ $query->query_vars['meta_query'][] = array(
310
+ 'key' => '_order_currency',
311
+ 'value' => $_GET['currency'],
312
+ );
313
+ }
314
+ }
315
+
316
+ /**
317
+ * Filters for post types.
318
+ *
319
+ * @version 3.9.0
320
+ */
321
+ function restrict_manage_posts() {
322
+ global $typenow, $wp_query;
323
+ if ( in_array( $typenow, wc_get_order_types( 'order-meta-boxes' ) ) ) {
324
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
325
+ $selected_coutry = isset( $_GET['country'] ) ? $_GET['country'] : 'all';
326
+ $countries = array_merge( array( 'all' => __( 'All countries', 'woocommerce-jetpack' ) ), wcj_get_countries() );
327
+ echo '<select id="country" name="country">';
328
+ foreach ( $countries as $code => $name ) {
329
+ echo '<option value="' . $code . '" ' . selected( $code, $selected_coutry, false ) . '>' . $name . '</option>';
330
+ }
331
+ echo '</select>';
332
+ }
333
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
334
+ $selected_currency = isset( $_GET['currency'] ) ? $_GET['currency'] : 'all';
335
+ $currencies = array_merge( array( 'all' => __( 'All currencies', 'woocommerce-jetpack' ) ), wcj_get_woocommerce_currencies_and_symbols() );
336
+ echo '<select id="currency" name="currency">';
337
+ foreach ( $currencies as $code => $name ) {
338
+ echo '<option value="' . $code . '" ' . selected( $code, $selected_currency, false ) . '>' . $name . '</option>';
339
+ }
340
+ echo '</select>';
341
+ }
342
+ }
343
+ }
344
+
345
+ /**
346
+ * rearange_order_columns.
347
+ *
348
+ * @version 2.5.7
349
+ * @version 2.5.7
350
+ */
351
+ function rearange_order_columns( $columns ) {
352
+ $reordered_columns = get_option( 'wcj_order_admin_list_columns_order', $this->get_orders_default_columns_in_order() );
353
+ $reordered_columns = explode( PHP_EOL, $reordered_columns );
354
+ $reordered_columns_result = array();
355
+ if ( ! empty( $reordered_columns ) ) {
356
+ foreach ( $reordered_columns as $column_id ) {
357
+ $column_id = str_replace( "\n", '', $column_id );
358
+ $column_id = str_replace( "\r", '', $column_id );
359
+ if ( '' != $column_id && isset( $columns[ $column_id ] ) ) {
360
+ $reordered_columns_result[ $column_id ] = $columns[ $column_id ];
361
+ unset( $columns[ $column_id ] );
362
+ }
363
+ }
364
+ }
365
+ return array_merge( $reordered_columns_result, $columns );
366
+ }
367
+
368
+ /**
369
+ * add_order_columns.
370
+ *
371
+ * @version 2.8.0
372
+ */
373
+ function add_order_columns( $columns ) {
374
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
375
+ $columns['country'] = __( 'Billing Country', 'woocommerce-jetpack' );
376
+ }
377
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
378
+ $columns['currency'] = __( 'Currency Code', 'woocommerce-jetpack' );
379
+ }
380
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
381
+ for ( $i = 1; $i <= $total_number; $i++ ) {
382
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
383
+ $columns[ 'wcj_orders_custom_column_' . $i ] = get_option( 'wcj_orders_list_custom_columns_label_' . $i, '' );
384
+ }
385
+ }
386
+ return $columns;
387
+ }
388
+
389
+ /**
390
+ * Output custom columns for orders
391
+ *
392
+ * @version 2.8.0
393
+ * @param string $column
394
+ */
395
+ function render_order_column( $column ) {
396
+ if ( 'country' === $column && 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
397
+ $country_code = do_shortcode( '[wcj_order_checkout_field field_id="billing_country"]' );
398
+ echo ( 2 == strlen( $country_code ) )
399
+ ? wcj_get_country_flag_by_code( $country_code ) . ' ' . wcj_get_country_name_by_code( $country_code )
400
+ : wcj_get_country_name_by_code( $country_code );
401
+ } elseif ( 'currency' === $column && 'yes' === get_option( 'wcj_orders_list_custom_columns_currency', 'no' ) ) {
402
+ echo do_shortcode( '[wcj_order_currency]' );
403
+ } else {
404
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
405
+ for ( $i = 1; $i <= $total_number; $i++ ) {
406
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
407
+ if ( 'wcj_orders_custom_column_' . $i === $column ) {
408
+ echo do_shortcode( get_option( 'wcj_orders_list_custom_columns_value_' . $i, '' ) );
409
+ }
410
+ }
411
+ }
412
+ }
413
+ }
414
+
415
+ }
416
+
417
+ endif;
418
+
419
+ return new WCJ_Admin_Orders_List();
includes/class-wcj-admin-products-list.php CHANGED
@@ -1,127 +1,127 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Admin Products List
4
- *
5
- * @version 3.2.4
6
- * @since 3.2.4
7
- * @author Algoritmika Ltd.
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 3.2.4
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.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-admin-products-list';
28
- parent::__construct();
29
-
30
- if ( $this->is_enabled() ) {
31
- // Admin list - custom columns
32
- if ( 'yes' === get_option( 'wcj_products_admin_list_custom_columns_enabled', 'no' ) ) {
33
- add_filter( 'manage_edit-product_columns', array( $this, 'add_product_columns' ), PHP_INT_MAX );
34
- add_action( 'manage_product_posts_custom_column', array( $this, 'render_product_column' ), PHP_INT_MAX );
35
- }
36
-
37
- // Admin list - columns order
38
- if ( 'yes' === get_option( 'wcj_products_admin_list_columns_order_enabled', 'no' ) ) {
39
- add_filter( 'manage_edit-product_columns', array( $this, 'rearange_product_columns' ), PHP_INT_MAX );
40
- }
41
- }
42
- }
43
-
44
- /**
45
- * rearange_product_columns.
46
- *
47
- * @version 2.9.0
48
- * @since 2.9.0
49
- */
50
- function rearange_product_columns( $columns ) {
51
- $reordered_columns = get_option( 'wcj_products_admin_list_columns_order', $this->get_products_default_columns_in_order() );
52
- $reordered_columns = explode( PHP_EOL, $reordered_columns );
53
- $reordered_columns_result = array();
54
- if ( ! empty( $reordered_columns ) ) {
55
- foreach ( $reordered_columns as $column_id ) {
56
- $column_id = str_replace( "\n", '', $column_id );
57
- $column_id = str_replace( "\r", '', $column_id );
58
- if ( '' != $column_id && isset( $columns[ $column_id ] ) ) {
59
- $reordered_columns_result[ $column_id ] = $columns[ $column_id ];
60
- unset( $columns[ $column_id ] );
61
- }
62
- }
63
- }
64
- return array_merge( $reordered_columns_result, $columns );
65
- }
66
-
67
- /**
68
- * get_products_default_columns_in_order.
69
- *
70
- * @version 2.9.0
71
- * @since 2.9.0
72
- */
73
- function get_products_default_columns_in_order() {
74
- $columns = array(
75
- 'cb',
76
- 'thumb',
77
- 'name',
78
- 'sku',
79
- 'is_in_stock',
80
- 'price',
81
- 'product_cat',
82
- 'product_tag',
83
- 'featured',
84
- 'product_type',
85
- 'date',
86
- );
87
- return implode( PHP_EOL, $columns );
88
- }
89
-
90
- /**
91
- * add_product_columns.
92
- *
93
- * @version 2.9.0
94
- * @since 2.9.0
95
- */
96
- function add_product_columns( $columns ) {
97
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_products_admin_list_custom_columns_total_number', 1 ) );
98
- for ( $i = 1; $i <= $total_number; $i++ ) {
99
- if ( 'yes' === get_option( 'wcj_products_admin_list_custom_columns_enabled_' . $i, 'no' ) ) {
100
- $columns[ 'wcj_products_custom_column_' . $i ] = get_option( 'wcj_products_admin_list_custom_columns_label_' . $i, '' );
101
- }
102
- }
103
- return $columns;
104
- }
105
-
106
- /**
107
- * render_product_column.
108
- *
109
- * @version 2.9.0
110
- * @since 2.9.0
111
- */
112
- function render_product_column( $column ) {
113
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_products_admin_list_custom_columns_total_number', 1 ) );
114
- for ( $i = 1; $i <= $total_number; $i++ ) {
115
- if ( 'yes' === get_option( 'wcj_products_admin_list_custom_columns_enabled_' . $i, 'no' ) ) {
116
- if ( 'wcj_products_custom_column_' . $i === $column ) {
117
- echo do_shortcode( get_option( 'wcj_products_admin_list_custom_columns_value_' . $i, '' ) );
118
- }
119
- }
120
- }
121
- }
122
-
123
- }
124
-
125
- endif;
126
-
127
- return new WCJ_Admin_Products_List();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Admin Products List
4
+ *
5
+ * @version 3.2.4
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 3.2.4
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.', 'woocommerce-jetpack' );
27
+ $this->link_slug = 'woocommerce-admin-products-list';
28
+ parent::__construct();
29
+
30
+ if ( $this->is_enabled() ) {
31
+ // Admin list - custom columns
32
+ if ( 'yes' === get_option( 'wcj_products_admin_list_custom_columns_enabled', 'no' ) ) {
33
+ add_filter( 'manage_edit-product_columns', array( $this, 'add_product_columns' ), PHP_INT_MAX );
34
+ add_action( 'manage_product_posts_custom_column', array( $this, 'render_product_column' ), PHP_INT_MAX );
35
+ }
36
+
37
+ // Admin list - columns order
38
+ if ( 'yes' === get_option( 'wcj_products_admin_list_columns_order_enabled', 'no' ) ) {
39
+ add_filter( 'manage_edit-product_columns', array( $this, 'rearange_product_columns' ), PHP_INT_MAX );
40
+ }
41
+ }
42
+ }
43
+
44
+ /**
45
+ * rearange_product_columns.
46
+ *
47
+ * @version 2.9.0
48
+ * @since 2.9.0
49
+ */
50
+ function rearange_product_columns( $columns ) {
51
+ $reordered_columns = get_option( 'wcj_products_admin_list_columns_order', $this->get_products_default_columns_in_order() );
52
+ $reordered_columns = explode( PHP_EOL, $reordered_columns );
53
+ $reordered_columns_result = array();
54
+ if ( ! empty( $reordered_columns ) ) {
55
+ foreach ( $reordered_columns as $column_id ) {
56
+ $column_id = str_replace( "\n", '', $column_id );
57
+ $column_id = str_replace( "\r", '', $column_id );
58
+ if ( '' != $column_id && isset( $columns[ $column_id ] ) ) {
59
+ $reordered_columns_result[ $column_id ] = $columns[ $column_id ];
60
+ unset( $columns[ $column_id ] );
61
+ }
62
+ }
63
+ }
64
+ return array_merge( $reordered_columns_result, $columns );
65
+ }
66
+
67
+ /**
68
+ * get_products_default_columns_in_order.
69
+ *
70
+ * @version 2.9.0
71
+ * @since 2.9.0
72
+ */
73
+ function get_products_default_columns_in_order() {
74
+ $columns = array(
75
+ 'cb',
76
+ 'thumb',
77
+ 'name',
78
+ 'sku',
79
+ 'is_in_stock',
80
+ 'price',
81
+ 'product_cat',
82
+ 'product_tag',
83
+ 'featured',
84
+ 'product_type',
85
+ 'date',
86
+ );
87
+ return implode( PHP_EOL, $columns );
88
+ }
89
+
90
+ /**
91
+ * add_product_columns.
92
+ *
93
+ * @version 2.9.0
94
+ * @since 2.9.0
95
+ */
96
+ function add_product_columns( $columns ) {
97
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_products_admin_list_custom_columns_total_number', 1 ) );
98
+ for ( $i = 1; $i <= $total_number; $i++ ) {
99
+ if ( 'yes' === get_option( 'wcj_products_admin_list_custom_columns_enabled_' . $i, 'no' ) ) {
100
+ $columns[ 'wcj_products_custom_column_' . $i ] = get_option( 'wcj_products_admin_list_custom_columns_label_' . $i, '' );
101
+ }
102
+ }
103
+ return $columns;
104
+ }
105
+
106
+ /**
107
+ * render_product_column.
108
+ *
109
+ * @version 2.9.0
110
+ * @since 2.9.0
111
+ */
112
+ function render_product_column( $column ) {
113
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_products_admin_list_custom_columns_total_number', 1 ) );
114
+ for ( $i = 1; $i <= $total_number; $i++ ) {
115
+ if ( 'yes' === get_option( 'wcj_products_admin_list_custom_columns_enabled_' . $i, 'no' ) ) {
116
+ if ( 'wcj_products_custom_column_' . $i === $column ) {
117
+ echo do_shortcode( get_option( 'wcj_products_admin_list_custom_columns_value_' . $i, '' ) );
118
+ }
119
+ }
120
+ }
121
+ }
122
+
123
+ }
124
+
125
+ endif;
126
+
127
+ return new WCJ_Admin_Products_List();
includes/class-wcj-admin-tools.php CHANGED
@@ -1,335 +1,335 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Admin Tools
4
- *
5
- * @version 4.9.0
6
- * @author Algoritmika Ltd.
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 4.9.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.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-booster-admin-tools';
27
- parent::__construct();
28
-
29
- $this->add_tools( array(
30
- 'products_atts' => array(
31
- 'title' => __( 'Products Attributes', 'woocommerce-jetpack' ),
32
- 'desc' => __( 'All Products and All Attributes.', 'woocommerce-jetpack' ),
33
- ),
34
- ) );
35
-
36
- if ( $this->is_enabled() ) {
37
- // Order Meta
38
- if ( 'yes' === get_option( 'wcj_admin_tools_show_order_meta_enabled', 'no' ) ) {
39
- add_action( 'add_meta_boxes', array( $this, 'add_order_meta_meta_box' ) );
40
- }
41
- // Product Meta
42
- if ( 'yes' === get_option( 'wcj_admin_tools_show_product_meta_enabled', 'no' ) ) {
43
- add_action( 'add_meta_boxes', array( $this, 'add_product_meta_meta_box' ) );
44
- }
45
- // Variable Product Pricing
46
- if ( 'yes' === get_option( 'wcj_admin_tools_variable_product_pricing_table_enabled', 'no' ) ) {
47
- add_action( 'admin_head', array( $this, 'make_original_variable_product_pricing_readonly' ) );
48
- add_action( 'add_meta_boxes', array( $this, 'maybe_add_variable_product_pricing_meta_box' ) );
49
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
50
- }
51
- // Product revisions
52
- if ( 'yes' === get_option( 'wcj_product_revisions_enabled', 'no' ) ) {
53
- add_filter( 'woocommerce_register_post_type_product', array( $this, 'enable_product_revisions' ) );
54
- }
55
- // Admin Notices
56
- if ( 'yes' === get_option( 'wcj_admin_tools_suppress_connect_notice', 'no' ) ) {
57
- add_filter( 'woocommerce_helper_suppress_connect_notice', '__return_true' );
58
- }
59
- if ( 'yes' === get_option( 'wcj_admin_tools_suppress_admin_notices', 'no' ) ) {
60
- add_filter( 'woocommerce_helper_suppress_admin_notices', '__return_true' );
61
- }
62
- // JSON product search limit
63
- if ( 0 != get_option( 'wcj_product_json_search_limit', 0 ) ) {
64
- add_filter( 'woocommerce_json_search_limit', array( $this, 'set_json_search_limit' ) );
65
- }
66
- // Enable interface by user role
67
- add_filter( 'wcj_can_create_admin_interface', array( $this, 'enable_interface_by_user_roles' ) );
68
- // Shop Manager Editable Roles
69
- add_filter( 'woocommerce_shop_manager_editable_roles', array( $this, 'change_shop_manager_editable_roles' ) );
70
- }
71
- }
72
-
73
- /**
74
- * change_shop_manager_editable_roles.
75
- *
76
- * @see wc_modify_editable_roles()
77
- *
78
- * @version 4.9.0
79
- * @since 4.9.0
80
- *
81
- * @param $roles
82
- *
83
- * @return mixed
84
- */
85
- function change_shop_manager_editable_roles( $roles ) {
86
- remove_filter( 'woocommerce_shop_manager_editable_roles', array( $this, 'change_shop_manager_editable_roles' ) );
87
- $roles = get_option( 'wcj_admin_tools_shop_manager_editable_roles', apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ) );
88
- return $roles;
89
- }
90
-
91
- /**
92
- * enable_interface_by_user_roles.
93
- *
94
- * @version 4.8.0
95
- * @since 4.8.0
96
- *
97
- * @param $allowed
98
- *
99
- * @return bool
100
- */
101
- function enable_interface_by_user_roles( $allowed ) {
102
- if ( empty( $disabled_roles = get_option( 'wcj_admin_tools_enable_interface_by_role', array() ) ) ) {
103
- return $allowed;
104
- }
105
- $current_user_roles = wcj_get_current_user_all_roles();
106
- if (
107
- ! in_array( 'administrator', $current_user_roles ) &&
108
- ! array_intersect( $disabled_roles, $current_user_roles )
109
- ) {
110
- $allowed = false;
111
- }
112
- return $allowed;
113
- }
114
-
115
- /**
116
- * set_json_search_limit.
117
- *
118
- * @version 4.1.0
119
- * @since 4.1.0
120
- */
121
- function set_json_search_limit( $limit ) {
122
- return get_option( 'wcj_product_json_search_limit', 0 );
123
- }
124
-
125
- /**
126
- * enable_product_revisions.
127
- *
128
- * @version 2.4.0
129
- * @since 2.4.0
130
- */
131
- function enable_product_revisions( $args ) {
132
- $args['supports'][] = 'revisions';
133
- return $args;
134
- }
135
-
136
- /**
137
- * make_original_variable_product_pricing_readonly.
138
- *
139
- * @version 3.3.0
140
- * @since 3.3.0
141
- * @todo [fix] this is not really making fields readonly (e.g. field is still editable via keyboard tab button)
142
- */
143
- function make_original_variable_product_pricing_readonly() {
144
- echo '<style>
145
- div.variable_pricing input.wc_input_price {
146
- pointer-events: none;
147
- }
148
- </style>';
149
- }
150
-
151
- /**
152
- * maybe_add_variable_product_pricing_meta_box.
153
- *
154
- * @version 3.3.0
155
- * @since 3.3.0
156
- */
157
- function maybe_add_variable_product_pricing_meta_box() {
158
- if ( ( $_product = wc_get_product() ) && $_product->is_type( 'variable' ) ) {
159
- parent::add_meta_box();
160
- }
161
- }
162
-
163
- /**
164
- * add_product_meta_meta_box.
165
- *
166
- * @version 2.5.8
167
- * @since 2.5.8
168
- */
169
- function add_product_meta_meta_box() {
170
- add_meta_box(
171
- 'wcj-admin-tools-product-meta',
172
- __( 'Product Meta', 'woocommerce-jetpack' ),
173
- array( $this, 'create_meta_meta_box' ),
174
- 'product',
175
- 'normal',
176
- 'low'
177
- );
178
- }
179
-
180
- /**
181
- * add_order_meta_meta_box.
182
- *
183
- * @version 2.5.8
184
- * @since 2.5.8
185
- */
186
- function add_order_meta_meta_box() {
187
- add_meta_box(
188
- 'wcj-admin-tools-order-meta',
189
- __( 'Order Meta', 'woocommerce-jetpack' ),
190
- array( $this, 'create_meta_meta_box' ),
191
- 'shop_order',
192
- 'normal',
193
- 'low'
194
- );
195
- }
196
-
197
- /**
198
- * create_meta_meta_box.
199
- *
200
- * @version 3.2.1
201
- * @since 2.5.8
202
- */
203
- function create_meta_meta_box( $post ) {
204
- $html = '';
205
- $post_id = get_the_ID();
206
- // Meta
207
- $meta = get_post_meta( $post_id );
208
- $table_data = array();
209
- foreach ( $meta as $meta_key => $meta_values ) {
210
- $table_data[] = array( $meta_key, esc_html( print_r( maybe_unserialize( $meta_values[0] ), true ) ) );
211
- }
212
- $html .= wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
213
- // Items Meta (for orders only)
214
- if ( 'shop_order' === $post->post_type ) {
215
- $_order = wc_get_order( $post_id );
216
- $table_data = array();
217
- foreach ( $_order->get_items() as $item_key => $item ) {
218
- foreach ( $item['item_meta'] as $item_meta_key => $item_meta_value ) {
219
- $table_data[] = array( $item_key, $item_meta_key, esc_html( print_r( maybe_unserialize( $item_meta_value ), true ) ) );
220
- }
221
- }
222
- if ( ! empty( $table_data ) ) {
223
- $html .= '<h3>' . __( 'Order Items Meta', 'woocommerce-jetpack' ) . '</h3>';
224
- $table_data = array_merge(
225
- array( array( __( 'Item Key', 'woocommerce-jetpack' ), __( 'Item Meta Key', 'woocommerce-jetpack' ), __( 'Item Meta Value', 'woocommerce-jetpack' ) ) ),
226
- $table_data
227
- );
228
- $html .= wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal' ) );
229
- }
230
- }
231
- // Output
232
- echo $html;
233
- }
234
-
235
- /**
236
- * create_products_atts_tool.
237
- *
238
- * @version 2.3.9
239
- * @since 2.3.9
240
- */
241
- function create_products_atts_tool() {
242
- $html = '';
243
- $html .= $this->get_products_atts();
244
- echo $html;
245
- }
246
-
247
- /*
248
- * get_products_atts.
249
- *
250
- * @version 4.0.0
251
- * @since 2.3.9
252
- * @todo [dev] rewrite; add module link;
253
- */
254
- function get_products_atts() {
255
-
256
- $total_products = 0;
257
-
258
- $products_attributes = array();
259
- $attributes_names = array();
260
- $attributes_names['wcj_title'] = __( 'Product', 'woocommerce-jetpack' );
261
- $attributes_names['wcj_category'] = __( 'Category', 'woocommerce-jetpack' );
262
-
263
- $offset = 0;
264
- $block_size = 96;
265
- while( true ) {
266
-
267
- $args_products = array(
268
- 'post_type' => 'product',
269
- 'post_status' => 'publish',
270
- 'posts_per_page' => $block_size,
271
- 'orderby' => 'title',
272
- 'order' => 'ASC',
273
- 'offset' => $offset,
274
- );
275
- $loop_products = new WP_Query( $args_products );
276
- if ( ! $loop_products->have_posts() ) break;
277
- while ( $loop_products->have_posts() ) : $loop_products->the_post();
278
-
279
- $total_products++;
280
- $product_id = $loop_products->post->ID;
281
- $the_product = wc_get_product( $product_id );
282
-
283
- $products_attributes[ $product_id ]['wcj_title'] = '<a href="' . get_permalink( $product_id ) . '">' . $the_product->get_title() . '</a>';
284
- $products_attributes[ $product_id ]['wcj_category'] = ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_product->get_categories() : wc_get_product_category_list( $product_id ) );
285
-
286
- foreach ( $the_product->get_attributes() as $attribute ) {
287
- $products_attributes[ $product_id ][ $attribute['name'] ] = $the_product->get_attribute( $attribute['name'] );
288
- if ( ! isset( $attributes_names[ $attribute['name'] ] ) ) {
289
- $attributes_names[ $attribute['name'] ] = wc_attribute_label( $attribute['name'] );
290
- }
291
- }
292
-
293
- endwhile;
294
-
295
- $offset += $block_size;
296
-
297
- }
298
-
299
- $table_data = array();
300
- if ( isset( $_GET['wcj_attribute'] ) && '' != $_GET['wcj_attribute'] ) {
301
- $table_data[] = array(
302
- __( 'Product', 'woocommerce-jetpack' ),
303
- __( 'Category', 'woocommerce-jetpack' ),
304
- $_GET['wcj_attribute'],
305
- );
306
- } else {
307
- $header = $attributes_names;
308
- unset( $header['wcj_title'] );
309
- unset( $header['wcj_category'] );
310
- $table_data[] = array_merge( array(
311
- __( 'Product', 'woocommerce-jetpack' ),
312
- __( 'Category', 'woocommerce-jetpack' ),
313
- ), array_keys( $header ) );
314
- }
315
- foreach ( $attributes_names as $attributes_name => $attribute_title ) {
316
-
317
- if ( isset( $_GET['wcj_attribute'] ) && '' != $_GET['wcj_attribute'] ) {
318
- if ( 'wcj_title' != $attributes_name && 'wcj_category' != $attributes_name && $_GET['wcj_attribute'] != $attributes_name ) {
319
- continue;
320
- }
321
- }
322
-
323
- foreach ( $products_attributes as $product_id => $product_attributes ) {
324
- $table_data[ $product_id ][ $attributes_name ] = isset( $product_attributes[ $attributes_name ] ) ? $product_attributes[ $attributes_name ] : '';
325
- }
326
- }
327
-
328
- return '<p>' . __( 'Total Products:', 'woocommerce-jetpack' ) . ' ' . $total_products . '</p>' . wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) );
329
- }
330
-
331
- }
332
-
333
- endif;
334
-
335
- return new WCJ_Admin_Tools();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Admin Tools
4
+ *
5
+ * @version 4.9.0
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 4.9.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.', 'woocommerce-jetpack' );
26
+ $this->link_slug = 'woocommerce-booster-admin-tools';
27
+ parent::__construct();
28
+
29
+ $this->add_tools( array(
30
+ 'products_atts' => array(
31
+ 'title' => __( 'Products Attributes', 'woocommerce-jetpack' ),
32
+ 'desc' => __( 'All Products and All Attributes.', 'woocommerce-jetpack' ),
33
+ ),
34
+ ) );
35
+
36
+ if ( $this->is_enabled() ) {
37
+ // Order Meta
38
+ if ( 'yes' === get_option( 'wcj_admin_tools_show_order_meta_enabled', 'no' ) ) {
39
+ add_action( 'add_meta_boxes', array( $this, 'add_order_meta_meta_box' ) );
40
+ }
41
+ // Product Meta
42
+ if ( 'yes' === get_option( 'wcj_admin_tools_show_product_meta_enabled', 'no' ) ) {
43
+ add_action( 'add_meta_boxes', array( $this, 'add_product_meta_meta_box' ) );
44
+ }
45
+ // Variable Product Pricing
46
+ if ( 'yes' === get_option( 'wcj_admin_tools_variable_product_pricing_table_enabled', 'no' ) ) {
47
+ add_action( 'admin_head', array( $this, 'make_original_variable_product_pricing_readonly' ) );
48
+ add_action( 'add_meta_boxes', array( $this, 'maybe_add_variable_product_pricing_meta_box' ) );
49
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
50
+ }
51
+ // Product revisions
52
+ if ( 'yes' === get_option( 'wcj_product_revisions_enabled', 'no' ) ) {
53
+ add_filter( 'woocommerce_register_post_type_product', array( $this, 'enable_product_revisions' ) );
54
+ }
55
+ // Admin Notices
56
+ if ( 'yes' === get_option( 'wcj_admin_tools_suppress_connect_notice', 'no' ) ) {
57
+ add_filter( 'woocommerce_helper_suppress_connect_notice', '__return_true' );
58
+ }
59
+ if ( 'yes' === get_option( 'wcj_admin_tools_suppress_admin_notices', 'no' ) ) {
60
+ add_filter( 'woocommerce_helper_suppress_admin_notices', '__return_true' );
61
+ }
62
+ // JSON product search limit
63
+ if ( 0 != get_option( 'wcj_product_json_search_limit', 0 ) ) {
64
+ add_filter( 'woocommerce_json_search_limit', array( $this, 'set_json_search_limit' ) );
65
+ }
66
+ // Enable interface by user role
67
+ add_filter( 'wcj_can_create_admin_interface', array( $this, 'enable_interface_by_user_roles' ) );
68
+ // Shop Manager Editable Roles
69
+ add_filter( 'woocommerce_shop_manager_editable_roles', array( $this, 'change_shop_manager_editable_roles' ) );
70
+ }
71
+ }
72
+
73
+ /**
74
+ * change_shop_manager_editable_roles.
75
+ *
76
+ * @see wc_modify_editable_roles()
77
+ *
78
+ * @version 4.9.0
79
+ * @since 4.9.0
80
+ *
81
+ * @param $roles
82
+ *
83
+ * @return mixed
84
+ */
85
+ function change_shop_manager_editable_roles( $roles ) {
86
+ remove_filter( 'woocommerce_shop_manager_editable_roles', array( $this, 'change_shop_manager_editable_roles' ) );
87
+ $roles = get_option( 'wcj_admin_tools_shop_manager_editable_roles', apply_filters( 'woocommerce_shop_manager_editable_roles', array( 'customer' ) ) );
88
+ return $roles;
89
+ }
90
+
91
+ /**
92
+ * enable_interface_by_user_roles.
93
+ *
94
+ * @version 4.8.0
95
+ * @since 4.8.0
96
+ *
97
+ * @param $allowed
98
+ *
99
+ * @return bool
100
+ */
101
+ function enable_interface_by_user_roles( $allowed ) {
102
+ if ( empty( $disabled_roles = get_option( 'wcj_admin_tools_enable_interface_by_role', array() ) ) ) {
103
+ return $allowed;
104
+ }
105
+ $current_user_roles = wcj_get_current_user_all_roles();
106
+ if (
107
+ ! in_array( 'administrator', $current_user_roles ) &&
108
+ ! array_intersect( $disabled_roles, $current_user_roles )
109
+ ) {
110
+ $allowed = false;
111
+ }
112
+ return $allowed;
113
+ }
114
+
115
+ /**
116
+ * set_json_search_limit.
117
+ *
118
+ * @version 4.1.0
119
+ * @since 4.1.0
120
+ */
121
+ function set_json_search_limit( $limit ) {
122
+ return get_option( 'wcj_product_json_search_limit', 0 );
123
+ }
124
+
125
+ /**
126
+ * enable_product_revisions.
127
+ *
128
+ * @version 2.4.0
129
+ * @since 2.4.0
130
+ */
131
+ function enable_product_revisions( $args ) {
132
+ $args['supports'][] = 'revisions';
133
+ return $args;
134
+ }
135
+
136
+ /**
137
+ * make_original_variable_product_pricing_readonly.
138
+ *
139
+ * @version 3.3.0
140
+ * @since 3.3.0
141
+ * @todo [fix] this is not really making fields readonly (e.g. field is still editable via keyboard tab button)
142
+ */
143
+ function make_original_variable_product_pricing_readonly() {
144
+ echo '<style>
145
+ div.variable_pricing input.wc_input_price {
146
+ pointer-events: none;
147
+ }
148
+ </style>';
149
+ }
150
+
151
+ /**
152
+ * maybe_add_variable_product_pricing_meta_box.
153
+ *
154
+ * @version 3.3.0
155
+ * @since 3.3.0
156
+ */
157
+ function maybe_add_variable_product_pricing_meta_box() {
158
+ if ( ( $_product = wc_get_product() ) && $_product->is_type( 'variable' ) ) {
159
+ parent::add_meta_box();
160
+ }
161
+ }
162
+
163
+ /**
164
+ * add_product_meta_meta_box.
165
+ *
166
+ * @version 2.5.8
167
+ * @since 2.5.8
168
+ */
169
+ function add_product_meta_meta_box() {
170
+ add_meta_box(
171
+ 'wcj-admin-tools-product-meta',
172
+ __( 'Product Meta', 'woocommerce-jetpack' ),
173
+ array( $this, 'create_meta_meta_box' ),
174
+ 'product',
175
+ 'normal',
176
+ 'low'
177
+ );
178
+ }
179
+
180
+ /**
181
+ * add_order_meta_meta_box.
182
+ *
183
+ * @version 2.5.8
184
+ * @since 2.5.8
185
+ */
186
+ function add_order_meta_meta_box() {
187
+ add_meta_box(
188
+ 'wcj-admin-tools-order-meta',
189
+ __( 'Order Meta', 'woocommerce-jetpack' ),
190
+ array( $this, 'create_meta_meta_box' ),
191
+ 'shop_order',
192
+ 'normal',
193
+ 'low'
194
+ );
195
+ }
196
+
197
+ /**
198
+ * create_meta_meta_box.
199
+ *
200
+ * @version 3.2.1
201
+ * @since 2.5.8
202
+ */
203
+ function create_meta_meta_box( $post ) {
204
+ $html = '';
205
+ $post_id = get_the_ID();
206
+ // Meta
207
+ $meta = get_post_meta( $post_id );
208
+ $table_data = array();
209
+ foreach ( $meta as $meta_key => $meta_values ) {
210
+ $table_data[] = array( $meta_key, esc_html( print_r( maybe_unserialize( $meta_values[0] ), true ) ) );
211
+ }
212
+ $html .= wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
213
+ // Items Meta (for orders only)
214
+ if ( 'shop_order' === $post->post_type ) {
215
+ $_order = wc_get_order( $post_id );
216
+ $table_data = array();
217
+ foreach ( $_order->get_items() as $item_key => $item ) {
218
+ foreach ( $item['item_meta'] as $item_meta_key => $item_meta_value ) {
219
+ $table_data[] = array( $item_key, $item_meta_key, esc_html( print_r( maybe_unserialize( $item_meta_value ), true ) ) );
220
+ }
221
+ }
222
+ if ( ! empty( $table_data ) ) {
223
+ $html .= '<h3>' . __( 'Order Items Meta', 'woocommerce-jetpack' ) . '</h3>';
224
+ $table_data = array_merge(
225
+ array( array( __( 'Item Key', 'woocommerce-jetpack' ), __( 'Item Meta Key', 'woocommerce-jetpack' ), __( 'Item Meta Value', 'woocommerce-jetpack' ) ) ),
226
+ $table_data
227
+ );
228
+ $html .= wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal' ) );
229
+ }
230
+ }
231
+ // Output
232
+ echo $html;
233
+ }
234
+
235
+ /**
236
+ * create_products_atts_tool.
237
+ *
238
+ * @version 2.3.9
239
+ * @since 2.3.9
240
+ */
241
+ function create_products_atts_tool() {
242
+ $html = '';
243
+ $html .= $this->get_products_atts();
244
+ echo $html;
245
+ }
246
+
247
+ /*
248
+ * get_products_atts.
249
+ *
250
+ * @version 4.0.0
251
+ * @since 2.3.9
252
+ * @todo [dev] rewrite; add module link;
253
+ */
254
+ function get_products_atts() {
255
+
256
+ $total_products = 0;
257
+
258
+ $products_attributes = array();
259
+ $attributes_names = array();
260
+ $attributes_names['wcj_title'] = __( 'Product', 'woocommerce-jetpack' );
261
+ $attributes_names['wcj_category'] = __( 'Category', 'woocommerce-jetpack' );
262
+
263
+ $offset = 0;
264
+ $block_size = 96;
265
+ while( true ) {
266
+
267
+ $args_products = array(
268
+ 'post_type' => 'product',
269
+ 'post_status' => 'publish',
270
+ 'posts_per_page' => $block_size,
271
+ 'orderby' => 'title',
272
+ 'order' => 'ASC',
273
+ 'offset' => $offset,
274
+ );
275
+ $loop_products = new WP_Query( $args_products );
276
+ if ( ! $loop_products->have_posts() ) break;
277
+ while ( $loop_products->have_posts() ) : $loop_products->the_post();
278
+
279
+ $total_products++;
280
+ $product_id = $loop_products->post->ID;
281
+ $the_product = wc_get_product( $product_id );
282
+
283
+ $products_attributes[ $product_id ]['wcj_title'] = '<a href="' . get_permalink( $product_id ) . '">' . $the_product->get_title() . '</a>';
284
+ $products_attributes[ $product_id ]['wcj_category'] = ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_product->get_categories() : wc_get_product_category_list( $product_id ) );
285
+
286
+ foreach ( $the_product->get_attributes() as $attribute ) {
287
+ $products_attributes[ $product_id ][ $attribute['name'] ] = $the_product->get_attribute( $attribute['name'] );
288
+ if ( ! isset( $attributes_names[ $attribute['name'] ] ) ) {
289
+ $attributes_names[ $attribute['name'] ] = wc_attribute_label( $attribute['name'] );
290
+ }
291
+ }
292
+
293
+ endwhile;
294
+
295
+ $offset += $block_size;
296
+
297
+ }
298
+
299
+ $table_data = array();
300
+ if ( isset( $_GET['wcj_attribute'] ) && '' != $_GET['wcj_attribute'] ) {
301
+ $table_data[] = array(
302
+ __( 'Product', 'woocommerce-jetpack' ),
303
+ __( 'Category', 'woocommerce-jetpack' ),
304
+ $_GET['wcj_attribute'],
305
+ );
306
+ } else {
307
+ $header = $attributes_names;
308
+ unset( $header['wcj_title'] );
309
+ unset( $header['wcj_category'] );
310
+ $table_data[] = array_merge( array(
311
+ __( 'Product', 'woocommerce-jetpack' ),
312
+ __( 'Category', 'woocommerce-jetpack' ),
313
+ ), array_keys( $header ) );
314
+ }
315
+ foreach ( $attributes_names as $attributes_name => $attribute_title ) {
316
+
317
+ if ( isset( $_GET['wcj_attribute'] ) && '' != $_GET['wcj_attribute'] ) {
318
+ if ( 'wcj_title' != $attributes_name && 'wcj_category' != $attributes_name && $_GET['wcj_attribute'] != $attributes_name ) {
319
+ continue;
320
+ }
321
+ }
322
+
323
+ foreach ( $products_attributes as $product_id => $product_attributes ) {
324
+ $table_data[ $product_id ][ $attributes_name ] = isset( $product_attributes[ $attributes_name ] ) ? $product_attributes[ $attributes_name ] : '';
325
+ }
326
+ }
327
+
328
+ return '<p>' . __( 'Total Products:', 'woocommerce-jetpack' ) . ' ' . $total_products . '</p>' . wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) );
329
+ }
330
+
331
+ }
332
+
333
+ endif;
334
+
335
+ return new WCJ_Admin_Tools();
includes/class-wcj-breadcrumbs.php CHANGED
@@ -1,92 +1,92 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Breadcrumbs
4
- *
5
- * @version 3.2.2
6
- * @since 2.9.0
7
- * @author Algoritmika Ltd.
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 2.9.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.', 'woocommerce-jetpack' );
30
- $this->link_slug = 'woocommerce-breadcrumbs';
31
- parent::__construct();
32
-
33
- if ( $this->is_enabled() ) {
34
- // Hide Breadcrumbs
35
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_breadcrumbs_hide', 'no' ) ) ) {
36
- add_filter( 'woocommerce_get_breadcrumb', '__return_false', PHP_INT_MAX );
37
- add_action( 'wp_head', array( $this, 'hide_breadcrumbs_with_css' ) );
38
- add_action( 'wp_loaded', array( $this, 'hide_breadcrumbs_by_removing_action' ), PHP_INT_MAX );
39
- }
40
- // Home URL
41
- if ( 'yes' === get_option( 'wcj_breadcrumbs_change_home_url_enabled', 'no' ) ) {
42
- add_filter( 'woocommerce_breadcrumb_home_url', array( $this, 'change_home_url' ), PHP_INT_MAX );
43
- }
44
- }
45
- }
46
-
47
- /**
48
- * change_home_url.
49
- *
50
- * @version 2.9.0
51
- * @since 2.9.0
52
- */
53
- function change_home_url( $_url ) {
54
- return get_option( 'wcj_breadcrumbs_home_url', home_url() );
55
- }
56
-
57
- /**
58
- * hide_breadcrumbs_with_css.
59
- *
60
- * @version 3.2.2
61
- * @since 2.9.0
62
- * @todo (maybe) option to add custom identifiers
63
- * @todo (maybe) add more identifiers
64
- */
65
- function hide_breadcrumbs_with_css() {
66
- $identifiers = array(
67
- '.woocommerce-breadcrumb',
68
- '.woo-breadcrumbs',
69
- '.breadcrumbs',
70
- '.breadcrumb',
71
- '#breadcrumbs',
72
- '.breadcrumbs-wrapper',
73
- );
74
- echo '<style>' . implode( ', ', $identifiers ) . ' { display: none !important; }' . '</style>';
75
- }
76
-
77
- /**
78
- * hide_breadcrumbs_by_removing_action.
79
- *
80
- * @version 2.9.0
81
- * @since 2.9.0
82
- * @see `add_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0 );`
83
- */
84
- function hide_breadcrumbs_by_removing_action() {
85
- remove_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20 );
86
- }
87
-
88
- }
89
-
90
- endif;
91
-
92
- return new WCJ_Breadcrumbs();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Breadcrumbs
4
+ *
5
+ * @version 3.2.2
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 2.9.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.', 'woocommerce-jetpack' );
30
+ $this->link_slug = 'woocommerce-breadcrumbs';
31
+ parent::__construct();
32
+
33
+ if ( $this->is_enabled() ) {
34
+ // Hide Breadcrumbs
35
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_breadcrumbs_hide', 'no' ) ) ) {
36
+ add_filter( 'woocommerce_get_breadcrumb', '__return_false', PHP_INT_MAX );
37
+ add_action( 'wp_head', array( $this, 'hide_breadcrumbs_with_css' ) );
38
+ add_action( 'wp_loaded', array( $this, 'hide_breadcrumbs_by_removing_action' ), PHP_INT_MAX );
39
+ }
40
+ // Home URL
41
+ if ( 'yes' === get_option( 'wcj_breadcrumbs_change_home_url_enabled', 'no' ) ) {
42
+ add_filter( 'woocommerce_breadcrumb_home_url', array( $this, 'change_home_url' ), PHP_INT_MAX );
43
+ }
44
+ }
45
+ }
46
+
47
+ /**
48
+ * change_home_url.
49
+ *
50
+ * @version 2.9.0
51
+ * @since 2.9.0
52
+ */
53
+ function change_home_url( $_url ) {
54
+ return get_option( 'wcj_breadcrumbs_home_url', home_url() );
55
+ }
56
+
57
+ /**
58
+ * hide_breadcrumbs_with_css.
59
+ *
60
+ * @version 3.2.2
61
+ * @since 2.9.0
62
+ * @todo (maybe) option to add custom identifiers
63
+ * @todo (maybe) add more identifiers
64
+ */
65
+ function hide_breadcrumbs_with_css() {
66
+ $identifiers = array(
67
+ '.woocommerce-breadcrumb',
68
+ '.woo-breadcrumbs',
69
+ '.breadcrumbs',
70
+ '.breadcrumb',
71
+ '#breadcrumbs',
72
+ '.breadcrumbs-wrapper',
73
+ );
74
+ echo '<style>' . implode( ', ', $identifiers ) . ' { display: none !important; }' . '</style>';
75
+ }
76
+
77
+ /**
78
+ * hide_breadcrumbs_by_removing_action.
79
+ *
80
+ * @version 2.9.0
81
+ * @since 2.9.0
82
+ * @see `add_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20, 0 );`
83
+ */
84
+ function hide_breadcrumbs_by_removing_action() {
85
+ remove_action( 'woocommerce_before_main_content', 'woocommerce_breadcrumb', 20 );
86
+ }
87
+
88
+ }
89
+
90
+ endif;
91
+
92
+ return new WCJ_Breadcrumbs();
includes/class-wcj-call-for-price.php CHANGED
@@ -1,173 +1,173 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Call for Price
4
- *
5
- * @version 3.2.4
6
- * @author Algoritmika Ltd.
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 3.2.4
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.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-call-for-price';
28
- parent::__construct();
29
-
30
- if ( $this->is_enabled() ) {
31
- add_filter( 'woocommerce_get_variation_prices_hash', array( $this, 'get_variation_prices_hash' ), PHP_INT_MAX, 3 );
32
- add_action( 'init', array( $this, 'add_empty_price_hooks' ), PHP_INT_MAX );
33
- add_filter( 'woocommerce_sale_flash', array( $this, 'hide_sales_flash' ), PHP_INT_MAX, 3 );
34
- add_action( 'admin_head', array( $this, 'hide_variation_price_required_placeholder' ), PHP_INT_MAX );
35
- add_filter( 'woocommerce_variation_is_visible', array( $this, 'make_variation_visible_with_empty_price' ), PHP_INT_MAX, 4 );
36
- add_action( 'wp_head', array( $this, 'hide_disabled_variation_add_to_cart_button' ) );
37
- if ( 'yes' === get_option( 'wcj_call_for_price_make_all_empty', 'no' ) ) {
38
- add_filter( WCJ_PRODUCT_GET_PRICE_FILTER, array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
39
- add_filter( 'woocommerce_variation_prices_price', array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
40
- if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
41
- add_filter( 'woocommerce_product_variation_get_price', array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
42
- }
43
- }
44
- }
45
- }
46
-
47
- /**
48
- * get_variation_prices_hash.
49
- *
50
- * @version 3.2.4
51
- * @since 3.2.4
52
- * @todo not sure if this is really needed
53
- */
54
- function get_variation_prices_hash( $price_hash, $_product, $display ) {
55
- $price_hash['wcj_call_for_price'] = array(
56
- get_option( 'wcj_call_for_price_make_all_empty', 'no' ),
57
- );
58
- return $price_hash;
59
- }
60
-
61
- /**
62
- * make_variation_visible_with_empty_price.
63
- *
64
- * @version 3.2.4
65
- * @since 3.2.4
66
- * @return bool
67
- */
68
- function make_variation_visible_with_empty_price( $visible, $_variation_id, $_id, $_product ) {
69
- if ( '' === $_product->get_price() ) {
70
- $visible = true;
71
- // Published == enabled checkbox
72
- if ( get_post_status( $_variation_id ) != 'publish' ) {
73
- $visible = false;
74
- }
75
- }
76
- return $visible;
77
- }
78
-
79
- /**
80
- * hide_disabled_variation_add_to_cart_button.
81
- *
82
- * @version 3.2.4
83
- * @since 3.2.4
84
- */
85
- function hide_disabled_variation_add_to_cart_button() {
86
- echo '<style>div.woocommerce-variation-add-to-cart-disabled { display: none ! important; }</style>';
87
- }
88
-
89
- /**
90
- * hide_variation_price_required_placeholder.
91
- *
92
- * @version 3.2.4
93
- * @since 3.2.4
94
- */
95
- function hide_variation_price_required_placeholder() {
96
- echo '<style>
97
- div.variable_pricing input.wc_input_price::-webkit-input-placeholder { /* WebKit browsers */
98
- color: transparent;
99
- }
100
- div.variable_pricing input.wc_input_price:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
101
- color: transparent;
102
- }
103
- div.variable_pricing input.wc_input_price::-moz-placeholder { /* Mozilla Firefox 19+ */
104
- color: transparent;
105
- }
106
- div.variable_pricing input.wc_input_price:-ms-input-placeholder { /* Internet Explorer 10+ */
107
- color: transparent;
108
- }
109
- </style>';
110
- }
111
-
112
- /**
113
- * make_empty_price.
114
- *
115
- * @version 3.2.4
116
- * @since 2.5.7
117
- */
118
- function make_empty_price( $price, $_product ) {
119
- return '';
120
- }
121
-
122
- /**
123
- * add_empty_price_hooks.
124
- *
125
- * @version 3.2.4
126
- */
127
- function add_empty_price_hooks() {
128
- add_filter( 'woocommerce_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
129
- add_filter( 'woocommerce_variable_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
130
- add_filter( 'woocommerce_grouped_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
131
- add_filter( 'woocommerce_variation_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 ); // Only in < WC3
132
- }
133
-
134
- /**
135
- * Hide "sales" icon for empty price products.
136
- *
137
- * @version 3.2.4
138
- * @todo recheck if we really need this
139
- */
140
- function hide_sales_flash( $onsale_html, $post, $product ) {
141
- if ( 'yes' === get_option( 'wcj_call_for_price_hide_sale_sign', 'yes' ) && '' === $product->get_price() ) {
142
- return '';
143
- }
144
- return $onsale_html;
145
- }
146
-
147
- /**
148
- * On empty price filter - return the label.
149
- *
150
- * @version 3.2.4
151
- * @todo `is_page()`
152
- */
153
- function on_empty_price( $price, $_product ) {
154
- if ( '' !== get_option( 'wcj_call_for_price_text_variation' ) && $_product->is_type( 'variation' ) ) {
155
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text_variation' ) ) );
156
- } elseif ( '' !== get_option( 'wcj_call_for_price_text' ) && is_single( get_the_ID() ) ) {
157
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text' ) ) );
158
- } elseif ( '' !== get_option( 'wcj_call_for_price_text_on_related' ) && is_single() && ! is_single( get_the_ID() ) ) {
159
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text_on_related' ) ) );
160
- } elseif ( '' !== get_option( 'wcj_call_for_price_text_on_archive' ) && is_archive() ) {
161
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text_on_archive' ) ) );
162
- } elseif ( '' !== get_option( 'wcj_call_for_price_text_on_home' ) && is_front_page() ) {
163
- return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text_on_home' ) ) );
164
- } else {
165
- return $price;
166
- }
167
- }
168
-
169
- }
170
-
171
- endif;
172
-
173
- return new WCJ_Call_For_Price();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Call for Price
4
+ *
5
+ * @version 3.2.4
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 3.2.4
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.', 'woocommerce-jetpack' );
27
+ $this->link_slug = 'woocommerce-call-for-price';
28
+ parent::__construct();
29
+
30
+ if ( $this->is_enabled() ) {
31
+ add_filter( 'woocommerce_get_variation_prices_hash', array( $this, 'get_variation_prices_hash' ), PHP_INT_MAX, 3 );
32
+ add_action( 'init', array( $this, 'add_empty_price_hooks' ), PHP_INT_MAX );
33
+ add_filter( 'woocommerce_sale_flash', array( $this, 'hide_sales_flash' ), PHP_INT_MAX, 3 );
34
+ add_action( 'admin_head', array( $this, 'hide_variation_price_required_placeholder' ), PHP_INT_MAX );
35
+ add_filter( 'woocommerce_variation_is_visible', array( $this, 'make_variation_visible_with_empty_price' ), PHP_INT_MAX, 4 );
36
+ add_action( 'wp_head', array( $this, 'hide_disabled_variation_add_to_cart_button' ) );
37
+ if ( 'yes' === get_option( 'wcj_call_for_price_make_all_empty', 'no' ) ) {
38
+ add_filter( WCJ_PRODUCT_GET_PRICE_FILTER, array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
39
+ add_filter( 'woocommerce_variation_prices_price', array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
40
+ if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
41
+ add_filter( 'woocommerce_product_variation_get_price', array( $this, 'make_empty_price' ), PHP_INT_MAX, 2 );
42
+ }
43
+ }
44
+ }
45
+ }
46
+
47
+ /**
48
+ * get_variation_prices_hash.
49
+ *
50
+ * @version 3.2.4
51
+ * @since 3.2.4
52
+ * @todo not sure if this is really needed
53
+ */
54
+ function get_variation_prices_hash( $price_hash, $_product, $display ) {
55
+ $price_hash['wcj_call_for_price'] = array(
56
+ get_option( 'wcj_call_for_price_make_all_empty', 'no' ),
57
+ );
58
+ return $price_hash;
59
+ }
60
+
61
+ /**
62
+ * make_variation_visible_with_empty_price.
63
+ *
64
+ * @version 3.2.4
65
+ * @since 3.2.4
66
+ * @return bool
67
+ */
68
+ function make_variation_visible_with_empty_price( $visible, $_variation_id, $_id, $_product ) {
69
+ if ( '' === $_product->get_price() ) {
70
+ $visible = true;
71
+ // Published == enabled checkbox
72
+ if ( get_post_status( $_variation_id ) != 'publish' ) {
73
+ $visible = false;
74
+ }
75
+ }
76
+ return $visible;
77
+ }
78
+
79
+ /**
80
+ * hide_disabled_variation_add_to_cart_button.
81
+ *
82
+ * @version 3.2.4
83
+ * @since 3.2.4
84
+ */
85
+ function hide_disabled_variation_add_to_cart_button() {
86
+ echo '<style>div.woocommerce-variation-add-to-cart-disabled { display: none ! important; }</style>';
87
+ }
88
+
89
+ /**
90
+ * hide_variation_price_required_placeholder.
91
+ *
92
+ * @version 3.2.4
93
+ * @since 3.2.4
94
+ */
95
+ function hide_variation_price_required_placeholder() {
96
+ echo '<style>
97
+ div.variable_pricing input.wc_input_price::-webkit-input-placeholder { /* WebKit browsers */
98
+ color: transparent;
99
+ }
100
+ div.variable_pricing input.wc_input_price:-moz-placeholder { /* Mozilla Firefox 4 to 18 */
101
+ color: transparent;
102
+ }
103
+ div.variable_pricing input.wc_input_price::-moz-placeholder { /* Mozilla Firefox 19+ */
104
+ color: transparent;
105
+ }
106
+ div.variable_pricing input.wc_input_price:-ms-input-placeholder { /* Internet Explorer 10+ */
107
+ color: transparent;
108
+ }
109
+ </style>';
110
+ }
111
+
112
+ /**
113
+ * make_empty_price.
114
+ *
115
+ * @version 3.2.4
116
+ * @since 2.5.7
117
+ */
118
+ function make_empty_price( $price, $_product ) {
119
+ return '';
120
+ }
121
+
122
+ /**
123
+ * add_empty_price_hooks.
124
+ *
125
+ * @version 3.2.4
126
+ */
127
+ function add_empty_price_hooks() {
128
+ add_filter( 'woocommerce_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
129
+ add_filter( 'woocommerce_variable_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
130
+ add_filter( 'woocommerce_grouped_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 );
131
+ add_filter( 'woocommerce_variation_empty_price_html', array( $this, 'on_empty_price' ), PHP_INT_MAX, 2 ); // Only in < WC3
132
+ }
133
+
134
+ /**
135
+ * Hide "sales" icon for empty price products.
136
+ *
137
+ * @version 3.2.4
138
+ * @todo recheck if we really need this
139
+ */
140
+ function hide_sales_flash( $onsale_html, $post, $product ) {
141
+ if ( 'yes' === get_option( 'wcj_call_for_price_hide_sale_sign', 'yes' ) && '' === $product->get_price() ) {
142
+ return '';
143
+ }
144
+ return $onsale_html;
145
+ }
146
+
147
+ /**
148
+ * On empty price filter - return the label.
149
+ *
150
+ * @version 3.2.4
151
+ * @todo `is_page()`
152
+ */
153
+ function on_empty_price( $price, $_product ) {
154
+ if ( '' !== get_option( 'wcj_call_for_price_text_variation' ) && $_product->is_type( 'variation' ) ) {
155
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text_variation' ) ) );
156
+ } elseif ( '' !== get_option( 'wcj_call_for_price_text' ) && is_single( get_the_ID() ) ) {
157
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text' ) ) );
158
+ } elseif ( '' !== get_option( 'wcj_call_for_price_text_on_related' ) && is_single() && ! is_single( get_the_ID() ) ) {
159
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text_on_related' ) ) );
160
+ } elseif ( '' !== get_option( 'wcj_call_for_price_text_on_archive' ) && is_archive() ) {
161
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text_on_archive' ) ) );
162
+ } elseif ( '' !== get_option( 'wcj_call_for_price_text_on_home' ) && is_front_page() ) {
163
+ return do_shortcode( apply_filters( 'booster_option', '<strong>Call for price</strong>', get_option( 'wcj_call_for_price_text_on_home' ) ) );
164
+ } else {
165
+ return $price;
166
+ }
167
+ }
168
+
169
+ }
170
+
171
+ endif;
172
+
173
+ return new WCJ_Call_For_Price();
includes/class-wcj-cart-customization.php CHANGED
@@ -1,118 +1,118 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Cart Customization
4
- *
5
- * @version 3.1.0
6
- * @since 2.7.0
7
- * @author Algoritmika Ltd.
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' === 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' === 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' === get_option( 'wcj_cart_customization_return_to_shop_button_enabled', 'no' ) ) {
41
- if ( 'js' === 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' === 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 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() ? 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' => 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();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Cart Customization
4
+ *
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' === 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' === 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' === get_option( 'wcj_cart_customization_return_to_shop_button_enabled', 'no' ) ) {
41
+ if ( 'js' === 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' === 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 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() ? 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' => 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();
includes/class-wcj-cart.php CHANGED
@@ -1,87 +1,87 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Cart Custom Info
4
- *
5
- * @version 3.7.0
6
- * @author Algoritmika Ltd.
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 2.8.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.', 'woocommerce-jetpack' );
25
- $this->link_slug = 'woocommerce-cart-custom-info';
26
- parent::__construct();
27
-
28
- if ( $this->is_enabled() ) {
29
- // Cart items table custom info
30
- add_filter( 'woocommerce_cart_item_name', array( $this, 'add_custom_info_to_cart_item_name' ), PHP_INT_MAX, 3 );
31
- // Cart custom info
32
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_cart_custom_info_total_number', 1 ) );
33
- for ( $i = 1; $i <= $total_number; $i++) {
34
- add_action(
35
- get_option( 'wcj_cart_custom_info_hook_' . $i, 'woocommerce_after_cart_totals' ),
36
- array( $this, 'add_cart_custom_info' ),
37
- get_option( 'wcj_cart_custom_info_priority_' . $i, 10 )
38
- );
39
- }
40
- }
41
- }
42
-
43
- /**
44
- * add_custom_info_to_cart_item_name.
45
- *
46
- * @version 3.7.0
47
- * @since 2.3.9
48
- * @todo (maybe) `wc_setup_product_data( $post );`
49
- */
50
- function add_custom_info_to_cart_item_name( $product_title, $cart_item, $cart_item_key ) {
51
- $custom_content = get_option( 'wcj_cart_custom_info_item' );
52
- if ( '' != $custom_content ) {
53
- global $post;
54
- $product_id = ( ! empty( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : $cart_item['product_id'] );
55
- $post = get_post( $product_id );
56
- setup_postdata( $post );
57
- $product_title .= do_shortcode( $custom_content );
58
- wp_reset_postdata();
59
- }
60
- return $product_title;
61
- }
62
-
63
- /**
64
- * add_cart_custom_info.
65
- *
66
- * @version 2.4.6
67
- */
68
- function add_cart_custom_info() {
69
- $current_filter = current_filter();
70
- $current_filter_priority = wcj_current_filter_priority();
71
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_cart_custom_info_total_number', 1 ) );
72
- for ( $i = 1; $i <= $total_number; $i++ ) {
73
- if (
74
- '' != get_option( 'wcj_cart_custom_info_content_' . $i ) &&
75
- $current_filter === get_option( 'wcj_cart_custom_info_hook_' . $i, 'woocommerce_after_cart_totals' ) &&
76
- $current_filter_priority == get_option( 'wcj_cart_custom_info_priority_' . $i, 10 )
77
- ) {
78
- echo do_shortcode( get_option( 'wcj_cart_custom_info_content_' . $i ) );
79
- }
80
- }
81
- }
82
-
83
- }
84
-
85
- endif;
86
-
87
- return new WCJ_Cart();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Cart Custom Info
4
+ *
5
+ * @version 3.7.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 2.8.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.', 'woocommerce-jetpack' );
25
+ $this->link_slug = 'woocommerce-cart-custom-info';
26
+ parent::__construct();
27
+
28
+ if ( $this->is_enabled() ) {
29
+ // Cart items table custom info
30
+ add_filter( 'woocommerce_cart_item_name', array( $this, 'add_custom_info_to_cart_item_name' ), PHP_INT_MAX, 3 );
31
+ // Cart custom info
32
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_cart_custom_info_total_number', 1 ) );
33
+ for ( $i = 1; $i <= $total_number; $i++) {
34
+ add_action(
35
+ get_option( 'wcj_cart_custom_info_hook_' . $i, 'woocommerce_after_cart_totals' ),
36
+ array( $this, 'add_cart_custom_info' ),
37
+ get_option( 'wcj_cart_custom_info_priority_' . $i, 10 )
38
+ );
39
+ }
40
+ }
41
+ }
42
+
43
+ /**
44
+ * add_custom_info_to_cart_item_name.
45
+ *
46
+ * @version 3.7.0
47
+ * @since 2.3.9
48
+ * @todo (maybe) `wc_setup_product_data( $post );`
49
+ */
50
+ function add_custom_info_to_cart_item_name( $product_title, $cart_item, $cart_item_key ) {
51
+ $custom_content = get_option( 'wcj_cart_custom_info_item' );
52
+ if ( '' != $custom_content ) {
53
+ global $post;
54
+ $product_id = ( ! empty( $cart_item['variation_id'] ) ? $cart_item['variation_id'] : $cart_item['product_id'] );
55
+ $post = get_post( $product_id );
56
+ setup_postdata( $post );
57
+ $product_title .= do_shortcode( $custom_content );
58
+ wp_reset_postdata();
59
+ }
60
+ return $product_title;
61
+ }
62
+
63
+ /**
64
+ * add_cart_custom_info.
65
+ *
66
+ * @version 2.4.6
67
+ */
68
+ function add_cart_custom_info() {
69
+ $current_filter = current_filter();
70
+ $current_filter_priority = wcj_current_filter_priority();
71
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_cart_custom_info_total_number', 1 ) );
72
+ for ( $i = 1; $i <= $total_number; $i++ ) {
73
+ if (
74
+ '' != get_option( 'wcj_cart_custom_info_content_' . $i ) &&
75
+ $current_filter === get_option( 'wcj_cart_custom_info_hook_' . $i, 'woocommerce_after_cart_totals' ) &&
76
+ $current_filter_priority == get_option( 'wcj_cart_custom_info_priority_' . $i, 10 )
77
+ ) {
78
+ echo do_shortcode( get_option( 'wcj_cart_custom_info_content_' . $i ) );
79
+ }
80
+ }
81
+ }
82
+
83
+ }
84
+
85
+ endif;
86
+
87
+ return new WCJ_Cart();
includes/class-wcj-checkout-core-fields.php CHANGED
@@ -1,265 +1,265 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Checkout Core Fields
4
- *
5
- * @version 4.9.0
6
- * @author Algoritmika Ltd.
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 3.6.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 etc.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-checkout-core-fields';
28
- parent::__construct();
29
-
30
- $this->woocommerce_core_checkout_fields = array(
31
- 'billing_country',
32
- 'billing_first_name',
33
- 'billing_last_name',
34
- 'billing_company',
35
- 'billing_address_1',
36
- 'billing_address_2',
37
- 'billing_city',
38
- 'billing_state',
39
- 'billing_postcode',
40
- 'billing_email',
41
- 'billing_phone',
42
- 'shipping_country',
43
- 'shipping_first_name',
44
- 'shipping_last_name',
45
- 'shipping_company',
46
- 'shipping_address_1',
47
- 'shipping_address_2',
48
- 'shipping_city',
49
- 'shipping_state',
50
- 'shipping_postcode',
51
- 'account_username',
52
- 'account_password',
53
- 'account_password-2',
54
- 'order_comments',
55
- );
56
-
57
- if ( $this->is_enabled() ) {
58
- add_filter( 'woocommerce_checkout_fields' , array( $this, 'custom_override_checkout_fields' ), PHP_INT_MAX );
59
- if ( 'disable' != ( $this->country_locale_override = get_option( 'wcj_checkout_core_fields_override_country_locale_fields', 'billing' ) ) ) {
60
- add_filter( 'woocommerce_get_country_locale', array( $this, 'custom_override_country_locale_fields' ), PHP_INT_MAX );
61
- }
62
- if ( 'disable' != ( $this->default_address_override = get_option( 'wcj_checkout_core_fields_override_default_address_fields', 'billing' ) ) ) {
63
- add_filter( 'woocommerce_default_address_fields', array( $this, 'custom_override_default_address_fields' ), PHP_INT_MAX );
64
- }
65
- }
66
- }
67
-
68
- /**
69
- * maybe_override_fields.
70
- *
71
- * @version 3.6.0
72
- * @since 3.1.0
73
- * @todo (maybe) add option to choose `$options_to_override`
74
- * @todo (maybe) add to `$options_to_override`: enabled; class;
75
- */
76
- function maybe_override_fields( $fields, $override_with_section ) {
77
- $options_to_override = array(
78
- 'label' => array(
79
- 'default' => '',
80
- ),
81
- 'placeholder' => array(
82
- 'default' => '',
83
- ),
84
- 'description' => array(
85
- 'default' => '',
86
- ),
87
- 'priority' => array(
88
- 'default' => 0,
89
- ),
90
- 'required' => array(
91
- 'default' => 'default',
92
- 'option_id' => 'is_required',
93
- 'values' => array(
94
- 'yes' => true,
95
- 'no' => false,
96
- ),
97
- ),
98
- );
99
- foreach ( $fields as $field_key => $field_values ) {
100
- $field = $override_with_section . '_' . $field_key;
101
- foreach ( $options_to_override as $option => $option_data ) {
102
- $default_value = $option_data['default'];
103
- $option_id = ( isset( $option_data['option_id'] ) ? $option_data['option_id'] : $option );
104
- $option_id = 'wcj_checkout_fields_' . $field . '_' . $option_id;
105
- if ( $default_value != ( $value = get_option( $option_id, $default_value ) ) ) {
106
- $value = ( isset( $option_data['values'][ $value ] ) ? $option_data['values'][ $value ] : $value );
107
- $fields[ $field_key ][ $option ] = $value;
108
- }
109
- }
110
- }
111
- return $fields;
112
- }
113
-
114
- /**
115
- * custom_override_country_locale_fields.
116
- *
117
- * @version 3.1.0
118
- * @since 3.1.0
119
- */
120
- function custom_override_country_locale_fields( $fields ) {
121
- foreach ( $fields as $country => $country_fields ) {
122
- $fields[ $country ] = $this->maybe_override_fields( $country_fields, $this->country_locale_override );
123
- }
124
- return $fields;
125
- }
126
-
127
- /**
128
- * custom_override_default_address_fields.
129
- *
130
- * @version 3.1.0
131
- * @since 2.3.8
132
- */
133
- function custom_override_default_address_fields( $fields ) {
134
- return $this->maybe_override_fields( $fields, $this->default_address_override );
135
- }
136
-
137
- /**
138
- * custom_override_checkout_fields.
139
- *
140
- * @version 4.9.0
141
- * @todo add "per products", "per products tags"
142
- * @todo (maybe) fix - priority seems to not affect tab order (same in Checkout Custom Fields module)
143
- * @todo (maybe) enable if was not enabled by default, i.e. `! isset( $checkout_fields[ $section ][ $field ] )`
144
- */
145
- function custom_override_checkout_fields( $checkout_fields ) {
146
- foreach ( $this->woocommerce_core_checkout_fields as $field ) {
147
- $field_parts = explode( '_', $field, 2 );
148
- $section = ( ! empty( $field_parts ) && is_array( $field_parts ) ? $field_parts[0] : '' ); // billing or shipping
149
- // enabled
150
- if ( 'no' === ( $is_enabled = get_option( 'wcj_checkout_fields_' . $field . '_' . 'is_enabled', 'default' ) ) ) {
151
- if ( isset( $checkout_fields[ $section ][ $field ] ) ) {
152
- unset( $checkout_fields[ $section ][ $field ] ); // e.g. unset( $checkout_fields['billing']['billing_country'] );
153
- continue;
154
- }
155
- }
156
- // enabled - per products categories
157
- if ( ! $this->is_visible( array(
158
- 'include_products' => '',
159
- 'exclude_products' => '',
160
- 'include_categories' => apply_filters( 'booster_option', '', get_option( 'wcj_checkout_fields_' . $field . '_' . 'cats_incl', '' ) ),
161
- 'exclude_categories' => apply_filters( 'booster_option', '', get_option( 'wcj_checkout_fields_' . $field . '_' . 'cats_excl', '' ) ),
162
- 'include_tags' => '',
163
- 'exclude_tags' => '',
164
- ), get_option( 'wcj_checkout_core_fields_checking_relation', 'all' ) )
165
- ) {
166
- unset( $checkout_fields[ $section ][ $field ] );
167
- continue;
168
- }
169
- if ( isset( $checkout_fields[ $section ][ $field ] ) ) {
170
- // required
171
- if ( 'default' != ( $is_required = get_option( 'wcj_checkout_fields_' . $field . '_' . 'is_required', 'default' ) ) ) {
172
- $checkout_fields[ $section ][ $field ]['required'] = ( 'yes' === $is_required );
173
- }
174
- // label
175
- if ( '' != ( $label = get_option( 'wcj_checkout_fields_' . $field . '_' . 'label', '' ) ) ) {
176
- $checkout_fields[ $section ][ $field ]['label'] = $label;
177
- }
178
- // placeholder
179
- if ( '' != ( $placeholder = get_option( 'wcj_checkout_fields_' . $field . '_' . 'placeholder', '' ) ) ) {
180
- $checkout_fields[ $section ][ $field ]['placeholder'] = $placeholder;
181
- }
182
- // description
183
- if ( '' != ( $description = get_option( 'wcj_checkout_fields_' . $field . '_' . 'description', '' ) ) ) {
184
- $checkout_fields[ $section ][ $field ]['description'] = $description;
185
- }
186
- // class
187
- if ( 'default' != ( $class = get_option( 'wcj_checkout_fields_' . $field . '_' . 'class', 'default' ) ) ) {
188
- $checkout_fields[ $section ][ $field ]['class'] = array( $class );
189
- }
190
- // priority
191
- if ( 0 != ( $priority = apply_filters( 'booster_option', 0, get_option( 'wcj_checkout_fields_' . $field . '_' . 'priority', 0 ) ) ) ) {
192
- $checkout_fields[ $section ][ $field ]['priority'] = $priority;
193
- }
194
- }
195
- }
196
- if ( 'yes' === get_option( 'wcj_checkout_core_fields_force_sort_by_priority', 'no' ) ) {
197
- $field_sets = array( 'billing', 'shipping', 'account', 'order' );
198
- foreach ( $field_sets as $field_set ) {
199
- if ( isset( $checkout_fields[ $field_set ] ) ) {
200
- uasort( $checkout_fields[ $field_set ], array( $this, 'sort_by_priority' ) );
201
- }
202
- }
203
- }
204
- return $checkout_fields;
205
- }
206
-
207
- /**
208
- * is_visible.
209
- *
210
- * @version 4.9.0
211
- * @since 3.4.0
212
- * @todo (maybe) save `$this->cart_product_ids` array (instead of calling `WC()->cart->get_cart()` for each field)
213
- *
214
- * @param $args
215
- * @param string $relation
216
- *
217
- * @return bool
218
- */
219
- function is_visible( $args, $relation = 'and' ) {
220
- $relation = strtolower( $relation );
221
- $all_empty = true;
222
- foreach ( $args as $arg ) {
223
- if ( ! empty( $arg ) ) {
224
- $all_empty = false;
225
- // At least one arg is filled - checking products in cart
226
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
227
- if ( 'and' === $relation ) {
228
- if ( ! wcj_is_enabled_for_product( $values['product_id'], $args ) ) {
229
- return false;
230
- }
231
- } elseif ( 'or' === $relation ) {
232
- if ( wcj_is_enabled_for_product( $values['product_id'], $args ) ) {
233
- return true;
234
- }
235
- }
236
- }
237
- break;
238
- }
239
- }
240
- if ( $all_empty ) {
241
- return true;
242
- }
243
- return 'and' === $relation ? true : false;
244
- }
245
-
246
- /**
247
- * sort_by_priority.
248
- *
249
- * @version 3.4.0
250
- * @since 3.4.0
251
- */
252
- function sort_by_priority( $a, $b ) {
253
- $a = ( isset( $a['priority'] ) ? $a['priority'] : 0 );
254
- $b = ( isset( $b['priority'] ) ? $b['priority'] : 0 );
255
- if ( $a == $b ) {
256
- return 0;
257
- }
258
- return ( $a < $b ) ? -1 : 1;
259
- }
260
-
261
- }
262
-
263
- endif;
264
-
265
- return new WCJ_Checkout_Core_Fields();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Checkout Core Fields
4
+ *
5
+ * @version 4.9.0
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 3.6.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 etc.', 'woocommerce-jetpack' );
27
+ $this->link_slug = 'woocommerce-checkout-core-fields';
28
+ parent::__construct();
29
+
30
+ $this->woocommerce_core_checkout_fields = array(
31
+ 'billing_country',
32
+ 'billing_first_name',
33
+ 'billing_last_name',
34
+ 'billing_company',
35
+ 'billing_address_1',
36
+ 'billing_address_2',
37
+ 'billing_city',
38
+ 'billing_state',
39
+ 'billing_postcode',
40
+ 'billing_email',
41
+ 'billing_phone',
42
+ 'shipping_country',
43
+ 'shipping_first_name',
44
+ 'shipping_last_name',
45
+ 'shipping_company',
46
+ 'shipping_address_1',
47
+ 'shipping_address_2',
48
+ 'shipping_city',
49
+ 'shipping_state',
50
+ 'shipping_postcode',
51
+ 'account_username',
52
+ 'account_password',
53
+ 'account_password-2',
54
+ 'order_comments',
55
+ );
56
+
57
+ if ( $this->is_enabled() ) {
58
+ add_filter( 'woocommerce_checkout_fields' , array( $this, 'custom_override_checkout_fields' ), PHP_INT_MAX );
59
+ if ( 'disable' != ( $this->country_locale_override = get_option( 'wcj_checkout_core_fields_override_country_locale_fields', 'billing' ) ) ) {
60
+ add_filter( 'woocommerce_get_country_locale', array( $this, 'custom_override_country_locale_fields' ), PHP_INT_MAX );
61
+ }
62
+ if ( 'disable' != ( $this->default_address_override = get_option( 'wcj_checkout_core_fields_override_default_address_fields', 'billing' ) ) ) {
63
+ add_filter( 'woocommerce_default_address_fields', array( $this, 'custom_override_default_address_fields' ), PHP_INT_MAX );
64
+ }
65
+ }
66
+ }
67
+
68
+ /**
69
+ * maybe_override_fields.
70
+ *
71
+ * @version 3.6.0
72
+ * @since 3.1.0
73
+ * @todo (maybe) add option to choose `$options_to_override`
74
+ * @todo (maybe) add to `$options_to_override`: enabled; class;
75
+ */
76
+ function maybe_override_fields( $fields, $override_with_section ) {
77
+ $options_to_override = array(
78
+ 'label' => array(
79
+ 'default' => '',
80
+ ),
81
+ 'placeholder' => array(
82
+ 'default' => '',
83
+ ),
84
+ 'description' => array(
85
+ 'default' => '',
86
+ ),
87
+ 'priority' => array(
88
+ 'default' => 0,
89
+ ),
90
+ 'required' => array(
91
+ 'default' => 'default',
92
+ 'option_id' => 'is_required',
93
+ 'values' => array(
94
+ 'yes' => true,
95
+ 'no' => false,
96
+ ),
97
+ ),
98
+ );
99
+ foreach ( $fields as $field_key => $field_values ) {
100
+ $field = $override_with_section . '_' . $field_key;
101
+ foreach ( $options_to_override as $option => $option_data ) {
102
+ $default_value = $option_data['default'];
103
+ $option_id = ( isset( $option_data['option_id'] ) ? $option_data['option_id'] : $option );
104
+ $option_id = 'wcj_checkout_fields_' . $field . '_' . $option_id;
105
+ if ( $default_value != ( $value = get_option( $option_id, $default_value ) ) ) {
106
+ $value = ( isset( $option_data['values'][ $value ] ) ? $option_data['values'][ $value ] : $value );
107
+ $fields[ $field_key ][ $option ] = $value;
108
+ }
109
+ }
110
+ }
111
+ return $fields;
112
+ }
113
+
114
+ /**
115
+ * custom_override_country_locale_fields.
116
+ *
117
+ * @version 3.1.0
118
+ * @since 3.1.0
119
+ */
120
+ function custom_override_country_locale_fields( $fields ) {
121
+ foreach ( $fields as $country => $country_fields ) {
122
+ $fields[ $country ] = $this->maybe_override_fields( $country_fields, $this->country_locale_override );
123
+ }
124
+ return $fields;
125
+ }
126
+
127
+ /**
128
+ * custom_override_default_address_fields.
129
+ *
130
+ * @version 3.1.0
131
+ * @since 2.3.8
132
+ */
133
+ function custom_override_default_address_fields( $fields ) {
134
+ return $this->maybe_override_fields( $fields, $this->default_address_override );
135
+ }
136
+
137
+ /**
138
+ * custom_override_checkout_fields.
139
+ *
140
+ * @version 4.9.0
141
+ * @todo add "per products", "per products tags"
142
+ * @todo (maybe) fix - priority seems to not affect tab order (same in Checkout Custom Fields module)
143
+ * @todo (maybe) enable if was not enabled by default, i.e. `! isset( $checkout_fields[ $section ][ $field ] )`
144
+ */
145
+ function custom_override_checkout_fields( $checkout_fields ) {
146
+ foreach ( $this->woocommerce_core_checkout_fields as $field ) {
147
+ $field_parts = explode( '_', $field, 2 );
148
+ $section = ( ! empty( $field_parts ) && is_array( $field_parts ) ? $field_parts[0] : '' ); // billing or shipping
149
+ // enabled
150
+ if ( 'no' === ( $is_enabled = get_option( 'wcj_checkout_fields_' . $field . '_' . 'is_enabled', 'default' ) ) ) {
151
+ if ( isset( $checkout_fields[ $section ][ $field ] ) ) {
152
+ unset( $checkout_fields[ $section ][ $field ] ); // e.g. unset( $checkout_fields['billing']['billing_country'] );
153
+ continue;
154
+ }
155
+ }
156
+ // enabled - per products categories
157
+ if ( ! $this->is_visible( array(
158
+ 'include_products' => '',
159
+ 'exclude_products' => '',
160
+ 'include_categories' => apply_filters( 'booster_option', '', get_option( 'wcj_checkout_fields_' . $field . '_' . 'cats_incl', '' ) ),
161
+ 'exclude_categories' => apply_filters( 'booster_option', '', get_option( 'wcj_checkout_fields_' . $field . '_' . 'cats_excl', '' ) ),
162
+ 'include_tags' => '',
163
+ 'exclude_tags' => '',
164
+ ), get_option( 'wcj_checkout_core_fields_checking_relation', 'all' ) )
165
+ ) {
166
+ unset( $checkout_fields[ $section ][ $field ] );
167
+ continue;
168
+ }
169
+ if ( isset( $checkout_fields[ $section ][ $field ] ) ) {
170
+ // required
171
+ if ( 'default' != ( $is_required = get_option( 'wcj_checkout_fields_' . $field . '_' . 'is_required', 'default' ) ) ) {
172
+ $checkout_fields[ $section ][ $field ]['required'] = ( 'yes' === $is_required );
173
+ }
174
+ // label
175
+ if ( '' != ( $label = get_option( 'wcj_checkout_fields_' . $field . '_' . 'label', '' ) ) ) {
176
+ $checkout_fields[ $section ][ $field ]['label'] = $label;
177
+ }
178
+ // placeholder
179
+ if ( '' != ( $placeholder = get_option( 'wcj_checkout_fields_' . $field . '_' . 'placeholder', '' ) ) ) {
180
+ $checkout_fields[ $section ][ $field ]['placeholder'] = $placeholder;
181
+ }
182
+ // description
183
+ if ( '' != ( $description = get_option( 'wcj_checkout_fields_' . $field . '_' . 'description', '' ) ) ) {
184
+ $checkout_fields[ $section ][ $field ]['description'] = $description;
185
+ }
186
+ // class
187
+ if ( 'default' != ( $class = get_option( 'wcj_checkout_fields_' . $field . '_' . 'class', 'default' ) ) ) {
188
+ $checkout_fields[ $section ][ $field ]['class'] = array( $class );
189
+ }
190
+ // priority
191
+ if ( 0 != ( $priority = apply_filters( 'booster_option', 0, get_option( 'wcj_checkout_fields_' . $field . '_' . 'priority', 0 ) ) ) ) {
192
+ $checkout_fields[ $section ][ $field ]['priority'] = $priority;
193
+ }
194
+ }
195
+ }
196
+ if ( 'yes' === get_option( 'wcj_checkout_core_fields_force_sort_by_priority', 'no' ) ) {
197
+ $field_sets = array( 'billing', 'shipping', 'account', 'order' );
198
+ foreach ( $field_sets as $field_set ) {
199
+ if ( isset( $checkout_fields[ $field_set ] ) ) {
200
+ uasort( $checkout_fields[ $field_set ], array( $this, 'sort_by_priority' ) );
201
+ }
202
+ }
203
+ }
204
+ return $checkout_fields;
205
+ }
206
+
207
+ /**
208
+ * is_visible.
209
+ *
210
+ * @version 4.9.0
211
+ * @since 3.4.0
212
+ * @todo (maybe) save `$this->cart_product_ids` array (instead of calling `WC()->cart->get_cart()` for each field)
213
+ *
214
+ * @param $args
215
+ * @param string $relation
216
+ *
217
+ * @return bool
218
+ */
219
+ function is_visible( $args, $relation = 'and' ) {
220
+ $relation = strtolower( $relation );
221
+ $all_empty = true;
222
+ foreach ( $args as $arg ) {
223
+ if ( ! empty( $arg ) ) {
224
+ $all_empty = false;
225
+ // At least one arg is filled - checking products in cart
226
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
227
+ if ( 'and' === $relation ) {
228
+ if ( ! wcj_is_enabled_for_product( $values['product_id'], $args ) ) {
229
+ return false;
230
+ }
231
+ } elseif ( 'or' === $relation ) {
232
+ if ( wcj_is_enabled_for_product( $values['product_id'], $args ) ) {
233
+ return true;
234
+ }
235
+ }
236
+ }
237
+ break;
238
+ }
239
+ }
240
+ if ( $all_empty ) {
241
+ return true;
242
+ }
243
+ return 'and' === $relation ? true : false;
244
+ }
245
+
246
+ /**
247
+ * sort_by_priority.
248
+ *
249
+ * @version 3.4.0
250
+ * @since 3.4.0
251
+ */
252
+ function sort_by_priority( $a, $b ) {
253
+ $a = ( isset( $a['priority'] ) ? $a['priority'] : 0 );
254
+ $b = ( isset( $b['priority'] ) ? $b['priority'] : 0 );
255
+ if ( $a == $b ) {
256
+ return 0;
257
+ }
258
+ return ( $a < $b ) ? -1 : 1;
259
+ }
260
+
261
+ }
262
+
263
+ endif;
264
+
265
+ return new WCJ_Checkout_Core_Fields();
includes/class-wcj-checkout-custom-fields.php CHANGED
@@ -1,631 +1,631 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Checkout Custom Fields
4
- *
5
- * @version 4.8.0
6
- * @author Algoritmika Ltd.
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 4.8.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.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-checkout-custom-fields';
27
- parent::__construct();
28
-
29
- if ( $this->is_enabled() ) {
30
- add_filter( 'woocommerce_checkout_fields', array( $this, 'add_custom_checkout_fields' ), PHP_INT_MAX );
31
- add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_custom_billing_fields_to_admin_order_display' ), PHP_INT_MAX );
32
- add_filter( 'woocommerce_admin_shipping_fields', array( $this, 'add_custom_shipping_fields_to_admin_order_display' ), PHP_INT_MAX );
33
- add_action( 'woocommerce_admin_order_data_after_shipping_address', array( $this, 'add_custom_order_and_account_fields_to_admin_order_display' ), PHP_INT_MAX );
34
- if ( 'yes' === get_option( 'wcj_checkout_custom_fields_add_to_order_received', 'yes' ) ) {
35
- add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_custom_fields_to_view_order_and_thankyou_pages' ), PHP_INT_MAX );
36
- }
37
- add_action( 'woocommerce_email_after_order_table', array( $this, 'add_custom_fields_to_emails' ), PHP_INT_MAX, 2 );
38
- add_filter( 'woo_ce_order_fields', array( $this, 'add_custom_fields_to_store_exporter' ) );
39
- add_filter( 'woo_ce_order', array( $this, 'add_custom_fields_to_store_exporter_order' ), PHP_INT_MAX, 2 );
40
- add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'update_custom_checkout_fields_order_meta' ) );
41
- add_filter( 'woocommerce_form_field_' . 'text', array( $this, 'woocommerce_form_field_type_number' ), PHP_INT_MAX, 4 );
42
- add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_checkout_custom_fields_customer_meta_fields' ) );
43
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
44
- if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
45
- $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
46
- $the_key = 'wcj_checkout_field_' . $i;
47
- $the_name = $the_section . '_' . $the_key;
48
- add_filter( 'default_checkout_' . $the_name, array( $this, 'add_default_checkout_custom_fields' ), PHP_INT_MAX, 2 );
49
- }
50
- }
51
- // select2 script
52
- add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ) );
53
-
54
- // Update checkout fields from admin edit order
55
- add_action( 'save_post_shop_order', array( $this, 'update_custom_checkout_fields_order_meta' ) );
56
-
57
- // Update checkout fields from admin on a subscription order
58
- add_action( 'save_post_shop_subscription', array( $this, 'update_custom_checkout_fields_order_meta' ) );
59
- }
60
- }
61
-
62
- /**
63
- * maybe_enqueue_scripts.
64
- *
65
- * @version 3.6.0
66
- * @since 3.2.0
67
- */
68
- function maybe_enqueue_scripts( $fields ) {
69
- if ( is_checkout() ) {
70
- $select2_fields = array();
71
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
72
- if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i, 'no' ) ) {
73
- if ( 'select' === get_option( 'wcj_checkout_custom_field_type_' . $i, 'text' ) ) {
74
- if ( 'yes' === get_option( 'wcj_checkout_custom_field_select_select2_' . $i, 'no' ) ) {
75
- $select2_fields[] = array(
76
- 'field_id' => get_option( 'wcj_checkout_custom_field_section_' . $i, 'billing' ) . '_' . 'wcj_checkout_field_' . $i,
77
- 'minimumInputLength' => get_option( 'wcj_checkout_custom_field_select_select2_min_input_length' . $i, 0 ),
78
- 'maximumInputLength' => get_option( 'wcj_checkout_custom_field_select_select2_max_input_length' . $i, 0 ),
79
- );
80
- }
81
- }
82
- }
83
- }
84
- if ( ! empty( $select2_fields ) ) {
85
- wp_enqueue_script(
86
- 'wcj-checkout-custom-fields',
87
- wcj_plugin_url() . '/includes/js/wcj-checkout-custom-fields.js',
88
- array( 'jquery' ),
89
- WCJ()->version,
90
- true
91
- );
92
- wp_localize_script(
93
- 'wcj-checkout-custom-fields',
94
- 'wcj_checkout_custom_fields',
95
- array(
96
- 'select2_fields' => $select2_fields,
97
- )
98
- );
99
- }
100
- }
101
- }
102
-
103
- /**
104
- * add_checkout_custom_fields_customer_meta_fields.
105
- *
106
- * @version 3.2.4
107
- * @since 2.4.5
108
- */
109
- function add_checkout_custom_fields_customer_meta_fields( $fields ) {
110
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
111
- if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
112
- if ( 'no' === get_option( 'wcj_checkout_custom_field_customer_meta_fields_' . $i, 'yes' ) ) {
113
- continue;
114
- }
115
- $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
116
- $the_key = 'wcj_checkout_field_' . $i;
117
- $the_name = $the_section . '_' . $the_key;
118
- $fields[ $the_section ]['fields'][ $the_name ] = array(
119
- 'label' => get_option( 'wcj_checkout_custom_field_label_' . $i ),
120
- 'description' => '',
121
- );
122
- }
123
- }
124
- return $fields;
125
- }
126
-
127
- /**
128
- * add_default_checkout_custom_fields.
129
- *
130
- * @version 2.4.5
131
- * @since 2.4.5
132
- */
133
- function add_default_checkout_custom_fields( $default_value, $field_key ) {
134
- if ( is_user_logged_in() ) {
135
- $current_user = wp_get_current_user();
136
- if ( $meta = get_user_meta( $current_user->ID, $field_key, true ) ) {
137
- return $meta;
138
- }
139
- }
140
- return $default_value;
141
- }
142
-
143
- /**
144
- * woocommerce_form_field_type_number.
145
- *
146
- * @version 2.3.0
147
- * @since 2.3.0
148
- */
149
- function woocommerce_form_field_type_number( $field, $key, $args, $value ) {
150
- if ( isset( $args['custom_attributes']['display'] ) && 'number' === $args['custom_attributes']['display'] ) {
151
- $field = str_replace( '<input type="text" ', '<input type="number" ', $field );
152
- }
153
- return $field;
154
- }
155
-
156
- /**
157
- * add_custom_fields_to_store_exporter_order.
158
- *
159
- * @version 2.3.0
160
- * @since 2.2.7
161
- */
162
- function add_custom_fields_to_store_exporter_order( $order, $order_id ) {
163
- $post_meta = get_post_meta( $order_id );
164
- foreach( $post_meta as $key => $values ) {
165
- if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
166
- if ( false !== strpos( $key, '_label_' ) ) {
167
- continue;
168
- }
169
- $order->$key = isset( $values[0]['value'] ) ? $values[0]['value'] : $values[0];
170
- }
171
- }
172
-
173
- return $order;
174
- }
175
-
176
- /**
177
- * add_custom_fields_to_store_exporter.
178
- */
179
- function add_custom_fields_to_store_exporter( $fields ) {
180
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
181
- if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
182
- $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
183
- $the_key = 'wcj_checkout_field_' . $i;
184
- $fields[] = array(
185
- 'name' => $the_section . '_' . $the_key,
186
- 'label' => get_option( 'wcj_checkout_custom_field_label_' . $i ),
187
- );
188
- }
189
- }
190
- return $fields;
191
- }
192
-
193
- /**
194
- * update_custom_checkout_fields_order_meta.
195
- *
196
- * @version 4.6.1
197
- */
198
- function update_custom_checkout_fields_order_meta( $order_id ) {
199
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
200
- if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
201
- if ( 'woocommerce_checkout_update_order_meta' === current_filter() && ! $this->is_visible( $i ) ) {
202
- continue;
203
- }
204
- $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
205
- $the_type = get_option( 'wcj_checkout_custom_field_type_' . $i );
206
- $option_name = $the_section . '_' . 'wcj_checkout_field_' . $i;
207
- $option_name_label = $the_section . '_' . 'wcj_checkout_field_label_' . $i;
208
- $option_name_type = $the_section . '_' . 'wcj_checkout_field_type_' . $i;
209
- $post_value = isset( $_POST[ $option_name ] ) ? $_POST[ $option_name ] : ( isset( $_POST[ '_' . $option_name ] ) ? $_POST[ '_' . $option_name ] : get_post_meta( $order_id, '_' . $option_name, true ) );
210
- if ( ! empty( $post_value ) || 'checkbox' === $the_type ) {
211
- update_post_meta( $order_id, '_' . $option_name_type, $the_type );
212
- update_post_meta( $order_id, '_' . $option_name_label, get_option( 'wcj_checkout_custom_field_label_' . $i ) );
213
- if ( 'checkbox' === $the_type ) {
214
- $the_value = ! empty( $post_value ) ? 1 : 0;
215
- update_post_meta( $order_id, '_' . $option_name, $the_value );
216
- $option_name_checkbox_value = $the_section . '_' . 'wcj_checkout_field_checkbox_value_' . $i;
217
- $checkbox_value = ( 1 == $the_value ) ?
218
- get_option( 'wcj_checkout_custom_field_checkbox_yes_' . $i ) :
219
- get_option( 'wcj_checkout_custom_field_checkbox_no_' . $i );
220
- update_post_meta( $order_id, '_' . $option_name_checkbox_value, $checkbox_value );
221
- } elseif ( 'radio' === $the_type || 'select' === $the_type ) {
222
- update_post_meta( $order_id, '_' . $option_name, wc_clean( urldecode( $post_value ) ) );
223
- $option_name_values = $the_section . '_' . 'wcj_checkout_field_select_options_' . $i;
224
- $the_values = get_option( 'wcj_checkout_custom_field_select_options_' . $i );
225
- update_post_meta( $order_id, '_' . $option_name_values, $the_values );
226
- } elseif ( 'textarea' === $the_type && 'no' === get_option( 'wcj_checkout_custom_fields_textarea_clean', 'yes' ) ) {
227
- update_post_meta( $order_id, '_' . $option_name, urldecode( $post_value ) );
228
- } else {
229
- update_post_meta( $order_id, '_' . $option_name, wc_clean( urldecode( $post_value ) ) );
230
- }
231
- }
232
- }
233
- }
234
- }
235
-
236
- /**
237
- * add_custom_fields_to_emails.
238
- *
239
- * @version 3.2.2
240
- */
241
- function add_custom_fields_to_emails( $order, $sent_to_admin ) {
242
- if (
243
- ( $sent_to_admin && 'yes' === get_option( 'wcj_checkout_custom_fields_email_all_to_admin' ) ) ||
244
- ( ! $sent_to_admin && 'yes' === get_option( 'wcj_checkout_custom_fields_email_all_to_customer' ) )
245
- ) {
246
- $templates = array(
247
- 'before' => get_option( 'wcj_checkout_custom_fields_emails_template_before', '' ),
248
- 'field' => get_option( 'wcj_checkout_custom_fields_emails_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
249
- 'after' => get_option( 'wcj_checkout_custom_fields_emails_template_after', '' ),
250
- );
251
- $this->add_custom_fields_to_order_display( $order, '', $templates );
252
- }
253
- }
254
-
255
- /**
256
- * add_custom_fields_to_view_order_and_thankyou_pages.
257
- *
258
- * @version 3.2.2
259
- * @since 3.2.2
260
- */
261
- function add_custom_fields_to_view_order_and_thankyou_pages( $order ) {
262
- $templates = array(
263
- 'before' => get_option( 'wcj_checkout_custom_fields_order_received_template_before', '' ),
264
- 'field' => get_option( 'wcj_checkout_custom_fields_order_received_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
265
- 'after' => get_option( 'wcj_checkout_custom_fields_order_received_template_after', '' ),
266
- );
267
- $this->add_custom_fields_to_order_display( $order, '', $templates );
268
- }
269
-
270
- /**
271
- * add_custom_fields_to_order_display.
272
- *
273
- * @version 3.8.0
274
- * @since 2.3.0
275
- * @todo convert from before version 2.3.0
276
- */
277
- function add_custom_fields_to_order_display( $order, $section = '', $templates ) {
278
- $post_meta = get_post_meta( wcj_get_order_id( $order ) );
279
- $final_output = '';
280
- foreach( $post_meta as $key => $values ) {
281
- if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
282
- // Checking section (if set)
283
- if ( '' != $section ) {
284
- $the_section = strtok( $key, '_' );
285
- if ( $section !== $the_section ) {
286
- continue;
287
- }
288
- }
289
- // Skipping unnecessary meta
290
- if (
291
- false !== strpos( $key, '_label_' ) ||
292
- false !== strpos( $key, '_type_' ) ||
293
- false !== strpos( $key, '_checkbox_value_' ) ||
294
- false !== strpos( $key, '_select_options_' )
295
- ) {
296
- continue;
297
- }
298
- // Field label
299
- $label = '';
300
- $the_label_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_label_', $key );
301
- if ( isset( $post_meta[ $the_label_key ][0] ) ) {
302
- $label = $post_meta[ $the_label_key ][0];
303
- } elseif ( is_array( $values[0] ) && isset( $values[0]['label'] ) ) {
304
- $label = $values[0]['label'];
305
- }
306
- // Field value
307
- $value = '';
308
- $_value = ( is_array( $values[0] ) && isset( $values[0]['value'] ) ? $values[0]['value'] : $values[0] );
309
- $type_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_type_', $key );
310
- if ( isset( $post_meta[ $type_key ][0] ) && 'checkbox' === $post_meta[ $type_key ][0] ) {
311
- $checkbox_value_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_checkbox_value_', $key );
312
- $value = ( isset( $post_meta[ $checkbox_value_key ][0] ) ? $post_meta[ $checkbox_value_key ][0] : $_value );
313
- } elseif ( isset( $post_meta[ $type_key ][0] ) && ( 'radio' === $post_meta[ $type_key ][0] || 'select' === $post_meta[ $type_key ][0] ) ) {
314
- $select_values_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_select_options_', $key );
315
- $select_values = ( isset( $post_meta[ $select_values_key ][0] ) ) ? $post_meta[ $select_values_key ][0] : '';
316
- if ( ! empty( $select_values ) ) {
317
- $select_values_prepared = wcj_get_select_options( $select_values );
318
- $value = ( isset( $select_values_prepared[ $_value ] ) ? $select_values_prepared[ $_value ] : $_value );
319
- } else {
320
- $value = $_value;
321
- }
322
- } elseif ( isset( $post_meta[ $type_key ][0] ) && 'textarea' === $post_meta[ $type_key ][0] && 'yes' === get_option( 'wcj_checkout_custom_fields_textarea_replace_line_breaks', 'no' ) ) {
323
- $value = str_replace( PHP_EOL, '<br>', $_value );
324
- } else {
325
- $value = $_value;
326
- }
327
- // Adding field to final output
328
- if ( '' != $label || '' != $value ) {
329
- $replaced_values = array(
330
- '%label%' => $label,
331
- '%value%' => $value,
332
- );
333
- $final_output .= str_replace( array_keys( $replaced_values ), $replaced_values, $templates['field'] );
334
- }
335
- }
336
- }
337
- // Outputting
338
- if ( '' != $final_output ) {
339
- echo $templates['before'] . $final_output . $templates['after'];
340
- }
341
- }
342
-
343
- /**
344
- * add_woocommerce_admin_fields.
345
- *
346
- * @version 4.7.0
347
- * @todo converting from before version 2.3.0: section?
348
- * @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)
349
- */
350
- function add_woocommerce_admin_fields( $fields, $section ) {
351
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
352
- if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
353
- $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
354
- if ( $section != $the_section ) {
355
- continue;
356
- }
357
- $the_type = get_option( 'wcj_checkout_custom_field_type_' . $i );
358
- if ( 'select' === $the_type ) {
359
- $the_class = 'first';
360
- $options = wcj_get_select_options( get_option( 'wcj_checkout_custom_field_select_options_' . $i ) );
361
- } elseif ( 'radio' === $the_type ) {
362
- $the_options = get_post_meta( get_the_ID(), '_' . $section . '_' . 'wcj_checkout_field_select_options_' . $i, true );
363
- if ( ! empty( $the_options ) ) {
364
- $the_type = 'select';
365
- $the_class = 'first';
366
- $options = wcj_get_select_options( $the_options );
367
- } else {
368
- $the_options = wcj_get_select_options( get_option( 'wcj_checkout_custom_field_select_options_' . $i ) );
369
- if ( ! empty( $the_options ) ) {
370
- $the_type = 'select';
371
- $the_class = 'first';
372
- $options = $the_options;
373
- } else {
374
- $the_type = 'text';
375
- $the_class = 'short';
376
- }
377
- }
378
- } elseif ( 'country' === $the_type ) {
379
- $the_type = 'select';
380
- $the_class = 'js_field-country select short';
381
- $options = WC()->countries->get_allowed_countries();
382
- } else {
383
- $the_type = 'text';
384
- $the_class = 'short';
385
- }
386
- $the_key = 'wcj_checkout_field_' . $i;
387
- $the_key_label = 'wcj_checkout_field_label_' . $i;
388
- $the_meta = get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key, true );
389
- if ( is_array( $the_meta ) ) {
390
- // Converting from before version 2.3.0
391
- if ( isset( $the_meta['value'] ) ) {
392
- update_post_meta( get_the_ID(), '_' . $section . '_' . $the_key, $the_meta['value'] );
393
- }
394
- if ( isset( $the_meta['label'] ) ) {
395
- update_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, $the_meta['label'] );
396
- }
397
- }
398
- if ( ! isset( $_POST[ '_' . $section . '_' . $the_key ] ) ) {
399
- $fields[ $the_key ] = array(
400
- 'type' => $the_type,
401
- 'label' => ( '' != get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, true ) ) ?
402
- get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, true ) :
403
- get_option( 'wcj_checkout_custom_field_label_' . $i ),
404
- 'show' => true,
405
- 'class' => $the_class,
406
- 'wrapper_class' => 'form-field-wide',
407
- );
408
- if ( ! empty( $the_meta ) && ! is_array( $the_meta ) ) {
409
- $fields[ $the_key ]['value'] = $the_meta;
410
- }
411
- if ( isset( $options ) ) {
412
- add_filter( "woocommerce_order_get__{$section}_{$the_key}", function ( $name ) use ( $options ) {
413
- if ( isset( $options[ $name ] ) ) {
414
- return $options[ $name ];
415
- }
416
- return $name;
417
- } );
418
- $fields[ $the_key ]['options'] = $options;
419
- }
420
- }
421
- }
422
- }
423
- return $fields;
424
- }
425
-
426
- /**
427
- * add_custom_billing_fields_to_admin_order_display.
428
- */
429
- function add_custom_billing_fields_to_admin_order_display( $fields ) {
430
- return $this->add_woocommerce_admin_fields( $fields, 'billing' );
431
- }
432
-
433
- /**
434
- * add_custom_shipping_fields_to_admin_order_display.
435
- */
436
- function add_custom_shipping_fields_to_admin_order_display( $fields ) {
437
- return $this->add_woocommerce_admin_fields( $fields, 'shipping' );
438
- }
439
-
440
- /**
441
- * add_custom_order_and_account_fields_to_admin_order_display
442
- *
443
- * @version 3.2.2
444
- */
445
- function add_custom_order_and_account_fields_to_admin_order_display( $order ) {
446
- $templates = array(
447
- 'before' => '<div class="clear"></div><p>',
448
- 'field' => '<strong>%label%: </strong>%value%<br>',
449
- 'after' => '</p>',
450
- );
451
- $this->add_custom_fields_to_order_display( $order, 'order', $templates );
452
- $this->add_custom_fields_to_order_display( $order, 'account', $templates );
453
- }
454
-
455
- /**
456
- * is_visible.
457
- *
458
- * @version 4.2.0
459
- * @since 2.6.0
460
- * @todo add "user roles to include/exclude"
461
- */
462
- function is_visible( $i ) {
463
-
464
- if ( apply_filters( 'wcj_checkout_custom_field_always_visible_on_empty_cart', false ) && WC()->cart->is_empty() ) {
465
- // Added for "One Page Checkout" plugin compatibility.
466
- return true;
467
- }
468
-
469
- // Checking categories
470
- $categories_ex = get_option( 'wcj_checkout_custom_field_categories_ex_' . $i );
471
- if ( ! empty( $categories_ex ) ) {
472
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
473
- $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
474
- if ( empty( $product_categories ) ) {
475
- continue;
476
- }
477
- foreach( $product_categories as $product_category ) {
478
- if ( in_array( $product_category->term_id, $categories_ex ) ) {
479
- return false;
480
- }
481
- }
482
- }
483
- }
484
- $categories_in = get_option( 'wcj_checkout_custom_field_categories_in_' . $i );
485
- if ( ! empty( $categories_in ) ) {
486
- $categories_in_cart = array();
487
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
488
- $product_categories = wp_get_post_terms( $values['product_id'], 'product_cat', array( "fields" => "ids" ) );
489
- $categories_in_cart = array_merge( $product_categories, $categories_in_cart );
490
- }
491
- if ( count( array_intersect( $categories_in, $categories_in_cart ) ) == 0 ) {
492
- return false;
493
- }
494
- }
495
-
496
- // Checking products
497
- $products_ex = get_option( 'wcj_checkout_custom_field_products_ex_' . $i );
498
- if ( ! empty( $products_ex ) ) {
499
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
500
- if ( in_array( $values['product_id'], $products_ex ) ) {
501
- return false;
502
- }
503
- }
504
- }
505
- $products_in = get_option( 'wcj_checkout_custom_field_products_in_' . $i );
506
- if ( ! empty( $products_in ) ) {
507
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
508
- if ( in_array( $values['product_id'], $products_in ) ) {
509
- return true;
510
- }
511
- }
512
- return false;
513
- }
514
-
515
- // Checking min/max cart amount
516
- $cart_total = false;
517
- if ( ( $min_cart_amount = get_option( 'wcj_checkout_custom_field_min_cart_amount_' . $i, 0 ) ) > 0 ) {
518
- WC()->cart->calculate_totals();
519
- $cart_total = WC()->cart->total;
520
- if ( $cart_total < $min_cart_amount ) {
521
- return false;
522
- }
523
- }
524
- if ( ( $max_cart_amount = get_option( 'wcj_checkout_custom_field_max_cart_amount_' . $i, 0 ) ) > 0 ) {
525
- if ( false === $cart_total ) {
526
- WC()->cart->calculate_totals();
527
- $cart_total = WC()->cart->total;
528
- }
529
- if ( $cart_total > $max_cart_amount ) {
530
- return false;
531
- }
532
- }
533
-
534
- // All passed
535
- return apply_filters( 'wcj_checkout_custom_field_visible', true, $i );
536
- }
537
-
538
- /**
539
- * add_custom_checkout_fields.
540
- *
541
- * @version 3.8.0
542
- * @todo (maybe) fix - priority seems to not affect tab order (same in Checkout Core Fields module)
543
- * @todo (dev) (maybe) add `do_shortcode` for e.g. `description` etc.
544
- */
545
- function add_custom_checkout_fields( $fields ) {
546
-
547
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
548
-
549
- if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
550
-
551
- if ( ! $this->is_visible( $i ) ) {
552
- continue;
553
- }
554
-
555
- $the_type = get_option( 'wcj_checkout_custom_field_type_' . $i );
556
- $custom_attributes = array();
557
- if ( 'datepicker' === $the_type || 'weekpicker' === $the_type || 'timepicker' === $the_type || 'number' === $the_type ) {
558
- if ( 'datepicker' === $the_type || 'weekpicker' === $the_type ) {
559
- $datepicker_format_option = get_option( 'wcj_checkout_custom_field_datepicker_format_' . $i, '' );
560
- $datepicker_format = ( '' == $datepicker_format_option ) ? get_option( 'date_format' ) : $datepicker_format_option;
561
- $datepicker_format = wcj_date_format_php_to_js( $datepicker_format );
562
- $custom_attributes['dateformat'] = $datepicker_format;
563
- $custom_attributes['mindate'] = get_option( 'wcj_checkout_custom_field_datepicker_mindate_' . $i, -365 );
564
- if ( 0 == $custom_attributes['mindate'] ) {
565
- $custom_attributes['mindate'] = 'zero';
566
- }
567
- $custom_attributes['maxdate'] = get_option( 'wcj_checkout_custom_field_datepicker_maxdate_' . $i, 365 );
568
- if ( 0 == $custom_attributes['maxdate'] ) {
569
- $custom_attributes['maxdate'] = 'zero';
570
- }
571
- $custom_attributes['firstday'] = get_option( 'wcj_checkout_custom_field_datepicker_firstday_' . $i, 0 );
572
- if ( 'yes' === get_option( 'wcj_checkout_custom_field_datepicker_changeyear_' . $i, 'yes' ) ) {
573
- $custom_attributes['changeyear'] = 1;
574
- $custom_attributes['yearrange'] = get_option( 'wcj_checkout_custom_field_datepicker_yearrange_' . $i, 'c-10:c+10' );
575
- }
576
- $custom_attributes['display'] = ( 'datepicker' === $the_type ) ? 'date' : 'week';
577
- } elseif ( 'timepicker' === $the_type ) {
578
- $custom_attributes['timeformat'] = get_option( 'wcj_checkout_custom_field_timepicker_format_' . $i, 'hh:mm p' );
579
- $custom_attributes['interval'] = get_option( 'wcj_checkout_custom_field_timepicker_interval_' . $i, 15 );
580
- $custom_attributes['display'] = 'time';
581
- } else { // 'number'
582
- $custom_attributes['display'] = $the_type;
583
- }
584
- $the_type = 'text';
585
- }
586
- $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
587
- $the_key = 'wcj_checkout_field_' . $i;
588
-
589
- $the_field = array(
590
- 'type' => $the_type,
591
- 'label' => get_option( 'wcj_checkout_custom_field_label_' . $i ),
592
- 'placeholder' => get_option( 'wcj_checkout_custom_field_placeholder_' . $i ),
593
- 'required' => ( 'yes' === get_option( 'wcj_checkout_custom_field_required_' . $i ) ),
594
- 'custom_attributes' => $custom_attributes,
595
- 'clear' => ( 'yes' === get_option( 'wcj_checkout_custom_field_clear_' . $i ) ),
596
- 'class' => array( get_option( 'wcj_checkout_custom_field_class_' . $i ) ),
597
- 'priority' => get_option( 'wcj_checkout_custom_field_priority_' . $i, '' ),
598
- 'description' => get_option( 'wcj_checkout_custom_field_description_' . $i, '' ),
599
- );
600
-
601
- if ( 'select' === $the_type || 'radio' === $the_type ) {
602
- $select_options_raw = get_option( 'wcj_checkout_custom_field_select_options_' . $i );
603
- $select_options = wcj_get_select_options( $select_options_raw );
604
- if ( 'select' === $the_type ) {
605
- $placeholder = get_option( 'wcj_checkout_custom_field_placeholder_' . $i );
606
- if ( '' != $placeholder ) {
607
- $select_options = array_replace( array( '' => $placeholder ), $select_options );
608
- }
609
- }
610
- $the_field['options'] = $select_options;
611
- if ( ! empty( $select_options ) ) {
612
- reset( $select_options );
613
- $the_field['default'] = key( $select_options );
614
- }
615
- }
616
-
617
- if ( 'checkbox' === $the_type ) {
618
- $the_field['default'] = ( 'yes' === get_option( 'wcj_checkout_custom_field_checkbox_default_' . $i ) ) ? 1 : 0;
619
- }
620
-
621
- $fields[ $the_section ][ $the_section . '_' . $the_key ] = $the_field;
622
- }
623
- }
624
- return $fields;
625
- }
626
-
627
- }
628
-
629
- endif;
630
-
631
- return new WCJ_Checkout_Custom_Fields();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Checkout Custom Fields
4
+ *
5
+ * @version 4.8.0
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 4.8.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.', 'woocommerce-jetpack' );
26
+ $this->link_slug = 'woocommerce-checkout-custom-fields';
27
+ parent::__construct();
28
+
29
+ if ( $this->is_enabled() ) {
30
+ add_filter( 'woocommerce_checkout_fields', array( $this, 'add_custom_checkout_fields' ), PHP_INT_MAX );
31
+ add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_custom_billing_fields_to_admin_order_display' ), PHP_INT_MAX );
32
+ add_filter( 'woocommerce_admin_shipping_fields', array( $this, 'add_custom_shipping_fields_to_admin_order_display' ), PHP_INT_MAX );
33
+ add_action( 'woocommerce_admin_order_data_after_shipping_address', array( $this, 'add_custom_order_and_account_fields_to_admin_order_display' ), PHP_INT_MAX );
34
+ if ( 'yes' === get_option( 'wcj_checkout_custom_fields_add_to_order_received', 'yes' ) ) {
35
+ add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_custom_fields_to_view_order_and_thankyou_pages' ), PHP_INT_MAX );
36
+ }
37
+ add_action( 'woocommerce_email_after_order_table', array( $this, 'add_custom_fields_to_emails' ), PHP_INT_MAX, 2 );
38
+ add_filter( 'woo_ce_order_fields', array( $this, 'add_custom_fields_to_store_exporter' ) );
39
+ add_filter( 'woo_ce_order', array( $this, 'add_custom_fields_to_store_exporter_order' ), PHP_INT_MAX, 2 );
40
+ add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'update_custom_checkout_fields_order_meta' ) );
41
+ add_filter( 'woocommerce_form_field_' . 'text', array( $this, 'woocommerce_form_field_type_number' ), PHP_INT_MAX, 4 );
42
+ add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_checkout_custom_fields_customer_meta_fields' ) );
43
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
44
+ if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
45
+ $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
46
+ $the_key = 'wcj_checkout_field_' . $i;
47
+ $the_name = $the_section . '_' . $the_key;
48
+ add_filter( 'default_checkout_' . $the_name, array( $this, 'add_default_checkout_custom_fields' ), PHP_INT_MAX, 2 );
49
+ }
50
+ }
51
+ // select2 script
52
+ add_action( 'wp_enqueue_scripts', array( $this, 'maybe_enqueue_scripts' ) );
53
+
54
+ // Update checkout fields from admin edit order
55
+ add_action( 'save_post_shop_order', array( $this, 'update_custom_checkout_fields_order_meta' ) );
56
+
57
+ // Update checkout fields from admin on a subscription order
58
+ add_action( 'save_post_shop_subscription', array( $this, 'update_custom_checkout_fields_order_meta' ) );
59
+ }
60
+ }
61
+
62
+ /**
63
+ * maybe_enqueue_scripts.
64
+ *
65
+ * @version 3.6.0
66
+ * @since 3.2.0
67
+ */
68
+ function maybe_enqueue_scripts( $fields ) {
69
+ if ( is_checkout() ) {
70
+ $select2_fields = array();
71
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
72
+ if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i, 'no' ) ) {
73
+ if ( 'select' === get_option( 'wcj_checkout_custom_field_type_' . $i, 'text' ) ) {
74
+ if ( 'yes' === get_option( 'wcj_checkout_custom_field_select_select2_' . $i, 'no' ) ) {
75
+ $select2_fields[] = array(
76
+ 'field_id' => get_option( 'wcj_checkout_custom_field_section_' . $i, 'billing' ) . '_' . 'wcj_checkout_field_' . $i,
77
+ 'minimumInputLength' => get_option( 'wcj_checkout_custom_field_select_select2_min_input_length' . $i, 0 ),
78
+ 'maximumInputLength' => get_option( 'wcj_checkout_custom_field_select_select2_max_input_length' . $i, 0 ),
79
+ );
80
+ }
81
+ }
82
+ }
83
+ }
84
+ if ( ! empty( $select2_fields ) ) {
85
+ wp_enqueue_script(
86
+ 'wcj-checkout-custom-fields',
87
+ wcj_plugin_url() . '/includes/js/wcj-checkout-custom-fields.js',
88
+ array( 'jquery' ),
89
+ WCJ()->version,
90
+ true
91
+ );
92
+ wp_localize_script(
93
+ 'wcj-checkout-custom-fields',
94
+ 'wcj_checkout_custom_fields',
95
+ array(
96
+ 'select2_fields' => $select2_fields,
97
+ )
98
+ );
99
+ }
100
+ }
101
+ }
102
+
103
+ /**
104
+ * add_checkout_custom_fields_customer_meta_fields.
105
+ *
106
+ * @version 3.2.4
107
+ * @since 2.4.5
108
+ */
109
+ function add_checkout_custom_fields_customer_meta_fields( $fields ) {
110
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
111
+ if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
112
+ if ( 'no' === get_option( 'wcj_checkout_custom_field_customer_meta_fields_' . $i, 'yes' ) ) {
113
+ continue;
114
+ }
115
+ $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
116
+ $the_key = 'wcj_checkout_field_' . $i;
117
+ $the_name = $the_section . '_' . $the_key;
118
+ $fields[ $the_section ]['fields'][ $the_name ] = array(
119
+ 'label' => get_option( 'wcj_checkout_custom_field_label_' . $i ),
120
+ 'description' => '',
121
+ );
122
+ }
123
+ }
124
+ return $fields;
125
+ }
126
+
127
+ /**
128
+ * add_default_checkout_custom_fields.
129
+ *
130
+ * @version 2.4.5
131
+ * @since 2.4.5
132
+ */
133
+ function add_default_checkout_custom_fields( $default_value, $field_key ) {
134
+ if ( is_user_logged_in() ) {
135
+ $current_user = wp_get_current_user();
136
+ if ( $meta = get_user_meta( $current_user->ID, $field_key, true ) ) {
137
+ return $meta;
138
+ }
139
+ }
140
+ return $default_value;
141
+ }
142
+
143
+ /**
144
+ * woocommerce_form_field_type_number.
145
+ *
146
+ * @version 2.3.0
147
+ * @since 2.3.0
148
+ */
149
+ function woocommerce_form_field_type_number( $field, $key, $args, $value ) {
150
+ if ( isset( $args['custom_attributes']['display'] ) && 'number' === $args['custom_attributes']['display'] ) {
151
+ $field = str_replace( '<input type="text" ', '<input type="number" ', $field );
152
+ }
153
+ return $field;
154
+ }
155
+
156
+ /**
157
+ * add_custom_fields_to_store_exporter_order.
158
+ *
159
+ * @version 2.3.0
160
+ * @since 2.2.7
161
+ */
162
+ function add_custom_fields_to_store_exporter_order( $order, $order_id ) {
163
+ $post_meta = get_post_meta( $order_id );
164
+ foreach( $post_meta as $key => $values ) {
165
+ if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
166
+ if ( false !== strpos( $key, '_label_' ) ) {
167
+ continue;
168
+ }
169
+ $order->$key = isset( $values[0]['value'] ) ? $values[0]['value'] : $values[0];
170
+ }
171
+ }
172
+
173
+ return $order;
174
+ }
175
+
176
+ /**
177
+ * add_custom_fields_to_store_exporter.
178
+ */
179
+ function add_custom_fields_to_store_exporter( $fields ) {
180
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
181
+ if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
182
+ $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
183
+ $the_key = 'wcj_checkout_field_' . $i;
184
+ $fields[] = array(
185
+ 'name' => $the_section . '_' . $the_key,
186
+ 'label' => get_option( 'wcj_checkout_custom_field_label_' . $i ),
187
+ );
188
+ }
189
+ }
190
+ return $fields;
191
+ }
192
+
193
+ /**
194
+ * update_custom_checkout_fields_order_meta.
195
+ *
196
+ * @version 4.6.1
197
+ */
198
+ function update_custom_checkout_fields_order_meta( $order_id ) {
199
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
200
+ if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
201
+ if ( 'woocommerce_checkout_update_order_meta' === current_filter() && ! $this->is_visible( $i ) ) {
202
+ continue;
203
+ }
204
+ $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
205
+ $the_type = get_option( 'wcj_checkout_custom_field_type_' . $i );
206
+ $option_name = $the_section . '_' . 'wcj_checkout_field_' . $i;
207
+ $option_name_label = $the_section . '_' . 'wcj_checkout_field_label_' . $i;
208
+ $option_name_type = $the_section . '_' . 'wcj_checkout_field_type_' . $i;
209
+ $post_value = isset( $_POST[ $option_name ] ) ? $_POST[ $option_name ] : ( isset( $_POST[ '_' . $option_name ] ) ? $_POST[ '_' . $option_name ] : get_post_meta( $order_id, '_' . $option_name, true ) );
210
+ if ( ! empty( $post_value ) || 'checkbox' === $the_type ) {
211
+ update_post_meta( $order_id, '_' . $option_name_type, $the_type );
212
+ update_post_meta( $order_id, '_' . $option_name_label, get_option( 'wcj_checkout_custom_field_label_' . $i ) );
213
+ if ( 'checkbox' === $the_type ) {
214
+ $the_value = ! empty( $post_value ) ? 1 : 0;
215
+ update_post_meta( $order_id, '_' . $option_name, $the_value );
216
+ $option_name_checkbox_value = $the_section . '_' . 'wcj_checkout_field_checkbox_value_' . $i;
217
+ $checkbox_value = ( 1 == $the_value ) ?
218
+ get_option( 'wcj_checkout_custom_field_checkbox_yes_' . $i ) :
219
+ get_option( 'wcj_checkout_custom_field_checkbox_no_' . $i );
220
+ update_post_meta( $order_id, '_' . $option_name_checkbox_value, $checkbox_value );
221
+ } elseif ( 'radio' === $the_type || 'select' === $the_type ) {
222
+ update_post_meta( $order_id, '_' . $option_name, wc_clean( urldecode( $post_value ) ) );
223
+ $option_name_values = $the_section . '_' . 'wcj_checkout_field_select_options_' . $i;
224
+ $the_values = get_option( 'wcj_checkout_custom_field_select_options_' . $i );
225
+ update_post_meta( $order_id, '_' . $option_name_values, $the_values );
226
+ } elseif ( 'textarea' === $the_type && 'no' === get_option( 'wcj_checkout_custom_fields_textarea_clean', 'yes' ) ) {
227
+ update_post_meta( $order_id, '_' . $option_name, urldecode( $post_value ) );
228
+ } else {
229
+ update_post_meta( $order_id, '_' . $option_name, wc_clean( urldecode( $post_value ) ) );
230
+ }
231
+ }
232
+ }
233
+ }
234
+ }
235
+
236
+ /**
237
+ * add_custom_fields_to_emails.
238
+ *
239
+ * @version 3.2.2
240
+ */
241
+ function add_custom_fields_to_emails( $order, $sent_to_admin ) {
242
+ if (
243
+ ( $sent_to_admin && 'yes' === get_option( 'wcj_checkout_custom_fields_email_all_to_admin' ) ) ||
244
+ ( ! $sent_to_admin && 'yes' === get_option( 'wcj_checkout_custom_fields_email_all_to_customer' ) )
245
+ ) {
246
+ $templates = array(
247
+ 'before' => get_option( 'wcj_checkout_custom_fields_emails_template_before', '' ),
248
+ 'field' => get_option( 'wcj_checkout_custom_fields_emails_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
249
+ 'after' => get_option( 'wcj_checkout_custom_fields_emails_template_after', '' ),
250
+ );
251
+ $this->add_custom_fields_to_order_display( $order, '', $templates );
252
+ }
253
+ }
254
+
255
+ /**
256
+ * add_custom_fields_to_view_order_and_thankyou_pages.
257
+ *
258
+ * @version 3.2.2
259
+ * @since 3.2.2
260
+ */
261
+ function add_custom_fields_to_view_order_and_thankyou_pages( $order ) {
262
+ $templates = array(
263
+ 'before' => get_option( 'wcj_checkout_custom_fields_order_received_template_before', '' ),
264
+ 'field' => get_option( 'wcj_checkout_custom_fields_order_received_template_field', '<p><strong>%label%:</strong> %value%</p>' ),
265
+ 'after' => get_option( 'wcj_checkout_custom_fields_order_received_template_after', '' ),
266
+ );
267
+ $this->add_custom_fields_to_order_display( $order, '', $templates );
268
+ }
269
+
270
+ /**
271
+ * add_custom_fields_to_order_display.
272
+ *
273
+ * @version 3.8.0
274
+ * @since 2.3.0
275
+ * @todo convert from before version 2.3.0
276
+ */
277
+ function add_custom_fields_to_order_display( $order, $section = '', $templates ) {
278
+ $post_meta = get_post_meta( wcj_get_order_id( $order ) );
279
+ $final_output = '';
280
+ foreach( $post_meta as $key => $values ) {
281
+ if ( false !== strpos( $key, 'wcj_checkout_field_' ) && isset( $values[0] ) ) {
282
+ // Checking section (if set)
283
+ if ( '' != $section ) {
284
+ $the_section = strtok( $key, '_' );
285
+ if ( $section !== $the_section ) {
286
+ continue;
287
+ }
288
+ }
289
+ // Skipping unnecessary meta
290
+ if (
291
+ false !== strpos( $key, '_label_' ) ||
292
+ false !== strpos( $key, '_type_' ) ||
293
+ false !== strpos( $key, '_checkbox_value_' ) ||
294
+ false !== strpos( $key, '_select_options_' )
295
+ ) {
296
+ continue;
297
+ }
298
+ // Field label
299
+ $label = '';
300
+ $the_label_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_label_', $key );
301
+ if ( isset( $post_meta[ $the_label_key ][0] ) ) {
302
+ $label = $post_meta[ $the_label_key ][0];
303
+ } elseif ( is_array( $values[0] ) && isset( $values[0]['label'] ) ) {
304
+ $label = $values[0]['label'];
305
+ }
306
+ // Field value
307
+ $value = '';
308
+ $_value = ( is_array( $values[0] ) && isset( $values[0]['value'] ) ? $values[0]['value'] : $values[0] );
309
+ $type_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_type_', $key );
310
+ if ( isset( $post_meta[ $type_key ][0] ) && 'checkbox' === $post_meta[ $type_key ][0] ) {
311
+ $checkbox_value_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_checkbox_value_', $key );
312
+ $value = ( isset( $post_meta[ $checkbox_value_key ][0] ) ? $post_meta[ $checkbox_value_key ][0] : $_value );
313
+ } elseif ( isset( $post_meta[ $type_key ][0] ) && ( 'radio' === $post_meta[ $type_key ][0] || 'select' === $post_meta[ $type_key ][0] ) ) {
314
+ $select_values_key = str_replace( 'wcj_checkout_field_', 'wcj_checkout_field_select_options_', $key );
315
+ $select_values = ( isset( $post_meta[ $select_values_key ][0] ) ) ? $post_meta[ $select_values_key ][0] : '';
316
+ if ( ! empty( $select_values ) ) {
317
+ $select_values_prepared = wcj_get_select_options( $select_values );
318
+ $value = ( isset( $select_values_prepared[ $_value ] ) ? $select_values_prepared[ $_value ] : $_value );
319
+ } else {
320
+ $value = $_value;
321
+ }
322
+ } elseif ( isset( $post_meta[ $type_key ][0] ) && 'textarea' === $post_meta[ $type_key ][0] && 'yes' === get_option( 'wcj_checkout_custom_fields_textarea_replace_line_breaks', 'no' ) ) {
323
+ $value = str_replace( PHP_EOL, '<br>', $_value );
324
+ } else {
325
+ $value = $_value;
326
+ }
327
+ // Adding field to final output
328
+ if ( '' != $label || '' != $value ) {
329
+ $replaced_values = array(
330
+ '%label%' => $label,
331
+ '%value%' => $value,
332
+ );
333
+ $final_output .= str_replace( array_keys( $replaced_values ), $replaced_values, $templates['field'] );
334
+ }
335
+ }
336
+ }
337
+ // Outputting
338
+ if ( '' != $final_output ) {
339
+ echo $templates['before'] . $final_output . $templates['after'];
340
+ }
341
+ }
342
+
343
+ /**
344
+ * add_woocommerce_admin_fields.
345
+ *
346
+ * @version 4.7.0
347
+ * @todo converting from before version 2.3.0: section?
348
+ * @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)
349
+ */
350
+ function add_woocommerce_admin_fields( $fields, $section ) {
351
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
352
+ if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
353
+ $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
354
+ if ( $section != $the_section ) {
355
+ continue;
356
+ }
357
+ $the_type = get_option( 'wcj_checkout_custom_field_type_' . $i );
358
+ if ( 'select' === $the_type ) {
359
+ $the_class = 'first';
360
+ $options = wcj_get_select_options( get_option( 'wcj_checkout_custom_field_select_options_' . $i ) );
361
+ } elseif ( 'radio' === $the_type ) {
362
+ $the_options = get_post_meta( get_the_ID(), '_' . $section . '_' . 'wcj_checkout_field_select_options_' . $i, true );
363
+ if ( ! empty( $the_options ) ) {
364
+ $the_type = 'select';
365
+ $the_class = 'first';
366
+ $options = wcj_get_select_options( $the_options );
367
+ } else {
368
+ $the_options = wcj_get_select_options( get_option( 'wcj_checkout_custom_field_select_options_' . $i ) );
369
+ if ( ! empty( $the_options ) ) {
370
+ $the_type = 'select';
371
+ $the_class = 'first';
372
+ $options = $the_options;
373
+ } else {
374
+ $the_type = 'text';
375
+ $the_class = 'short';
376
+ }
377
+ }
378
+ } elseif ( 'country' === $the_type ) {
379
+ $the_type = 'select';
380
+ $the_class = 'js_field-country select short';
381
+ $options = WC()->countries->get_allowed_countries();
382
+ } else {
383
+ $the_type = 'text';
384
+ $the_class = 'short';
385
+ }
386
+ $the_key = 'wcj_checkout_field_' . $i;
387
+ $the_key_label = 'wcj_checkout_field_label_' . $i;
388
+ $the_meta = get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key, true );
389
+ if ( is_array( $the_meta ) ) {
390
+ // Converting from before version 2.3.0
391
+ if ( isset( $the_meta['value'] ) ) {
392
+ update_post_meta( get_the_ID(), '_' . $section . '_' . $the_key, $the_meta['value'] );
393
+ }
394
+ if ( isset( $the_meta['label'] ) ) {
395
+ update_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, $the_meta['label'] );
396
+ }
397
+ }
398
+ if ( ! isset( $_POST[ '_' . $section . '_' . $the_key ] ) ) {
399
+ $fields[ $the_key ] = array(
400
+ 'type' => $the_type,
401
+ 'label' => ( '' != get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, true ) ) ?
402
+ get_post_meta( get_the_ID(), '_' . $section . '_' . $the_key_label, true ) :
403
+ get_option( 'wcj_checkout_custom_field_label_' . $i ),
404
+ 'show' => true,
405
+ 'class' => $the_class,
406
+ 'wrapper_class' => 'form-field-wide',
407
+ );
408
+ if ( ! empty( $the_meta ) && ! is_array( $the_meta ) ) {
409
+ $fields[ $the_key ]['value'] = $the_meta;
410
+ }
411
+ if ( isset( $options ) ) {
412
+ add_filter( "woocommerce_order_get__{$section}_{$the_key}", function ( $name ) use ( $options ) {
413
+ if ( isset( $options[ $name ] ) ) {
414
+ return $options[ $name ];
415
+ }
416
+ return $name;
417
+ } );
418
+ $fields[ $the_key ]['options'] = $options;
419
+ }
420
+ }
421
+ }
422
+ }
423
+ return $fields;
424
+ }
425
+
426
+ /**
427
+ * add_custom_billing_fields_to_admin_order_display.
428
+ */
429
+ function add_custom_billing_fields_to_admin_order_display( $fields ) {
430
+ return $this->add_woocommerce_admin_fields( $fields, 'billing' );
431
+ }
432
+
433
+ /**
434
+ * add_custom_shipping_fields_to_admin_order_display.
435
+ */
436
+ function add_custom_shipping_fields_to_admin_order_display( $fields ) {
437
+ return $this->add_woocommerce_admin_fields( $fields, 'shipping' );
438
+ }
439
+
440
+ /**
441
+ * add_custom_order_and_account_fields_to_admin_order_display
442
+ *
443
+ * @version 3.2.2
444
+ */
445
+ function add_custom_order_and_account_fields_to_admin_order_display( $order ) {
446
+ $templates = array(
447
+ 'before' => '<div class="clear"></div><p>',
448
+ 'field' => '<strong>%label%: </strong>%value%<br>',
449
+ 'after' => '</p>',
450
+ );
451
+ $this->add_custom_fields_to_order_display( $order, 'order', $templates );
452
+ $this->add_custom_fields_to_order_display( $order, 'account', $templates );
453
+ }
454
+
455
+ /**
456
+ * is_visible.
457
+ *
458
+ * @version 4.2.0
459
+ * @since 2.6.0
460
+ * @todo add "user roles to include/exclude"
461
+ */
462
+ function is_visible( $i ) {
463
+
464
+ if ( apply_filters( 'wcj_checkout_custom_field_always_visible_on_empty_cart', false ) && WC()->cart->is_empty() ) {
465
+ // Added for "One Page Checkout" plugin compatibility.
466
+ return true;
467
+ }
468
+
469
+ // Checking categories
470
+ $categories_ex = get_option( 'wcj_checkout_custom_field_categories_ex_' . $i );
471
+ if ( ! empty( $categories_ex ) ) {
472
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
473
+ $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
474
+ if ( empty( $product_categories ) ) {
475
+ continue;
476
+ }
477
+ foreach( $product_categories as $product_category ) {
478
+ if ( in_array( $product_category->term_id, $categories_ex ) ) {
479
+ return false;
480
+ }
481
+ }
482
+ }
483
+ }
484
+ $categories_in = get_option( 'wcj_checkout_custom_field_categories_in_' . $i );
485
+ if ( ! empty( $categories_in ) ) {
486
+ $categories_in_cart = array();
487
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
488
+ $product_categories = wp_get_post_terms( $values['product_id'], 'product_cat', array( "fields" => "ids" ) );
489
+ $categories_in_cart = array_merge( $product_categories, $categories_in_cart );
490
+ }
491
+ if ( count( array_intersect( $categories_in, $categories_in_cart ) ) == 0 ) {
492
+ return false;
493
+ }
494
+ }
495
+
496
+ // Checking products
497
+ $products_ex = get_option( 'wcj_checkout_custom_field_products_ex_' . $i );
498
+ if ( ! empty( $products_ex ) ) {
499
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
500
+ if ( in_array( $values['product_id'], $products_ex ) ) {
501
+ return false;
502
+ }
503
+ }
504
+ }
505
+ $products_in = get_option( 'wcj_checkout_custom_field_products_in_' . $i );
506
+ if ( ! empty( $products_in ) ) {
507
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
508
+ if ( in_array( $values['product_id'], $products_in ) ) {
509
+ return true;
510
+ }
511
+ }
512
+ return false;
513
+ }
514
+
515
+ // Checking min/max cart amount
516
+ $cart_total = false;
517
+ if ( ( $min_cart_amount = get_option( 'wcj_checkout_custom_field_min_cart_amount_' . $i, 0 ) ) > 0 ) {
518
+ WC()->cart->calculate_totals();
519
+ $cart_total = WC()->cart->total;
520
+ if ( $cart_total < $min_cart_amount ) {
521
+ return false;
522
+ }
523
+ }
524
+ if ( ( $max_cart_amount = get_option( 'wcj_checkout_custom_field_max_cart_amount_' . $i, 0 ) ) > 0 ) {
525
+ if ( false === $cart_total ) {
526
+ WC()->cart->calculate_totals();
527
+ $cart_total = WC()->cart->total;
528
+ }
529
+ if ( $cart_total > $max_cart_amount ) {
530
+ return false;
531
+ }
532
+ }
533
+
534
+ // All passed
535
+ return apply_filters( 'wcj_checkout_custom_field_visible', true, $i );
536
+ }
537
+
538
+ /**
539
+ * add_custom_checkout_fields.
540
+ *
541
+ * @version 3.8.0
542
+ * @todo (maybe) fix - priority seems to not affect tab order (same in Checkout Core Fields module)
543
+ * @todo (dev) (maybe) add `do_shortcode` for e.g. `description` etc.
544
+ */
545
+ function add_custom_checkout_fields( $fields ) {
546
+
547
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_fields_total_number', 1 ) ); $i++ ) {
548
+
549
+ if ( 'yes' === get_option( 'wcj_checkout_custom_field_enabled_' . $i ) ) {
550
+
551
+ if ( ! $this->is_visible( $i ) ) {
552
+ continue;
553
+ }
554
+
555
+ $the_type = get_option( 'wcj_checkout_custom_field_type_' . $i );
556
+ $custom_attributes = array();
557
+ if ( 'datepicker' === $the_type || 'weekpicker' === $the_type || 'timepicker' === $the_type || 'number' === $the_type ) {
558
+ if ( 'datepicker' === $the_type || 'weekpicker' === $the_type ) {
559
+ $datepicker_format_option = get_option( 'wcj_checkout_custom_field_datepicker_format_' . $i, '' );
560
+ $datepicker_format = ( '' == $datepicker_format_option ) ? get_option( 'date_format' ) : $datepicker_format_option;
561
+ $datepicker_format = wcj_date_format_php_to_js( $datepicker_format );
562
+ $custom_attributes['dateformat'] = $datepicker_format;
563
+ $custom_attributes['mindate'] = get_option( 'wcj_checkout_custom_field_datepicker_mindate_' . $i, -365 );
564
+ if ( 0 == $custom_attributes['mindate'] ) {
565
+ $custom_attributes['mindate'] = 'zero';
566
+ }
567
+ $custom_attributes['maxdate'] = get_option( 'wcj_checkout_custom_field_datepicker_maxdate_' . $i, 365 );
568
+ if ( 0 == $custom_attributes['maxdate'] ) {
569
+ $custom_attributes['maxdate'] = 'zero';
570
+ }
571
+ $custom_attributes['firstday'] = get_option( 'wcj_checkout_custom_field_datepicker_firstday_' . $i, 0 );
572
+ if ( 'yes' === get_option( 'wcj_checkout_custom_field_datepicker_changeyear_' . $i, 'yes' ) ) {
573
+ $custom_attributes['changeyear'] = 1;
574
+ $custom_attributes['yearrange'] = get_option( 'wcj_checkout_custom_field_datepicker_yearrange_' . $i, 'c-10:c+10' );
575
+ }
576
+ $custom_attributes['display'] = ( 'datepicker' === $the_type ) ? 'date' : 'week';
577
+ } elseif ( 'timepicker' === $the_type ) {
578
+ $custom_attributes['timeformat'] = get_option( 'wcj_checkout_custom_field_timepicker_format_' . $i, 'hh:mm p' );
579
+ $custom_attributes['interval'] = get_option( 'wcj_checkout_custom_field_timepicker_interval_' . $i, 15 );
580
+ $custom_attributes['display'] = 'time';
581
+ } else { // 'number'
582
+ $custom_attributes['display'] = $the_type;
583
+ }
584
+ $the_type = 'text';
585
+ }
586
+ $the_section = get_option( 'wcj_checkout_custom_field_section_' . $i );
587
+ $the_key = 'wcj_checkout_field_' . $i;
588
+
589
+ $the_field = array(
590
+ 'type' => $the_type,
591
+ 'label' => get_option( 'wcj_checkout_custom_field_label_' . $i ),
592
+ 'placeholder' => get_option( 'wcj_checkout_custom_field_placeholder_' . $i ),
593
+ 'required' => ( 'yes' === get_option( 'wcj_checkout_custom_field_required_' . $i ) ),
594
+ 'custom_attributes' => $custom_attributes,
595
+ 'clear' => ( 'yes' === get_option( 'wcj_checkout_custom_field_clear_' . $i ) ),
596
+ 'class' => array( get_option( 'wcj_checkout_custom_field_class_' . $i ) ),
597
+ 'priority' => get_option( 'wcj_checkout_custom_field_priority_' . $i, '' ),
598
+ 'description' => get_option( 'wcj_checkout_custom_field_description_' . $i, '' ),
599
+ );
600
+
601
+ if ( 'select' === $the_type || 'radio' === $the_type ) {
602
+ $select_options_raw = get_option( 'wcj_checkout_custom_field_select_options_' . $i );
603
+ $select_options = wcj_get_select_options( $select_options_raw );
604
+ if ( 'select' === $the_type ) {
605
+ $placeholder = get_option( 'wcj_checkout_custom_field_placeholder_' . $i );
606
+ if ( '' != $placeholder ) {
607
+ $select_options = array_replace( array( '' => $placeholder ), $select_options );
608
+ }
609
+ }
610
+ $the_field['options'] = $select_options;
611
+ if ( ! empty( $select_options ) ) {
612
+ reset( $select_options );
613
+ $the_field['default'] = key( $select_options );
614
+ }
615
+ }
616
+
617
+ if ( 'checkbox' === $the_type ) {
618
+ $the_field['default'] = ( 'yes' === get_option( 'wcj_checkout_custom_field_checkbox_default_' . $i ) ) ? 1 : 0;
619
+ }
620
+
621
+ $fields[ $the_section ][ $the_section . '_' . $the_key ] = $the_field;
622
+ }
623
+ }
624
+ return $fields;
625
+ }
626
+
627
+ }
628
+
629
+ endif;
630
+
631
+ return new WCJ_Checkout_Custom_Fields();
includes/class-wcj-checkout-custom-info.php CHANGED
@@ -1,64 +1,64 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Checkout Custom Info
4
- *
5
- * @version 2.8.0
6
- * @since 2.2.0
7
- * @author Algoritmika Ltd.
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 2.8.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.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-checkout-custom-info';
27
- parent::__construct();
28
-
29
- if ( $this->is_enabled() ) {
30
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_info_total_number', 1 ) ); $i++) {
31
- add_action(
32
- get_option( 'wcj_checkout_custom_info_hook_' . $i, 'woocommerce_checkout_after_order_review' ),
33
- array( $this, 'add_checkout_custom_info' ),
34
- get_option( 'wcj_checkout_custom_info_priority_' . $i, 10 )
35
- );
36
- }
37
- }
38
- }
39
-
40
- /**
41
- * add_checkout_custom_info.
42
- *
43
- * @version 2.4.7
44
- */
45
- function add_checkout_custom_info() {
46
- $current_filter = current_filter();
47
- $current_filter_priority = wcj_current_filter_priority();
48
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_info_total_number', 1 ) );
49
- for ( $i = 1; $i <= $total_number; $i++ ) {
50
- if (
51
- '' != get_option( 'wcj_checkout_custom_info_content_' . $i ) &&
52
- $current_filter === get_option( 'wcj_checkout_custom_info_hook_' . $i ) &&
53
- $current_filter_priority == get_option( 'wcj_checkout_custom_info_priority_' . $i, 10 )
54
- ) {
55
- echo do_shortcode( get_option( 'wcj_checkout_custom_info_content_' . $i ) );
56
- }
57
- }
58
- }
59
-
60
- }
61
-
62
- endif;
63
-
64
- return new WCJ_Checkout_Custom_Info();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Checkout Custom Info
4
+ *
5
+ * @version 2.8.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 2.8.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.', 'woocommerce-jetpack' );
26
+ $this->link_slug = 'woocommerce-checkout-custom-info';
27
+ parent::__construct();
28
+
29
+ if ( $this->is_enabled() ) {
30
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_info_total_number', 1 ) ); $i++) {
31
+ add_action(
32
+ get_option( 'wcj_checkout_custom_info_hook_' . $i, 'woocommerce_checkout_after_order_review' ),
33
+ array( $this, 'add_checkout_custom_info' ),
34
+ get_option( 'wcj_checkout_custom_info_priority_' . $i, 10 )
35
+ );
36
+ }
37
+ }
38
+ }
39
+
40
+ /**
41
+ * add_checkout_custom_info.
42
+ *
43
+ * @version 2.4.7
44
+ */
45
+ function add_checkout_custom_info() {
46
+ $current_filter = current_filter();
47
+ $current_filter_priority = wcj_current_filter_priority();
48
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_custom_info_total_number', 1 ) );
49
+ for ( $i = 1; $i <= $total_number; $i++ ) {
50
+ if (
51
+ '' != get_option( 'wcj_checkout_custom_info_content_' . $i ) &&
52
+ $current_filter === get_option( 'wcj_checkout_custom_info_hook_' . $i ) &&
53
+ $current_filter_priority == get_option( 'wcj_checkout_custom_info_priority_' . $i, 10 )
54
+ ) {
55
+ echo do_shortcode( get_option( 'wcj_checkout_custom_info_content_' . $i ) );
56
+ }
57
+ }
58
+ }
59
+
60
+ }
61
+
62
+ endif;
63
+
64
+ return new WCJ_Checkout_Custom_Info();
includes/class-wcj-checkout-customization.php CHANGED
@@ -1,308 +1,308 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Checkout Customization
4
- *
5
- * @version 4.6.0
6
- * @since 2.7.0
7
- * @author Algoritmika Ltd.
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 4.1.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; hide "Order Again" button; disable selected fields on checkout for logged users and more.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-checkout-customization';
28
- parent::__construct();
29
-
30
- if ( $this->is_enabled() ) {
31
- // "Create an account?" Checkbox
32
- if ( 'default' != ( $create_account_default = get_option( 'wcj_checkout_create_account_default_checked', 'default' ) ) ) {
33
- if ( 'checked' === $create_account_default ) {
34
- add_filter( 'woocommerce_create_account_default_checked', '__return_true' );
35
- } elseif ( 'not_checked' === $create_account_default ) {
36
- add_filter( 'woocommerce_create_account_default_checked', '__return_false' );
37
- }
38
- }
39
- // Hide "Order Again" button
40
- if ( 'yes' === get_option( 'wcj_checkout_hide_order_again', 'no' ) ) {
41
- add_action( 'init', array( $this, 'checkout_hide_order_again' ), PHP_INT_MAX );
42
- }
43
- // Disable Fields on Checkout for Logged Users
44
- add_filter( 'woocommerce_checkout_fields' , array( $this, 'maybe_disable_fields' ), PHP_INT_MAX );
45
- $checkout_fields_types = array(
46
- 'country',
47
- 'state',
48
- 'textarea',
49
- 'checkbox',
50
- 'password',
51
- 'text',
52
- 'email',
53
- 'tel',
54
- 'number',
55
- 'select',
56
- 'radio',
57
- );
58
- foreach ( $checkout_fields_types as $checkout_fields_type ) {
59
- add_filter( 'woocommerce_form_field_' . $checkout_fields_type, array( $this, 'maybe_add_description' ), PHP_INT_MAX, 4 );
60
- }
61
- // Custom "order received" message text
62
- if ( 'yes' === get_option( 'wcj_checkout_customization_order_received_message_enabled', 'no' ) ) {
63
- add_filter( 'woocommerce_thankyou_order_received_text', array( $this, 'customize_order_received_message' ), PHP_INT_MAX, 2 );
64
- }
65
- // Custom checkout login message
66
- if ( 'yes' === get_option( 'wcj_checkout_customization_checkout_login_message_enabled', 'no' ) ) {
67
- add_filter( 'woocommerce_checkout_login_message', array( $this, 'checkout_login_message' ), PHP_INT_MAX );
68
- }
69
- // Restrict countries by customer's IP
70
- if ( 'yes' === get_option( 'wcj_checkout_restrict_countries_by_customer_ip_billing', 'no' ) ) {
71
- add_filter( 'woocommerce_countries_allowed_countries', array( $this, 'restrict_countries_by_customer_ip' ), PHP_INT_MAX );
72
- }
73
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_checkout_restrict_countries_by_customer_ip_shipping', 'no' ) ) ) {
74
- add_filter( 'woocommerce_countries_shipping_countries', array( $this, 'restrict_countries_by_customer_ip' ), PHP_INT_MAX );
75
- }
76
- // Recalculate Checkout
77
- if ( 'yes' === get_option( 'wcj_checkout_recalculate_checkout_update_enable', 'no' ) ) {
78
- add_action( 'wp_footer', array( $this, 'recalculate_checkout' ), 50 );
79
- }
80
- // Update Checkout
81
- if ( 'yes' === get_option( 'wcj_checkout_force_checkout_update_enable', 'no' ) ) {
82
- add_action( 'wp_footer', array( $this, 'update_checkout' ), 50 );
83
- }
84
- }
85
- }
86
-
87
- /**
88
- * Updates checkout.
89
- *
90
- * @version 4.1.0
91
- * @since 4.1.0
92
- */
93
- function update_checkout() {
94
- if ( ! is_checkout() ) {
95
- return;
96
- }
97
- ?>
98
- <script type="text/javascript">
99
- jQuery(function ($) {
100
- var selector = <?php echo wp_json_encode( get_option( 'wcj_checkout_force_checkout_update_fields', '' ) ); ?>;
101
- jQuery(selector).on('change', function () {
102
- $('body').trigger('update_checkout');
103
- });
104
- });
105
- </script>
106
- <?php
107
- }
108
-
109
- /**
110
- * Recalculates checkout.
111
- *
112
- * @version 4.1.0
113
- * @since 4.1.0
114
- */
115
- function recalculate_checkout() {
116
- if ( ! is_checkout() ) {
117
- return;
118
- }
119
- ?>
120
- <script type="text/javascript">
121
- jQuery(function ($) {
122
- var old_values = [];
123
- var selector = <?php echo wp_json_encode( get_option( 'wcj_checkout_recalculate_checkout_update_fields', '#billing_country, #shipping_country' ) ); ?>;
124
- jQuery(document.body).on("updated_checkout", function () {
125
- jQuery(selector).each(function (index) {
126
- if (old_values[index] != $(this).val()) {
127
- $('body').trigger('update_checkout');
128
- }
129
- old_values[index] = $(this).val();
130
- });
131
- });
132
- });
133
- </script>
134
- <?php
135
- }
136
-
137
- /**
138
- * Checks if conditions are valid in order for the country restriction to work.
139
- *
140
- * @version 4.6.0
141
- * @since 4.6.0
142
- *
143
- * @return bool
144
- */
145
- function are_conditions_valid() {
146
- $valid = false;
147
- $conditions = $this->get_option( 'wcj_checkout_restrict_countries_by_customer_ip_conditions', array() );
148
- foreach ( $conditions as $key => $condition ) {
149
- $function = $condition;
150
- $valid = $function();
151
- if ( $valid ) {
152
- break;
153
- }
154
- }
155
- return $valid;
156
- }
157
-
158
- /**
159
- * restrict_countries_by_customer_ip.
160
- *
161
- * @version 4.6.0
162
- * @since 3.4.0
163
- * @todo (maybe) handle case when `wcj_get_country_by_ip()` returns empty string
164
- * @todo (maybe) for shipping countries - filter `woocommerce_ship_to_countries` option
165
- */
166
- function restrict_countries_by_customer_ip( $countries ) {
167
- if (
168
- ( 'yes' === $this->get_option( 'wcj_checkout_restrict_countries_by_customer_ip_ignore_admin', 'no' ) && is_admin() ) ||
169
- ( ! empty( $this->get_option( 'wcj_checkout_restrict_countries_by_customer_ip_conditions', array() ) ) && ! $this->are_conditions_valid() )
170
- ) {
171
- return $countries;
172
- }
173
- $user_country = wcj_get_country_by_ip();
174
-
175
- // Get country from 'billing_country' user meta
176
- if (
177
- 'yes' === get_option( 'wcj_checkout_restrict_countries_by_user_billing_country', 'no' ) &&
178
- 0 != ( $user_id = get_current_user_id() )
179
- ) {
180
- $user_country = ! empty( $user_billing_country = get_user_meta( $user_id, 'billing_country', true ) ) ? $user_billing_country : wcj_get_country_by_ip();
181
- }
182
-
183
- // Get country from a manual order ID created by YITH Request a Quote plugin
184
- if ( 'yes' === get_option( 'wcj_checkout_restrict_countries_based_on_yith_raq', 'no' ) && class_exists( 'YITH_Request_Quote' ) ) {
185
- $yith_order_id = WC()->session->get( 'order_awaiting_payment' );
186
- if ( ! empty( $yith_order_id ) ) {
187
- $user_country = ! empty( $order_billing_country = get_post_meta( $yith_order_id, '_billing_country', true ) ) ? $order_billing_country : wcj_get_country_by_ip();
188
- }
189
- }
190
- return array( $user_country => wcj_get_country_name_by_code( $user_country ) );
191
- }
192
-
193
- /**
194
- * checkout_login_message.
195
- *
196
- * @version 3.3.0
197
- * @since 3.3.0
198
- */
199
- function checkout_login_message( $message ) {
200
- return get_option( 'wcj_checkout_customization_checkout_login_message', __( 'Returning customer?', 'woocommerce' ) );
201
- }
202
-
203
- /**
204
- * customize_order_received_message.
205
- *
206
- * @version 3.1.0
207
- * @since 3.1.0
208
- */
209
- function customize_order_received_message( $message, $_order ) {
210
- if ( null != $_order ) {
211
- global $post;
212
- $post = get_post( wcj_get_order_id( $_order ) );
213
- setup_postdata( $post );
214
- }
215
- $message = do_shortcode( get_option( 'wcj_checkout_customization_order_received_message', __( 'Thank you. Your order has been received.', 'woocommerce' ) ) );
216
- if ( null != $_order ) {
217
- wp_reset_postdata();
218
- }
219
- return $message;
220
- }
221
-
222
- /**
223
- * maybe_add_description.
224
- *
225
- * @version 3.8.0
226
- * @since 2.9.0
227
- */
228
- function maybe_add_description( $field, $key, $args, $value ) {
229
- if ( is_user_logged_in() ) {
230
- $fields_to_disable = get_option( 'wcj_checkout_customization_disable_fields_for_logged', array() );
231
- if ( empty( $fields_to_disable ) ) {
232
- $fields_to_disable = array();
233
- }
234
- $fields_to_disable_custom_r = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_r', '' ) ) ) );
235
- $fields_to_disable_custom_d = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_d', '' ) ) ) );
236
- $fields_to_disable = array_merge( $fields_to_disable, $fields_to_disable_custom_r, $fields_to_disable_custom_d );
237
- if ( ! empty( $fields_to_disable ) ) {
238
- if ( in_array( $key, $fields_to_disable ) ) {
239
- $desc = get_option( 'wcj_checkout_customization_disable_fields_for_logged_message',
240
- '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>' );
241
- if ( '' != $desc ) {
242
- $field = str_replace( '__WCJ_TEMPORARY_VALUE_TO_REPLACE__', $desc, $field );
243
- }
244
- }
245
- }
246
- }
247
- return $field;
248
- }
249
-
250
- /**
251
- * maybe_disable_fields.
252
- *
253
- * @version 3.8.0
254
- * @since 2.9.0
255
- * @see woocommerce_form_field
256
- * @todo (maybe) add single option (probably checkbox) to disable all fields
257
- * @todo (maybe) on `'billing_country', 'shipping_country'` change to simple `select` (i.e. probably remove `wc-enhanced-select` class)
258
- */
259
- function maybe_disable_fields( $checkout_fields ) {
260
- if ( is_user_logged_in() ) {
261
- $fields_to_disable = get_option( 'wcj_checkout_customization_disable_fields_for_logged', array() );
262
- if ( empty( $fields_to_disable ) ) {
263
- $fields_to_disable = array();
264
- }
265
- $fields_to_disable_custom_r = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_r', '' ) ) ) );
266
- $fields_to_disable_custom_d = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_d', '' ) ) ) );
267
- $fields_to_disable = array_merge( $fields_to_disable, $fields_to_disable_custom_r, $fields_to_disable_custom_d );
268
- $disable_type_fields = array_merge( array( 'billing_country', 'shipping_country' ), $fields_to_disable_custom_d );
269
- $do_add_desc_placeholder = ( '' != get_option( 'wcj_checkout_customization_disable_fields_for_logged_message',
270
- '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>' ) );
271
- if ( ! empty( $fields_to_disable ) ) {
272
- foreach ( $fields_to_disable as $field_to_disable ) {
273
- $section = explode( '_', $field_to_disable );
274
- $section = $section[0];
275
- if ( isset( $checkout_fields[ $section ][ $field_to_disable ] ) ) {
276
- if ( ! isset( $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] ) ) {
277
- $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] = array();
278
- }
279
- $custom_attributes = ( in_array( $field_to_disable, $disable_type_fields ) ? array( 'disabled' => 'disabled' ) : array( 'readonly' => 'readonly' ) );
280
- $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] = array_merge(
281
- $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'],
282
- $custom_attributes
283
- );
284
- if ( $do_add_desc_placeholder ) {
285
- $checkout_fields[ $section ][ $field_to_disable ]['description'] = '__WCJ_TEMPORARY_VALUE_TO_REPLACE__';
286
- }
287
- }
288
- }
289
- }
290
- }
291
- return $checkout_fields;
292
- }
293
-
294
- /**
295
- * checkout_hide_order_again.
296
- *
297
- * @version 2.6.0
298
- * @since 2.6.0
299
- */
300
- function checkout_hide_order_again() {
301
- remove_action( 'woocommerce_order_details_after_order_table', 'woocommerce_order_again_button' );
302
- }
303
-
304
- }
305
-
306
- endif;
307
-
308
- return new WCJ_Checkout_Customization();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Checkout Customization
4
+ *
5
+ * @version 4.6.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 4.1.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; hide "Order Again" button; disable selected fields on checkout for logged users and more.', 'woocommerce-jetpack' );
27
+ $this->link_slug = 'woocommerce-checkout-customization';
28
+ parent::__construct();
29
+
30
+ if ( $this->is_enabled() ) {
31
+ // "Create an account?" Checkbox
32
+ if ( 'default' != ( $create_account_default = get_option( 'wcj_checkout_create_account_default_checked', 'default' ) ) ) {
33
+ if ( 'checked' === $create_account_default ) {
34
+ add_filter( 'woocommerce_create_account_default_checked', '__return_true' );
35
+ } elseif ( 'not_checked' === $create_account_default ) {
36
+ add_filter( 'woocommerce_create_account_default_checked', '__return_false' );
37
+ }
38
+ }
39
+ // Hide "Order Again" button
40
+ if ( 'yes' === get_option( 'wcj_checkout_hide_order_again', 'no' ) ) {
41
+ add_action( 'init', array( $this, 'checkout_hide_order_again' ), PHP_INT_MAX );
42
+ }
43
+ // Disable Fields on Checkout for Logged Users
44
+ add_filter( 'woocommerce_checkout_fields' , array( $this, 'maybe_disable_fields' ), PHP_INT_MAX );
45
+ $checkout_fields_types = array(
46
+ 'country',
47
+ 'state',
48
+ 'textarea',
49
+ 'checkbox',
50
+ 'password',
51
+ 'text',
52
+ 'email',
53
+ 'tel',
54
+ 'number',
55
+ 'select',
56
+ 'radio',
57
+ );
58
+ foreach ( $checkout_fields_types as $checkout_fields_type ) {
59
+ add_filter( 'woocommerce_form_field_' . $checkout_fields_type, array( $this, 'maybe_add_description' ), PHP_INT_MAX, 4 );
60
+ }
61
+ // Custom "order received" message text
62
+ if ( 'yes' === get_option( 'wcj_checkout_customization_order_received_message_enabled', 'no' ) ) {
63
+ add_filter( 'woocommerce_thankyou_order_received_text', array( $this, 'customize_order_received_message' ), PHP_INT_MAX, 2 );
64
+ }
65
+ // Custom checkout login message
66
+ if ( 'yes' === get_option( 'wcj_checkout_customization_checkout_login_message_enabled', 'no' ) ) {
67
+ add_filter( 'woocommerce_checkout_login_message', array( $this, 'checkout_login_message' ), PHP_INT_MAX );
68
+ }
69
+ // Restrict countries by customer's IP
70
+ if ( 'yes' === get_option( 'wcj_checkout_restrict_countries_by_customer_ip_billing', 'no' ) ) {
71
+ add_filter( 'woocommerce_countries_allowed_countries', array( $this, 'restrict_countries_by_customer_ip' ), PHP_INT_MAX );
72
+ }
73
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_checkout_restrict_countries_by_customer_ip_shipping', 'no' ) ) ) {
74
+ add_filter( 'woocommerce_countries_shipping_countries', array( $this, 'restrict_countries_by_customer_ip' ), PHP_INT_MAX );
75
+ }
76
+ // Recalculate Checkout
77
+ if ( 'yes' === get_option( 'wcj_checkout_recalculate_checkout_update_enable', 'no' ) ) {
78
+ add_action( 'wp_footer', array( $this, 'recalculate_checkout' ), 50 );
79
+ }
80
+ // Update Checkout
81
+ if ( 'yes' === get_option( 'wcj_checkout_force_checkout_update_enable', 'no' ) ) {
82
+ add_action( 'wp_footer', array( $this, 'update_checkout' ), 50 );
83
+ }
84
+ }
85
+ }
86
+
87
+ /**
88
+ * Updates checkout.
89
+ *
90
+ * @version 4.1.0
91
+ * @since 4.1.0
92
+ */
93
+ function update_checkout() {
94
+ if ( ! is_checkout() ) {
95
+ return;
96
+ }
97
+ ?>
98
+ <script type="text/javascript">
99
+ jQuery(function ($) {
100
+ var selector = <?php echo wp_json_encode( get_option( 'wcj_checkout_force_checkout_update_fields', '' ) ); ?>;
101
+ jQuery(selector).on('change', function () {
102
+ $('body').trigger('update_checkout');
103
+ });
104
+ });
105
+ </script>
106
+ <?php
107
+ }
108
+
109
+ /**
110
+ * Recalculates checkout.
111
+ *
112
+ * @version 4.1.0
113
+ * @since 4.1.0
114
+ */
115
+ function recalculate_checkout() {
116
+ if ( ! is_checkout() ) {
117
+ return;
118
+ }
119
+ ?>
120
+ <script type="text/javascript">
121
+ jQuery(function ($) {
122
+ var old_values = [];
123
+ var selector = <?php echo wp_json_encode( get_option( 'wcj_checkout_recalculate_checkout_update_fields', '#billing_country, #shipping_country' ) ); ?>;
124
+ jQuery(document.body).on("updated_checkout", function () {
125
+ jQuery(selector).each(function (index) {
126
+ if (old_values[index] != $(this).val()) {
127
+ $('body').trigger('update_checkout');
128
+ }
129
+ old_values[index] = $(this).val();
130
+ });
131
+ });
132
+ });
133
+ </script>
134
+ <?php
135
+ }
136
+
137
+ /**
138
+ * Checks if conditions are valid in order for the country restriction to work.
139
+ *
140
+ * @version 4.6.0
141
+ * @since 4.6.0
142
+ *
143
+ * @return bool
144
+ */
145
+ function are_conditions_valid() {
146
+ $valid = false;
147
+ $conditions = $this->get_option( 'wcj_checkout_restrict_countries_by_customer_ip_conditions', array() );
148
+ foreach ( $conditions as $key => $condition ) {
149
+ $function = $condition;
150
+ $valid = $function();
151
+ if ( $valid ) {
152
+ break;
153
+ }
154
+ }
155
+ return $valid;
156
+ }
157
+
158
+ /**
159
+ * restrict_countries_by_customer_ip.
160
+ *
161
+ * @version 4.6.0
162
+ * @since 3.4.0
163
+ * @todo (maybe) handle case when `wcj_get_country_by_ip()` returns empty string
164
+ * @todo (maybe) for shipping countries - filter `woocommerce_ship_to_countries` option
165
+ */
166
+ function restrict_countries_by_customer_ip( $countries ) {
167
+ if (
168
+ ( 'yes' === $this->get_option( 'wcj_checkout_restrict_countries_by_customer_ip_ignore_admin', 'no' ) && is_admin() ) ||
169
+ ( ! empty( $this->get_option( 'wcj_checkout_restrict_countries_by_customer_ip_conditions', array() ) ) && ! $this->are_conditions_valid() )
170
+ ) {
171
+ return $countries;
172
+ }
173
+ $user_country = wcj_get_country_by_ip();
174
+
175
+ // Get country from 'billing_country' user meta
176
+ if (
177
+ 'yes' === get_option( 'wcj_checkout_restrict_countries_by_user_billing_country', 'no' ) &&
178
+ 0 != ( $user_id = get_current_user_id() )
179
+ ) {
180
+ $user_country = ! empty( $user_billing_country = get_user_meta( $user_id, 'billing_country', true ) ) ? $user_billing_country : wcj_get_country_by_ip();
181
+ }
182
+
183
+ // Get country from a manual order ID created by YITH Request a Quote plugin
184
+ if ( 'yes' === get_option( 'wcj_checkout_restrict_countries_based_on_yith_raq', 'no' ) && class_exists( 'YITH_Request_Quote' ) ) {
185
+ $yith_order_id = WC()->session->get( 'order_awaiting_payment' );
186
+ if ( ! empty( $yith_order_id ) ) {
187
+ $user_country = ! empty( $order_billing_country = get_post_meta( $yith_order_id, '_billing_country', true ) ) ? $order_billing_country : wcj_get_country_by_ip();
188
+ }
189
+ }
190
+ return array( $user_country => wcj_get_country_name_by_code( $user_country ) );
191
+ }
192
+
193
+ /**
194
+ * checkout_login_message.
195
+ *
196
+ * @version 3.3.0
197
+ * @since 3.3.0
198
+ */
199
+ function checkout_login_message( $message ) {
200
+ return get_option( 'wcj_checkout_customization_checkout_login_message', __( 'Returning customer?', 'woocommerce' ) );
201
+ }
202
+
203
+ /**
204
+ * customize_order_received_message.
205
+ *
206
+ * @version 3.1.0
207
+ * @since 3.1.0
208
+ */
209
+ function customize_order_received_message( $message, $_order ) {
210
+ if ( null != $_order ) {
211
+ global $post;
212
+ $post = get_post( wcj_get_order_id( $_order ) );
213
+ setup_postdata( $post );
214
+ }
215
+ $message = do_shortcode( get_option( 'wcj_checkout_customization_order_received_message', __( 'Thank you. Your order has been received.', 'woocommerce' ) ) );
216
+ if ( null != $_order ) {
217
+ wp_reset_postdata();
218
+ }
219
+ return $message;
220
+ }
221
+
222
+ /**
223
+ * maybe_add_description.
224
+ *
225
+ * @version 3.8.0
226
+ * @since 2.9.0
227
+ */
228
+ function maybe_add_description( $field, $key, $args, $value ) {
229
+ if ( is_user_logged_in() ) {
230
+ $fields_to_disable = get_option( 'wcj_checkout_customization_disable_fields_for_logged', array() );
231
+ if ( empty( $fields_to_disable ) ) {
232
+ $fields_to_disable = array();
233
+ }
234
+ $fields_to_disable_custom_r = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_r', '' ) ) ) );
235
+ $fields_to_disable_custom_d = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_d', '' ) ) ) );
236
+ $fields_to_disable = array_merge( $fields_to_disable, $fields_to_disable_custom_r, $fields_to_disable_custom_d );
237
+ if ( ! empty( $fields_to_disable ) ) {
238
+ if ( in_array( $key, $fields_to_disable ) ) {
239
+ $desc = get_option( 'wcj_checkout_customization_disable_fields_for_logged_message',
240
+ '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>' );
241
+ if ( '' != $desc ) {
242
+ $field = str_replace( '__WCJ_TEMPORARY_VALUE_TO_REPLACE__', $desc, $field );
243
+ }
244
+ }
245
+ }
246
+ }
247
+ return $field;
248
+ }
249
+
250
+ /**
251
+ * maybe_disable_fields.
252
+ *
253
+ * @version 3.8.0
254
+ * @since 2.9.0
255
+ * @see woocommerce_form_field
256
+ * @todo (maybe) add single option (probably checkbox) to disable all fields
257
+ * @todo (maybe) on `'billing_country', 'shipping_country'` change to simple `select` (i.e. probably remove `wc-enhanced-select` class)
258
+ */
259
+ function maybe_disable_fields( $checkout_fields ) {
260
+ if ( is_user_logged_in() ) {
261
+ $fields_to_disable = get_option( 'wcj_checkout_customization_disable_fields_for_logged', array() );
262
+ if ( empty( $fields_to_disable ) ) {
263
+ $fields_to_disable = array();
264
+ }
265
+ $fields_to_disable_custom_r = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_r', '' ) ) ) );
266
+ $fields_to_disable_custom_d = array_map( 'trim', explode( ',', apply_filters( 'booster_option', '', get_option( 'wcj_checkout_customization_disable_fields_for_logged_custom_d', '' ) ) ) );
267
+ $fields_to_disable = array_merge( $fields_to_disable, $fields_to_disable_custom_r, $fields_to_disable_custom_d );
268
+ $disable_type_fields = array_merge( array( 'billing_country', 'shipping_country' ), $fields_to_disable_custom_d );
269
+ $do_add_desc_placeholder = ( '' != get_option( 'wcj_checkout_customization_disable_fields_for_logged_message',
270
+ '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>' ) );
271
+ if ( ! empty( $fields_to_disable ) ) {
272
+ foreach ( $fields_to_disable as $field_to_disable ) {
273
+ $section = explode( '_', $field_to_disable );
274
+ $section = $section[0];
275
+ if ( isset( $checkout_fields[ $section ][ $field_to_disable ] ) ) {
276
+ if ( ! isset( $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] ) ) {
277
+ $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] = array();
278
+ }
279
+ $custom_attributes = ( in_array( $field_to_disable, $disable_type_fields ) ? array( 'disabled' => 'disabled' ) : array( 'readonly' => 'readonly' ) );
280
+ $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'] = array_merge(
281
+ $checkout_fields[ $section ][ $field_to_disable ]['custom_attributes'],
282
+ $custom_attributes
283
+ );
284
+ if ( $do_add_desc_placeholder ) {
285
+ $checkout_fields[ $section ][ $field_to_disable ]['description'] = '__WCJ_TEMPORARY_VALUE_TO_REPLACE__';
286
+ }
287
+ }
288
+ }
289
+ }
290
+ }
291
+ return $checkout_fields;
292
+ }
293
+
294
+ /**
295
+ * checkout_hide_order_again.
296
+ *
297
+ * @version 2.6.0
298
+ * @since 2.6.0
299
+ */
300
+ function checkout_hide_order_again() {
301
+ remove_action( 'woocommerce_order_details_after_order_table', 'woocommerce_order_again_button' );
302
+ }
303
+
304
+ }
305
+
306
+ endif;
307
+
308
+ return new WCJ_Checkout_Customization();
includes/class-wcj-checkout-fees.php CHANGED
@@ -1,280 +1,280 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Checkout Fees
4
- *
5
- * @version 4.6.1
6
- * @since 3.7.0
7
- * @author Algoritmika Ltd.
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 4.5.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.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-checkout-fees';
29
- parent::__construct();
30
-
31
- if ( $this->is_enabled() ) {
32
- // Core function
33
- add_action( 'woocommerce_cart_calculate_fees', array( $this, 'add_fees' ), PHP_INT_MAX );
34
- // Checkout fields
35
- $this->checkout_fields = $this->get_option( 'wcj_checkout_fees_data_checkout_fields', array() );
36
- $this->checkout_fields = array_filter( $this->checkout_fields );
37
- if ( ! empty( $this->checkout_fields ) ) {
38
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
39
- }
40
- }
41
- }
42
-
43
- /**
44
- * enqueue_scripts.
45
- *
46
- * @version 3.8.0
47
- * @since 3.8.0
48
- */
49
- function enqueue_scripts() {
50
- if ( is_checkout() ) {
51
- wp_enqueue_script( 'wcj-checkout-fees', wcj_plugin_url() . '/includes/js/wcj-checkout-fees.js', array( 'jquery' ), WCJ()->version, true );
52
- wp_localize_script( 'wcj-checkout-fees', 'wcj_checkout_fees', array(
53
- 'checkout_fields' => 'input[name="' . implode( '"], input[name="', $this->checkout_fields ) . '"]',
54
- ) );
55
- }
56
- }
57
-
58
- /**
59
- * Validate fee without considering overlapping.
60
- *
61
- * @version 4.6.1
62
- * @since 4.5.0
63
- *
64
- * @param $fee_id
65
- * @param WC_Cart $cart
66
- *
67
- * @return bool
68
- */
69
- function is_fee_valid( $fee_id, \WC_Cart $cart ) {
70
- $fees = $this->get_fees();
71
- $enabled = $this->get_option( 'wcj_checkout_fees_data_enabled', array() );
72
- $values = $this->get_option( 'wcj_checkout_fees_data_values', array() );
73
-
74
- // Check if is active and empty value
75
- if (
76
- ( isset( $enabled[ $fee_id ] ) && 'no' === $enabled[ $fee_id ] ) ||
77
- ( 0 == ( $value = ( isset( $values[ $fee_id ] ) ? $values[ $fee_id ] : 0 ) ) )
78
- ) {
79
- return false;
80
- }
81
-
82
- // Check cart quantity
83
- if (
84
- $cart->get_cart_contents_count() < $fees[ $fee_id ]['cart_min'] ||
85
- ( $fees[ $fee_id ]['cart_max'] > 0 && $cart->get_cart_contents_count() > $fees[ $fee_id ]['cart_max'] )
86
- ) {
87
- return false;
88
- }
89
-
90
- // Check cart total
91
- if (
92
- $cart->get_cart_contents_total() < $fees[ $fee_id ]['cart_min_total'] ||
93
- ( ! 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'] )
94
- ) {
95
- return false;
96
- }
97
-
98
- // Check checkout fields
99
- if ( ! empty( $this->checkout_fields[ $fee_id ] ) ) {
100
- if ( isset( $post_data ) || isset( $_REQUEST['post_data'] ) ) {
101
- if ( ! isset( $post_data ) ) {
102
- $post_data = array();
103
- parse_str( $_REQUEST['post_data'], $post_data );
104
- }
105
- if ( empty( $post_data[ $this->checkout_fields[ $fee_id ] ] ) ) {
106
- return false;
107
- }
108
- } elseif ( empty( $_REQUEST[ $this->checkout_fields[ $fee_id ] ] ) ) {
109
- return false;
110
- }
111
- }
112
- return true;
113
- }
114
-
115
- /**
116
- * @version 4.5.0
117
- * @since 4.5.0
118
- *
119
- * @param $valid_fees
120
- *
121
- * @return array
122
- */
123
- function get_overlapped_fees( $valid_fees ) {
124
- $fees = $this->get_fees();
125
- $overlapped = array();
126
- foreach ( $valid_fees as $fee_id ) {
127
- if ( ! in_array( $fee_id, $overlapped ) ) {
128
- $overlapped = array_unique( array_merge( $overlapped, $fees[ $fee_id ]['overlap'] ) );
129
- }
130
- }
131
- return $overlapped;
132
- }
133
-
134
- /**
135
- * Get Fees.
136
- *
137
- * @version 4.6.1
138
- * @since 4.5.0
139
- *
140
- * @param bool $only_enabled
141
- * @param bool $adjust_priority
142
- *
143
- * @return array
144
- */
145
- function get_fees( $only_enabled = true, $adjust_priority = true ) {
146
- $total_number = apply_filters( 'booster_option', 1, $this->get_option( 'wcj_checkout_fees_total_number', 1 ) );
147
- $titles = $this->get_option( 'wcj_checkout_fees_data_titles', array() );
148
- $types = $this->get_option( 'wcj_checkout_fees_data_types', array() );
149
- $values = $this->get_option( 'wcj_checkout_fees_data_values', array() );
150
- $cart_min = $this->get_option( 'wcj_checkout_fees_cart_min_amount', array() );
151
- $cart_min_total = $this->get_option( 'wcj_checkout_fees_cart_min_total_amount', array() );
152
- $cart_max = $this->get_option( 'wcj_checkout_fees_cart_max_amount', array() );
153
- $cart_max_total = $this->get_option( 'wcj_checkout_fees_cart_max_total_amount', array() );
154
- $taxable = $this->get_option( 'wcj_checkout_fees_data_taxable', array() );
155
- $checkout_fields = $this->get_option( 'wcj_checkout_fees_data_values', array() );
156
- $enabled = $this->get_option( 'wcj_checkout_fees_data_enabled', array() );
157
- $overlap_opt = $this->get_option( 'wcj_checkout_fees_overlap', array() );
158
- $priorities = $this->get_option( 'wcj_checkout_fees_priority', array() );
159
-
160
- $fees = array();
161
- for ( $i = 1; $i <= $total_number; $i ++ ) {
162
- if ( ! isset( $priorities[ $i ] ) || empty( $priorities[ $i ] ) ) {
163
- $priorities[ $i ] = 0;
164
- }
165
- $enabled = isset( $enabled[ $i ] ) ? $enabled[ $i ] : 'yes';
166
- if ( $only_enabled && "no" === $enabled ) {
167
- continue;
168
- }
169
- $fees[ $i ] = array(
170
- 'enabled' => $enabled,
171
- 'cart_min' => isset( $cart_min[ $i ] ) ? $cart_min[ $i ] : 1,
172
- 'cart_min_total' => isset( $cart_min_total[ $i ] ) ? $cart_min_total[ $i ] : 0,
173
- 'cart_max' => isset( $cart_max[ $i ] ) ? $cart_max[ $i ] : 0,
174
- 'cart_max_total' => isset( $cart_max_total[ $i ] ) ? $cart_max_total[ $i ] : '',
175
- 'title' => isset( $titles[ $i ] ) ? $titles[ $i ] : '',
176
- 'type' => isset( $types[ $i ] ) ? $types[ $i ] : 'fixed',
177
- 'value' => isset( $values[ $i ] ) ? $values[ $i ] : 0,
178
- 'priority' => isset( $priorities[ $i ] ) ? ( $priorities[ $i ] ) : 0,
179
- 'taxable' => isset( $taxable[ $i ] ) ? $taxable[ $i ] : 'yes',
180
- 'checkout_field' => isset( $checkout_fields[ $i ] ) ? $checkout_fields[ $i ] : '',
181
- 'overlap' => isset( $overlap_opt[ $i ] ) ? $overlap_opt[ $i ] : array(),
182
- );
183
- }
184
- if ( $adjust_priority ) {
185
- uksort( $fees, function ( $a, $b ) use ( $fees, $priorities ) {
186
- return $priorities[ $a ] < $priorities[ $b ];
187
- } );
188
- }
189
- return $fees;
190
- }
191
-
192
- /**
193
- * Get valid fees.
194
- *
195
- * @version 4.5.0
196
- * @since 4.5.0
197
- *
198
- * @param $cart
199
- * @param bool $ignore_overlapped
200
- *
201
- * @return array
202
- */
203
- function get_valid_fees( $cart, $ignore_overlapped = true ) {
204
- $titles = $this->get_option( 'wcj_checkout_fees_data_titles', array() );
205
- $types = $this->get_option( 'wcj_checkout_fees_data_types', array() );
206
- $values = $this->get_option( 'wcj_checkout_fees_data_values', array() );
207
- $taxable = $this->get_option( 'wcj_checkout_fees_data_taxable', array() );
208
-
209
- //$total_number = apply_filters( 'booster_option', 1, $this->get_option( 'wcj_checkout_fees_total_number', 1 ) );
210
- $fees = $this->get_fees();
211
-
212
- $fees_to_add = array();
213
- $valid_fees = array();
214
-
215
- // Get Valid fees
216
- foreach ( $fees as $fee_id => $fee_title ) {
217
- if ( ! $this->is_fee_valid( $fee_id, $cart ) ) {
218
- continue;
219
- }
220
- $valid_fees[] = $fee_id;
221
- }
222
-
223
- // Ignore overlapped
224
- if ( $ignore_overlapped ) {
225
- $overlapped_fees = $this->get_overlapped_fees( $valid_fees );
226
- $valid_fees = array_diff( $valid_fees, $overlapped_fees );
227
- }
228
-
229
- foreach ( $valid_fees as $fee_id ) {
230
- // Adding the fee
231
- $title = ( isset( $titles[ $fee_id ] ) ? $titles[ $fee_id ] : __( 'Fee', 'woocommerce-jetpack' ) . ' #' . $fee_id );
232
- $value = isset( $values[ $fee_id ] ) ? $values[ $fee_id ] : 0;
233
- if ( isset( $types[ $fee_id ] ) && 'percent' === $types[ $fee_id ] ) {
234
- $value = $cart->get_cart_contents_total() * $value / 100;
235
- }
236
- $fees_to_add[ $fee_id ] = array(
237
- 'name' => $title,
238
- 'amount' => $value,
239
- 'taxable' => ( isset( $taxable[ $fee_id ] ) ? ( 'yes' === $taxable[ $fee_id ] ) : true ),
240
- 'tax_class' => 'standard',
241
- );
242
- }
243
-
244
- return $fees_to_add;
245
- }
246
-
247
- /**
248
- * add_fees.
249
- *
250
- * @version 4.5.0
251
- * @since 3.7.0
252
- * @todo fees with same title
253
- * @todo options: `tax_class`
254
- * @todo options: `cart total` (for percent) - include/exclude shipping etc. - https://docs.woocommerce.com/wc-apidocs/class-WC_Cart.html
255
- * @todo options: `rounding` (for percent)
256
- * @todo options: `min/max cart amount`
257
- * @todo options: `products, cats, tags to include/exclude`
258
- * @todo options: `countries to include/exclude`
259
- * @todo options: `user roles to include/exclude`
260
- * @todo see https://wcbooster.zendesk.com/agent/tickets/446
261
- */
262
- function add_fees( $cart ) {
263
- if ( ! wcj_is_frontend() ) {
264
- return;
265
- }
266
-
267
- $fees_to_add = $this->get_valid_fees( $cart );
268
-
269
- if ( ! empty( $fees_to_add ) ) {
270
- foreach ( $fees_to_add as $fee_to_add ) {
271
- $cart->add_fee( $fee_to_add['name'], $fee_to_add['amount'], $fee_to_add['taxable'], $fee_to_add['tax_class'] );
272
- }
273
- }
274
- }
275
-
276
- }
277
-
278
- endif;
279
-
280
- return new WCJ_Checkout_Fees();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Checkout Fees
4
+ *
5
+ * @version 4.6.1
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 4.5.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.', 'woocommerce-jetpack' );
28
+ $this->link_slug = 'woocommerce-checkout-fees';
29
+ parent::__construct();
30
+
31
+ if ( $this->is_enabled() ) {
32
+ // Core function
33
+ add_action( 'woocommerce_cart_calculate_fees', array( $this, 'add_fees' ), PHP_INT_MAX );
34
+ // Checkout fields
35
+ $this->checkout_fields = $this->get_option( 'wcj_checkout_fees_data_checkout_fields', array() );
36
+ $this->checkout_fields = array_filter( $this->checkout_fields );
37
+ if ( ! empty( $this->checkout_fields ) ) {
38
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
39
+ }
40
+ }
41
+ }
42
+
43
+ /**
44
+ * enqueue_scripts.
45
+ *
46
+ * @version 3.8.0
47
+ * @since 3.8.0
48
+ */
49
+ function enqueue_scripts() {
50
+ if ( is_checkout() ) {
51
+ wp_enqueue_script( 'wcj-checkout-fees', wcj_plugin_url() . '/includes/js/wcj-checkout-fees.js', array( 'jquery' ), WCJ()->version, true );
52
+ wp_localize_script( 'wcj-checkout-fees', 'wcj_checkout_fees', array(
53
+ 'checkout_fields' => 'input[name="' . implode( '"], input[name="', $this->checkout_fields ) . '"]',
54
+ ) );
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Validate fee without considering overlapping.
60
+ *
61
+ * @version 4.6.1
62
+ * @since 4.5.0
63
+ *
64
+ * @param $fee_id
65
+ * @param WC_Cart $cart
66
+ *
67
+ * @return bool
68
+ */
69
+ function is_fee_valid( $fee_id, \WC_Cart $cart ) {
70
+ $fees = $this->get_fees();
71
+ $enabled = $this->get_option( 'wcj_checkout_fees_data_enabled', array() );
72
+ $values = $this->get_option( 'wcj_checkout_fees_data_values', array() );
73
+
74
+ // Check if is active and empty value
75
+ if (
76
+ ( isset( $enabled[ $fee_id ] ) && 'no' === $enabled[ $fee_id ] ) ||
77
+ ( 0 == ( $value = ( isset( $values[ $fee_id ] ) ? $values[ $fee_id ] : 0 ) ) )
78
+ ) {
79
+ return false;
80
+ }
81
+
82
+ // Check cart quantity
83
+ if (
84
+ $cart->get_cart_contents_count() < $fees[ $fee_id ]['cart_min'] ||
85
+ ( $fees[ $fee_id ]['cart_max'] > 0 && $cart->get_cart_contents_count() > $fees[ $fee_id ]['cart_max'] )
86
+ ) {
87
+ return false;
88
+ }
89
+
90
+ // Check cart total
91
+ if (
92
+ $cart->get_cart_contents_total() < $fees[ $fee_id ]['cart_min_total'] ||
93
+ ( ! 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'] )
94
+ ) {
95
+ return false;
96
+ }
97
+
98
+ // Check checkout fields
99
+ if ( ! empty( $this->checkout_fields[ $fee_id ] ) ) {
100
+ if ( isset( $post_data ) || isset( $_REQUEST['post_data'] ) ) {
101
+ if ( ! isset( $post_data ) ) {
102
+ $post_data = array();
103
+ parse_str( $_REQUEST['post_data'], $post_data );
104
+ }
105
+ if ( empty( $post_data[ $this->checkout_fields[ $fee_id ] ] ) ) {
106
+ return false;
107
+ }
108
+ } elseif ( empty( $_REQUEST[ $this->checkout_fields[ $fee_id ] ] ) ) {
109
+ return false;
110
+ }
111
+ }
112
+ return true;
113
+ }
114
+
115
+ /**
116
+ * @version 4.5.0
117
+ * @since 4.5.0
118
+ *
119
+ * @param $valid_fees
120
+ *
121
+ * @return array
122
+ */
123
+ function get_overlapped_fees( $valid_fees ) {
124
+ $fees = $this->get_fees();
125
+ $overlapped = array();
126
+ foreach ( $valid_fees as $fee_id ) {
127
+ if ( ! in_array( $fee_id, $overlapped ) ) {
128
+ $overlapped = array_unique( array_merge( $overlapped, $fees[ $fee_id ]['overlap'] ) );
129
+ }
130
+ }
131
+ return $overlapped;
132
+ }
133
+
134
+ /**
135
+ * Get Fees.
136
+ *
137
+ * @version 4.6.1
138
+ * @since 4.5.0
139
+ *
140
+ * @param bool $only_enabled
141
+ * @param bool $adjust_priority
142
+ *
143
+ * @return array
144
+ */
145
+ function get_fees( $only_enabled = true, $adjust_priority = true ) {
146
+ $total_number = apply_filters( 'booster_option', 1, $this->get_option( 'wcj_checkout_fees_total_number', 1 ) );
147
+ $titles = $this->get_option( 'wcj_checkout_fees_data_titles', array() );
148
+ $types = $this->get_option( 'wcj_checkout_fees_data_types', array() );
149
+ $values = $this->get_option( 'wcj_checkout_fees_data_values', array() );
150
+ $cart_min = $this->get_option( 'wcj_checkout_fees_cart_min_amount', array() );
151
+ $cart_min_total = $this->get_option( 'wcj_checkout_fees_cart_min_total_amount', array() );
152
+ $cart_max = $this->get_option( 'wcj_checkout_fees_cart_max_amount', array() );
153
+ $cart_max_total = $this->get_option( 'wcj_checkout_fees_cart_max_total_amount', array() );
154
+ $taxable = $this->get_option( 'wcj_checkout_fees_data_taxable', array() );
155
+ $checkout_fields = $this->get_option( 'wcj_checkout_fees_data_values', array() );
156
+ $enabled = $this->get_option( 'wcj_checkout_fees_data_enabled', array() );
157
+ $overlap_opt = $this->get_option( 'wcj_checkout_fees_overlap', array() );
158
+ $priorities = $this->get_option( 'wcj_checkout_fees_priority', array() );
159
+
160
+ $fees = array();
161
+ for ( $i = 1; $i <= $total_number; $i ++ ) {
162
+ if ( ! isset( $priorities[ $i ] ) || empty( $priorities[ $i ] ) ) {
163
+ $priorities[ $i ] = 0;
164
+ }
165
+ $enabled = isset( $enabled[ $i ] ) ? $enabled[ $i ] : 'yes';
166
+ if ( $only_enabled && "no" === $enabled ) {
167
+ continue;
168
+ }
169
+ $fees[ $i ] = array(
170
+ 'enabled' => $enabled,
171
+ 'cart_min' => isset( $cart_min[ $i ] ) ? $cart_min[ $i ] : 1,
172
+ 'cart_min_total' => isset( $cart_min_total[ $i ] ) ? $cart_min_total[ $i ] : 0,
173
+ 'cart_max' => isset( $cart_max[ $i ] ) ? $cart_max[ $i ] : 0,
174
+ 'cart_max_total' => isset( $cart_max_total[ $i ] ) ? $cart_max_total[ $i ] : '',
175
+ 'title' => isset( $titles[ $i ] ) ? $titles[ $i ] : '',
176
+ 'type' => isset( $types[ $i ] ) ? $types[ $i ] : 'fixed',
177
+ 'value' => isset( $values[ $i ] ) ? $values[ $i ] : 0,
178
+ 'priority' => isset( $priorities[ $i ] ) ? ( $priorities[ $i ] ) : 0,
179
+ 'taxable' => isset( $taxable[ $i ] ) ? $taxable[ $i ] : 'yes',
180
+ 'checkout_field' => isset( $checkout_fields[ $i ] ) ? $checkout_fields[ $i ] : '',
181
+ 'overlap' => isset( $overlap_opt[ $i ] ) ? $overlap_opt[ $i ] : array(),
182
+ );
183
+ }
184
+ if ( $adjust_priority ) {
185
+ uksort( $fees, function ( $a, $b ) use ( $fees, $priorities ) {
186
+ return $priorities[ $a ] < $priorities[ $b ];
187
+ } );
188
+ }
189
+ return $fees;
190
+ }
191
+
192
+ /**
193
+ * Get valid fees.
194
+ *
195
+ * @version 4.5.0
196
+ * @since 4.5.0
197
+ *
198
+ * @param $cart
199
+ * @param bool $ignore_overlapped
200
+ *
201
+ * @return array
202
+ */
203
+ function get_valid_fees( $cart, $ignore_overlapped = true ) {
204
+ $titles = $this->get_option( 'wcj_checkout_fees_data_titles', array() );
205
+ $types = $this->get_option( 'wcj_checkout_fees_data_types', array() );
206
+ $values = $this->get_option( 'wcj_checkout_fees_data_values', array() );
207
+ $taxable = $this->get_option( 'wcj_checkout_fees_data_taxable', array() );
208
+
209
+ //$total_number = apply_filters( 'booster_option', 1, $this->get_option( 'wcj_checkout_fees_total_number', 1 ) );
210
+ $fees = $this->get_fees();
211
+
212
+ $fees_to_add = array();
213
+ $valid_fees = array();
214
+
215
+ // Get Valid fees
216
+ foreach ( $fees as $fee_id => $fee_title ) {
217
+ if ( ! $this->is_fee_valid( $fee_id, $cart ) ) {
218
+ continue;
219
+ }
220
+ $valid_fees[] = $fee_id;
221
+ }
222
+
223
+ // Ignore overlapped
224
+ if ( $ignore_overlapped ) {
225
+ $overlapped_fees = $this->get_overlapped_fees( $valid_fees );
226
+ $valid_fees = array_diff( $valid_fees, $overlapped_fees );
227
+ }
228
+
229
+ foreach ( $valid_fees as $fee_id ) {
230
+ // Adding the fee
231
+ $title = ( isset( $titles[ $fee_id ] ) ? $titles[ $fee_id ] : __( 'Fee', 'woocommerce-jetpack' ) . ' #' . $fee_id );
232
+ $value = isset( $values[ $fee_id ] ) ? $values[ $fee_id ] : 0;
233
+ if ( isset( $types[ $fee_id ] ) && 'percent' === $types[ $fee_id ] ) {
234
+ $value = $cart->get_cart_contents_total() * $value / 100;
235
+ }
236
+ $fees_to_add[ $fee_id ] = array(
237
+ 'name' => $title,
238
+ 'amount' => $value,
239
+ 'taxable' => ( isset( $taxable[ $fee_id ] ) ? ( 'yes' === $taxable[ $fee_id ] ) : true ),
240
+ 'tax_class' => 'standard',
241
+ );
242
+ }
243
+
244
+ return $fees_to_add;
245
+ }
246
+
247
+ /**
248
+ * add_fees.
249
+ *
250
+ * @version 4.5.0
251
+ * @since 3.7.0
252
+ * @todo fees with same title
253
+ * @todo options: `tax_class`
254
+ * @todo options: `cart total` (for percent) - include/exclude shipping etc. - https://docs.woocommerce.com/wc-apidocs/class-WC_Cart.html
255
+ * @todo options: `rounding` (for percent)
256
+ * @todo options: `min/max cart amount`
257
+ * @todo options: `products, cats, tags to include/exclude`
258
+ * @todo options: `countries to include/exclude`
259
+ * @todo options: `user roles to include/exclude`
260
+ * @todo see https://wcbooster.zendesk.com/agent/tickets/446
261
+ */
262
+ function add_fees( $cart ) {
263
+ if ( ! wcj_is_frontend() ) {
264
+ return;
265
+ }
266
+
267
+ $fees_to_add = $this->get_valid_fees( $cart );
268
+
269
+ if ( ! empty( $fees_to_add ) ) {
270
+ foreach ( $fees_to_add as $fee_to_add ) {
271
+ $cart->add_fee( $fee_to_add['name'], $fee_to_add['amount'], $fee_to_add['taxable'], $fee_to_add['tax_class'] );
272
+ }
273
+ }
274
+ }
275
+
276
+ }
277
+
278
+ endif;
279
+
280
+ return new WCJ_Checkout_Fees();
includes/class-wcj-checkout-files-upload.php CHANGED
@@ -1,829 +1,829 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Checkout Files Upload
4
- *
5
- * @version 4.2.0
6
- * @since 2.4.5
7
- * @author Algoritmika Ltd.
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 3.8.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.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-checkout-files-upload';
29
- parent::__construct();
30
-
31
- if ( $this->is_enabled() ) {
32
- $this->init_settings();
33
- add_action( 'add_meta_boxes', array( $this, 'add_file_admin_order_meta_box' ) );
34
- add_action( 'init', array( $this, 'process_checkout_files_upload' ) );
35
- if ( 'yes' === get_option( 'wcj_checkout_files_upload_remove_on_empty_cart', 'no' ) ) {
36
- add_action( 'woocommerce_cart_item_removed', array( $this, 'remove_files_on_empty_cart' ), PHP_INT_MAX, 2 );
37
- }
38
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
39
- for ( $i = 1; $i <= $total_number; $i++ ) {
40
- if ( 'disable' != ( $the_hook = get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' ) ) ) {
41
- add_action( $the_hook, array( $this, 'add_files_upload_form_to_checkout_frontend' ), get_option( 'wcj_checkout_files_upload_hook_priority_' . $i, 10 ) );
42
- }
43
- if ( 'yes' === get_option( 'wcj_checkout_files_upload_add_to_thankyou_' . $i, 'no' ) ) {
44
- add_action( 'woocommerce_thankyou', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
45
- }
46
- if ( 'yes' === get_option( 'wcj_checkout_files_upload_add_to_myaccount_' . $i, 'no' ) ) {
47
- add_action( 'woocommerce_view_order', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
48
- }
49
- }
50
- add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_files_to_order' ), PHP_INT_MAX, 2 );
51
- add_action( 'woocommerce_after_checkout_validation', array( $this, 'validate_on_checkout' ) );
52
- add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
53
- add_action( 'woocommerce_email_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
54
- add_filter( 'woocommerce_email_attachments', array( $this, 'add_files_to_email_attachments' ), PHP_INT_MAX, 3 );
55
- }
56
- }
57
-
58
- /**
59
- * init_settings.
60
- *
61
- * @version 3.9.0
62
- * @since 3.8.0
63
- * @todo (dev) (maybe) init settings on demand only
64
- */
65
- function init_settings() {
66
- $this->templates_settings = get_option( 'wcj_checkout_files_upload_templates', array() );
67
- $this->templates_settings = wp_parse_args( $this->templates_settings, array(
68
- 'order_before' => '',
69
- 'order_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
70
- 'order_after' => '',
71
- 'order_image_style' => 'width:64px;',
72
- 'email_before' => '',
73
- 'email_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
74
- 'email_after' => '',
75
- ) );
76
- $this->additional_admin_emails_settings = get_option( 'wcj_checkout_files_upload_additional_admin_emails', array() );
77
- $this->additional_admin_emails_settings = wp_parse_args( $this->additional_admin_emails_settings, array(
78
- 'actions' => array(),
79
- 'do_attach' => 'yes',
80
- ) );
81
- $this->checkout_files_upload_notice_type = get_option( 'wcj_checkout_files_upload_notice_type', 'wc_add_notice' );
82
- }
83
-
84
- /**
85
- * add_files_to_email_attachments.
86
- *
87
- * @version 2.7.0
88
- * @since 2.5.5
89
- */
90
- function add_files_to_email_attachments( $attachments, $status, $order ) {
91
- if (
92
- ( 'new_order' === $status && 'yes' === get_option( 'wcj_checkout_files_upload_attach_to_admin_new_order', 'yes' ) ) ||
93
- ( 'customer_processing_order' === $status && 'yes' === get_option( 'wcj_checkout_files_upload_attach_to_customer_processing_order', 'yes' ) )
94
- ) {
95
- $total_files = get_post_meta( wcj_get_order_id( $order ), '_' . 'wcj_checkout_files_total_files', true );
96
- for ( $i = 1; $i <= $total_files; $i++ ) {
97
- $attachments[] = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( wcj_get_order_id( $order ), '_' . 'wcj_checkout_files_upload_' . $i, true );
98
- }
99
- }
100
- return $attachments;
101
- }
102
-
103
- /**
104
- * add_files_to_order_display.
105
- *
106
- * @version 3.8.0
107
- * @since 2.4.7
108
- * @todo (maybe) somehow add `%image%` to emails also
109
- */
110
- function add_files_to_order_display( $order ) {
111
- $order_id = wcj_get_order_id( $order );
112
- $html = '';
113
- $total_files = get_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', true );
114
- $do_add_img = false;
115
- if ( 'woocommerce_email_after_order_table' === current_filter() ) {
116
- $template_before = $this->templates_settings['email_before'];
117
- $template_after = $this->templates_settings['email_after'];
118
- $template = $this->templates_settings['email_item'];
119
- } else {
120
- $template_before = $this->templates_settings['order_before'];
121
- $template_after = $this->templates_settings['order_after'];
122
- $template = $this->templates_settings['order_item'];
123
- $do_add_img = ( false !== strpos( $template, '%image%' ) );
124
- if ( $do_add_img ) {
125
- $img_style = $this->templates_settings['order_image_style'];
126
- }
127
- }
128
- for ( $i = 1; $i <= $total_files; $i++ ) {
129
- $real_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
130
- if ( '' != $real_file_name ) {
131
- $img = '';
132
- if ( $do_add_img ) {
133
- $order_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
134
- if ( @is_array( getimagesize( $order_file_name ) ) ) {
135
- $link = 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 ) );
136
- $img = '<img style="' . $img_style . '" src="' . $link. '"> ';
137
- }
138
- }
139
- $html .= wcj_handle_replacements( array(
140
- '%file_name%' => $real_file_name,
141
- '%image%' => $img,
142
- ), $template );
143
- }
144
- }
145
- if ( '' != $html ) {
146
- echo $template_before . $html . $template_after;
147
- }
148
- }
149
-
150
- /**
151
- * add_notice.
152
- *
153
- * @version 3.9.0
154
- * @since 3.9.0
155
- */
156
- function add_notice( $message, $notice_type = 'success' ) {
157
- if ( 'wc_add_notice' === $this->checkout_files_upload_notice_type ) {
158
- wc_add_notice( $message, $notice_type );
159
- } elseif ( 'wc_print_notice' === $this->checkout_files_upload_notice_type ) {
160
- wc_print_notice( $message, $notice_type );
161
- }
162
- }
163
-
164
- /**
165
- * validate_on_checkout.
166
- *
167
- * @version 3.9.0
168
- * @since 2.4.5
169
- */
170
- function validate_on_checkout( $posted ) {
171
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
172
- for ( $i = 1; $i <= $total_number; $i++ ) {
173
- if (
174
- 'yes' === get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) &&
175
- $this->is_visible( $i ) &&
176
- 'disable' != get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' )
177
- ) {
178
- if ( 'yes' === get_option( 'wcj_checkout_files_upload_required_' . $i, 'no' ) && null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
179
- // Is required
180
- $this->add_notice( get_option( 'wcj_checkout_files_upload_notice_required_' . $i, __( 'File is required!', 'woocommerce-jetpack' ) ), 'error' );
181
- }
182
- if ( null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
183
- continue;
184
- }
185
- $file_name = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
186
- $file_name = $file_name['name'];
187
- $file_type = '.' . pathinfo( $file_name, PATHINFO_EXTENSION );
188
- if ( '' != ( $file_accept = get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) ) ) {
189
- // Validate file type
190
- $file_accept = explode( ',', $file_accept );
191
- if ( is_array( $file_accept ) && ! empty( $file_accept ) ) {
192
- if ( ! in_array( $file_type, $file_accept ) ) {
193
- $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
194
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $file_name ), 'error' );
195
- }
196
- }
197
- }
198
- if ( $this->is_extension_blocked( $file_type ) ) {
199
- $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
200
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $file_name ), 'error' );
201
- }
202
- }
203
- }
204
- }
205
-
206
- /**
207
- * add_file_admin_order_meta_box.
208
- *
209
- * @version 2.4.5
210
- * @since 2.4.5
211
- */
212
- function add_file_admin_order_meta_box() {
213
- $screen = 'shop_order';
214
- $context = 'side';
215
- $priority = 'high';
216
- add_meta_box(
217
- 'wc-jetpack-' . $this->id,
218
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Uploaded Files', 'woocommerce-jetpack' ),
219
- array( $this, 'create_file_admin_order_meta_box' ),
220
- $screen,
221
- $context,
222
- $priority
223
- );
224
- }
225
-
226
- /**
227
- * create_file_admin_order_meta_box.
228
- *
229
- * @version 3.4.0
230
- * @since 2.4.5
231
- */
232
- function create_file_admin_order_meta_box() {
233
- $order_id = get_the_ID();
234
- $html = '';
235
- $total_files = get_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', true );
236
- $files_exists = false;
237
- for ( $i = 1; $i <= $total_files; $i++ ) {
238
- $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
239
- $real_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
240
- if ( '' != $order_file_name ) {
241
- $files_exists = true;
242
- $html .= '<p><a href="' . add_query_arg(
243
- array(
244
- 'wcj_download_checkout_file_admin' => $order_file_name,
245
- 'wcj_checkout_file_number' => $i,
246
- ) ) . '">' . $real_file_name . '</a></p>';
247
- }
248
- }
249
- if ( ! $files_exists ) {
250
- $html .= '<p><em>' . __( 'No files uploaded.', 'woocommerce-jetpack' ) . '</em></p>';
251
- } else {
252
- $html .= '<p><a style="color:#a00;" href="' . add_query_arg( 'wcj_download_checkout_file_admin_delete_all', $order_id ) . '"' . wcj_get_js_confirmation() . '>' .
253
- __( 'Delete all files', 'woocommerce-jetpack' ) . '</a></p>';
254
- }
255
- echo $html;
256
- }
257
-
258
- /**
259
- * is_extension_blocked.
260
- *
261
- * @version 3.2.3
262
- * @since 3.2.3
263
- */
264
- function is_extension_blocked( $ext ) {
265
- if ( 'no' === get_option( 'wcj_checkout_files_upload_block_files_enabled', 'yes' ) ) {
266
- return false;
267
- }
268
- $ext = strtolower( $ext );
269
- if ( strlen( $ext ) > 0 && '.' === $ext[0] ) {
270
- $ext = substr( $ext, 1 );
271
- }
272
- $blocked_file_exts = get_option( 'wcj_checkout_files_upload_block_files_exts',
273
- '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'
274
- );
275
- $blocked_file_exts = explode( '|', $blocked_file_exts );
276
- return in_array( $ext, $blocked_file_exts );
277
- }
278
-
279
- /**
280
- * add_files_to_order.
281
- *
282
- * @version 3.4.0
283
- * @since 2.4.5
284
- */
285
- function add_files_to_order( $order_id, $posted ) {
286
- $upload_dir = wcj_get_wcj_uploads_dir( 'checkout_files_upload' );
287
- if ( ! file_exists( $upload_dir ) ) {
288
- mkdir( $upload_dir, 0755, true );
289
- }
290
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
291
- for ( $i = 1; $i <= $total_number; $i++ ) {
292
- if ( null !== wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
293
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
294
- $file_name = $session_data['name'];
295
- $ext = pathinfo( $file_name, PATHINFO_EXTENSION );
296
- $download_file_name = $order_id . '_' . $i . '.' . $ext;
297
- $file_path = $upload_dir . '/' . $download_file_name;
298
- $tmp_file_name = $session_data['tmp_name'];
299
- $file_data = file_get_contents( $tmp_file_name );
300
- if ( ! $this->is_extension_blocked( $ext ) ) { // should already be validated earlier, but just in case...
301
- file_put_contents( $file_path, $file_data );
302
- }
303
- unlink( $tmp_file_name );
304
- wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
305
- update_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, $download_file_name );
306
- update_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, $file_name );
307
- }
308
- }
309
- update_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', $total_number );
310
- }
311
-
312
- /**
313
- * remove_files_on_empty_cart.
314
- *
315
- * @version 3.9.0
316
- * @since 3.6.0
317
- */
318
- function remove_files_on_empty_cart( $cart_item_key, $cart ) {
319
- if ( $cart->is_empty() ) {
320
- wcj_session_maybe_start();
321
- $any_files_removed = false;
322
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) ); $i++ ) {
323
- if ( null != ( $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) ) {
324
- $any_files_removed = true;
325
- if ( isset( $session_data['tmp_name'] ) ) {
326
- unlink( $session_data['tmp_name'] );
327
- }
328
- wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
329
- }
330
- }
331
- if ( $any_files_removed && 'yes' === get_option( 'wcj_checkout_files_upload_remove_on_empty_cart_add_notice', 'no' ) ) {
332
- $this->add_notice( get_option( 'wcj_checkout_files_upload_notice_remove_on_empty_cart', __( 'Files were successfully removed.', 'woocommerce-jetpack' ) ) );
333
- }
334
- }
335
- }
336
-
337
- /**
338
- * get_order_full_file_name.
339
- *
340
- * @version 3.8.0
341
- * @since 3.8.0
342
- * @todo use where needed
343
- */
344
- function get_order_full_file_name( $order_id, $file_num ) {
345
- return wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $file_num, true );
346
- }
347
-
348
- /**
349
- * process_checkout_files_upload.
350
- *
351
- * @version 3.9.0
352
- * @since 2.4.5
353
- * @todo add option for admin to delete files one by one (i.e. not all at once)
354
- * @todo `$this->additional_admin_emails_settings` - more customization options, e.g.: admin email, subject, content, from
355
- */
356
- function process_checkout_files_upload() {
357
- wcj_session_maybe_start();
358
- $admin_email = get_option( 'admin_email' );
359
- $admin_email_subject = __( 'Booster for WooCommerce: Checkout Files Upload: %action%', 'woocommerce-jetpack' );
360
- $admin_email_content = __( 'Order ID: %order_id%; File name: %file_name%', 'woocommerce-jetpack' );
361
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
362
- // Remove file
363
- for ( $i = 1; $i <= $total_number; $i++ ) {
364
- if ( isset( $_POST[ 'wcj_remove_checkout_file_' . $i ] ) ) {
365
- if ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ) {
366
- $order_id = $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ];
367
- $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
368
- if ( '' != $order_file_name ) {
369
- $file_path = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
370
- unlink( $file_path );
371
- $file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
372
- $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_success_remove_' . $i,
373
- __( 'File "%s" was successfully removed.', 'woocommerce-jetpack' ) ), $file_name ) );
374
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i );
375
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i );
376
- if ( in_array( 'remove_file', $this->additional_admin_emails_settings['actions'] ) ) {
377
- wp_mail(
378
- $admin_email,
379
- wcj_handle_replacements( array(
380
- '%action%' => __( 'File Removed', 'woocommerce-jetpack' ),
381
- ), $admin_email_subject ),
382
- wcj_handle_replacements( array(
383
- '%order_id%' => $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ],
384
- '%file_name%' => $file_name,
385
- ), $admin_email_content )
386
- );
387
- }
388
- do_action( 'wcj_checkout_files_upload', 'remove_file', $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ], $file_name );
389
- }
390
- } else {
391
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
392
- $file_name = $session_data['name'];
393
- unlink( $session_data['tmp_name'] );
394
- wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
395
- $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_success_remove_' . $i,
396
- __( 'File "%s" was successfully removed.', 'woocommerce-jetpack' ) ), $file_name ) );
397
- do_action( 'wcj_checkout_files_upload', 'remove_file', false, $file_name );
398
- }
399
- }
400
- }
401
- // Upload file
402
- for ( $i = 1; $i <= $total_number; $i++ ) {
403
- if ( isset( $_POST[ 'wcj_upload_checkout_file_' . $i ] ) ) {
404
- $file_name = 'wcj_checkout_files_upload_' . $i;
405
- if ( isset( $_FILES[ $file_name ] ) && '' != $_FILES[ $file_name ]['tmp_name'] ) {
406
- // Validate
407
- $is_valid = true;
408
- $real_file_name = $_FILES[ $file_name ]['name'];
409
- $file_type = '.' . pathinfo( $real_file_name, PATHINFO_EXTENSION );
410
- if ( '' != ( $file_accept = get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) ) ) {
411
- // Validate file type
412
- $file_accept = explode( ',', $file_accept );
413
- if ( is_array( $file_accept ) && ! empty( $file_accept ) ) {
414
- if ( ! in_array( $file_type, $file_accept ) ) {
415
- $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
416
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $real_file_name ), 'error' );
417
- $is_valid = false;
418
- }
419
- }
420
- }
421
- if ( $this->is_extension_blocked( $file_type ) ) {
422
- $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
423
- __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $real_file_name ), 'error' );
424
- $is_valid = false;
425
- }
426
- if ( $is_valid ) {
427
- // To session
428
- $tmp_dest_file = tempnam( sys_get_temp_dir(), 'wcj' );
429
- move_uploaded_file( $_FILES[ $file_name ]['tmp_name'], $tmp_dest_file );
430
- $session_data = $_FILES[ $file_name ];
431
- $session_data['tmp_name'] = $tmp_dest_file;
432
- wcj_session_set( $file_name, $session_data );
433
- $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_success_upload_' . $i,
434
- __( 'File "%s" was successfully uploaded.', 'woocommerce-jetpack' ) ), $_FILES[ $file_name ]['name'] ) );
435
- // To order
436
- if ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ) {
437
- $this->add_files_to_order( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ], null );
438
- if ( in_array( 'upload_file', $this->additional_admin_emails_settings['actions'] ) ) {
439
- $attachments = ( 'no' === $this->additional_admin_emails_settings['do_attach'] ?
440
- array() : array( $this->get_order_full_file_name( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ], $i ) ) );
441
- wp_mail(
442
- $admin_email,
443
- wcj_handle_replacements( array(
444
- '%action%' => __( 'File Uploaded', 'woocommerce-jetpack' ),
445
- ), $admin_email_subject ),
446
- wcj_handle_replacements( array(
447
- '%order_id%' => $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ],
448
- '%file_name%' => $_FILES[ $file_name ]['name'],
449
- ), $admin_email_content ),
450
- '',
451
- $attachments
452
- );
453
- }
454
- }
455
- // Action
456
- do_action( 'wcj_checkout_files_upload', 'upload_file',
457
- ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ? $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] : false ),
458
- $_FILES[ $file_name ]['name'] );
459
- }
460
- } else {
461
- $this->add_notice( get_option( 'wcj_checkout_files_upload_notice_upload_no_file_' . $i,
462
- __( 'Please select file to upload!', 'woocommerce-jetpack' ) ), 'notice' );
463
- }
464
- }
465
- }
466
- // Admin file download
467
- if ( isset( $_GET['wcj_download_checkout_file_admin'] ) ) {
468
- $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $_GET['wcj_download_checkout_file_admin'];
469
- $file_name = get_post_meta( $_GET['post'], '_' . 'wcj_checkout_files_upload_real_name_' . $_GET['wcj_checkout_file_number'], true );
470
- if ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) {
471
- header( "Expires: 0" );
472
- header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
473
- header( "Cache-Control: private", false );
474
- header( 'Content-disposition: attachment; filename=' . $file_name );
475
- header( "Content-Transfer-Encoding: binary" );
476
- header( "Content-Length: ". filesize( $tmp_file_name ) );
477
- readfile( $tmp_file_name );
478
- exit();
479
- }
480
- }
481
- // Admin all files delete
482
- if ( isset( $_GET['wcj_download_checkout_file_admin_delete_all'] ) && ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) ) {
483
- $order_id = $_GET['wcj_download_checkout_file_admin_delete_all'];
484
- $total_files = get_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', true );
485
- for ( $i = 1; $i <= $total_files; $i++ ) {
486
- if ( '' != ( $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true ) ) ) {
487
- unlink( wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name );
488
- }
489
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i );
490
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i );
491
- }
492
- delete_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files' );
493
- wp_safe_redirect( remove_query_arg( 'wcj_download_checkout_file_admin_delete_all' ) );
494
- exit;
495
- }
496
- // User file download
497
- if ( isset( $_GET['wcj_download_checkout_file'] ) && isset( $_GET['_wpnonce'] ) && ( false !== wp_verify_nonce( $_GET['_wpnonce'], 'wcj_download_checkout_file' ) ) ) {
498
- $i = $_GET['wcj_download_checkout_file'];
499
- if ( ! empty( $_GET['wcj_download_checkout_file_order_id'] ) ) {
500
- $order_id = $_GET['wcj_download_checkout_file_order_id'];
501
- if ( ! ( $order = wc_get_order( $order_id ) ) ) {
502
- return;
503
- }
504
- if ( isset( $_GET['key'] ) ) {
505
- // Thank you page
506
- if ( ! $order->key_is_valid( $_GET['key'] ) ) {
507
- return;
508
- }
509
- } else {
510
- // My Account
511
- if ( ! wcj_is_user_logged_in() || $order->get_customer_id() != wcj_get_current_user_id() ) {
512
- return;
513
- }
514
- }
515
- $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
516
- $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
517
- $file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
518
- } else {
519
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
520
- $tmp_file_name = $session_data['tmp_name'];
521
- $file_name = $session_data['name'];
522
- }
523
- header( "Expires: 0" );
524
- header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
525
- header( "Cache-Control: private", false );
526
- header( 'Content-disposition: attachment; filename=' . $file_name );
527
- header( "Content-Transfer-Encoding: binary" );
528
- header( "Content-Length: ". filesize( $tmp_file_name ) );
529
- readfile( $tmp_file_name );
530
- exit();
531
- }
532
- }
533
-
534
- /**
535
- * is_visible.
536
- *
537
- * @version 3.6.0
538
- * @since 2.4.7
539
- */
540
- function is_visible( $i, $order_id = 0 ) {
541
-
542
- if ( apply_filters( 'wcj_checkout_files_always_visible_on_empty_cart', false ) && 0 == $order_id && WC()->cart->is_empty() ) {
543
- // Added for "One Page Checkout" plugin compatibility.
544
- return true;
545
- }
546
-
547
- // Include by user role
548
- $user_roles = get_option( 'wcj_checkout_files_upload_show_user_roles_' . $i, '' );
549
- if ( ! empty( $user_roles ) && ! in_array( wcj_get_current_user_first_role(), $user_roles ) ) {
550
- return false;
551
- }
552
-
553
- // Exclude by user role
554
- $user_roles = get_option( 'wcj_checkout_files_upload_hide_user_roles_' . $i, '' );
555
- if ( ! empty( $user_roles ) && in_array( wcj_get_current_user_first_role(), $user_roles ) ) {
556
- return false;
557
- }
558
-
559
- // Include by product id
560
- $products_in = get_option( 'wcj_checkout_files_upload_show_products_in_' . $i );
561
- if ( ! empty( $products_in ) ) {
562
- $do_skip_by_products = true;
563
- if ( 0 != $order_id ) {
564
- $the_order = wc_get_order( $order_id );
565
- $the_items = $the_order->get_items();
566
- } else {
567
- $the_items = WC()->cart->get_cart();
568
- }
569
- foreach ( $the_items as $cart_item_key => $values ) {
570
- if ( in_array( $values['product_id'], $products_in ) ) {
571
- $do_skip_by_products = false;
572
- break;
573
- }
574
- }
575
- if ( $do_skip_by_products ) return false;
576
- }
577
-
578
- // Exclude by product id
579
- $products_in = get_option( 'wcj_checkout_files_upload_hide_products_in_' . $i );
580
- if ( ! empty( $products_in ) ) {
581
- if ( 0 != $order_id ) {
582
- $the_order = wc_get_order( $order_id );
583
- $the_items = $the_order->get_items();
584
- } else {
585
- $the_items = WC()->cart->get_cart();
586
- }
587
- foreach ( $the_items as $cart_item_key => $values ) {
588
- if ( in_array( $values['product_id'], $products_in ) ) {
589
- return false;
590
- }
591
- }
592
- }
593
-
594
- // Include by product category
595
- $categories_in = get_option( 'wcj_checkout_files_upload_show_cats_in_' . $i );
596
- if ( ! empty( $categories_in ) ) {
597
- $do_skip_by_cats = true;
598
- if ( 0 != $order_id ) {
599
- $the_order = wc_get_order( $order_id );
600
- $the_items = $the_order->get_items();
601
- } else {
602
- $the_items = WC()->cart->get_cart();
603
- }
604
- foreach ( $the_items as $cart_item_key => $values ) {
605
- $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
606
- if ( empty( $product_categories ) ) continue;
607
- foreach( $product_categories as $product_category ) {
608
- if ( in_array( $product_category->term_id, $categories_in ) ) {
609
- $do_skip_by_cats = false;
610
- break;
611
- }
612
- }
613
- if ( ! $do_skip_by_cats ) break;
614
- }
615
- if ( $do_skip_by_cats ) return false;
616
- }
617
-
618
- // Exclude by product category
619
- $categories_in = get_option( 'wcj_checkout_files_upload_hide_cats_in_' . $i );
620
- if ( ! empty( $categories_in ) ) {
621
- if ( 0 != $order_id ) {
622
- $the_order = wc_get_order( $order_id );
623
- $the_items = $the_order->get_items();
624
- } else {
625
- $the_items = WC()->cart->get_cart();
626
- }
627
- foreach ( $the_items as $cart_item_key => $values ) {
628
- $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
629
- if ( empty( $product_categories ) ) continue;
630
- foreach( $product_categories as $product_category ) {
631
- if ( in_array( $product_category->term_id, $categories_in ) ) {
632
- return false;
633
- }
634
- }
635
- }
636
- }
637
-
638
- // Include by product tag
639
- $tags_in = get_option( 'wcj_checkout_files_upload_show_tags_in_' . $i );
640
- if ( ! empty( $tags_in ) ) {
641
- $do_skip_by_tags = true;
642
- if ( 0 != $order_id ) {
643
- $the_order = wc_get_order( $order_id );
644
- $the_items = $the_order->get_items();
645
- } else {
646
- $the_items = WC()->cart->get_cart();
647
- }
648
- foreach ( $the_items as $cart_item_key => $values ) {
649
- $product_tags = get_the_terms( $values['product_id'], 'product_tag' );
650
- if ( empty( $product_tags ) ) continue;
651
- foreach( $product_tags as $product_tag ) {
652
- if ( in_array( $product_tag->term_id, $tags_in ) ) {
653
- $do_skip_by_tags = false;
654
- break;
655
- }
656
- }
657
- if ( ! $do_skip_by_tags ) break;
658
- }
659
- if ( $do_skip_by_tags ) return false;
660
- }
661
-
662
- // Exclude by product tag
663
- $tags_in = get_option( 'wcj_checkout_files_upload_hide_tags_in_' . $i );
664
- if ( ! empty( $tags_in ) ) {
665
- if ( 0 != $order_id ) {
666
- $the_order = wc_get_order( $order_id );
667
- $the_items = $the_order->get_items();
668
- } else {
669
- $the_items = WC()->cart->get_cart();
670
- }
671
- foreach ( $the_items as $cart_item_key => $values ) {
672
- $product_tags = get_the_terms( $values['product_id'], 'product_tag' );
673
- if ( empty( $product_tags ) ) continue;
674
- foreach( $product_tags as $product_tag ) {
675
- if ( in_array( $product_tag->term_id, $tags_in ) ) {
676
- return false;
677
- }
678
- }
679
- }
680
- }
681
-
682
- return true;
683
- }
684
-
685
- /**
686
- * maybe_get_image.
687
- *
688
- * @version 3.7.0
689
- * @since 3.7.0
690
- */
691
- function maybe_get_image( $link, $i, $order_id = 0 ) {
692
- if ( 'yes' === get_option( 'wcj_checkout_files_upload_form_template_field_show_images', 'no' ) ) {
693
- if ( 0 != $order_id && isset( $_GET['key'] ) && ( $order = wc_get_order( $order_id ) ) && $order->key_is_valid( $_GET['key'] ) ) {
694
- $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
695
- $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
696
- } else {
697
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
698
- $tmp_file_name = $session_data['tmp_name'];
699
- }
700
- if ( @is_array( getimagesize( $tmp_file_name ) ) ) {
701
- return '<img style="' . get_option( 'wcj_checkout_files_upload_form_template_field_image_style', 'width:64px;' ) . '" src="' . $link. '"> ';
702
- }
703
- }
704
- return '';
705
- }
706
-
707
- /**
708
- * get_the_form.
709
- *
710
- * @version 4.2.0
711
- * @since 2.5.0
712
- */
713
- function get_the_form( $i, $file_name, $order_id = 0 ) {
714
- $html = '';
715
- $html .= '<form enctype="multipart/form-data" action="" method="POST">';
716
- $html .= get_option( 'wcj_checkout_files_upload_form_template_before', '<table>' );
717
- if ( '' != ( $the_label = get_option( 'wcj_checkout_files_upload_label_' . $i, '' ) ) ) {
718
- $template = get_option( 'wcj_checkout_files_upload_form_template_label',
719
- '<tr><td colspan="2"><label for="%field_id%">%field_label%</label>%required_html%</td></tr>' );
720
- $required_html = ( 'yes' === get_option( 'wcj_checkout_files_upload_required_' . $i, 'no' ) ) ?
721
- '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
722
- $html .= str_replace(
723
- array( '%field_id%', '%field_label%', '%required_html%' ),
724
- array( 'wcj_checkout_files_upload_' . $i, $the_label, $required_html ),
725
- $template
726
- );
727
- }
728
- if ( '' == $file_name ) {
729
- $field_html = '<input type="file" name="wcj_checkout_files_upload_' . $i . '" id="wcj_checkout_files_upload_' . $i .
730
- '" accept="' . get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) . '">';
731
- $button_html = '<input type="submit"' .
732
- ' class="button alt"' .
733
- ' style="width:100%;"' .
734
- ' name="wcj_upload_checkout_file_' . $i . '"' .
735
- ' id="wcj_upload_checkout_file_' . $i . '"' .
736
- ' value="' . get_option( 'wcj_checkout_files_upload_label_upload_button_' . $i, __( 'Upload', 'woocommerce-jetpack' ) ) . '"' .
737
- ' data-value="' . get_option( 'wcj_checkout_files_upload_label_upload_button_' . $i, __( 'Upload', 'woocommerce-jetpack' ) ) . '">';
738
- } else {
739
- $link = 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 ) );
740
- $field_html = '<a href="' . $link . '">' . $this->maybe_get_image( $link, $i, $order_id ) . $file_name . '</a>';
741
- $button_html = '<input type="submit"' .
742
- ' class="button"' .
743
- ' style="width:100%;"' .
744
- ' name="wcj_remove_checkout_file_' . $i . '"' .
745
- ' id="wcj_remove_checkout_file_' . $i . '"' .
746
- ' value="' . get_option( 'wcj_checkout_files_upload_label_remove_button_' . $i, __( 'Remove', 'woocommerce-jetpack' ) ) . '"' .
747
- ' data-value="' . get_option( 'wcj_checkout_files_upload_label_remove_button_' . $i, __( 'Remove', 'woocommerce-jetpack' ) ) . '">';
748
- }
749
- $template = get_option( 'wcj_checkout_files_upload_form_template_field',
750
- '<tr><td style="width:50%;max-width:50vw;">%field_html%</td><td style="width:50%;">%button_html%</td></tr>' );
751
- $html .= str_replace(
752
- array( '%field_html%', '%button_html%' ),
753
- array( $field_html, $button_html ),
754
- $template
755
- );
756
- $html .= get_option( 'wcj_checkout_files_upload_form_template_after', '</table>' );
757
- if ( 0 != $order_id ) {
758
- $html .= '<input type="hidden" name="wcj_checkout_files_upload_order_id_' . $i . '" value="' . $order_id . '">';
759
- }
760
- $html .= '</form>';
761
- return $html;
762
- }
763
-
764
- /**
765
- * add_files_upload_form_to_thankyou_and_myaccount_page.
766
- *
767
- * @version 2.5.6
768
- * @since 2.5.0
769
- */
770
- function add_files_upload_form_to_thankyou_and_myaccount_page( $order_id ) {
771
- $html = '';
772
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
773
- $current_filter = current_filter();
774
- for ( $i = 1; $i <= $total_number; $i++ ) {
775
- if ( 'yes' === get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) && $this->is_visible( $i, $order_id ) ) {
776
- if (
777
- ( 'yes' === get_option( 'wcj_checkout_files_upload_add_to_thankyou_' . $i, 'no' ) && 'woocommerce_thankyou' === $current_filter ) ||
778
- ( 'yes' === get_option( 'wcj_checkout_files_upload_add_to_myaccount_' . $i, 'no' ) && 'woocommerce_view_order' === $current_filter )
779
- ) {
780
- $file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
781
- $html .= $this->get_the_form( $i, $file_name, $order_id );
782
- }
783
- }
784
- }
785
- echo $html;
786
- }
787
-
788
- /**
789
- * add_files_upload_form_to_checkout_frontend.
790
- *
791
- * @version 2.5.2
792
- * @since 2.4.5
793
- */
794
- function add_files_upload_form_to_checkout_frontend() {
795
- $this->add_files_upload_form_to_checkout_frontend_all();
796
- }
797
-
798
- /**
799
- * add_files_upload_form_to_checkout_frontend_all.
800
- *
801
- * @version 3.4.0
802
- * @since 2.5.2
803
- */
804
- function add_files_upload_form_to_checkout_frontend_all( $is_direct_call = false ) {
805
- $html = '';
806
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
807
- if ( ! $is_direct_call ) {
808
- $current_filter = current_filter();
809
- $current_filter_priority = wcj_current_filter_priority();
810
- }
811
- for ( $i = 1; $i <= $total_number; $i++ ) {
812
- $is_filter_ok = ( $is_direct_call ) ? true : (
813
- $current_filter === get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' ) &&
814
- $current_filter_priority == get_option( 'wcj_checkout_files_upload_hook_priority_' . $i, 10 )
815
- );
816
- if ( 'yes' === get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) && $is_filter_ok && $this->is_visible( $i ) ) {
817
- $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
818
- $file_name = ( null !== $session_data ? $session_data['name'] : '' );
819
- $html .= $this->get_the_form( $i, $file_name );
820
- }
821
- }
822
- echo $html;
823
- }
824
-
825
- }
826
-
827
- endif;
828
-
829
- return new WCJ_Checkout_Files_Upload();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Checkout Files Upload
4
+ *
5
+ * @version 4.2.0
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 3.8.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.', 'woocommerce-jetpack' );
28
+ $this->link_slug = 'woocommerce-checkout-files-upload';
29
+ parent::__construct();
30
+
31
+ if ( $this->is_enabled() ) {
32
+ $this->init_settings();
33
+ add_action( 'add_meta_boxes', array( $this, 'add_file_admin_order_meta_box' ) );
34
+ add_action( 'init', array( $this, 'process_checkout_files_upload' ) );
35
+ if ( 'yes' === get_option( 'wcj_checkout_files_upload_remove_on_empty_cart', 'no' ) ) {
36
+ add_action( 'woocommerce_cart_item_removed', array( $this, 'remove_files_on_empty_cart' ), PHP_INT_MAX, 2 );
37
+ }
38
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
39
+ for ( $i = 1; $i <= $total_number; $i++ ) {
40
+ if ( 'disable' != ( $the_hook = get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' ) ) ) {
41
+ add_action( $the_hook, array( $this, 'add_files_upload_form_to_checkout_frontend' ), get_option( 'wcj_checkout_files_upload_hook_priority_' . $i, 10 ) );
42
+ }
43
+ if ( 'yes' === get_option( 'wcj_checkout_files_upload_add_to_thankyou_' . $i, 'no' ) ) {
44
+ add_action( 'woocommerce_thankyou', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
45
+ }
46
+ if ( 'yes' === get_option( 'wcj_checkout_files_upload_add_to_myaccount_' . $i, 'no' ) ) {
47
+ add_action( 'woocommerce_view_order', array( $this, 'add_files_upload_form_to_thankyou_and_myaccount_page' ), PHP_INT_MAX, 1 );
48
+ }
49
+ }
50
+ add_action( 'woocommerce_checkout_order_processed', array( $this, 'add_files_to_order' ), PHP_INT_MAX, 2 );
51
+ add_action( 'woocommerce_after_checkout_validation', array( $this, 'validate_on_checkout' ) );
52
+ add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
53
+ add_action( 'woocommerce_email_after_order_table', array( $this, 'add_files_to_order_display' ), PHP_INT_MAX );
54
+ add_filter( 'woocommerce_email_attachments', array( $this, 'add_files_to_email_attachments' ), PHP_INT_MAX, 3 );
55
+ }
56
+ }
57
+
58
+ /**
59
+ * init_settings.
60
+ *
61
+ * @version 3.9.0
62
+ * @since 3.8.0
63
+ * @todo (dev) (maybe) init settings on demand only
64
+ */
65
+ function init_settings() {
66
+ $this->templates_settings = get_option( 'wcj_checkout_files_upload_templates', array() );
67
+ $this->templates_settings = wp_parse_args( $this->templates_settings, array(
68
+ 'order_before' => '',
69
+ 'order_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
70
+ 'order_after' => '',
71
+ 'order_image_style' => 'width:64px;',
72
+ 'email_before' => '',
73
+ 'email_item' => sprintf( __( 'File: %s', 'woocommerce-jetpack' ), '%file_name%' ) . '<br>',
74
+ 'email_after' => '',
75
+ ) );
76
+ $this->additional_admin_emails_settings = get_option( 'wcj_checkout_files_upload_additional_admin_emails', array() );
77
+ $this->additional_admin_emails_settings = wp_parse_args( $this->additional_admin_emails_settings, array(
78
+ 'actions' => array(),
79
+ 'do_attach' => 'yes',
80
+ ) );
81
+ $this->checkout_files_upload_notice_type = get_option( 'wcj_checkout_files_upload_notice_type', 'wc_add_notice' );
82
+ }
83
+
84
+ /**
85
+ * add_files_to_email_attachments.
86
+ *
87
+ * @version 2.7.0
88
+ * @since 2.5.5
89
+ */
90
+ function add_files_to_email_attachments( $attachments, $status, $order ) {
91
+ if (
92
+ ( 'new_order' === $status && 'yes' === get_option( 'wcj_checkout_files_upload_attach_to_admin_new_order', 'yes' ) ) ||
93
+ ( 'customer_processing_order' === $status && 'yes' === get_option( 'wcj_checkout_files_upload_attach_to_customer_processing_order', 'yes' ) )
94
+ ) {
95
+ $total_files = get_post_meta( wcj_get_order_id( $order ), '_' . 'wcj_checkout_files_total_files', true );
96
+ for ( $i = 1; $i <= $total_files; $i++ ) {
97
+ $attachments[] = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( wcj_get_order_id( $order ), '_' . 'wcj_checkout_files_upload_' . $i, true );
98
+ }
99
+ }
100
+ return $attachments;
101
+ }
102
+
103
+ /**
104
+ * add_files_to_order_display.
105
+ *
106
+ * @version 3.8.0
107
+ * @since 2.4.7
108
+ * @todo (maybe) somehow add `%image%` to emails also
109
+ */
110
+ function add_files_to_order_display( $order ) {
111
+ $order_id = wcj_get_order_id( $order );
112
+ $html = '';
113
+ $total_files = get_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', true );
114
+ $do_add_img = false;
115
+ if ( 'woocommerce_email_after_order_table' === current_filter() ) {
116
+ $template_before = $this->templates_settings['email_before'];
117
+ $template_after = $this->templates_settings['email_after'];
118
+ $template = $this->templates_settings['email_item'];
119
+ } else {
120
+ $template_before = $this->templates_settings['order_before'];
121
+ $template_after = $this->templates_settings['order_after'];
122
+ $template = $this->templates_settings['order_item'];
123
+ $do_add_img = ( false !== strpos( $template, '%image%' ) );
124
+ if ( $do_add_img ) {
125
+ $img_style = $this->templates_settings['order_image_style'];
126
+ }
127
+ }
128
+ for ( $i = 1; $i <= $total_files; $i++ ) {
129
+ $real_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
130
+ if ( '' != $real_file_name ) {
131
+ $img = '';
132
+ if ( $do_add_img ) {
133
+ $order_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
134
+ if ( @is_array( getimagesize( $order_file_name ) ) ) {
135
+ $link = 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 ) );
136
+ $img = '<img style="' . $img_style . '" src="' . $link. '"> ';
137
+ }
138
+ }
139
+ $html .= wcj_handle_replacements( array(
140
+ '%file_name%' => $real_file_name,
141
+ '%image%' => $img,
142
+ ), $template );
143
+ }
144
+ }
145
+ if ( '' != $html ) {
146
+ echo $template_before . $html . $template_after;
147
+ }
148
+ }
149
+
150
+ /**
151
+ * add_notice.
152
+ *
153
+ * @version 3.9.0
154
+ * @since 3.9.0
155
+ */
156
+ function add_notice( $message, $notice_type = 'success' ) {
157
+ if ( 'wc_add_notice' === $this->checkout_files_upload_notice_type ) {
158
+ wc_add_notice( $message, $notice_type );
159
+ } elseif ( 'wc_print_notice' === $this->checkout_files_upload_notice_type ) {
160
+ wc_print_notice( $message, $notice_type );
161
+ }
162
+ }
163
+
164
+ /**
165
+ * validate_on_checkout.
166
+ *
167
+ * @version 3.9.0
168
+ * @since 2.4.5
169
+ */
170
+ function validate_on_checkout( $posted ) {
171
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
172
+ for ( $i = 1; $i <= $total_number; $i++ ) {
173
+ if (
174
+ 'yes' === get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) &&
175
+ $this->is_visible( $i ) &&
176
+ 'disable' != get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' )
177
+ ) {
178
+ if ( 'yes' === get_option( 'wcj_checkout_files_upload_required_' . $i, 'no' ) && null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
179
+ // Is required
180
+ $this->add_notice( get_option( 'wcj_checkout_files_upload_notice_required_' . $i, __( 'File is required!', 'woocommerce-jetpack' ) ), 'error' );
181
+ }
182
+ if ( null === wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
183
+ continue;
184
+ }
185
+ $file_name = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
186
+ $file_name = $file_name['name'];
187
+ $file_type = '.' . pathinfo( $file_name, PATHINFO_EXTENSION );
188
+ if ( '' != ( $file_accept = get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) ) ) {
189
+ // Validate file type
190
+ $file_accept = explode( ',', $file_accept );
191
+ if ( is_array( $file_accept ) && ! empty( $file_accept ) ) {
192
+ if ( ! in_array( $file_type, $file_accept ) ) {
193
+ $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
194
+ __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $file_name ), 'error' );
195
+ }
196
+ }
197
+ }
198
+ if ( $this->is_extension_blocked( $file_type ) ) {
199
+ $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
200
+ __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $file_name ), 'error' );
201
+ }
202
+ }
203
+ }
204
+ }
205
+
206
+ /**
207
+ * add_file_admin_order_meta_box.
208
+ *
209
+ * @version 2.4.5
210
+ * @since 2.4.5
211
+ */
212
+ function add_file_admin_order_meta_box() {
213
+ $screen = 'shop_order';
214
+ $context = 'side';
215
+ $priority = 'high';
216
+ add_meta_box(
217
+ 'wc-jetpack-' . $this->id,
218
+ __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Uploaded Files', 'woocommerce-jetpack' ),
219
+ array( $this, 'create_file_admin_order_meta_box' ),
220
+ $screen,
221
+ $context,
222
+ $priority
223
+ );
224
+ }
225
+
226
+ /**
227
+ * create_file_admin_order_meta_box.
228
+ *
229
+ * @version 3.4.0
230
+ * @since 2.4.5
231
+ */
232
+ function create_file_admin_order_meta_box() {
233
+ $order_id = get_the_ID();
234
+ $html = '';
235
+ $total_files = get_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', true );
236
+ $files_exists = false;
237
+ for ( $i = 1; $i <= $total_files; $i++ ) {
238
+ $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
239
+ $real_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
240
+ if ( '' != $order_file_name ) {
241
+ $files_exists = true;
242
+ $html .= '<p><a href="' . add_query_arg(
243
+ array(
244
+ 'wcj_download_checkout_file_admin' => $order_file_name,
245
+ 'wcj_checkout_file_number' => $i,
246
+ ) ) . '">' . $real_file_name . '</a></p>';
247
+ }
248
+ }
249
+ if ( ! $files_exists ) {
250
+ $html .= '<p><em>' . __( 'No files uploaded.', 'woocommerce-jetpack' ) . '</em></p>';
251
+ } else {
252
+ $html .= '<p><a style="color:#a00;" href="' . add_query_arg( 'wcj_download_checkout_file_admin_delete_all', $order_id ) . '"' . wcj_get_js_confirmation() . '>' .
253
+ __( 'Delete all files', 'woocommerce-jetpack' ) . '</a></p>';
254
+ }
255
+ echo $html;
256
+ }
257
+
258
+ /**
259
+ * is_extension_blocked.
260
+ *
261
+ * @version 3.2.3
262
+ * @since 3.2.3
263
+ */
264
+ function is_extension_blocked( $ext ) {
265
+ if ( 'no' === get_option( 'wcj_checkout_files_upload_block_files_enabled', 'yes' ) ) {
266
+ return false;
267
+ }
268
+ $ext = strtolower( $ext );
269
+ if ( strlen( $ext ) > 0 && '.' === $ext[0] ) {
270
+ $ext = substr( $ext, 1 );
271
+ }
272
+ $blocked_file_exts = get_option( 'wcj_checkout_files_upload_block_files_exts',
273
+ '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'
274
+ );
275
+ $blocked_file_exts = explode( '|', $blocked_file_exts );
276
+ return in_array( $ext, $blocked_file_exts );
277
+ }
278
+
279
+ /**
280
+ * add_files_to_order.
281
+ *
282
+ * @version 3.4.0
283
+ * @since 2.4.5
284
+ */
285
+ function add_files_to_order( $order_id, $posted ) {
286
+ $upload_dir = wcj_get_wcj_uploads_dir( 'checkout_files_upload' );
287
+ if ( ! file_exists( $upload_dir ) ) {
288
+ mkdir( $upload_dir, 0755, true );
289
+ }
290
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
291
+ for ( $i = 1; $i <= $total_number; $i++ ) {
292
+ if ( null !== wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) {
293
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
294
+ $file_name = $session_data['name'];
295
+ $ext = pathinfo( $file_name, PATHINFO_EXTENSION );
296
+ $download_file_name = $order_id . '_' . $i . '.' . $ext;
297
+ $file_path = $upload_dir . '/' . $download_file_name;
298
+ $tmp_file_name = $session_data['tmp_name'];
299
+ $file_data = file_get_contents( $tmp_file_name );
300
+ if ( ! $this->is_extension_blocked( $ext ) ) { // should already be validated earlier, but just in case...
301
+ file_put_contents( $file_path, $file_data );
302
+ }
303
+ unlink( $tmp_file_name );
304
+ wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
305
+ update_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, $download_file_name );
306
+ update_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, $file_name );
307
+ }
308
+ }
309
+ update_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', $total_number );
310
+ }
311
+
312
+ /**
313
+ * remove_files_on_empty_cart.
314
+ *
315
+ * @version 3.9.0
316
+ * @since 3.6.0
317
+ */
318
+ function remove_files_on_empty_cart( $cart_item_key, $cart ) {
319
+ if ( $cart->is_empty() ) {
320
+ wcj_session_maybe_start();
321
+ $any_files_removed = false;
322
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) ); $i++ ) {
323
+ if ( null != ( $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i ) ) ) {
324
+ $any_files_removed = true;
325
+ if ( isset( $session_data['tmp_name'] ) ) {
326
+ unlink( $session_data['tmp_name'] );
327
+ }
328
+ wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
329
+ }
330
+ }
331
+ if ( $any_files_removed && 'yes' === get_option( 'wcj_checkout_files_upload_remove_on_empty_cart_add_notice', 'no' ) ) {
332
+ $this->add_notice( get_option( 'wcj_checkout_files_upload_notice_remove_on_empty_cart', __( 'Files were successfully removed.', 'woocommerce-jetpack' ) ) );
333
+ }
334
+ }
335
+ }
336
+
337
+ /**
338
+ * get_order_full_file_name.
339
+ *
340
+ * @version 3.8.0
341
+ * @since 3.8.0
342
+ * @todo use where needed
343
+ */
344
+ function get_order_full_file_name( $order_id, $file_num ) {
345
+ return wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $file_num, true );
346
+ }
347
+
348
+ /**
349
+ * process_checkout_files_upload.
350
+ *
351
+ * @version 3.9.0
352
+ * @since 2.4.5
353
+ * @todo add option for admin to delete files one by one (i.e. not all at once)
354
+ * @todo `$this->additional_admin_emails_settings` - more customization options, e.g.: admin email, subject, content, from
355
+ */
356
+ function process_checkout_files_upload() {
357
+ wcj_session_maybe_start();
358
+ $admin_email = get_option( 'admin_email' );
359
+ $admin_email_subject = __( 'Booster for WooCommerce: Checkout Files Upload: %action%', 'woocommerce-jetpack' );
360
+ $admin_email_content = __( 'Order ID: %order_id%; File name: %file_name%', 'woocommerce-jetpack' );
361
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
362
+ // Remove file
363
+ for ( $i = 1; $i <= $total_number; $i++ ) {
364
+ if ( isset( $_POST[ 'wcj_remove_checkout_file_' . $i ] ) ) {
365
+ if ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ) {
366
+ $order_id = $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ];
367
+ $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
368
+ if ( '' != $order_file_name ) {
369
+ $file_path = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
370
+ unlink( $file_path );
371
+ $file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
372
+ $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_success_remove_' . $i,
373
+ __( 'File "%s" was successfully removed.', 'woocommerce-jetpack' ) ), $file_name ) );
374
+ delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i );
375
+ delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i );
376
+ if ( in_array( 'remove_file', $this->additional_admin_emails_settings['actions'] ) ) {
377
+ wp_mail(
378
+ $admin_email,
379
+ wcj_handle_replacements( array(
380
+ '%action%' => __( 'File Removed', 'woocommerce-jetpack' ),
381
+ ), $admin_email_subject ),
382
+ wcj_handle_replacements( array(
383
+ '%order_id%' => $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ],
384
+ '%file_name%' => $file_name,
385
+ ), $admin_email_content )
386
+ );
387
+ }
388
+ do_action( 'wcj_checkout_files_upload', 'remove_file', $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ], $file_name );
389
+ }
390
+ } else {
391
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
392
+ $file_name = $session_data['name'];
393
+ unlink( $session_data['tmp_name'] );
394
+ wcj_session_set( 'wcj_checkout_files_upload_' . $i, null );
395
+ $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_success_remove_' . $i,
396
+ __( 'File "%s" was successfully removed.', 'woocommerce-jetpack' ) ), $file_name ) );
397
+ do_action( 'wcj_checkout_files_upload', 'remove_file', false, $file_name );
398
+ }
399
+ }
400
+ }
401
+ // Upload file
402
+ for ( $i = 1; $i <= $total_number; $i++ ) {
403
+ if ( isset( $_POST[ 'wcj_upload_checkout_file_' . $i ] ) ) {
404
+ $file_name = 'wcj_checkout_files_upload_' . $i;
405
+ if ( isset( $_FILES[ $file_name ] ) && '' != $_FILES[ $file_name ]['tmp_name'] ) {
406
+ // Validate
407
+ $is_valid = true;
408
+ $real_file_name = $_FILES[ $file_name ]['name'];
409
+ $file_type = '.' . pathinfo( $real_file_name, PATHINFO_EXTENSION );
410
+ if ( '' != ( $file_accept = get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) ) ) {
411
+ // Validate file type
412
+ $file_accept = explode( ',', $file_accept );
413
+ if ( is_array( $file_accept ) && ! empty( $file_accept ) ) {
414
+ if ( ! in_array( $file_type, $file_accept ) ) {
415
+ $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
416
+ __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $real_file_name ), 'error' );
417
+ $is_valid = false;
418
+ }
419
+ }
420
+ }
421
+ if ( $this->is_extension_blocked( $file_type ) ) {
422
+ $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_wrong_file_type_' . $i,
423
+ __( 'Wrong file type: "%s"!', 'woocommerce-jetpack' ) ), $real_file_name ), 'error' );
424
+ $is_valid = false;
425
+ }
426
+ if ( $is_valid ) {
427
+ // To session
428
+ $tmp_dest_file = tempnam( sys_get_temp_dir(), 'wcj' );
429
+ move_uploaded_file( $_FILES[ $file_name ]['tmp_name'], $tmp_dest_file );
430
+ $session_data = $_FILES[ $file_name ];
431
+ $session_data['tmp_name'] = $tmp_dest_file;
432
+ wcj_session_set( $file_name, $session_data );
433
+ $this->add_notice( sprintf( get_option( 'wcj_checkout_files_upload_notice_success_upload_' . $i,
434
+ __( 'File "%s" was successfully uploaded.', 'woocommerce-jetpack' ) ), $_FILES[ $file_name ]['name'] ) );
435
+ // To order
436
+ if ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ) {
437
+ $this->add_files_to_order( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ], null );
438
+ if ( in_array( 'upload_file', $this->additional_admin_emails_settings['actions'] ) ) {
439
+ $attachments = ( 'no' === $this->additional_admin_emails_settings['do_attach'] ?
440
+ array() : array( $this->get_order_full_file_name( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ], $i ) ) );
441
+ wp_mail(
442
+ $admin_email,
443
+ wcj_handle_replacements( array(
444
+ '%action%' => __( 'File Uploaded', 'woocommerce-jetpack' ),
445
+ ), $admin_email_subject ),
446
+ wcj_handle_replacements( array(
447
+ '%order_id%' => $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ],
448
+ '%file_name%' => $_FILES[ $file_name ]['name'],
449
+ ), $admin_email_content ),
450
+ '',
451
+ $attachments
452
+ );
453
+ }
454
+ }
455
+ // Action
456
+ do_action( 'wcj_checkout_files_upload', 'upload_file',
457
+ ( isset( $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] ) ? $_POST[ 'wcj_checkout_files_upload_order_id_' . $i ] : false ),
458
+ $_FILES[ $file_name ]['name'] );
459
+ }
460
+ } else {
461
+ $this->add_notice( get_option( 'wcj_checkout_files_upload_notice_upload_no_file_' . $i,
462
+ __( 'Please select file to upload!', 'woocommerce-jetpack' ) ), 'notice' );
463
+ }
464
+ }
465
+ }
466
+ // Admin file download
467
+ if ( isset( $_GET['wcj_download_checkout_file_admin'] ) ) {
468
+ $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $_GET['wcj_download_checkout_file_admin'];
469
+ $file_name = get_post_meta( $_GET['post'], '_' . 'wcj_checkout_files_upload_real_name_' . $_GET['wcj_checkout_file_number'], true );
470
+ if ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) {
471
+ header( "Expires: 0" );
472
+ header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
473
+ header( "Cache-Control: private", false );
474
+ header( 'Content-disposition: attachment; filename=' . $file_name );
475
+ header( "Content-Transfer-Encoding: binary" );
476
+ header( "Content-Length: ". filesize( $tmp_file_name ) );
477
+ readfile( $tmp_file_name );
478
+ exit();
479
+ }
480
+ }
481
+ // Admin all files delete
482
+ if ( isset( $_GET['wcj_download_checkout_file_admin_delete_all'] ) && ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) ) {
483
+ $order_id = $_GET['wcj_download_checkout_file_admin_delete_all'];
484
+ $total_files = get_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files', true );
485
+ for ( $i = 1; $i <= $total_files; $i++ ) {
486
+ if ( '' != ( $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true ) ) ) {
487
+ unlink( wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name );
488
+ }
489
+ delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i );
490
+ delete_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i );
491
+ }
492
+ delete_post_meta( $order_id, '_' . 'wcj_checkout_files_total_files' );
493
+ wp_safe_redirect( remove_query_arg( 'wcj_download_checkout_file_admin_delete_all' ) );
494
+ exit;
495
+ }
496
+ // User file download
497
+ if ( isset( $_GET['wcj_download_checkout_file'] ) && isset( $_GET['_wpnonce'] ) && ( false !== wp_verify_nonce( $_GET['_wpnonce'], 'wcj_download_checkout_file' ) ) ) {
498
+ $i = $_GET['wcj_download_checkout_file'];
499
+ if ( ! empty( $_GET['wcj_download_checkout_file_order_id'] ) ) {
500
+ $order_id = $_GET['wcj_download_checkout_file_order_id'];
501
+ if ( ! ( $order = wc_get_order( $order_id ) ) ) {
502
+ return;
503
+ }
504
+ if ( isset( $_GET['key'] ) ) {
505
+ // Thank you page
506
+ if ( ! $order->key_is_valid( $_GET['key'] ) ) {
507
+ return;
508
+ }
509
+ } else {
510
+ // My Account
511
+ if ( ! wcj_is_user_logged_in() || $order->get_customer_id() != wcj_get_current_user_id() ) {
512
+ return;
513
+ }
514
+ }
515
+ $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
516
+ $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
517
+ $file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
518
+ } else {
519
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
520
+ $tmp_file_name = $session_data['tmp_name'];
521
+ $file_name = $session_data['name'];
522
+ }
523
+ header( "Expires: 0" );
524
+ header( "Cache-Control: must-revalidate, post-check=0, pre-check=0" );
525
+ header( "Cache-Control: private", false );
526
+ header( 'Content-disposition: attachment; filename=' . $file_name );
527
+ header( "Content-Transfer-Encoding: binary" );
528
+ header( "Content-Length: ". filesize( $tmp_file_name ) );
529
+ readfile( $tmp_file_name );
530
+ exit();
531
+ }
532
+ }
533
+
534
+ /**
535
+ * is_visible.
536
+ *
537
+ * @version 3.6.0
538
+ * @since 2.4.7
539
+ */
540
+ function is_visible( $i, $order_id = 0 ) {
541
+
542
+ if ( apply_filters( 'wcj_checkout_files_always_visible_on_empty_cart', false ) && 0 == $order_id && WC()->cart->is_empty() ) {
543
+ // Added for "One Page Checkout" plugin compatibility.
544
+ return true;
545
+ }
546
+
547
+ // Include by user role
548
+ $user_roles = get_option( 'wcj_checkout_files_upload_show_user_roles_' . $i, '' );
549
+ if ( ! empty( $user_roles ) && ! in_array( wcj_get_current_user_first_role(), $user_roles ) ) {
550
+ return false;
551
+ }
552
+
553
+ // Exclude by user role
554
+ $user_roles = get_option( 'wcj_checkout_files_upload_hide_user_roles_' . $i, '' );
555
+ if ( ! empty( $user_roles ) && in_array( wcj_get_current_user_first_role(), $user_roles ) ) {
556
+ return false;
557
+ }
558
+
559
+ // Include by product id
560
+ $products_in = get_option( 'wcj_checkout_files_upload_show_products_in_' . $i );
561
+ if ( ! empty( $products_in ) ) {
562
+ $do_skip_by_products = true;
563
+ if ( 0 != $order_id ) {
564
+ $the_order = wc_get_order( $order_id );
565
+ $the_items = $the_order->get_items();
566
+ } else {
567
+ $the_items = WC()->cart->get_cart();
568
+ }
569
+ foreach ( $the_items as $cart_item_key => $values ) {
570
+ if ( in_array( $values['product_id'], $products_in ) ) {
571
+ $do_skip_by_products = false;
572
+ break;
573
+ }
574
+ }
575
+ if ( $do_skip_by_products ) return false;
576
+ }
577
+
578
+ // Exclude by product id
579
+ $products_in = get_option( 'wcj_checkout_files_upload_hide_products_in_' . $i );
580
+ if ( ! empty( $products_in ) ) {
581
+ if ( 0 != $order_id ) {
582
+ $the_order = wc_get_order( $order_id );
583
+ $the_items = $the_order->get_items();
584
+ } else {
585
+ $the_items = WC()->cart->get_cart();
586
+ }
587
+ foreach ( $the_items as $cart_item_key => $values ) {
588
+ if ( in_array( $values['product_id'], $products_in ) ) {
589
+ return false;
590
+ }
591
+ }
592
+ }
593
+
594
+ // Include by product category
595
+ $categories_in = get_option( 'wcj_checkout_files_upload_show_cats_in_' . $i );
596
+ if ( ! empty( $categories_in ) ) {
597
+ $do_skip_by_cats = true;
598
+ if ( 0 != $order_id ) {
599
+ $the_order = wc_get_order( $order_id );
600
+ $the_items = $the_order->get_items();
601
+ } else {
602
+ $the_items = WC()->cart->get_cart();
603
+ }
604
+ foreach ( $the_items as $cart_item_key => $values ) {
605
+ $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
606
+ if ( empty( $product_categories ) ) continue;
607
+ foreach( $product_categories as $product_category ) {
608
+ if ( in_array( $product_category->term_id, $categories_in ) ) {
609
+ $do_skip_by_cats = false;
610
+ break;
611
+ }
612
+ }
613
+ if ( ! $do_skip_by_cats ) break;
614
+ }
615
+ if ( $do_skip_by_cats ) return false;
616
+ }
617
+
618
+ // Exclude by product category
619
+ $categories_in = get_option( 'wcj_checkout_files_upload_hide_cats_in_' . $i );
620
+ if ( ! empty( $categories_in ) ) {
621
+ if ( 0 != $order_id ) {
622
+ $the_order = wc_get_order( $order_id );
623
+ $the_items = $the_order->get_items();
624
+ } else {
625
+ $the_items = WC()->cart->get_cart();
626
+ }
627
+ foreach ( $the_items as $cart_item_key => $values ) {
628
+ $product_categories = get_the_terms( $values['product_id'], 'product_cat' );
629
+ if ( empty( $product_categories ) ) continue;
630
+ foreach( $product_categories as $product_category ) {
631
+ if ( in_array( $product_category->term_id, $categories_in ) ) {
632
+ return false;
633
+ }
634
+ }
635
+ }
636
+ }
637
+
638
+ // Include by product tag
639
+ $tags_in = get_option( 'wcj_checkout_files_upload_show_tags_in_' . $i );
640
+ if ( ! empty( $tags_in ) ) {
641
+ $do_skip_by_tags = true;
642
+ if ( 0 != $order_id ) {
643
+ $the_order = wc_get_order( $order_id );
644
+ $the_items = $the_order->get_items();
645
+ } else {
646
+ $the_items = WC()->cart->get_cart();
647
+ }
648
+ foreach ( $the_items as $cart_item_key => $values ) {
649
+ $product_tags = get_the_terms( $values['product_id'], 'product_tag' );
650
+ if ( empty( $product_tags ) ) continue;
651
+ foreach( $product_tags as $product_tag ) {
652
+ if ( in_array( $product_tag->term_id, $tags_in ) ) {
653
+ $do_skip_by_tags = false;
654
+ break;
655
+ }
656
+ }
657
+ if ( ! $do_skip_by_tags ) break;
658
+ }
659
+ if ( $do_skip_by_tags ) return false;
660
+ }
661
+
662
+ // Exclude by product tag
663
+ $tags_in = get_option( 'wcj_checkout_files_upload_hide_tags_in_' . $i );
664
+ if ( ! empty( $tags_in ) ) {
665
+ if ( 0 != $order_id ) {
666
+ $the_order = wc_get_order( $order_id );
667
+ $the_items = $the_order->get_items();
668
+ } else {
669
+ $the_items = WC()->cart->get_cart();
670
+ }
671
+ foreach ( $the_items as $cart_item_key => $values ) {
672
+ $product_tags = get_the_terms( $values['product_id'], 'product_tag' );
673
+ if ( empty( $product_tags ) ) continue;
674
+ foreach( $product_tags as $product_tag ) {
675
+ if ( in_array( $product_tag->term_id, $tags_in ) ) {
676
+ return false;
677
+ }
678
+ }
679
+ }
680
+ }
681
+
682
+ return true;
683
+ }
684
+
685
+ /**
686
+ * maybe_get_image.
687
+ *
688
+ * @version 3.7.0
689
+ * @since 3.7.0
690
+ */
691
+ function maybe_get_image( $link, $i, $order_id = 0 ) {
692
+ if ( 'yes' === get_option( 'wcj_checkout_files_upload_form_template_field_show_images', 'no' ) ) {
693
+ if ( 0 != $order_id && isset( $_GET['key'] ) && ( $order = wc_get_order( $order_id ) ) && $order->key_is_valid( $_GET['key'] ) ) {
694
+ $order_file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_' . $i, true );
695
+ $tmp_file_name = wcj_get_wcj_uploads_dir( 'checkout_files_upload' ) . '/' . $order_file_name;
696
+ } else {
697
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
698
+ $tmp_file_name = $session_data['tmp_name'];
699
+ }
700
+ if ( @is_array( getimagesize( $tmp_file_name ) ) ) {
701
+ return '<img style="' . get_option( 'wcj_checkout_files_upload_form_template_field_image_style', 'width:64px;' ) . '" src="' . $link. '"> ';
702
+ }
703
+ }
704
+ return '';
705
+ }
706
+
707
+ /**
708
+ * get_the_form.
709
+ *
710
+ * @version 4.2.0
711
+ * @since 2.5.0
712
+ */
713
+ function get_the_form( $i, $file_name, $order_id = 0 ) {
714
+ $html = '';
715
+ $html .= '<form enctype="multipart/form-data" action="" method="POST">';
716
+ $html .= get_option( 'wcj_checkout_files_upload_form_template_before', '<table>' );
717
+ if ( '' != ( $the_label = get_option( 'wcj_checkout_files_upload_label_' . $i, '' ) ) ) {
718
+ $template = get_option( 'wcj_checkout_files_upload_form_template_label',
719
+ '<tr><td colspan="2"><label for="%field_id%">%field_label%</label>%required_html%</td></tr>' );
720
+ $required_html = ( 'yes' === get_option( 'wcj_checkout_files_upload_required_' . $i, 'no' ) ) ?
721
+ '&nbsp;<abbr class="required" title="required">*</abbr>' : '';
722
+ $html .= str_replace(
723
+ array( '%field_id%', '%field_label%', '%required_html%' ),
724
+ array( 'wcj_checkout_files_upload_' . $i, $the_label, $required_html ),
725
+ $template
726
+ );
727
+ }
728
+ if ( '' == $file_name ) {
729
+ $field_html = '<input type="file" name="wcj_checkout_files_upload_' . $i . '" id="wcj_checkout_files_upload_' . $i .
730
+ '" accept="' . get_option( 'wcj_checkout_files_upload_file_accept_' . $i, '' ) . '">';
731
+ $button_html = '<input type="submit"' .
732
+ ' class="button alt"' .
733
+ ' style="width:100%;"' .
734
+ ' name="wcj_upload_checkout_file_' . $i . '"' .
735
+ ' id="wcj_upload_checkout_file_' . $i . '"' .
736
+ ' value="' . get_option( 'wcj_checkout_files_upload_label_upload_button_' . $i, __( 'Upload', 'woocommerce-jetpack' ) ) . '"' .
737
+ ' data-value="' . get_option( 'wcj_checkout_files_upload_label_upload_button_' . $i, __( 'Upload', 'woocommerce-jetpack' ) ) . '">';
738
+ } else {
739
+ $link = 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 ) );
740
+ $field_html = '<a href="' . $link . '">' . $this->maybe_get_image( $link, $i, $order_id ) . $file_name . '</a>';
741
+ $button_html = '<input type="submit"' .
742
+ ' class="button"' .
743
+ ' style="width:100%;"' .
744
+ ' name="wcj_remove_checkout_file_' . $i . '"' .
745
+ ' id="wcj_remove_checkout_file_' . $i . '"' .
746
+ ' value="' . get_option( 'wcj_checkout_files_upload_label_remove_button_' . $i, __( 'Remove', 'woocommerce-jetpack' ) ) . '"' .
747
+ ' data-value="' . get_option( 'wcj_checkout_files_upload_label_remove_button_' . $i, __( 'Remove', 'woocommerce-jetpack' ) ) . '">';
748
+ }
749
+ $template = get_option( 'wcj_checkout_files_upload_form_template_field',
750
+ '<tr><td style="width:50%;max-width:50vw;">%field_html%</td><td style="width:50%;">%button_html%</td></tr>' );
751
+ $html .= str_replace(
752
+ array( '%field_html%', '%button_html%' ),
753
+ array( $field_html, $button_html ),
754
+ $template
755
+ );
756
+ $html .= get_option( 'wcj_checkout_files_upload_form_template_after', '</table>' );
757
+ if ( 0 != $order_id ) {
758
+ $html .= '<input type="hidden" name="wcj_checkout_files_upload_order_id_' . $i . '" value="' . $order_id . '">';
759
+ }
760
+ $html .= '</form>';
761
+ return $html;
762
+ }
763
+
764
+ /**
765
+ * add_files_upload_form_to_thankyou_and_myaccount_page.
766
+ *
767
+ * @version 2.5.6
768
+ * @since 2.5.0
769
+ */
770
+ function add_files_upload_form_to_thankyou_and_myaccount_page( $order_id ) {
771
+ $html = '';
772
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
773
+ $current_filter = current_filter();
774
+ for ( $i = 1; $i <= $total_number; $i++ ) {
775
+ if ( 'yes' === get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) && $this->is_visible( $i, $order_id ) ) {
776
+ if (
777
+ ( 'yes' === get_option( 'wcj_checkout_files_upload_add_to_thankyou_' . $i, 'no' ) && 'woocommerce_thankyou' === $current_filter ) ||
778
+ ( 'yes' === get_option( 'wcj_checkout_files_upload_add_to_myaccount_' . $i, 'no' ) && 'woocommerce_view_order' === $current_filter )
779
+ ) {
780
+ $file_name = get_post_meta( $order_id, '_' . 'wcj_checkout_files_upload_real_name_' . $i, true );
781
+ $html .= $this->get_the_form( $i, $file_name, $order_id );
782
+ }
783
+ }
784
+ }
785
+ echo $html;
786
+ }
787
+
788
+ /**
789
+ * add_files_upload_form_to_checkout_frontend.
790
+ *
791
+ * @version 2.5.2
792
+ * @since 2.4.5
793
+ */
794
+ function add_files_upload_form_to_checkout_frontend() {
795
+ $this->add_files_upload_form_to_checkout_frontend_all();
796
+ }
797
+
798
+ /**
799
+ * add_files_upload_form_to_checkout_frontend_all.
800
+ *
801
+ * @version 3.4.0
802
+ * @since 2.5.2
803
+ */
804
+ function add_files_upload_form_to_checkout_frontend_all( $is_direct_call = false ) {
805
+ $html = '';
806
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_checkout_files_upload_total_number', 1 ) );
807
+ if ( ! $is_direct_call ) {
808
+ $current_filter = current_filter();
809
+ $current_filter_priority = wcj_current_filter_priority();
810
+ }
811
+ for ( $i = 1; $i <= $total_number; $i++ ) {
812
+ $is_filter_ok = ( $is_direct_call ) ? true : (
813
+ $current_filter === get_option( 'wcj_checkout_files_upload_hook_' . $i, 'woocommerce_before_checkout_form' ) &&
814
+ $current_filter_priority == get_option( 'wcj_checkout_files_upload_hook_priority_' . $i, 10 )
815
+ );
816
+ if ( 'yes' === get_option( 'wcj_checkout_files_upload_enabled_' . $i, 'yes' ) && $is_filter_ok && $this->is_visible( $i ) ) {
817
+ $session_data = wcj_session_get( 'wcj_checkout_files_upload_' . $i );
818
+ $file_name = ( null !== $session_data ? $session_data['name'] : '' );
819
+ $html .= $this->get_the_form( $i, $file_name );
820
+ }
821
+ }
822
+ echo $html;
823
+ }
824
+
825
+ }
826
+
827
+ endif;
828
+
829
+ return new WCJ_Checkout_Files_Upload();
includes/class-wcj-coupon-by-user-role.php CHANGED
@@ -1,104 +1,104 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Coupon by User Role
4
- *
5
- * @version 3.6.0
6
- * @since 3.6.0
7
- * @author Algoritmika Ltd.
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 3.6.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.', 'woocommerce-jetpack' );
29
- $this->link_slug = 'woocommerce-coupon-by-user-role';
30
- parent::__construct();
31
-
32
- if ( $this->is_enabled() ) {
33
- add_filter( 'woocommerce_coupons_enabled', array( $this, 'coupons_enabled' ), PHP_INT_MAX, 1 );
34
- add_filter( 'woocommerce_coupon_is_valid', array( $this, 'coupon_valid' ), PHP_INT_MAX, 3 );
35
- add_filter( 'woocommerce_coupon_error', array( $this, 'coupon_not_valid_message' ), PHP_INT_MAX, 3 );
36
- if ( $this->invalid_per_coupon_enabled = ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_coupon_by_user_role_invalid_per_coupon', 'no' ) ) ) ) {
37
- $this->meta_box_screen = 'shop_coupon';
38
- $this->meta_box_context = 'side';
39
- $this->meta_box_priority = 'default';
40
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
41
- add_action( 'save_post_shop_coupon', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
42
- }
43
- }
44
- }
45
-
46
- /**
47
- * coupons_enabled.
48
- *
49
- * @version 3.6.0
50
- * @since 3.6.0
51
- */
52
- function coupons_enabled( $is_enabled ) {
53
- $disabled_user_roles = get_option( 'wcj_coupon_by_user_role_disabled', '' );
54
- if ( ! empty( $disabled_user_roles ) && in_array( wcj_get_current_user_first_role(), $disabled_user_roles ) ) {
55
- return false;
56
- }
57
- return $is_enabled;
58
- }
59
-
60
- /**
61
- * coupon_valid.
62
- *
63
- * @version 3.6.0
64
- * @since 3.6.0
65
- * @todo (maybe) check if `$coupon->get_id()` is working in WC below v3.0.0
66
- */
67
- function coupon_valid( $valid, $coupon, $discounts ) {
68
- $invalid_user_roles = get_option( 'wcj_coupon_by_user_role_invalid', '' );
69
- if ( empty( $invalid_user_roles ) ) {
70
- $invalid_user_roles = array();
71
- }
72
- if ( $this->invalid_per_coupon_enabled ) {
73
- $invalid_user_roles_per_coupon = get_post_meta( $coupon->get_id(), '_' . 'wcj_coupon_by_user_role_invalid', true );
74
- if ( ! empty( $invalid_user_roles_per_coupon ) ) {
75
- $invalid_user_roles = array_merge( $invalid_user_roles, $invalid_user_roles_per_coupon );
76
- }
77
- }
78
- if ( ! empty( $invalid_user_roles ) && in_array( wcj_get_current_user_first_role(), $invalid_user_roles ) ) {
79
- throw new Exception( apply_filters( 'booster_option', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ),
80
- get_option( 'wcj_coupon_by_user_role_invalid_message', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ) ) ), 10000 );
81
- return false;
82
- }
83
- return $valid;
84
- }
85
-
86
- /**
87
- * coupon_not_valid_message.
88
- *
89
- * @version 3.6.0
90
- * @since 3.6.0
91
- */
92
- function coupon_not_valid_message( $message, $code, $coupon ) {
93
- if ( 10000 === $code ) {
94
- return apply_filters( 'booster_option', __( '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
- return $message;
98
- }
99
-
100
- }
101
-
102
- endif;
103
-
104
- return new WCJ_Coupon_By_User_Role();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Coupon by User Role
4
+ *
5
+ * @version 3.6.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 3.6.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.', 'woocommerce-jetpack' );
29
+ $this->link_slug = 'woocommerce-coupon-by-user-role';
30
+ parent::__construct();
31
+
32
+ if ( $this->is_enabled() ) {
33
+ add_filter( 'woocommerce_coupons_enabled', array( $this, 'coupons_enabled' ), PHP_INT_MAX, 1 );
34
+ add_filter( 'woocommerce_coupon_is_valid', array( $this, 'coupon_valid' ), PHP_INT_MAX, 3 );
35
+ add_filter( 'woocommerce_coupon_error', array( $this, 'coupon_not_valid_message' ), PHP_INT_MAX, 3 );
36
+ if ( $this->invalid_per_coupon_enabled = ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_coupon_by_user_role_invalid_per_coupon', 'no' ) ) ) ) {
37
+ $this->meta_box_screen = 'shop_coupon';
38
+ $this->meta_box_context = 'side';
39
+ $this->meta_box_priority = 'default';
40
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
41
+ add_action( 'save_post_shop_coupon', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
42
+ }
43
+ }
44
+ }
45
+
46
+ /**
47
+ * coupons_enabled.
48
+ *
49
+ * @version 3.6.0
50
+ * @since 3.6.0
51
+ */
52
+ function coupons_enabled( $is_enabled ) {
53
+ $disabled_user_roles = get_option( 'wcj_coupon_by_user_role_disabled', '' );
54
+ if ( ! empty( $disabled_user_roles ) && in_array( wcj_get_current_user_first_role(), $disabled_user_roles ) ) {
55
+ return false;
56
+ }
57
+ return $is_enabled;
58
+ }
59
+
60
+ /**
61
+ * coupon_valid.
62
+ *
63
+ * @version 3.6.0
64
+ * @since 3.6.0
65
+ * @todo (maybe) check if `$coupon->get_id()` is working in WC below v3.0.0
66
+ */
67
+ function coupon_valid( $valid, $coupon, $discounts ) {
68
+ $invalid_user_roles = get_option( 'wcj_coupon_by_user_role_invalid', '' );
69
+ if ( empty( $invalid_user_roles ) ) {
70
+ $invalid_user_roles = array();
71
+ }
72
+ if ( $this->invalid_per_coupon_enabled ) {
73
+ $invalid_user_roles_per_coupon = get_post_meta( $coupon->get_id(), '_' . 'wcj_coupon_by_user_role_invalid', true );
74
+ if ( ! empty( $invalid_user_roles_per_coupon ) ) {
75
+ $invalid_user_roles = array_merge( $invalid_user_roles, $invalid_user_roles_per_coupon );
76
+ }
77
+ }
78
+ if ( ! empty( $invalid_user_roles ) && in_array( wcj_get_current_user_first_role(), $invalid_user_roles ) ) {
79
+ throw new Exception( apply_filters( 'booster_option', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ),
80
+ get_option( 'wcj_coupon_by_user_role_invalid_message', __( 'Coupon is not valid for your user role.', 'woocommerce-jetpack' ) ) ), 10000 );
81
+ return false;
82
+ }
83
+ return $valid;
84
+ }
85
+
86
+ /**
87
+ * coupon_not_valid_message.
88
+ *
89
+ * @version 3.6.0
90
+ * @since 3.6.0
91
+ */
92
+ function coupon_not_valid_message( $message, $code, $coupon ) {
93
+ if ( 10000 === $code ) {
94
+ return apply_filters( 'booster_option', __( '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
+ return $message;
98
+ }
99
+
100
+ }
101
+
102
+ endif;
103
+
104
+ return new WCJ_Coupon_By_User_Role();
includes/class-wcj-coupon-code-generator.php CHANGED
@@ -1,142 +1,142 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Coupon Code Generator
4
- *
5
- * @version 3.2.3
6
- * @since 3.2.3
7
- * @author Algoritmika Ltd.
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 3.2.3
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.', 'woocommerce-jetpack' );
30
- $this->link_slug = 'woocommerce-coupon-code-generator';
31
- parent::__construct();
32
-
33
- if ( $this->is_enabled() ) {
34
- if ( 'yes' === get_option( 'wcj_coupons_code_generator_enabled', 'no' ) ) {
35
- add_action( 'wp_ajax_wcj_generate_coupon_code', array( $this, 'ajax_generate_coupon_code' ) );
36
- add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_generate_coupon_code_script' ) );
37
- }
38
- }
39
- }
40
-
41
- /**
42
- * enqueue_generate_coupon_code_script.
43
- *
44
- * @version 3.1.3
45
- * @since 3.1.3
46
- */
47
- function enqueue_generate_coupon_code_script() {
48
- global $pagenow;
49
- if ( 'post-new.php' === $pagenow && isset( $_GET['post_type'] ) && 'shop_coupon' === $_GET['post_type'] ) {
50
- wp_enqueue_script( 'wcj-coupons-code-generator', wcj_plugin_url() . '/includes/js/wcj-coupons-code-generator.js', array( 'jquery' ), WCJ()->version, true );
51
- wp_localize_script( 'wcj-coupons-code-generator', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
52
- }
53
- }
54
-
55
- /**
56
- * random_string.
57
- *
58
- * @version 3.2.3
59
- * @since 3.2.3
60
- * @todo (maybe) $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
61
- */
62
- function random_string( $length = 32, $characters = 'abcdefghijklmnopqrstuvwxyz' ) {
63
- $characters_length = strlen( $characters );
64
- $random_string = '';
65
- for ( $i = 0; $i < $length; $i++ ) {
66
- $random_string .= $characters[ rand( 0, $characters_length - 1 ) ];
67
- }
68
- return $random_string;
69
- }
70
-
71
- /**
72
- * generate_coupon_code.
73
- *
74
- * @version 3.2.3
75
- * @since 3.1.3
76
- * @todo (maybe) more algorithms
77
- */
78
- function generate_coupon_code( $str = '', $algorithm = '', $length = '' ) {
79
- if ( '' === $str ) {
80
- $str = time();
81
- }
82
- if ( '' === $algorithm ) {
83
- $algorithm = apply_filters( 'booster_option', 'crc32', get_option( 'wcj_coupons_code_generator_algorithm', 'crc32' ) );
84
- }
85
- switch ( $algorithm ) {
86
- case 'random_letters_and_numbers':
87
- $code = $this->random_string( 32, '0123456789abcdefghijklmnopqrstuvwxyz' );
88
- break;
89
- case 'random_letters':
90
- $code = $this->random_string( 32, 'abcdefghijklmnopqrstuvwxyz' );
91
- break;
92
- case 'random_numbers':
93
- $code = $this->random_string( 32, '0123456789' );
94
- break;
95
- case 'md5':
96
- $code = md5( $str );
97
- break;
98
- case 'sha1':
99
- $code = sha1( $str );
100
- break;
101
- default: // 'crc32'
102
- $code = sprintf( '%08x', crc32( $str ) );
103
- break;
104
- }
105
- if ( '' === $length ) {
106
- $length = apply_filters( 'booster_option', 0, get_option( 'wcj_coupons_code_generator_length', 0 ) );
107
- }
108
- if ( $length > 0 && strlen( $code ) > $length ) {
109
- $code = substr( $code, 0, $length );
110
- }
111
- return $code;
112
- }
113
-
114
- /**
115
- * ajax_generate_coupon_code.
116
- *
117
- * @version 3.1.3
118
- * @since 3.1.3
119
- * @todo (maybe) optionally generate some description for coupon (e.g. "Automatically generated coupon [YYYY-MM-DD]")
120
- */
121
- function ajax_generate_coupon_code() {
122
- $attempts = 0;
123
- while ( true ) {
124
- $coupon_code = $this->generate_coupon_code();
125
- $coupon = new WC_Coupon( $coupon_code );
126
- if ( ! $coupon->get_id() ) {
127
- echo $coupon_code;
128
- die();
129
- }
130
- $attempts++;
131
- if ( $attempts > 100 ) { // shouldn't happen, but just in case...
132
- echo '';
133
- die();
134
- }
135
- }
136
- }
137
-
138
- }
139
-
140
- endif;
141
-
142
- return new WCJ_Coupon_Code_Generator();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Coupon Code Generator
4
+ *
5
+ * @version 3.2.3
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 3.2.3
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.', 'woocommerce-jetpack' );
30
+ $this->link_slug = 'woocommerce-coupon-code-generator';
31
+ parent::__construct();
32
+
33
+ if ( $this->is_enabled() ) {
34
+ if ( 'yes' === get_option( 'wcj_coupons_code_generator_enabled', 'no' ) ) {
35
+ add_action( 'wp_ajax_wcj_generate_coupon_code', array( $this, 'ajax_generate_coupon_code' ) );
36
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_generate_coupon_code_script' ) );
37
+ }
38
+ }
39
+ }
40
+
41
+ /**
42
+ * enqueue_generate_coupon_code_script.
43
+ *
44
+ * @version 3.1.3
45
+ * @since 3.1.3
46
+ */
47
+ function enqueue_generate_coupon_code_script() {
48
+ global $pagenow;
49
+ if ( 'post-new.php' === $pagenow && isset( $_GET['post_type'] ) && 'shop_coupon' === $_GET['post_type'] ) {
50
+ wp_enqueue_script( 'wcj-coupons-code-generator', wcj_plugin_url() . '/includes/js/wcj-coupons-code-generator.js', array( 'jquery' ), WCJ()->version, true );
51
+ wp_localize_script( 'wcj-coupons-code-generator', 'ajax_object', array( 'ajax_url' => admin_url( 'admin-ajax.php' ) ) );
52
+ }
53
+ }
54
+
55
+ /**
56
+ * random_string.
57
+ *
58
+ * @version 3.2.3
59
+ * @since 3.2.3
60
+ * @todo (maybe) $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
61
+ */
62
+ function random_string( $length = 32, $characters = 'abcdefghijklmnopqrstuvwxyz' ) {
63
+ $characters_length = strlen( $characters );
64
+ $random_string = '';
65
+ for ( $i = 0; $i < $length; $i++ ) {
66
+ $random_string .= $characters[ rand( 0, $characters_length - 1 ) ];
67
+ }
68
+ return $random_string;
69
+ }
70
+
71
+ /**
72
+ * generate_coupon_code.
73
+ *
74
+ * @version 3.2.3
75
+ * @since 3.1.3
76
+ * @todo (maybe) more algorithms
77
+ */
78
+ function generate_coupon_code( $str = '', $algorithm = '', $length = '' ) {
79
+ if ( '' === $str ) {
80
+ $str = time();
81
+ }
82
+ if ( '' === $algorithm ) {
83
+ $algorithm = apply_filters( 'booster_option', 'crc32', get_option( 'wcj_coupons_code_generator_algorithm', 'crc32' ) );
84
+ }
85
+ switch ( $algorithm ) {
86
+ case 'random_letters_and_numbers':
87
+ $code = $this->random_string( 32, '0123456789abcdefghijklmnopqrstuvwxyz' );
88
+ break;
89
+ case 'random_letters':
90
+ $code = $this->random_string( 32, 'abcdefghijklmnopqrstuvwxyz' );
91
+ break;
92
+ case 'random_numbers':
93
+ $code = $this->random_string( 32, '0123456789' );
94
+ break;
95
+ case 'md5':
96
+ $code = md5( $str );
97
+ break;
98
+ case 'sha1':
99
+ $code = sha1( $str );
100
+ break;
101
+ default: // 'crc32'
102
+ $code = sprintf( '%08x', crc32( $str ) );
103
+ break;
104
+ }
105
+ if ( '' === $length ) {
106
+ $length = apply_filters( 'booster_option', 0, get_option( 'wcj_coupons_code_generator_length', 0 ) );
107
+ }
108
+ if ( $length > 0 && strlen( $code ) > $length ) {
109
+ $code = substr( $code, 0, $length );
110
+ }
111
+ return $code;
112
+ }
113
+
114
+ /**
115
+ * ajax_generate_coupon_code.
116
+ *
117
+ * @version 3.1.3
118
+ * @since 3.1.3
119
+ * @todo (maybe) optionally generate some description for coupon (e.g. "Automatically generated coupon [YYYY-MM-DD]")
120
+ */
121
+ function ajax_generate_coupon_code() {
122
+ $attempts = 0;
123
+ while ( true ) {
124
+ $coupon_code = $this->generate_coupon_code();
125
+ $coupon = new WC_Coupon( $coupon_code );
126
+ if ( ! $coupon->get_id() ) {
127
+ echo $coupon_code;
128
+ die();
129
+ }
130
+ $attempts++;
131
+ if ( $attempts > 100 ) { // shouldn't happen, but just in case...
132
+ echo '';
133
+ die();
134
+ }
135
+ }
136
+ }
137
+
138
+ }
139
+
140
+ endif;
141
+
142
+ return new WCJ_Coupon_Code_Generator();
includes/class-wcj-cross-sells.php CHANGED
@@ -1,215 +1,215 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Cross-sells
4
- *
5
- * @version 3.9.0
6
- * @since 3.5.3
7
- * @author Algoritmika Ltd.
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 3.9.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.', 'woocommerce-jetpack' );
33
- $this->link_slug = 'woocommerce-cross-sells';
34
- parent::__construct();
35
-
36
- if ( $this->is_enabled() ) {
37
- add_filter( 'woocommerce_cross_sells_total', array( $this, 'cross_sells_total' ), PHP_INT_MAX );
38
- add_filter( 'woocommerce_cross_sells_columns', array( $this, 'cross_sells_columns' ), PHP_INT_MAX );
39
- add_filter( 'woocommerce_cross_sells_orderby', array( $this, 'cross_sells_orderby' ), PHP_INT_MAX );
40
- if ( ! WCJ_IS_WC_VERSION_BELOW_3_3_0 ) {
41
- add_filter( 'woocommerce_cross_sells_order', array( $this, 'cross_sells_order' ), PHP_INT_MAX );
42
- }
43
- if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
44
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_cross_sells_global_enabled', 'no' ) ) ) {
45
- add_filter( 'woocommerce_product_get_cross_sell_ids', array( $this, 'cross_sells_ids' ), PHP_INT_MAX, 2 );
46
- }
47
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_cross_sells_exclude_not_in_stock', 'no' ) ) ) {
48
- add_filter( 'woocommerce_product_get_cross_sell_ids', array( $this, 'cross_sells_exclude_not_in_stock' ), PHP_INT_MAX, 2 );
49
- }
50
- }
51
- if ( 'yes' === get_option( 'wcj_cross_sells_hide', 'no' ) ) {
52
- add_action( 'init', array( $this, 'hide_cross_sells' ), PHP_INT_MAX );
53
- }
54
- if ( 'no_changes' != get_option( 'wcj_cross_sells_position', 'no_changes' ) ) {
55
- add_action( 'init', array( $this, 'reposition_cross_sells' ), PHP_INT_MAX );
56
- }
57
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_cross_sells_replace_with_cross_sells', 'no' ) ) ) {
58
- add_filter( 'woocommerce_product_add_to_cart_url', array( $this, 'replace_with_cross_sells_to_url' ), PHP_INT_MAX, 2 );
59
- add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'remove_from_cart_by_product_id' ) );
60
- }
61
- }
62
-
63
- }
64
-
65
- /**
66
- * replace_with_cross_sells_to_url.
67
- *
68
- * @version 3.9.0
69
- * @since 3.9.0
70
- * @todo [dev] re-check variable products
71
- */
72
- function replace_with_cross_sells_to_url( $url, $product ) {
73
- if ( is_cart() && ( $_cart = WC()->cart ) ) {
74
- $product_id = $product->get_id();
75
- $product_ids_to_remove = array();
76
- foreach ( $_cart->get_cart() as $cart_item_key => $values ) {
77
- $_product = wc_get_product( $values['product_id'] );
78
- $cross_sell_ids = $_product->get_cross_sell_ids();
79
- if ( in_array( $product_id, $cross_sell_ids ) ) {
80
- $product_ids_to_remove[] = $values['product_id'];
81
- }
82
- }
83
- if ( ! empty( $product_ids_to_remove ) ) {
84
- $url = add_query_arg( array( 'wcj-remove-from-cart' => implode( ',', array_unique( $product_ids_to_remove ) ) ), $url );
85
- }
86
- }
87
- return $url;
88
- }
89
-
90
- /**
91
- * remove_from_cart_by_product_id.
92
- *
93
- * @version 3.9.0
94
- * @since 3.9.0
95
- * @todo [dev] AJAX
96
- */
97
- function remove_from_cart_by_product_id() {
98
- if ( isset( $_GET['wcj-remove-from-cart'] ) ) {
99
- if ( $_cart = WC()->cart ) {
100
- $product_ids_to_remove = explode( ',', $_GET['wcj-remove-from-cart'] );
101
- foreach ( $_cart->get_cart() as $cart_item_key => $values ) {
102
- if ( in_array( $values['product_id'], $product_ids_to_remove ) ) {
103
- $_cart->remove_cart_item( $cart_item_key );
104
- }
105
- }
106
- }
107
- wp_safe_redirect( remove_query_arg( 'wcj-remove-from-cart' ) );
108
- exit;
109
- }
110
- }
111
-
112
- /**
113
- * reposition_cross_sells.
114
- *
115
- * @version 3.6.0
116
- * @since 3.6.0
117
- * @todo [dev] (maybe) check `woocommerce\templates\cart\cart.php` for more positions
118
- */
119
- function reposition_cross_sells() {
120
- $this->hide_cross_sells();
121
- add_action( get_option( 'wcj_cross_sells_position', 'no_changes' ), 'woocommerce_cross_sell_display', get_option( 'wcj_cross_sells_position_priority', 10 ) );
122
- }
123
-
124
- /**
125
- * hide_cross_sells.
126
- *
127
- * @version 3.6.0
128
- * @since 3.6.0
129
- */
130
- function hide_cross_sells() {
131
- remove_action( 'woocommerce_cart_collaterals', 'woocommerce_cross_sell_display' );
132
- }
133
-
134
- /**
135
- * cross_sells_exclude_not_in_stock.
136
- *
137
- * @version 3.9.0
138
- * @since 3.9.0
139
- */
140
- function cross_sells_exclude_not_in_stock( $ids, $_product ) {
141
- foreach ( $ids as $key => $product_id ) {
142
- $product = wc_get_product( $product_id );
143
- if ( ! $product->is_in_stock() ) {
144
- unset( $ids[ $key ] );
145
- }
146
- }
147
- return $ids;
148
- }
149
-
150
- /**
151
- * cross_sells_ids.
152
- *
153
- * @version 3.6.0
154
- * @since 3.6.0
155
- * @todo [dev] (maybe) ids instead of list
156
- * @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)
157
- * @todo [feature] (maybe) on per category/tag basis
158
- */
159
- function cross_sells_ids( $ids, $_product ) {
160
- $global_cross_sells = get_option( 'wcj_cross_sells_global_ids', '' );
161
- if ( ! empty( $global_cross_sells ) ) {
162
- $global_cross_sells = array_unique( $global_cross_sells );
163
- $product_id = wcj_get_product_id_or_variation_parent_id( $_product );
164
- if ( false !== ( $key = array_search( $product_id, $global_cross_sells ) ) ) {
165
- unset( $global_cross_sells[ $key ] );
166
- }
167
- }
168
- return ( empty( $global_cross_sells ) ? $ids : array_unique( array_merge( $ids, $global_cross_sells ) ) );
169
- }
170
-
171
- /**
172
- * cross_sells_order.
173
- *
174
- * @version 3.5.3
175
- * @since 3.5.3
176
- */
177
- function cross_sells_order( $order ) {
178
- return ( 'no_changes' != ( $_order = get_option( 'wcj_cross_sells_order', 'no_changes' ) ) ? $_order : $order );
179
- }
180
-
181
- /**
182
- * cross_sells_orderby.
183
- *
184
- * @version 3.5.3
185
- * @since 3.5.3
186
- */
187
- function cross_sells_orderby( $orderby ) {
188
- return ( 'no_changes' != ( $_orderby = get_option( 'wcj_cross_sells_orderby', 'no_changes' ) ) ? $_orderby : $orderby );
189
- }
190
-
191
- /**
192
- * cross_sells_columns.
193
- *
194
- * @version 3.5.3
195
- * @since 3.5.3
196
- */
197
- function cross_sells_columns( $columns ) {
198
- return ( 0 != ( $_columns = get_option( 'wcj_cross_sells_columns', 0 ) ) ? $_columns : $columns );
199
- }
200
-
201
- /**
202
- * cross_sells_total.
203
- *
204
- * @version 3.6.0
205
- * @since 3.5.3
206
- */
207
- function cross_sells_total( $limit ) {
208
- return ( 0 != ( $_limit = get_option( 'wcj_cross_sells_total', 0 ) ) ? $_limit : $limit );
209
- }
210
-
211
- }
212
-
213
- endif;
214
-
215
- return new WCJ_Cross_Sells();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Cross-sells
4
+ *
5
+ * @version 3.9.0
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 3.9.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.', 'woocommerce-jetpack' );
33
+ $this->link_slug = 'woocommerce-cross-sells';
34
+ parent::__construct();
35
+
36
+ if ( $this->is_enabled() ) {
37
+ add_filter( 'woocommerce_cross_sells_total', array( $this, 'cross_sells_total' ), PHP_INT_MAX );
38
+ add_filter( 'woocommerce_cross_sells_columns', array( $this, 'cross_sells_columns' ), PHP_INT_MAX );
39
+ add_filter( 'woocommerce_cross_sells_orderby', array( $this, 'cross_sells_orderby' ), PHP_INT_MAX );
40
+ if ( ! WCJ_IS_WC_VERSION_BELOW_3_3_0 ) {
41
+ add_filter( 'woocommerce_cross_sells_order', array( $this, 'cross_sells_order' ), PHP_INT_MAX );
42
+ }
43
+ if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
44
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_cross_sells_global_enabled', 'no' ) ) ) {
45
+ add_filter( 'woocommerce_product_get_cross_sell_ids', array( $this, 'cross_sells_ids' ), PHP_INT_MAX, 2 );
46
+ }
47
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_cross_sells_exclude_not_in_stock', 'no' ) ) ) {
48
+ add_filter( 'woocommerce_product_get_cross_sell_ids', array( $this, 'cross_sells_exclude_not_in_stock' ), PHP_INT_MAX, 2 );
49
+ }
50
+ }
51
+ if ( 'yes' === get_option( 'wcj_cross_sells_hide', 'no' ) ) {
52
+ add_action( 'init', array( $this, 'hide_cross_sells' ), PHP_INT_MAX );
53
+ }
54
+ if ( 'no_changes' != get_option( 'wcj_cross_sells_position', 'no_changes' ) ) {
55
+ add_action( 'init', array( $this, 'reposition_cross_sells' ), PHP_INT_MAX );
56
+ }
57
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_cross_sells_replace_with_cross_sells', 'no' ) ) ) {
58
+ add_filter( 'woocommerce_product_add_to_cart_url', array( $this, 'replace_with_cross_sells_to_url' ), PHP_INT_MAX, 2 );
59
+ add_action( 'woocommerce_cart_loaded_from_session', array( $this, 'remove_from_cart_by_product_id' ) );
60
+ }
61
+ }
62
+
63
+ }
64
+
65
+ /**
66
+ * replace_with_cross_sells_to_url.
67
+ *
68
+ * @version 3.9.0
69
+ * @since 3.9.0
70
+ * @todo [dev] re-check variable products
71
+ */
72
+ function replace_with_cross_sells_to_url( $url, $product ) {
73
+ if ( is_cart() && ( $_cart = WC()->cart ) ) {
74
+ $product_id = $product->get_id();
75
+ $product_ids_to_remove = array();
76
+ foreach ( $_cart->get_cart() as $cart_item_key => $values ) {
77
+ $_product = wc_get_product( $values['product_id'] );
78
+ $cross_sell_ids = $_product->get_cross_sell_ids();
79
+ if ( in_array( $product_id, $cross_sell_ids ) ) {
80
+ $product_ids_to_remove[] = $values['product_id'];
81
+ }
82
+ }
83
+ if ( ! empty( $product_ids_to_remove ) ) {
84
+ $url = add_query_arg( array( 'wcj-remove-from-cart' => implode( ',', array_unique( $product_ids_to_remove ) ) ), $url );
85
+ }
86
+ }
87
+ return $url;
88
+ }
89
+
90
+ /**
91
+ * remove_from_cart_by_product_id.
92
+ *
93
+ * @version 3.9.0
94
+ * @since 3.9.0
95
+ * @todo [dev] AJAX
96
+ */
97
+ function remove_from_cart_by_product_id() {
98
+ if ( isset( $_GET['wcj-remove-from-cart'] ) ) {
99
+ if ( $_cart = WC()->cart ) {
100
+ $product_ids_to_remove = explode( ',', $_GET['wcj-remove-from-cart'] );
101
+ foreach ( $_cart->get_cart() as $cart_item_key => $values ) {
102
+ if ( in_array( $values['product_id'], $product_ids_to_remove ) ) {
103
+ $_cart->remove_cart_item( $cart_item_key );
104
+ }
105
+ }
106
+ }
107
+ wp_safe_redirect( remove_query_arg( 'wcj-remove-from-cart' ) );
108
+ exit;
109
+ }
110
+ }
111
+
112
+ /**
113
+ * reposition_cross_sells.
114
+ *
115
+ * @version 3.6.0
116
+ * @since 3.6.0
117
+ * @todo [dev] (maybe) check `woocommerce\templates\cart\cart.php` for more positions
118
+ */
119
+ function reposition_cross_sells() {
120
+ $this->hide_cross_sells();
121
+ add_action( get_option( 'wcj_cross_sells_position', 'no_changes' ), 'woocommerce_cross_sell_display', get_option( 'wcj_cross_sells_position_priority', 10 ) );
122
+ }
123
+
124
+ /**
125
+ * hide_cross_sells.
126
+ *
127
+ * @version 3.6.0
128
+ * @since 3.6.0
129
+ */
130
+ function hide_cross_sells() {
131
+ remove_action( 'woocommerce_cart_collaterals', 'woocommerce_cross_sell_display' );
132
+ }
133
+
134
+ /**
135
+ * cross_sells_exclude_not_in_stock.
136
+ *
137
+ * @version 3.9.0
138
+ * @since 3.9.0
139
+ */
140
+ function cross_sells_exclude_not_in_stock( $ids, $_product ) {
141
+ foreach ( $ids as $key => $product_id ) {
142
+ $product = wc_get_product( $product_id );
143
+ if ( ! $product->is_in_stock() ) {
144
+ unset( $ids[ $key ] );
145
+ }
146
+ }
147
+ return $ids;
148
+ }
149
+
150
+ /**
151
+ * cross_sells_ids.
152
+ *
153
+ * @version 3.6.0
154
+ * @since 3.6.0
155
+ * @todo [dev] (maybe) ids instead of list
156
+ * @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)
157
+ * @todo [feature] (maybe) on per category/tag basis
158
+ */
159
+ function cross_sells_ids( $ids, $_product ) {
160
+ $global_cross_sells = get_option( 'wcj_cross_sells_global_ids', '' );
161
+ if ( ! empty( $global_cross_sells ) ) {
162
+ $global_cross_sells = array_unique( $global_cross_sells );
163
+ $product_id = wcj_get_product_id_or_variation_parent_id( $_product );
164
+ if ( false !== ( $key = array_search( $product_id, $global_cross_sells ) ) ) {
165
+ unset( $global_cross_sells[ $key ] );
166
+ }
167
+ }
168
+ return ( empty( $global_cross_sells ) ? $ids : array_unique( array_merge( $ids, $global_cross_sells ) ) );
169
+ }
170
+
171
+ /**
172
+ * cross_sells_order.
173
+ *
174
+ * @version 3.5.3
175
+ * @since 3.5.3
176
+ */
177
+ function cross_sells_order( $order ) {
178
+ return ( 'no_changes' != ( $_order = get_option( 'wcj_cross_sells_order', 'no_changes' ) ) ? $_order : $order );
179
+ }
180
+
181
+ /**
182
+ * cross_sells_orderby.
183
+ *
184
+ * @version 3.5.3
185
+ * @since 3.5.3
186
+ */
187
+ function cross_sells_orderby( $orderby ) {
188
+ return ( 'no_changes' != ( $_orderby = get_option( 'wcj_cross_sells_orderby', 'no_changes' ) ) ? $_orderby : $orderby );
189
+ }
190
+
191
+ /**
192
+ * cross_sells_columns.
193
+ *
194
+ * @version 3.5.3
195
+ * @since 3.5.3
196
+ */
197
+ function cross_sells_columns( $columns ) {
198
+ return ( 0 != ( $_columns = get_option( 'wcj_cross_sells_columns', 0 ) ) ? $_columns : $columns );
199
+ }
200
+
201
+ /**
202
+ * cross_sells_total.
203
+ *
204
+ * @version 3.6.0
205
+ * @since 3.5.3
206
+ */
207
+ function cross_sells_total( $limit ) {
208
+ return ( 0 != ( $_limit = get_option( 'wcj_cross_sells_total', 0 ) ) ? $_limit : $limit );
209
+ }
210
+
211
+ }
212
+
213
+ endif;
214
+
215
+ return new WCJ_Cross_Sells();
includes/class-wcj-crowdfunding.php CHANGED
@@ -1,80 +1,80 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Crowdfunding
4
- *
5
- * @version 2.8.0
6
- * @since 2.2.6
7
- * @author Algoritmika Ltd.
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 2.8.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
- sprintf(
30
- __( 'To add crowdfunding info to the product, use <a href="%s" target="_blank">Booster\'s crowdfunding shortcodes</a>.', 'woocommerce-jetpack' ),
31
- 'https://booster.io/category/shortcodes/products-crowdfunding/'
32
- ) . ' ' .
33
- sprintf(
34
- __( 'Shortcodes could be used for example in <a href="%s">Product Info module</a>.', 'woocommerce-jetpack' ),
35
- admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=products&section=product_custom_info' )
36
- ) . '<br>' .
37
- sprintf(
38
- __( 'To change add to cart button labels use <a href="%s">Add to Cart Labels module</a>.', 'woocommerce-jetpack' ),
39
- admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=labels&section=add_to_cart' )
40
- );
41
- parent::__construct();
42
-
43
- if ( $this->is_enabled() ) {
44
-
45
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
46
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
47
-
48
- add_action( 'woocommerce_is_purchasable', array( $this, 'check_dates' ), PHP_INT_MAX, 2 );
49
- }
50
- }
51
-
52
- /**
53
- * check_dates.
54
- *
55
- * @version 2.7.0
56
- * @since 2.2.6
57
- */
58
- function check_dates( $purchasable, $_product ) {
59
- $_product_id = wcj_get_product_id_or_variation_parent_id( $_product );
60
- $goal = get_post_meta( $_product_id, '_' . 'wcj_crowdfunding_goal_sum', true );
61
- if ( 0 != $goal ) {
62
- $start_date_str = get_post_meta( $_product_id, '_' . 'wcj_crowdfunding_startdate', true );
63
- $end_date_str = get_post_meta( $_product_id, '_' . 'wcj_crowdfunding_deadline', true );
64
- $start_date = ( '' != $start_date_str ) ? strtotime( $start_date_str ) : 0;
65
- $end_date = ( '' != $end_date_str ) ? strtotime( $end_date_str ) : 0;
66
- if ( $start_date > 0 && ( $start_date - current_time( 'timestamp' ) ) > 0 ) {
67
- $purchasable = false;
68
- }
69
- if ( $end_date > 0 && ( $end_date - current_time( 'timestamp' ) ) < 0 ) {
70
- $purchasable = false;
71
- }
72
- }
73
- return $purchasable;
74
- }
75
-
76
- }
77
-
78
- endif;
79
-
80
- return new WCJ_Crowdfunding();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Crowdfunding
4
+ *
5
+ * @version 2.8.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 2.8.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
+ sprintf(
30
+ __( 'To add crowdfunding info to the product, use <a href="%s" target="_blank">Booster\'s crowdfunding shortcodes</a>.', 'woocommerce-jetpack' ),
31
+ 'https://booster.io/category/shortcodes/products-crowdfunding/'
32
+ ) . ' ' .
33
+ sprintf(
34
+ __( 'Shortcodes could be used for example in <a href="%s">Product Info module</a>.', 'woocommerce-jetpack' ),
35
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=products&section=product_custom_info' )
36
+ ) . '<br>' .
37
+ sprintf(
38
+ __( 'To change add to cart button labels use <a href="%s">Add to Cart Labels module</a>.', 'woocommerce-jetpack' ),
39
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=labels&section=add_to_cart' )
40
+ );
41
+ parent::__construct();
42
+
43
+ if ( $this->is_enabled() ) {
44
+
45
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
46
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
47
+
48
+ add_action( 'woocommerce_is_purchasable', array( $this, 'check_dates' ), PHP_INT_MAX, 2 );
49
+ }
50
+ }
51
+
52
+ /**
53
+ * check_dates.
54
+ *
55
+ * @version 2.7.0
56
+ * @since 2.2.6
57
+ */
58
+ function check_dates( $purchasable, $_product ) {
59
+ $_product_id = wcj_get_product_id_or_variation_parent_id( $_product );
60
+ $goal = get_post_meta( $_product_id, '_' . 'wcj_crowdfunding_goal_sum', true );
61
+ if ( 0 != $goal ) {
62
+ $start_date_str = get_post_meta( $_product_id, '_' . 'wcj_crowdfunding_startdate', true );
63
+ $end_date_str = get_post_meta( $_product_id, '_' . 'wcj_crowdfunding_deadline', true );
64
+ $start_date = ( '' != $start_date_str ) ? strtotime( $start_date_str ) : 0;
65
+ $end_date = ( '' != $end_date_str ) ? strtotime( $end_date_str ) : 0;
66
+ if ( $start_date > 0 && ( $start_date - current_time( 'timestamp' ) ) > 0 ) {
67
+ $purchasable = false;
68
+ }
69
+ if ( $end_date > 0 && ( $end_date - current_time( 'timestamp' ) ) < 0 ) {
70
+ $purchasable = false;
71
+ }
72
+ }
73
+ return $purchasable;
74
+ }
75
+
76
+ }
77
+
78
+ endif;
79
+
80
+ return new WCJ_Crowdfunding();
includes/class-wcj-currency-exchange-rates.php CHANGED
@@ -1,262 +1,262 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Currency Exchange Rates
4
- *
5
- * @version 3.4.5
6
- * @since 2.3.0
7
- * @author Algoritmika Ltd.
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 3.4.5
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.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-currency-exchange-rates';
27
- parent::__construct();
28
-
29
- add_action( 'wp_ajax_' . 'wcj_ajax_get_exchange_rates', array( $this, 'wcj_ajax_get_exchange_rates' ) );
30
- add_action( 'wp_ajax_nopriv_' . 'wcj_ajax_get_exchange_rates', array( $this, 'wcj_ajax_get_exchange_rates' ) );
31
-
32
- if ( $this->is_enabled() ) {
33
- include_once( 'exchange-rates/class-wcj-exchange-rates-crons.php' );
34
- add_action( 'admin_init', array( $this, 'maybe_update_all_rates' ) );
35
- }
36
- include_once( 'exchange-rates/class-wcj-exchange-rates.php' );
37
- }
38
-
39
- /**
40
- * maybe_update_all_rates.
41
- *
42
- * @version 3.4.5
43
- * @since 3.4.5
44
- */
45
- function maybe_update_all_rates() {
46
- if ( isset( $_GET['wcj_currency_exchange_rates_update_now'] ) ) {
47
- do_action( 'auto_update_exchange_rates_hook' );
48
- wp_safe_redirect( remove_query_arg( 'wcj_currency_exchange_rates_update_now' ) );
49
- }
50
- }
51
-
52
- /**
53
- * wcj_ajax_get_exchange_rates.
54
- *
55
- * @version 2.7.0
56
- * @since 2.6.0
57
- * @todo (maybe) move this to `class-wcj-exchange-rates.php`
58
- */
59
- function wcj_ajax_get_exchange_rates() {
60
- echo wcj_get_exchange_rate( $_POST['wcj_currency_from'], $_POST['wcj_currency_to'] );
61
- die();
62
- }
63
-
64
- /**
65
- * add_currency_pair_setting.
66
- *
67
- * @version 3.2.4
68
- */
69
- function add_currency_pair_setting( $currency_from, $currency_to, $settings ) {
70
- if ( $currency_from != $currency_to ) {
71
- $field_id = 'wcj_currency_exchange_rates_' . sanitize_title( $currency_from . $currency_to );
72
- foreach ( $settings as $setting ) {
73
- if ( $setting['id'] === $field_id ) {
74
- return $settings;
75
- }
76
- }
77
- $custom_attributes = array(
78
- 'currency_from' => $currency_from,
79
- 'currency_to' => $currency_to,
80
- 'multiply_by_field_id' => $field_id,
81
- );
82
- $settings[] = array(
83
- 'title' => $currency_from . ' / ' . $currency_to,
84
- 'id' => $field_id,
85
- 'default' => 0,
86
- 'type' => 'exchange_rate',
87
- 'custom_attributes_button' => $custom_attributes,
88
- 'value' => $currency_from . '/' . $currency_to,
89
- );
90
- }
91
- return $settings;
92
- }
93
-
94
- /**
95
- * get_all_currencies_exchange_rates_currencies.
96
- *
97
- * @version 2.9.0
98
- * @since 2.9.0
99
- */
100
- function get_all_currencies_exchange_rates_currencies() {
101
- $currencies = array();
102
- // Additional currencies (via filter)
103
- $additional_currencies = apply_filters( 'wcj_currency_exchange_rates_additional_currencies', array() );
104
- foreach ( $additional_currencies as $additional_currency ) {
105
- $currencies[] = $additional_currency;
106
- }
107
- // Additional currencies (via custom currencies section)
108
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_currency_exchange_custom_currencies_total_number', 1 ) );
109
- for ( $i = 1; $i <= $total_number; $i++ ) {
110
- if ( 'disabled' != ( $additional_currency = get_option( 'wcj_currency_exchange_custom_currencies_' . $i, 'disabled' ) ) ) {
111
- $currencies[] = $additional_currency;
112
- }
113
- }
114
- if ( wcj_is_module_enabled( 'price_by_country' ) ) {
115
- // Currency Pairs - Price by Country
116
- if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_price_by_country_auto_exchange_rates', 'manual' ) ) ) {
117
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_price_by_country_total_groups_number', 1 ) ); $i++ ) {
118
- $currency_to = get_option( 'wcj_price_by_country_exchange_rate_currency_group_' . $i );
119
- $currencies[] = $currency_to;
120
- }
121
- }
122
- }
123
- if ( wcj_is_module_enabled( 'multicurrency' ) ) {
124
- // Currency Pairs - Multicurrency
125
- if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_multicurrency_exchange_rate_update_auto', 'manual' ) ) ) {
126
- for ( $i = 1; $i <= apply_filters( 'booster_option', 2, get_option( 'wcj_multicurrency_total_number', 2 ) ); $i++ ) {
127
- $currency_to = get_option( 'wcj_multicurrency_currency_' . $i );
128
- $currencies[] = $currency_to;
129
- }
130
- }
131
- }
132
- if ( wcj_is_module_enabled( 'multicurrency_base_price' ) ) {
133
- // Currency Pairs - Multicurrency Product Base Price
134
- if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_multicurrency_base_price_exchange_rate_update', 'manual' ) ) ) {
135
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_multicurrency_base_price_total_number', 1 ) ); $i++ ) {
136
- $currency_to = get_option( 'wcj_multicurrency_base_price_currency_' . $i );
137
- $currencies[] = $currency_to;
138
- }
139
- }
140
- }
141
- if ( wcj_is_module_enabled( 'currency_per_product' ) ) {
142
- // Currency Pairs - Currency per Product
143
- if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_currency_per_product_exchange_rate_update', 'manual' ) ) ) {
144
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_currency_per_product_total_number', 1 ) ); $i++ ) {
145
- $currency_to = get_option( 'wcj_currency_per_product_currency_' . $i );
146
- $currencies[] = $currency_to;
147
- }
148
- }
149
- }
150
- if ( wcj_is_module_enabled( 'payment_gateways_currency' ) ) {
151
- if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_gateways_currency_exchange_rate_update_auto', 'manual' ) ) ) {
152
- // Currency Pairs - Gateway Currency
153
- global $woocommerce;
154
- $available_gateways = $woocommerce->payment_gateways->payment_gateways();
155
- foreach ( $available_gateways as $key => $gateway ) {
156
- $currency_to = get_option( 'wcj_gateways_currency_' . $key );
157
- if ( 'no_changes' != $currency_to ) {
158
- $currencies[] = $currency_to;
159
- }
160
- }
161
- }
162
- }
163
- return $currencies;
164
- }
165
-
166
- /**
167
- * add_currency_pair_server_setting.
168
- *
169
- * @version 3.2.4
170
- * @since 3.2.4
171
- */
172
- function add_currency_pair_server_setting( $currency_from, $currency_to, $default_server, $settings ) {
173
- if ( $currency_from != $currency_to ) {
174
- $field_id = 'wcj_currency_exchange_rates_server_' . sanitize_title( $currency_from . $currency_to );
175
- foreach ( $settings as $setting ) {
176
- if ( $setting['id'] === $field_id ) {
177
- return $settings;
178
- }
179
- }
180
- $settings[] = array(
181
- 'desc' => __( 'Exchange Rates Server', 'woocommerce-jetpack' ),
182
- 'id' => $field_id,
183
- 'default' => 'default_server',
184
- 'type' => 'select',
185
- 'options' => array_merge(
186
- array( 'default_server' => sprintf( __( 'Use default: %s', 'woocommerce-jetpack' ), $default_server ) ),
187
- wcj_get_currency_exchange_rate_servers()
188
- ),
189
- );
190
- }
191
- return $settings;
192
- }
193
-
194
- /**
195
- * add_currency_pair_offset_percent_setting.
196
- *
197
- * @version 3.4.5
198
- * @since 3.4.5
199
- */
200
- function add_currency_pair_offset_percent_setting( $currency_from, $currency_to, $default_offset, $settings ) {
201
- if ( $currency_from != $currency_to ) {
202
- $field_id = 'wcj_currency_exchange_rates_offset_percent_' . sanitize_title( $currency_from . $currency_to );
203
- foreach ( $settings as $setting ) {
204
- if ( $setting['id'] === $field_id ) {
205
- return $settings;
206
- }
207
- }
208
- $settings[] = array(
209
- 'desc' => __( 'Exchange Rates Offset (Percent)', 'woocommerce-jetpack' ),
210
- 'id' => $field_id,
211
- 'default' => 'default_offset',
212
- 'type' => 'select',
213
- 'options' => array(
214
- 'default_offset' => sprintf( __( 'Use default: %s%%', 'woocommerce-jetpack' ), $default_offset ),
215
- 'custom_offset' => __( 'Custom offset', 'woocommerce-jetpack' ),
216
- ),
217
- );
218
- $settings[] = array(
219
- 'desc' => __( 'Custom offset (Percent)', 'woocommerce-jetpack' ),
220
- 'desc_tip' => __( 'Used when "Custom offset" option is selected above.', 'woocommerce-jetpack' ),
221
- 'id' => $field_id . '_' . 'custom_offset',
222
- 'default' => 0,
223
- 'type' => 'number',
224
- 'custom_attributes' => array( 'step' => '0.001' ),
225
- );
226
- }
227
- return $settings;
228
- }
229
-
230
- /**
231
- * get_all_currencies_exchange_rates_settings.
232
- *
233
- * @version 3.4.5
234
- * @since 2.9.0
235
- */
236
- function get_all_currencies_exchange_rates_settings( $add_extra_settings = false ) {
237
- if ( $add_extra_settings ) {
238
- // Server
239
- $exchange_rate_servers = wcj_get_currency_exchange_rate_servers();
240
- $exchange_rate_server = get_option( 'wcj_currency_exchange_rates_server', 'ecb' );
241
- $default_server = ( isset( $exchange_rate_servers[ $exchange_rate_server ] ) ? $exchange_rate_servers[ $exchange_rate_server ] : $exchange_rate_server );
242
- // Offset
243
- $default_offset = get_option( 'wcj_currency_exchange_rates_offset_percent', 0 );
244
- }
245
- $settings = array();
246
- $currency_from = get_option( 'woocommerce_currency' );
247
- $currencies = $this->get_all_currencies_exchange_rates_currencies();
248
- foreach ( $currencies as $currency ) {
249
- $settings = $this->add_currency_pair_setting( $currency_from, $currency, $settings );
250
- if ( $add_extra_settings ) {
251
- $settings = $this->add_currency_pair_server_setting( $currency_from, $currency, $default_server, $settings );
252
- $settings = $this->add_currency_pair_offset_percent_setting( $currency_from, $currency, $default_offset, $settings );
253
- }
254
- }
255
- return $settings;
256
- }
257
-
258
- }
259
-
260
- endif;
261
-
262
- return new WCJ_Currency_Exchange_Rates();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Currency Exchange Rates
4
+ *
5
+ * @version 3.4.5
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 3.4.5
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.', 'woocommerce-jetpack' );
26
+ $this->link_slug = 'woocommerce-currency-exchange-rates';
27
+ parent::__construct();
28
+
29
+ add_action( 'wp_ajax_' . 'wcj_ajax_get_exchange_rates', array( $this, 'wcj_ajax_get_exchange_rates' ) );
30
+ add_action( 'wp_ajax_nopriv_' . 'wcj_ajax_get_exchange_rates', array( $this, 'wcj_ajax_get_exchange_rates' ) );
31
+
32
+ if ( $this->is_enabled() ) {
33
+ include_once( 'exchange-rates/class-wcj-exchange-rates-crons.php' );
34
+ add_action( 'admin_init', array( $this, 'maybe_update_all_rates' ) );
35
+ }
36
+ include_once( 'exchange-rates/class-wcj-exchange-rates.php' );
37
+ }
38
+
39
+ /**
40
+ * maybe_update_all_rates.
41
+ *
42
+ * @version 3.4.5
43
+ * @since 3.4.5
44
+ */
45
+ function maybe_update_all_rates() {
46
+ if ( isset( $_GET['wcj_currency_exchange_rates_update_now'] ) ) {
47
+ do_action( 'auto_update_exchange_rates_hook' );
48
+ wp_safe_redirect( remove_query_arg( 'wcj_currency_exchange_rates_update_now' ) );
49
+ }
50
+ }
51
+
52
+ /**
53
+ * wcj_ajax_get_exchange_rates.
54
+ *
55
+ * @version 2.7.0
56
+ * @since 2.6.0
57
+ * @todo (maybe) move this to `class-wcj-exchange-rates.php`
58
+ */
59
+ function wcj_ajax_get_exchange_rates() {
60
+ echo wcj_get_exchange_rate( $_POST['wcj_currency_from'], $_POST['wcj_currency_to'] );
61
+ die();
62
+ }
63
+
64
+ /**
65
+ * add_currency_pair_setting.
66
+ *
67
+ * @version 3.2.4
68
+ */
69
+ function add_currency_pair_setting( $currency_from, $currency_to, $settings ) {
70
+ if ( $currency_from != $currency_to ) {
71
+ $field_id = 'wcj_currency_exchange_rates_' . sanitize_title( $currency_from . $currency_to );
72
+ foreach ( $settings as $setting ) {
73
+ if ( $setting['id'] === $field_id ) {
74
+ return $settings;
75
+ }
76
+ }
77
+ $custom_attributes = array(
78
+ 'currency_from' => $currency_from,
79
+ 'currency_to' => $currency_to,
80
+ 'multiply_by_field_id' => $field_id,
81
+ );
82
+ $settings[] = array(
83
+ 'title' => $currency_from . ' / ' . $currency_to,
84
+ 'id' => $field_id,
85
+ 'default' => 0,
86
+ 'type' => 'exchange_rate',
87
+ 'custom_attributes_button' => $custom_attributes,
88
+ 'value' => $currency_from . '/' . $currency_to,
89
+ );
90
+ }
91
+ return $settings;
92
+ }
93
+
94
+ /**
95
+ * get_all_currencies_exchange_rates_currencies.
96
+ *
97
+ * @version 2.9.0
98
+ * @since 2.9.0
99
+ */
100
+ function get_all_currencies_exchange_rates_currencies() {
101
+ $currencies = array();
102
+ // Additional currencies (via filter)
103
+ $additional_currencies = apply_filters( 'wcj_currency_exchange_rates_additional_currencies', array() );
104
+ foreach ( $additional_currencies as $additional_currency ) {
105
+ $currencies[] = $additional_currency;
106
+ }
107
+ // Additional currencies (via custom currencies section)
108
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_currency_exchange_custom_currencies_total_number', 1 ) );
109
+ for ( $i = 1; $i <= $total_number; $i++ ) {
110
+ if ( 'disabled' != ( $additional_currency = get_option( 'wcj_currency_exchange_custom_currencies_' . $i, 'disabled' ) ) ) {
111
+ $currencies[] = $additional_currency;
112
+ }
113
+ }
114
+ if ( wcj_is_module_enabled( 'price_by_country' ) ) {
115
+ // Currency Pairs - Price by Country
116
+ if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_price_by_country_auto_exchange_rates', 'manual' ) ) ) {
117
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_price_by_country_total_groups_number', 1 ) ); $i++ ) {
118
+ $currency_to = get_option( 'wcj_price_by_country_exchange_rate_currency_group_' . $i );
119
+ $currencies[] = $currency_to;
120
+ }
121
+ }
122
+ }
123
+ if ( wcj_is_module_enabled( 'multicurrency' ) ) {
124
+ // Currency Pairs - Multicurrency
125
+ if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_multicurrency_exchange_rate_update_auto', 'manual' ) ) ) {
126
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 2, get_option( 'wcj_multicurrency_total_number', 2 ) ); $i++ ) {
127
+ $currency_to = get_option( 'wcj_multicurrency_currency_' . $i );
128
+ $currencies[] = $currency_to;
129
+ }
130
+ }
131
+ }
132
+ if ( wcj_is_module_enabled( 'multicurrency_base_price' ) ) {
133
+ // Currency Pairs - Multicurrency Product Base Price
134
+ if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_multicurrency_base_price_exchange_rate_update', 'manual' ) ) ) {
135
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_multicurrency_base_price_total_number', 1 ) ); $i++ ) {
136
+ $currency_to = get_option( 'wcj_multicurrency_base_price_currency_' . $i );
137
+ $currencies[] = $currency_to;
138
+ }
139
+ }
140
+ }
141
+ if ( wcj_is_module_enabled( 'currency_per_product' ) ) {
142
+ // Currency Pairs - Currency per Product
143
+ if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_currency_per_product_exchange_rate_update', 'manual' ) ) ) {
144
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_currency_per_product_total_number', 1 ) ); $i++ ) {
145
+ $currency_to = get_option( 'wcj_currency_per_product_currency_' . $i );
146
+ $currencies[] = $currency_to;
147
+ }
148
+ }
149
+ }
150
+ if ( wcj_is_module_enabled( 'payment_gateways_currency' ) ) {
151
+ if ( 'manual' != apply_filters( 'booster_option', 'manual', get_option( 'wcj_gateways_currency_exchange_rate_update_auto', 'manual' ) ) ) {
152
+ // Currency Pairs - Gateway Currency
153
+ global $woocommerce;
154
+ $available_gateways = $woocommerce->payment_gateways->payment_gateways();
155
+ foreach ( $available_gateways as $key => $gateway ) {
156
+ $currency_to = get_option( 'wcj_gateways_currency_' . $key );
157
+ if ( 'no_changes' != $currency_to ) {
158
+ $currencies[] = $currency_to;
159
+ }
160
+ }
161
+ }
162
+ }
163
+ return $currencies;
164
+ }
165
+
166
+ /**
167
+ * add_currency_pair_server_setting.
168
+ *
169
+ * @version 3.2.4
170
+ * @since 3.2.4
171
+ */
172
+ function add_currency_pair_server_setting( $currency_from, $currency_to, $default_server, $settings ) {
173
+ if ( $currency_from != $currency_to ) {
174
+ $field_id = 'wcj_currency_exchange_rates_server_' . sanitize_title( $currency_from . $currency_to );
175
+ foreach ( $settings as $setting ) {
176
+ if ( $setting['id'] === $field_id ) {
177
+ return $settings;
178
+ }
179
+ }
180
+ $settings[] = array(
181
+ 'desc' => __( 'Exchange Rates Server', 'woocommerce-jetpack' ),
182
+ 'id' => $field_id,
183
+ 'default' => 'default_server',
184
+ 'type' => 'select',
185
+ 'options' => array_merge(
186
+ array( 'default_server' => sprintf( __( 'Use default: %s', 'woocommerce-jetpack' ), $default_server ) ),
187
+ wcj_get_currency_exchange_rate_servers()
188
+ ),
189
+ );
190
+ }
191
+ return $settings;
192
+ }
193
+
194
+ /**
195
+ * add_currency_pair_offset_percent_setting.
196
+ *
197
+ * @version 3.4.5
198
+ * @since 3.4.5
199
+ */
200
+ function add_currency_pair_offset_percent_setting( $currency_from, $currency_to, $default_offset, $settings ) {
201
+ if ( $currency_from != $currency_to ) {
202
+ $field_id = 'wcj_currency_exchange_rates_offset_percent_' . sanitize_title( $currency_from . $currency_to );
203
+ foreach ( $settings as $setting ) {
204
+ if ( $setting['id'] === $field_id ) {
205
+ return $settings;
206
+ }
207
+ }
208
+ $settings[] = array(
209
+ 'desc' => __( 'Exchange Rates Offset (Percent)', 'woocommerce-jetpack' ),
210
+ 'id' => $field_id,
211
+ 'default' => 'default_offset',
212
+ 'type' => 'select',
213
+ 'options' => array(
214
+ 'default_offset' => sprintf( __( 'Use default: %s%%', 'woocommerce-jetpack' ), $default_offset ),
215
+ 'custom_offset' => __( 'Custom offset', 'woocommerce-jetpack' ),
216
+ ),
217
+ );
218
+ $settings[] = array(
219
+ 'desc' => __( 'Custom offset (Percent)', 'woocommerce-jetpack' ),
220
+ 'desc_tip' => __( 'Used when "Custom offset" option is selected above.', 'woocommerce-jetpack' ),
221
+ 'id' => $field_id . '_' . 'custom_offset',
222
+ 'default' => 0,
223
+ 'type' => 'number',
224
+ 'custom_attributes' => array( 'step' => '0.001' ),
225
+ );
226
+ }
227
+ return $settings;
228
+ }
229
+
230
+ /**
231
+ * get_all_currencies_exchange_rates_settings.
232
+ *
233
+ * @version 3.4.5
234
+ * @since 2.9.0
235
+ */
236
+ function get_all_currencies_exchange_rates_settings( $add_extra_settings = false ) {
237
+ if ( $add_extra_settings ) {
238
+ // Server
239
+ $exchange_rate_servers = wcj_get_currency_exchange_rate_servers();
240
+ $exchange_rate_server = get_option( 'wcj_currency_exchange_rates_server', 'ecb' );
241
+ $default_server = ( isset( $exchange_rate_servers[ $exchange_rate_server ] ) ? $exchange_rate_servers[ $exchange_rate_server ] : $exchange_rate_server );
242
+ // Offset
243
+ $default_offset = get_option( 'wcj_currency_exchange_rates_offset_percent', 0 );
244
+ }
245
+ $settings = array();
246
+ $currency_from = get_option( 'woocommerce_currency' );
247
+ $currencies = $this->get_all_currencies_exchange_rates_currencies();
248
+ foreach ( $currencies as $currency ) {
249
+ $settings = $this->add_currency_pair_setting( $currency_from, $currency, $settings );
250
+ if ( $add_extra_settings ) {
251
+ $settings = $this->add_currency_pair_server_setting( $currency_from, $currency, $default_server, $settings );
252
+ $settings = $this->add_currency_pair_offset_percent_setting( $currency_from, $currency, $default_offset, $settings );
253
+ }
254
+ }
255
+ return $settings;
256
+ }
257
+
258
+ }
259
+
260
+ endif;
261
+
262
+ return new WCJ_Currency_Exchange_Rates();
includes/class-wcj-currency-external-products.php CHANGED
@@ -1,53 +1,53 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Currency for External Products
4
- *
5
- * @version 3.9.0
6
- * @author Algoritmika Ltd.
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 ( '' != 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 get_option( 'wcj_currency_external_products_symbol', 'EUR' );
45
- }
46
- return $currency;
47
- }
48
-
49
- }
50
-
51
- endif;
52
-
53
- return new WCJ_Currency_External_Products();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Currency for External Products
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 ( '' != 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 get_option( 'wcj_currency_external_products_symbol', 'EUR' );
45
+ }
46
+ return $currency;
47
+ }
48
+
49
+ }
50
+
51
+ endif;
52
+
53
+ return new WCJ_Currency_External_Products();
includes/class-wcj-currency-per-product.php CHANGED
@@ -1,489 +1,489 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Currency per Product
4
- *
5
- * @version 3.9.0
6
- * @since 2.5.2
7
- * @author Algoritmika Ltd.
8
- */
9
-
10
- if ( ! defined( 'ABSPATH' ) ) exit;
11
-
12
- if ( ! class_exists( 'WCJ_Currency_Per_Product' ) ) :
13
-
14
- class WCJ_Currency_Per_Product extends WCJ_Module {
15
-
16
- /**
17
- * Constructor.
18
- *
19
- * @version 3.9.0
20
- * @since 2.5.2
21
- * @todo (maybe) add `$this->price_hooks_priority`
22
- */
23
- function __construct() {
24
-
25
- $this->id = 'currency_per_product';
26
- $this->short_desc = __( 'Currency per Product', 'woocommerce-jetpack' );
27
- $this->desc = __( 'Display prices for products in different currencies.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-currency-per-product';
29
- parent::__construct();
30
-
31
- if ( $this->is_enabled() ) {
32
-
33
- $this->do_save_converted_prices = ( 'yes' === get_option( 'wcj_currency_per_product_save_prices', 'no' ) );
34
-
35
- $this->is_currency_per_product_by_product_enabled = ( 'yes' === get_option( 'wcj_currency_per_product_per_product', 'yes' ) );
36
- if ( $this->is_currency_per_product_by_product_enabled ) {
37
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
38
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
39
- }
40
-
41
- // Currency code and symbol
42
- add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX );
43
-
44
- // Add to cart
45
- add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_cart_item_data' ), PHP_INT_MAX, 3 );
46
- add_filter( 'woocommerce_add_cart_item', array( $this, 'add_cart_item' ), PHP_INT_MAX, 2 );
47
- add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'get_cart_item_from_session' ), PHP_INT_MAX, 3 );
48
- add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_on_add_to_cart' ), PHP_INT_MAX, 2 );
49
-
50
- // Price
51
- add_filter( WCJ_PRODUCT_GET_PRICE_FILTER, array( $this, 'change_price' ), PHP_INT_MAX, 2 );
52
- add_filter( 'woocommerce_product_variation_get_price', array( $this, 'change_price' ), PHP_INT_MAX, 2 );
53
-
54
- // Grouped
55
- add_filter( 'woocommerce_grouped_price_html', array( $this, 'grouped_price_html' ), PHP_INT_MAX, 2 );
56
-
57
- // Shipping
58
- add_filter( 'woocommerce_package_rates', array( $this, 'change_shipping_price' ), PHP_INT_MAX, 2 );
59
-
60
- }
61
- }
62
-
63
- /**
64
- * change_shipping_price.
65
- *
66
- * @version 3.2.0
67
- * @since 2.7.0
68
- */
69
- function change_shipping_price( $package_rates, $package ) {
70
- if ( isset( WC()->cart ) ) {
71
- if ( WC()->cart->is_empty() ) {
72
- return $package_rates;
73
- }
74
- $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
75
- switch ( $cart_checkout_behaviour ) {
76
- case 'leave_one_product':
77
- case 'leave_same_currency':
78
- case 'convert_first_product':
79
- case 'convert_last_product':
80
- $shop_currency = get_option( 'woocommerce_currency' );
81
- if ( false != ( $_currency = $this->get_cart_checkout_currency() ) && $_currency != $shop_currency ) {
82
- $currency_exchange_rate = $this->get_currency_exchange_rate( $_currency );
83
- if ( 0 != $currency_exchange_rate && 1 != $currency_exchange_rate ) {
84
- $currency_exchange_rate = 1 / $currency_exchange_rate;
85
- return wcj_change_price_shipping_package_rates( $package_rates, $currency_exchange_rate );
86
- } else {
87
- return $package_rates;
88
- }
89
- } else {
90
- return $package_rates;
91
- }
92
- default: // case 'convert_shop_default':
93
- return $package_rates;
94
- }
95
- }
96
- return $package_rates;
97
- }
98
-
99
- /**
100
- * get_product_currency.
101
- *
102
- * @version 3.7.0
103
- * @since 2.9.0
104
- * @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 );`
105
- */
106
- function get_product_currency( $product_id ) {
107
- // By users or user roles
108
- $do_check_by_users = ( 'yes' === get_option( 'wcj_currency_per_product_by_users_enabled', 'no' ) );
109
- $do_check_by_user_roles = ( 'yes' === get_option( 'wcj_currency_per_product_by_user_roles_enabled', 'no' ) );
110
- $do_check_by_product_cats = ( 'yes' === get_option( 'wcj_currency_per_product_by_product_cats_enabled', 'no' ) );
111
- $do_check_by_product_tags = ( 'yes' === get_option( 'wcj_currency_per_product_by_product_tags_enabled', 'no' ) );
112
- if ( $do_check_by_users || $do_check_by_user_roles || $do_check_by_product_cats || $do_check_by_product_tags ) {
113
- if ( $do_check_by_users || $do_check_by_user_roles ) {
114
- $product_author_id = get_post_field( 'post_author', $product_id );
115
- }
116
- if ( $do_check_by_product_cats ) {
117
- $_product_cats = wcj_get_the_terms( $product_id, 'product_cat' );
118
- }
119
- if ( $do_check_by_product_tags ) {
120
- $_product_tags = wcj_get_the_terms( $product_id, 'product_tag' );
121
- }
122
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_currency_per_product_total_number', 1 ) );
123
- for ( $i = 1; $i <= $total_number; $i++ ) {
124
- if ( $do_check_by_users ) {
125
- $users = get_option( 'wcj_currency_per_product_users_' . $i, '' );
126
- if ( ! empty( $users ) && in_array( $product_author_id, $users ) ) {
127
- return get_option( 'wcj_currency_per_product_currency_' . $i );
128
- }
129
- }
130
- if ( $do_check_by_user_roles ) {
131
- $user_roles = get_option( 'wcj_currency_per_product_user_roles_' . $i, '' );
132
- if ( ! empty( $user_roles ) && wcj_is_user_role( $user_roles, $product_author_id ) ) {
133
- return get_option( 'wcj_currency_per_product_currency_' . $i );
134
- }
135
- }
136
- if ( $do_check_by_product_cats ) {
137
- $product_cats = get_option( 'wcj_currency_per_product_product_cats_' . $i, '' );
138
- if ( ! empty( $_product_cats ) && ! empty( $product_cats ) ) {
139
- $_intersect = array_intersect( $_product_cats, $product_cats );
140
- if ( ! empty( $_intersect ) ) {
141
- return get_option( 'wcj_currency_per_product_currency_' . $i );
142
- }
143
- }
144
- }
145
- if ( $do_check_by_product_tags ) {
146
- $product_tags = get_option( 'wcj_currency_per_product_product_tags_' . $i, '' );
147
- if ( ! empty( $_product_tags ) && ! empty( $product_tags ) ) {
148
- $_intersect = array_intersect( $_product_tags, $product_tags );
149
- if ( ! empty( $_intersect ) ) {
150
- return get_option( 'wcj_currency_per_product_currency_' . $i );
151
- }
152
- }
153
- }
154
- }
155
- }
156
- // By product meta
157
- return ( $this->is_currency_per_product_by_product_enabled ? get_post_meta( $product_id, '_' . 'wcj_currency_per_product_currency', true ) : false );
158
- }
159
-
160
- /**
161
- * validate_on_add_to_cart.
162
- *
163
- * @version 2.9.0
164
- * @since 2.7.0
165
- */
166
- function validate_on_add_to_cart( $passed, $product_id ) {
167
- $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
168
- if ( 'leave_one_product' === $cart_checkout_behaviour ) {
169
- foreach ( WC()->cart->get_cart() as $cart_item ) {
170
- if ( $cart_item['product_id'] != $product_id ) {
171
- wc_add_notice( get_option( 'wcj_currency_per_product_cart_checkout_leave_one_product',
172
- __( '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' ) ), 'error' );
173
- return false;
174
- }
175
- }
176
- } elseif ( 'leave_same_currency' === $cart_checkout_behaviour ) {
177
- $shop_currency = get_option( 'woocommerce_currency' );
178
- $product_currency = $this->get_product_currency( $product_id );
179
- if ( '' == $product_currency ) {
180
- $product_currency = $shop_currency;
181
- }
182
- foreach ( WC()->cart->get_cart() as $cart_item ) {
183
- $cart_product_currency = ( isset( $cart_item['wcj_currency_per_product'] ) && '' != $cart_item['wcj_currency_per_product'] ) ?
184
- $cart_item['wcj_currency_per_product'] : $shop_currency;
185
- if ( $cart_product_currency != $product_currency ) {
186
- wc_add_notice( get_option( 'wcj_currency_per_product_cart_checkout_leave_same_currency',
187
- __( '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' ) ), 'error' );
188
- return false;
189
- }
190
- }
191
- }
192
- return $passed;
193
- }
194
-
195
- /**
196
- * grouped_price_html.
197
- *
198
- * @version 2.9.0
199
- * @since 2.5.2
200
- */
201
- function grouped_price_html( $price_html, $_product ) {
202
- $child_prices = array();
203
- foreach ( $_product->get_children() as $child_id ) {
204
- $child_prices[ $child_id ] = get_post_meta( $child_id, '_price', true );
205
- }
206
- if ( ! empty( $child_prices ) ) {
207
- asort( $child_prices );
208
- $min_price = current( $child_prices );
209
- $min_price_id = key( $child_prices );
210
- end( $child_prices );
211
- $max_price = current( $child_prices );
212
- $max_price_id = key( $child_prices );
213
- $min_currency_per_product_currency = $this->get_product_currency( $min_price_id );
214
- $max_currency_per_product_currency = $this->get_product_currency( $max_price_id );
215
- } else {
216
- $min_price = '';
217
- $max_price = '';
218
- }
219
-
220
- if ( $min_price ) {
221
- if ( $min_price == $max_price && $min_currency_per_product_currency === $max_currency_per_product_currency ) {
222
- $display_price = wc_price( wcj_get_product_display_price( $_product, $min_price, 1 ), array( 'currency' => $min_currency_per_product_currency ) );
223
- } else {
224
- $from = wc_price( wcj_get_product_display_price( $_product, $min_price, 1 ), array( 'currency' => $min_currency_per_product_currency ) );
225
- $to = wc_price( wcj_get_product_display_price( $_product, $max_price, 1 ), array( 'currency' => $max_currency_per_product_currency ) );
226
- $display_price = sprintf( _x( '%1$s&ndash;%2$s', 'Price range: from-to', 'woocommerce' ), $from, $to );
227
- }
228
- $new_price_html = $display_price . $_product->get_price_suffix();
229
- return $new_price_html;
230
- }
231
-
232
- return $price_html;
233
- }
234
-
235
- /**
236
- * get_currency_exchange_rate.
237
- *
238
- * @version 3.6.0
239
- * @since 2.5.2
240
- */
241
- function get_currency_exchange_rate( $currency_code ) {
242
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_currency_per_product_total_number', 1 ) );
243
- for ( $i = 1; $i <= $total_number; $i++ ) {
244
- if ( $currency_code === get_option( 'wcj_currency_per_product_currency_' . $i ) ) {
245
- return ( 0 != ( $rate = get_option( 'wcj_currency_per_product_exchange_rate_' . $i, 1 ) ) ? ( 1 / $rate ) : 1 );
246
- }
247
- }
248
- return 1;
249
- }
250
-
251
- /**
252
- * maybe_return_saved_converted_price.
253
- *
254
- * @version 3.3.0
255
- * @since 3.3.0
256
- */
257
- function maybe_return_saved_converted_price( $_product, $_currency ) {
258
- if ( $this->do_save_converted_prices ) {
259
- $product_id = ( isset( $_product->wcj_currency_per_product_item_key ) ? $_product->wcj_currency_per_product_item_key : wcj_get_product_id( $_product ) );
260
- if ( isset( $this->saved_product_prices[ $product_id ][ $_product->wcj_currency_per_product ][ $_currency ] ) ) {
261
- return $this->saved_product_prices[ $product_id ][ $_product->wcj_currency_per_product ][ $_currency ];
262
- }
263
- }
264
- return false;
265
- }
266
-
267
- /**
268
- * maybe_save_converted_price.
269
- *
270
- * @version 3.3.0
271
- * @since 3.3.0
272
- */
273
- function maybe_save_converted_price( $price, $_product, $_currency ) {
274
- if ( $this->do_save_converted_prices ) {
275
- $product_id = ( isset( $_product->wcj_currency_per_product_item_key ) ? $_product->wcj_currency_per_product_item_key : wcj_get_product_id( $_product ) );
276
- $this->saved_product_prices[ $product_id ][ $_product->wcj_currency_per_product ][ $_currency ] = $price;
277
- }
278
- return $price;
279
- }
280
-
281
- /**
282
- * change_price.
283
- *
284
- * @version 3.3.0
285
- * @since 2.5.2
286
- */
287
- function change_price( $price, $_product ) {
288
- if ( isset( $_product->wcj_currency_per_product ) ) {
289
- $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
290
- switch ( $cart_checkout_behaviour ) {
291
- case 'leave_one_product':
292
- case 'leave_same_currency':
293
- return $price;
294
- case 'convert_first_product':
295
- case 'convert_last_product':
296
- $shop_currency = get_option( 'woocommerce_currency' );
297
- if ( false != ( $_currency = $this->get_cart_checkout_currency() ) && $_currency != $shop_currency ) {
298
- if ( $_product->wcj_currency_per_product === $_currency ) {
299
- return $price;
300
- } else {
301
- if ( false !== ( $saved_price = $this->maybe_return_saved_converted_price( $_product, $_currency ) ) ) {
302
- return $saved_price;
303
- }
304
- $exchange_rate_product = $this->get_currency_exchange_rate( $_product->wcj_currency_per_product );
305
- $exchange_rate_cart_checkout = $this->get_currency_exchange_rate( $_currency );
306
- $exchange_rate = $exchange_rate_product / $exchange_rate_cart_checkout;
307
- return $this->maybe_save_converted_price( $price * $exchange_rate, $_product, $_currency );
308
- }
309
- } elseif ( $_product->wcj_currency_per_product === $shop_currency ) {
310
- return $price;
311
- } else {
312
- if ( false !== ( $saved_price = $this->maybe_return_saved_converted_price( $_product, $shop_currency ) ) ) {
313
- return $saved_price;
314
- }
315
- $exchange_rate = $this->get_currency_exchange_rate( $_product->wcj_currency_per_product );
316
- return $this->maybe_save_converted_price( $price * $exchange_rate, $_product, $shop_currency );
317
- }
318
- default: // case 'convert_shop_default':
319
- $shop_currency = get_option( 'woocommerce_currency' );
320
- if ( false !== ( $saved_price = $this->maybe_return_saved_converted_price( $_product, $shop_currency ) ) ) {
321
- return $saved_price;
322
- }
323
- $exchange_rate = $this->get_currency_exchange_rate( $_product->wcj_currency_per_product );
324
- return $this->maybe_save_converted_price( $price * $exchange_rate, $_product, $shop_currency );
325
- }
326
- }
327
- return $price;
328
- }
329
-
330
- /**
331
- * get_cart_item_from_session.
332
- *
333
- * @version 3.3.0
334
- * @since 2.5.2
335
- */
336
- function get_cart_item_from_session( $item, $values, $key ) {
337
- if ( array_key_exists( 'wcj_currency_per_product', $values ) ) {
338
- $item['data']->wcj_currency_per_product = $values['wcj_currency_per_product'];
339
- if ( $this->do_save_converted_prices ) {
340
- $item['data']->wcj_currency_per_product_item_key = $key;
341
- }
342
- }
343
- return $item;
344
- }
345
-
346
- /**
347
- * add_cart_item_data.
348
- *
349
- * @version 2.9.0
350
- * @since 2.5.2
351
- */
352
- function add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
353
- $currency_per_product_currency = $this->get_product_currency( $product_id );
354
- if ( '' != $currency_per_product_currency ) {
355
- $cart_item_data['wcj_currency_per_product'] = $currency_per_product_currency;
356
- }
357
- return $cart_item_data;
358
- }
359
-
360
- /**
361
- * add_cart_item.
362
- *
363
- * @version 3.3.0
364
- * @since 2.5.2
365
- * @todo `wcj_currency_per_product_item_key` seems to be not working here
366
- */
367
- function add_cart_item( $cart_item_data, $cart_item_key ) {
368
- if ( isset( $cart_item_data['wcj_currency_per_product'] ) ) {
369
- $cart_item_data['data']->wcj_currency_per_product = $cart_item_data['wcj_currency_per_product'];
370
- if ( $this->do_save_converted_prices ) {
371
- $cart_item_data['data']->wcj_currency_per_product_item_key = $cart_item_key;
372
- }
373
- }
374
- return $cart_item_data;
375
- }
376
-
377
- /**
378
- * get_current_product_id_and_currency.
379
- *
380
- * @version 2.9.0
381
- * @since 2.7.0
382
- */
383
- function get_current_product_id_and_currency() {
384
- // Get ID
385
- $the_ID = false;
386
- global $product;
387
- if ( $product ) {
388
- $the_ID = wcj_get_product_id_or_variation_parent_id( $product );
389
- }
390
- if ( ! $the_ID && isset( $_REQUEST['product_id'] ) ) {
391
- $the_ID = $_REQUEST['product_id'];
392
- }
393
- if ( ! $the_ID && isset( $_POST['form'] ) ) { // WooCommerce Bookings plugin
394
- $posted = array();
395
- parse_str( $_POST['form'], $posted );
396
- $the_ID = isset( $posted['add-to-cart'] ) ? $posted['add-to-cart'] : 0;
397
- }
398
- if ( ! $the_ID && '' != ( $eventon_wc_product_id = get_post_meta( get_the_ID(), 'tx_woocommerce_product_id', true ) ) ) { // EventON plugin
399
- $the_ID = $eventon_wc_product_id;
400
- }
401
- if ( ! $the_ID ) {
402
- $the_ID = get_the_ID();
403
- }
404
- // Get currency
405
- if ( $the_ID && 'product' === get_post_type( $the_ID ) ) {
406
- $currency_per_product_currency = $this->get_product_currency( $the_ID );
407
- return ( '' != $currency_per_product_currency ) ? $currency_per_product_currency : false;
408
- }
409
- return false;
410
- }
411
-
412
- /**
413
- * get_cart_checkout_currency.
414
- *
415
- * @version 3.7.0
416
- * @since 2.7.0
417
- */
418
- function get_cart_checkout_currency() {
419
- $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
420
- if ( false !== ( $value = apply_filters( 'wcj_currency_per_product_cart_checkout_currency', false, $cart_checkout_behaviour ) ) ) {
421
- return $value;
422
- }
423
- /*
424
- * `wcj_currency_per_product_cart_checkout_currency` filter example:
425
- *
426
- * if ( function_exists( 'YITH_Request_Quote' ) && isset( YITH_Request_Quote()->raq_content ) ) {
427
- * foreach ( YITH_Request_Quote()->raq_content as $raq_product ) {
428
- * if ( isset( $raq_product['product_id'] ) ) {
429
- * return get_post_meta( $raq_product['product_id'], '_' . 'wcj_currency_per_product_currency', true );
430
- * }
431
- * }
432
- * }
433
- *
434
- */
435
- if ( ! isset( WC()->cart ) || WC()->cart->is_empty() ) {
436
- return false;
437
- }
438
- if ( 'convert_shop_default' === $cart_checkout_behaviour ) {
439
- return false;
440
- }
441
- $cart_items = WC()->cart->get_cart();
442
- if ( 'convert_last_product' === $cart_checkout_behaviour ) {
443
- $cart_items = array_reverse( $cart_items );
444
- }
445
- foreach ( $cart_items as $cart_item ) {
446
- return ( isset( $cart_item['wcj_currency_per_product'] ) ) ? $cart_item['wcj_currency_per_product'] : false;
447
- }
448
- }
449
-
450
- /**
451
- * is_cart_or_checkout_or_ajax.
452
- *
453
- * @version 3.7.0
454
- * @since 2.7.0
455
- * @todo fix AJAX issue (for minicart)
456
- */
457
- function is_cart_or_checkout_or_ajax() {
458
- return apply_filters( 'wcj_currency_per_product_is_cart_or_checkout',
459
- ( ( function_exists( 'is_cart' ) && is_cart() ) || ( function_exists( 'is_checkout' ) && is_checkout() ) /* || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) */ ) );
460
- /*
461
- * `wcj_currency_per_product_is_cart_or_checkout` filter example:
462
- *
463
- * if ( function_exists( 'YITH_Request_Quote' ) && 0 != ( $raq_page_id = YITH_Request_Quote()->get_raq_page_id() ) && $raq_page_id == get_the_ID() ) {
464
- * return true;
465
- * }
466
- *
467
- */
468
- }
469
-
470
- /**
471
- * change_currency_code.
472
- *
473
- * @version 2.7.0
474
- * @since 2.5.2
475
- */
476
- function change_currency_code( $currency ) {
477
- if ( false != ( $_currency = $this->get_current_product_id_and_currency() ) ) {
478
- return $_currency;
479
- } elseif ( $this->is_cart_or_checkout_or_ajax() ) {
480
- return ( false != ( $_currency = $this->get_cart_checkout_currency() ) ) ? $_currency : $currency;
481
- }
482
- return $currency;
483
- }
484
-
485
- }
486
-
487
- endif;
488
-
489
- return new WCJ_Currency_Per_Product();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Currency per Product
4
+ *
5
+ * @version 3.9.0
6
+ * @since 2.5.2
7
+ * @author Pluggabl LLC.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit;
11
+
12
+ if ( ! class_exists( 'WCJ_Currency_Per_Product' ) ) :
13
+
14
+ class WCJ_Currency_Per_Product extends WCJ_Module {
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 3.9.0
20
+ * @since 2.5.2
21
+ * @todo (maybe) add `$this->price_hooks_priority`
22
+ */
23
+ function __construct() {
24
+
25
+ $this->id = 'currency_per_product';
26
+ $this->short_desc = __( 'Currency per Product', 'woocommerce-jetpack' );
27
+ $this->desc = __( 'Display prices for products in different currencies.', 'woocommerce-jetpack' );
28
+ $this->link_slug = 'woocommerce-currency-per-product';
29
+ parent::__construct();
30
+
31
+ if ( $this->is_enabled() ) {
32
+
33
+ $this->do_save_converted_prices = ( 'yes' === get_option( 'wcj_currency_per_product_save_prices', 'no' ) );
34
+
35
+ $this->is_currency_per_product_by_product_enabled = ( 'yes' === get_option( 'wcj_currency_per_product_per_product', 'yes' ) );
36
+ if ( $this->is_currency_per_product_by_product_enabled ) {
37
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
38
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
39
+ }
40
+
41
+ // Currency code and symbol
42
+ add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX );
43
+
44
+ // Add to cart
45
+ add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_cart_item_data' ), PHP_INT_MAX, 3 );
46
+ add_filter( 'woocommerce_add_cart_item', array( $this, 'add_cart_item' ), PHP_INT_MAX, 2 );
47
+ add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'get_cart_item_from_session' ), PHP_INT_MAX, 3 );
48
+ add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_on_add_to_cart' ), PHP_INT_MAX, 2 );
49
+
50
+ // Price
51
+ add_filter( WCJ_PRODUCT_GET_PRICE_FILTER, array( $this, 'change_price' ), PHP_INT_MAX, 2 );
52
+ add_filter( 'woocommerce_product_variation_get_price', array( $this, 'change_price' ), PHP_INT_MAX, 2 );
53
+
54
+ // Grouped
55
+ add_filter( 'woocommerce_grouped_price_html', array( $this, 'grouped_price_html' ), PHP_INT_MAX, 2 );
56
+
57
+ // Shipping
58
+ add_filter( 'woocommerce_package_rates', array( $this, 'change_shipping_price' ), PHP_INT_MAX, 2 );
59
+
60
+ }
61
+ }
62
+
63
+ /**
64
+ * change_shipping_price.
65
+ *
66
+ * @version 3.2.0
67
+ * @since 2.7.0
68
+ */
69
+ function change_shipping_price( $package_rates, $package ) {
70
+ if ( isset( WC()->cart ) ) {
71
+ if ( WC()->cart->is_empty() ) {
72
+ return $package_rates;
73
+ }
74
+ $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
75
+ switch ( $cart_checkout_behaviour ) {
76
+ case 'leave_one_product':
77
+ case 'leave_same_currency':
78
+ case 'convert_first_product':
79
+ case 'convert_last_product':
80
+ $shop_currency = get_option( 'woocommerce_currency' );
81
+ if ( false != ( $_currency = $this->get_cart_checkout_currency() ) && $_currency != $shop_currency ) {
82
+ $currency_exchange_rate = $this->get_currency_exchange_rate( $_currency );
83
+ if ( 0 != $currency_exchange_rate && 1 != $currency_exchange_rate ) {
84
+ $currency_exchange_rate = 1 / $currency_exchange_rate;
85
+ return wcj_change_price_shipping_package_rates( $package_rates, $currency_exchange_rate );
86
+ } else {
87
+ return $package_rates;
88
+ }
89
+ } else {
90
+ return $package_rates;
91
+ }
92
+ default: // case 'convert_shop_default':
93
+ return $package_rates;
94
+ }
95
+ }
96
+ return $package_rates;
97
+ }
98
+
99
+ /**
100
+ * get_product_currency.
101
+ *
102
+ * @version 3.7.0
103
+ * @since 2.9.0
104
+ * @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 );`
105
+ */
106
+ function get_product_currency( $product_id ) {
107
+ // By users or user roles
108
+ $do_check_by_users = ( 'yes' === get_option( 'wcj_currency_per_product_by_users_enabled', 'no' ) );
109
+ $do_check_by_user_roles = ( 'yes' === get_option( 'wcj_currency_per_product_by_user_roles_enabled', 'no' ) );
110
+ $do_check_by_product_cats = ( 'yes' === get_option( 'wcj_currency_per_product_by_product_cats_enabled', 'no' ) );
111
+ $do_check_by_product_tags = ( 'yes' === get_option( 'wcj_currency_per_product_by_product_tags_enabled', 'no' ) );
112
+ if ( $do_check_by_users || $do_check_by_user_roles || $do_check_by_product_cats || $do_check_by_product_tags ) {
113
+ if ( $do_check_by_users || $do_check_by_user_roles ) {
114
+ $product_author_id = get_post_field( 'post_author', $product_id );
115
+ }
116
+ if ( $do_check_by_product_cats ) {
117
+ $_product_cats = wcj_get_the_terms( $product_id, 'product_cat' );
118
+ }
119
+ if ( $do_check_by_product_tags ) {
120
+ $_product_tags = wcj_get_the_terms( $product_id, 'product_tag' );
121
+ }
122
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_currency_per_product_total_number', 1 ) );
123
+ for ( $i = 1; $i <= $total_number; $i++ ) {
124
+ if ( $do_check_by_users ) {
125
+ $users = get_option( 'wcj_currency_per_product_users_' . $i, '' );
126
+ if ( ! empty( $users ) && in_array( $product_author_id, $users ) ) {
127
+ return get_option( 'wcj_currency_per_product_currency_' . $i );
128
+ }
129
+ }
130
+ if ( $do_check_by_user_roles ) {
131
+ $user_roles = get_option( 'wcj_currency_per_product_user_roles_' . $i, '' );
132
+ if ( ! empty( $user_roles ) && wcj_is_user_role( $user_roles, $product_author_id ) ) {
133
+ return get_option( 'wcj_currency_per_product_currency_' . $i );
134
+ }
135
+ }
136
+ if ( $do_check_by_product_cats ) {
137
+ $product_cats = get_option( 'wcj_currency_per_product_product_cats_' . $i, '' );
138
+ if ( ! empty( $_product_cats ) && ! empty( $product_cats ) ) {
139
+ $_intersect = array_intersect( $_product_cats, $product_cats );
140
+ if ( ! empty( $_intersect ) ) {
141
+ return get_option( 'wcj_currency_per_product_currency_' . $i );
142
+ }
143
+ }
144
+ }
145
+ if ( $do_check_by_product_tags ) {
146
+ $product_tags = get_option( 'wcj_currency_per_product_product_tags_' . $i, '' );
147
+ if ( ! empty( $_product_tags ) && ! empty( $product_tags ) ) {
148
+ $_intersect = array_intersect( $_product_tags, $product_tags );
149
+ if ( ! empty( $_intersect ) ) {
150
+ return get_option( 'wcj_currency_per_product_currency_' . $i );
151
+ }
152
+ }
153
+ }
154
+ }
155
+ }
156
+ // By product meta
157
+ return ( $this->is_currency_per_product_by_product_enabled ? get_post_meta( $product_id, '_' . 'wcj_currency_per_product_currency', true ) : false );
158
+ }
159
+
160
+ /**
161
+ * validate_on_add_to_cart.
162
+ *
163
+ * @version 2.9.0
164
+ * @since 2.7.0
165
+ */
166
+ function validate_on_add_to_cart( $passed, $product_id ) {
167
+ $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
168
+ if ( 'leave_one_product' === $cart_checkout_behaviour ) {
169
+ foreach ( WC()->cart->get_cart() as $cart_item ) {
170
+ if ( $cart_item['product_id'] != $product_id ) {
171
+ wc_add_notice( get_option( 'wcj_currency_per_product_cart_checkout_leave_one_product',
172
+ __( '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' ) ), 'error' );
173
+ return false;
174
+ }
175
+ }
176
+ } elseif ( 'leave_same_currency' === $cart_checkout_behaviour ) {
177
+ $shop_currency = get_option( 'woocommerce_currency' );
178
+ $product_currency = $this->get_product_currency( $product_id );
179
+ if ( '' == $product_currency ) {
180
+ $product_currency = $shop_currency;
181
+ }
182
+ foreach ( WC()->cart->get_cart() as $cart_item ) {
183
+ $cart_product_currency = ( isset( $cart_item['wcj_currency_per_product'] ) && '' != $cart_item['wcj_currency_per_product'] ) ?
184
+ $cart_item['wcj_currency_per_product'] : $shop_currency;
185
+ if ( $cart_product_currency != $product_currency ) {
186
+ wc_add_notice( get_option( 'wcj_currency_per_product_cart_checkout_leave_same_currency',
187
+ __( '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' ) ), 'error' );
188
+ return false;
189
+ }
190
+ }
191
+ }
192
+ return $passed;
193
+ }
194
+
195
+ /**
196
+ * grouped_price_html.
197
+ *
198
+ * @version 2.9.0
199
+ * @since 2.5.2
200
+ */
201
+ function grouped_price_html( $price_html, $_product ) {
202
+ $child_prices = array();
203
+ foreach ( $_product->get_children() as $child_id ) {
204
+ $child_prices[ $child_id ] = get_post_meta( $child_id, '_price', true );
205
+ }
206
+ if ( ! empty( $child_prices ) ) {
207
+ asort( $child_prices );
208
+ $min_price = current( $child_prices );
209
+ $min_price_id = key( $child_prices );
210
+ end( $child_prices );
211
+ $max_price = current( $child_prices );
212
+ $max_price_id = key( $child_prices );
213
+ $min_currency_per_product_currency = $this->get_product_currency( $min_price_id );
214
+ $max_currency_per_product_currency = $this->get_product_currency( $max_price_id );
215
+ } else {
216
+ $min_price = '';
217
+ $max_price = '';
218
+ }
219
+
220
+ if ( $min_price ) {
221
+ if ( $min_price == $max_price && $min_currency_per_product_currency === $max_currency_per_product_currency ) {
222
+ $display_price = wc_price( wcj_get_product_display_price( $_product, $min_price, 1 ), array( 'currency' => $min_currency_per_product_currency ) );
223
+ } else {
224
+ $from = wc_price( wcj_get_product_display_price( $_product, $min_price, 1 ), array( 'currency' => $min_currency_per_product_currency ) );
225
+ $to = wc_price( wcj_get_product_display_price( $_product, $max_price, 1 ), array( 'currency' => $max_currency_per_product_currency ) );
226
+ $display_price = sprintf( _x( '%1$s&ndash;%2$s', 'Price range: from-to', 'woocommerce' ), $from, $to );
227
+ }
228
+ $new_price_html = $display_price . $_product->get_price_suffix();
229
+ return $new_price_html;
230
+ }
231
+
232
+ return $price_html;
233
+ }
234
+
235
+ /**
236
+ * get_currency_exchange_rate.
237
+ *
238
+ * @version 3.6.0
239
+ * @since 2.5.2
240
+ */
241
+ function get_currency_exchange_rate( $currency_code ) {
242
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_currency_per_product_total_number', 1 ) );
243
+ for ( $i = 1; $i <= $total_number; $i++ ) {
244
+ if ( $currency_code === get_option( 'wcj_currency_per_product_currency_' . $i ) ) {
245
+ return ( 0 != ( $rate = get_option( 'wcj_currency_per_product_exchange_rate_' . $i, 1 ) ) ? ( 1 / $rate ) : 1 );
246
+ }
247
+ }
248
+ return 1;
249
+ }
250
+
251
+ /**
252
+ * maybe_return_saved_converted_price.
253
+ *
254
+ * @version 3.3.0
255
+ * @since 3.3.0
256
+ */
257
+ function maybe_return_saved_converted_price( $_product, $_currency ) {
258
+ if ( $this->do_save_converted_prices ) {
259
+ $product_id = ( isset( $_product->wcj_currency_per_product_item_key ) ? $_product->wcj_currency_per_product_item_key : wcj_get_product_id( $_product ) );
260
+ if ( isset( $this->saved_product_prices[ $product_id ][ $_product->wcj_currency_per_product ][ $_currency ] ) ) {
261
+ return $this->saved_product_prices[ $product_id ][ $_product->wcj_currency_per_product ][ $_currency ];
262
+ }
263
+ }
264
+ return false;
265
+ }
266
+
267
+ /**
268
+ * maybe_save_converted_price.
269
+ *
270
+ * @version 3.3.0
271
+ * @since 3.3.0
272
+ */
273
+ function maybe_save_converted_price( $price, $_product, $_currency ) {
274
+ if ( $this->do_save_converted_prices ) {
275
+ $product_id = ( isset( $_product->wcj_currency_per_product_item_key ) ? $_product->wcj_currency_per_product_item_key : wcj_get_product_id( $_product ) );
276
+ $this->saved_product_prices[ $product_id ][ $_product->wcj_currency_per_product ][ $_currency ] = $price;
277
+ }
278
+ return $price;
279
+ }
280
+
281
+ /**
282
+ * change_price.
283
+ *
284
+ * @version 3.3.0
285
+ * @since 2.5.2
286
+ */
287
+ function change_price( $price, $_product ) {
288
+ if ( isset( $_product->wcj_currency_per_product ) ) {
289
+ $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
290
+ switch ( $cart_checkout_behaviour ) {
291
+ case 'leave_one_product':
292
+ case 'leave_same_currency':
293
+ return $price;
294
+ case 'convert_first_product':
295
+ case 'convert_last_product':
296
+ $shop_currency = get_option( 'woocommerce_currency' );
297
+ if ( false != ( $_currency = $this->get_cart_checkout_currency() ) && $_currency != $shop_currency ) {
298
+ if ( $_product->wcj_currency_per_product === $_currency ) {
299
+ return $price;
300
+ } else {
301
+ if ( false !== ( $saved_price = $this->maybe_return_saved_converted_price( $_product, $_currency ) ) ) {
302
+ return $saved_price;
303
+ }
304
+ $exchange_rate_product = $this->get_currency_exchange_rate( $_product->wcj_currency_per_product );
305
+ $exchange_rate_cart_checkout = $this->get_currency_exchange_rate( $_currency );
306
+ $exchange_rate = $exchange_rate_product / $exchange_rate_cart_checkout;
307
+ return $this->maybe_save_converted_price( $price * $exchange_rate, $_product, $_currency );
308
+ }
309
+ } elseif ( $_product->wcj_currency_per_product === $shop_currency ) {
310
+ return $price;
311
+ } else {
312
+ if ( false !== ( $saved_price = $this->maybe_return_saved_converted_price( $_product, $shop_currency ) ) ) {
313
+ return $saved_price;
314
+ }
315
+ $exchange_rate = $this->get_currency_exchange_rate( $_product->wcj_currency_per_product );
316
+ return $this->maybe_save_converted_price( $price * $exchange_rate, $_product, $shop_currency );
317
+ }
318
+ default: // case 'convert_shop_default':
319
+ $shop_currency = get_option( 'woocommerce_currency' );
320
+ if ( false !== ( $saved_price = $this->maybe_return_saved_converted_price( $_product, $shop_currency ) ) ) {
321
+ return $saved_price;
322
+ }
323
+ $exchange_rate = $this->get_currency_exchange_rate( $_product->wcj_currency_per_product );
324
+ return $this->maybe_save_converted_price( $price * $exchange_rate, $_product, $shop_currency );
325
+ }
326
+ }
327
+ return $price;
328
+ }
329
+
330
+ /**
331
+ * get_cart_item_from_session.
332
+ *
333
+ * @version 3.3.0
334
+ * @since 2.5.2
335
+ */
336
+ function get_cart_item_from_session( $item, $values, $key ) {
337
+ if ( array_key_exists( 'wcj_currency_per_product', $values ) ) {
338
+ $item['data']->wcj_currency_per_product = $values['wcj_currency_per_product'];
339
+ if ( $this->do_save_converted_prices ) {
340
+ $item['data']->wcj_currency_per_product_item_key = $key;
341
+ }
342
+ }
343
+ return $item;
344
+ }
345
+
346
+ /**
347
+ * add_cart_item_data.
348
+ *
349
+ * @version 2.9.0
350
+ * @since 2.5.2
351
+ */
352
+ function add_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
353
+ $currency_per_product_currency = $this->get_product_currency( $product_id );
354
+ if ( '' != $currency_per_product_currency ) {
355
+ $cart_item_data['wcj_currency_per_product'] = $currency_per_product_currency;
356
+ }
357
+ return $cart_item_data;
358
+ }
359
+
360
+ /**
361
+ * add_cart_item.
362
+ *
363
+ * @version 3.3.0
364
+ * @since 2.5.2
365
+ * @todo `wcj_currency_per_product_item_key` seems to be not working here
366
+ */
367
+ function add_cart_item( $cart_item_data, $cart_item_key ) {
368
+ if ( isset( $cart_item_data['wcj_currency_per_product'] ) ) {
369
+ $cart_item_data['data']->wcj_currency_per_product = $cart_item_data['wcj_currency_per_product'];
370
+ if ( $this->do_save_converted_prices ) {
371
+ $cart_item_data['data']->wcj_currency_per_product_item_key = $cart_item_key;
372
+ }
373
+ }
374
+ return $cart_item_data;
375
+ }
376
+
377
+ /**
378
+ * get_current_product_id_and_currency.
379
+ *
380
+ * @version 2.9.0
381
+ * @since 2.7.0
382
+ */
383
+ function get_current_product_id_and_currency() {
384
+ // Get ID
385
+ $the_ID = false;
386
+ global $product;
387
+ if ( $product ) {
388
+ $the_ID = wcj_get_product_id_or_variation_parent_id( $product );
389
+ }
390
+ if ( ! $the_ID && isset( $_REQUEST['product_id'] ) ) {
391
+ $the_ID = $_REQUEST['product_id'];
392
+ }
393
+ if ( ! $the_ID && isset( $_POST['form'] ) ) { // WooCommerce Bookings plugin
394
+ $posted = array();
395
+ parse_str( $_POST['form'], $posted );
396
+ $the_ID = isset( $posted['add-to-cart'] ) ? $posted['add-to-cart'] : 0;
397
+ }
398
+ if ( ! $the_ID && '' != ( $eventon_wc_product_id = get_post_meta( get_the_ID(), 'tx_woocommerce_product_id', true ) ) ) { // EventON plugin
399
+ $the_ID = $eventon_wc_product_id;
400
+ }
401
+ if ( ! $the_ID ) {
402
+ $the_ID = get_the_ID();
403
+ }
404
+ // Get currency
405
+ if ( $the_ID && 'product' === get_post_type( $the_ID ) ) {
406
+ $currency_per_product_currency = $this->get_product_currency( $the_ID );
407
+ return ( '' != $currency_per_product_currency ) ? $currency_per_product_currency : false;
408
+ }
409
+ return false;
410
+ }
411
+
412
+ /**
413
+ * get_cart_checkout_currency.
414
+ *
415
+ * @version 3.7.0
416
+ * @since 2.7.0
417
+ */
418
+ function get_cart_checkout_currency() {
419
+ $cart_checkout_behaviour = get_option( 'wcj_currency_per_product_cart_checkout', 'convert_shop_default' );
420
+ if ( false !== ( $value = apply_filters( 'wcj_currency_per_product_cart_checkout_currency', false, $cart_checkout_behaviour ) ) ) {
421
+ return $value;
422
+ }
423
+ /*
424
+ * `wcj_currency_per_product_cart_checkout_currency` filter example:
425
+ *
426
+ * if ( function_exists( 'YITH_Request_Quote' ) && isset( YITH_Request_Quote()->raq_content ) ) {
427
+ * foreach ( YITH_Request_Quote()->raq_content as $raq_product ) {
428
+ * if ( isset( $raq_product['product_id'] ) ) {
429
+ * return get_post_meta( $raq_product['product_id'], '_' . 'wcj_currency_per_product_currency', true );
430
+ * }
431
+ * }
432
+ * }
433
+ *
434
+ */
435
+ if ( ! isset( WC()->cart ) || WC()->cart->is_empty() ) {
436
+ return false;
437
+ }
438
+ if ( 'convert_shop_default' === $cart_checkout_behaviour ) {
439
+ return false;
440
+ }
441
+ $cart_items = WC()->cart->get_cart();
442
+ if ( 'convert_last_product' === $cart_checkout_behaviour ) {
443
+ $cart_items = array_reverse( $cart_items );
444
+ }
445
+ foreach ( $cart_items as $cart_item ) {
446
+ return ( isset( $cart_item['wcj_currency_per_product'] ) ) ? $cart_item['wcj_currency_per_product'] : false;
447
+ }
448
+ }
449
+
450
+ /**
451
+ * is_cart_or_checkout_or_ajax.
452
+ *
453
+ * @version 3.7.0
454
+ * @since 2.7.0
455
+ * @todo fix AJAX issue (for minicart)
456
+ */
457
+ function is_cart_or_checkout_or_ajax() {
458
+ return apply_filters( 'wcj_currency_per_product_is_cart_or_checkout',
459
+ ( ( function_exists( 'is_cart' ) && is_cart() ) || ( function_exists( 'is_checkout' ) && is_checkout() ) /* || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) */ ) );
460
+ /*
461
+ * `wcj_currency_per_product_is_cart_or_checkout` filter example:
462
+ *
463
+ * if ( function_exists( 'YITH_Request_Quote' ) && 0 != ( $raq_page_id = YITH_Request_Quote()->get_raq_page_id() ) && $raq_page_id == get_the_ID() ) {
464
+ * return true;
465
+ * }
466
+ *
467
+ */
468
+ }
469
+
470
+ /**
471
+ * change_currency_code.
472
+ *
473
+ * @version 2.7.0
474
+ * @since 2.5.2
475
+ */
476
+ function change_currency_code( $currency ) {
477
+ if ( false != ( $_currency = $this->get_current_product_id_and_currency() ) ) {
478
+ return $_currency;
479
+ } elseif ( $this->is_cart_or_checkout_or_ajax() ) {
480
+ return ( false != ( $_currency = $this->get_cart_checkout_currency() ) ) ? $_currency : $currency;
481
+ }
482
+ return $currency;
483
+ }
484
+
485
+ }
486
+
487
+ endif;
488
+
489
+ return new WCJ_Currency_Per_Product();
includes/class-wcj-currency.php CHANGED
@@ -1,192 +1,192 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Currencies
4
- *
5
- * @version 3.9.0
6
- * @author Algoritmika Ltd.
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.', 'woocommerce-jetpack' );
29
- $this->link_slug = 'woocommerce-all-currencies';
30
- parent::__construct();
31
-
32
- if ( $this->is_enabled() ) {
33
- add_filter( 'woocommerce_currencies', array( $this, 'add_all_currencies'), PHP_INT_MAX );
34
- add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol'), PHP_INT_MAX, 2 );
35
- add_filter( 'woocommerce_general_settings', array( $this, 'add_edit_currency_symbol_field' ), PHP_INT_MAX );
36
- }
37
- }
38
-
39
- /**
40
- * get_custom_currencies.
41
- *
42
- * @version 3.9.0
43
- * @since 3.9.0
44
- */
45
- function get_custom_currencies() {
46
- $custom_currencies = array();
47
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_currency_custom_currency_total_number', 1 ) ); $i++ ) {
48
- $custom_currency_code = get_option( 'wcj_currency_custom_currency_code_' . $i, '' );
49
- $custom_currency_name = get_option( 'wcj_currency_custom_currency_name_' . $i, '' );
50
- if ( '' != $custom_currency_code && '' != $custom_currency_name ) {
51
- $custom_currencies[ $custom_currency_code ] = $custom_currency_name;
52
- }
53
- }
54
- return $custom_currencies;
55
- }
56
-
57
- /**
58
- * get_additional_currencies.
59
- *
60
- * @version 3.9.0
61
- * @since 3.9.0
62
- * @todo [dev] (maybe) add more cryptocurrencies
63
- */
64
- function get_additional_currencies() {
65
- return array(
66
- // Crypto
67
- 'AUR' => __( 'Auroracoin', 'woocommerce-jetpack' ),
68
- 'BCC' => __( 'BitConnect', 'woocommerce-jetpack' ),
69
- 'BCH' => __( 'Bitcoin Cash', 'woocommerce-jetpack' ),
70
- 'KOI' => __( 'Coinye', 'woocommerce-jetpack' ),
71
- 'XDN' => __( 'DigitalNote', 'woocommerce-jetpack' ),
72
- 'EMC' => __( 'Emercoin', 'woocommerce-jetpack' ),
73
- 'ETC' => __( 'Ethereum Classic', 'woocommerce-jetpack' ),
74
- 'ETH' => __( 'Ethereum', 'woocommerce-jetpack' ),
75
- 'FMC' => __( 'Freemasoncoin', 'woocommerce-jetpack' ),
76
- 'GRC' => __( 'Gridcoin', 'woocommerce-jetpack' ),
77
- 'IOT' => __( 'IOTA', 'woocommerce-jetpack' ),
78
- 'LTC' => __( 'Litecoin', 'woocommerce-jetpack' ),
79
- 'MZC' => __( 'MazaCoin', 'woocommerce-jetpack' ),
80
- 'XMR' => __( 'Monero', 'woocommerce-jetpack' ),
81
- 'NMC' => __( 'Namecoin', 'woocommerce-jetpack' ),
82
- 'XEM' => __( 'NEM', 'woocommerce-jetpack' ),
83
- 'NXT' => __( 'Nxt', 'woocommerce-jetpack' ),
84
- 'MSC' => __( 'Omni', 'woocommerce-jetpack' ),
85
- 'PPC' => __( 'Peercoin', 'woocommerce-jetpack' ),
86
- 'POT' => __( 'PotCoin', 'woocommerce-jetpack' ),
87
- 'XPM' => __( 'Primecoin', 'woocommerce-jetpack' ),
88
- 'XRP' => __( 'Ripple', 'woocommerce-jetpack' ),
89
- 'SIL' => __( 'SixEleven', 'woocommerce-jetpack' ),
90
- 'AMP' => __( 'Synereo AMP', 'woocommerce-jetpack' ),
91
- 'TIT' => __( 'Titcoin', 'woocommerce-jetpack' ),
92
- 'UBQ' => __( 'Ubiq', 'woocommerce-jetpack' ),
93
- 'VTC' => __( 'Vertcoin', 'woocommerce-jetpack' ),
94
- 'ZEC' => __( 'Zcash', 'woocommerce-jetpack' ),
95
- // Other
96
- 'XDR' => __( 'Special Drawing Rights', 'woocommerce-jetpack' ),
97
- // Virtual
98
- 'MYC' => __( 'myCred', 'woocommerce-jetpack' ),
99
- );
100
- }
101
-
102
- /**
103
- * get_additional_currency_symbol.
104
- *
105
- * @version 3.9.0
106
- * @since 3.9.0
107
- */
108
- function get_additional_currency_symbol( $currency_code ) {
109
- return $currency_code;
110
- }
111
-
112
- /**
113
- * add_all_currencies.
114
- *
115
- * @version 3.9.0
116
- */
117
- function add_all_currencies( $currencies ) {
118
- return array_merge( $currencies, $this->get_additional_currencies(), $this->get_custom_currencies() );
119
- }
120
-
121
- /**
122
- * get_saved_currency_symbol.
123
- *
124
- * @version 3.9.0
125
- * @since 3.9.0
126
- */
127
- function get_saved_currency_symbol( $currency, $default_symbol ) {
128
- if ( false === ( $saved_currency_symbol = get_option( 'wcj_currency_' . $currency, false ) ) ) {
129
- return ( in_array( $currency, array_keys( $this->get_additional_currencies() ) ) ? $this->get_additional_currency_symbol( $currency ) : $default_symbol );
130
- } else {
131
- return $saved_currency_symbol;
132
- }
133
- }
134
-
135
- /**
136
- * change_currency_symbol.
137
- *
138
- * @version 3.9.0
139
- */
140
- function change_currency_symbol( $currency_symbol, $currency ) {
141
- // Maybe return saved value
142
- if ( isset( $this->saved_symbol[ $currency ] ) ) {
143
- return $this->saved_symbol[ $currency ];
144
- }
145
- // Maybe hide symbol
146
- if ( 'yes' === get_option( 'wcj_currency_hide_symbol', 'no' ) ) {
147
- return '';
148
- }
149
- // Custom currencies
150
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_currency_custom_currency_total_number', 1 ) ); $i++ ) {
151
- $custom_currency_code = get_option( 'wcj_currency_custom_currency_code_' . $i, '' );
152
- $custom_currency_name = get_option( 'wcj_currency_custom_currency_name_' . $i, '' );
153
- if ( '' != $custom_currency_code && '' != $custom_currency_name && $currency === $custom_currency_code ) {
154
- $this->saved_symbol[ $currency ] = do_shortcode( get_option( 'wcj_currency_custom_currency_symbol_' . $i, '' ) );
155
- return $this->saved_symbol[ $currency ];
156
- }
157
- }
158
- // List
159
- $this->saved_symbol[ $currency ] = apply_filters( 'booster_option', $currency_symbol, do_shortcode( $this->get_saved_currency_symbol( $currency, $currency_symbol ) ) );
160
- return $this->saved_symbol[ $currency ];
161
- }
162
-
163
- /**
164
- * add_edit_currency_symbol_field.
165
- *
166
- * @version 3.9.0
167
- * @todo [dev] (maybe) remove this
168
- */
169
- function add_edit_currency_symbol_field( $settings ) {
170
- $updated_settings = array();
171
- foreach ( $settings as $section ) {
172
- if ( isset( $section['id'] ) && 'woocommerce_currency_pos' == $section['id'] ) {
173
- $updated_settings[] = array(
174
- 'name' => __( 'Booster: Currency Symbol', 'woocommerce-jetpack' ),
175
- 'desc_tip' => __( 'This sets the currency symbol.', 'woocommerce-jetpack' ),
176
- 'id' => 'wcj_currency_' . get_woocommerce_currency(),
177
- 'type' => 'text',
178
- 'default' => get_woocommerce_currency_symbol(),
179
- 'desc' => apply_filters( 'booster_message', '', 'desc' ),
180
- 'custom_attributes' => apply_filters( 'booster_message', '', 'readonly' ),
181
- );
182
- }
183
- $updated_settings[] = $section;
184
- }
185
- return $updated_settings;
186
- }
187
-
188
- }
189
-
190
- endif;
191
-
192
- return new WCJ_Currencies();
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.', 'woocommerce-jetpack' );
29
+ $this->link_slug = 'woocommerce-all-currencies';
30
+ parent::__construct();
31
+
32
+ if ( $this->is_enabled() ) {
33
+ add_filter( 'woocommerce_currencies', array( $this, 'add_all_currencies'), PHP_INT_MAX );
34
+ add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol'), PHP_INT_MAX, 2 );
35
+ add_filter( 'woocommerce_general_settings', array( $this, 'add_edit_currency_symbol_field' ), PHP_INT_MAX );
36
+ }
37
+ }
38
+
39
+ /**
40
+ * get_custom_currencies.
41
+ *
42
+ * @version 3.9.0
43
+ * @since 3.9.0
44
+ */
45
+ function get_custom_currencies() {
46
+ $custom_currencies = array();
47
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_currency_custom_currency_total_number', 1 ) ); $i++ ) {
48
+ $custom_currency_code = get_option( 'wcj_currency_custom_currency_code_' . $i, '' );
49
+ $custom_currency_name = get_option( 'wcj_currency_custom_currency_name_' . $i, '' );
50
+ if ( '' != $custom_currency_code && '' != $custom_currency_name ) {
51
+ $custom_currencies[ $custom_currency_code ] = $custom_currency_name;
52
+ }
53
+ }
54
+ return $custom_currencies;
55
+ }
56
+
57
+ /**
58
+ * get_additional_currencies.
59
+ *
60
+ * @version 3.9.0
61
+ * @since 3.9.0
62
+ * @todo [dev] (maybe) add more cryptocurrencies
63
+ */
64
+ function get_additional_currencies() {
65
+ return array(
66
+ // Crypto
67
+ 'AUR' => __( 'Auroracoin', 'woocommerce-jetpack' ),
68
+ 'BCC' => __( 'BitConnect', 'woocommerce-jetpack' ),
69
+ 'BCH' => __( 'Bitcoin Cash', 'woocommerce-jetpack' ),
70
+ 'KOI' => __( 'Coinye', 'woocommerce-jetpack' ),
71
+ 'XDN' => __( 'DigitalNote', 'woocommerce-jetpack' ),
72
+ 'EMC' => __( 'Emercoin', 'woocommerce-jetpack' ),
73
+ 'ETC' => __( 'Ethereum Classic', 'woocommerce-jetpack' ),
74
+ 'ETH' => __( 'Ethereum', 'woocommerce-jetpack' ),
75
+ 'FMC' => __( 'Freemasoncoin', 'woocommerce-jetpack' ),
76
+ 'GRC' => __( 'Gridcoin', 'woocommerce-jetpack' ),
77
+ 'IOT' => __( 'IOTA', 'woocommerce-jetpack' ),
78
+ 'LTC' => __( 'Litecoin', 'woocommerce-jetpack' ),
79
+ 'MZC' => __( 'MazaCoin', 'woocommerce-jetpack' ),
80
+ 'XMR' => __( 'Monero', 'woocommerce-jetpack' ),
81
+ 'NMC' => __( 'Namecoin', 'woocommerce-jetpack' ),
82
+ 'XEM' => __( 'NEM', 'woocommerce-jetpack' ),
83
+ 'NXT' => __( 'Nxt', 'woocommerce-jetpack' ),
84
+ 'MSC' => __( 'Omni', 'woocommerce-jetpack' ),
85
+ 'PPC' => __( 'Peercoin', 'woocommerce-jetpack' ),
86
+ 'POT' => __( 'PotCoin', 'woocommerce-jetpack' ),
87
+ 'XPM' => __( 'Primecoin', 'woocommerce-jetpack' ),
88
+ 'XRP' => __( 'Ripple', 'woocommerce-jetpack' ),
89
+ 'SIL' => __( 'SixEleven', 'woocommerce-jetpack' ),
90
+ 'AMP' => __( 'Synereo AMP', 'woocommerce-jetpack' ),
91
+ 'TIT' => __( 'Titcoin', 'woocommerce-jetpack' ),
92
+ 'UBQ' => __( 'Ubiq', 'woocommerce-jetpack' ),
93
+ 'VTC' => __( 'Vertcoin', 'woocommerce-jetpack' ),
94
+ 'ZEC' => __( 'Zcash', 'woocommerce-jetpack' ),
95
+ // Other
96
+ 'XDR' => __( 'Special Drawing Rights', 'woocommerce-jetpack' ),
97
+ // Virtual
98
+ 'MYC' => __( 'myCred', 'woocommerce-jetpack' ),
99
+ );
100
+ }
101
+
102
+ /**
103
+ * get_additional_currency_symbol.
104
+ *
105
+ * @version 3.9.0
106
+ * @since 3.9.0
107
+ */
108
+ function get_additional_currency_symbol( $currency_code ) {
109
+ return $currency_code;
110
+ }
111
+
112
+ /**
113
+ * add_all_currencies.
114
+ *
115
+ * @version 3.9.0
116
+ */
117
+ function add_all_currencies( $currencies ) {
118
+ return array_merge( $currencies, $this->get_additional_currencies(), $this->get_custom_currencies() );
119
+ }
120
+
121
+ /**
122
+ * get_saved_currency_symbol.
123
+ *
124
+ * @version 3.9.0
125
+ * @since 3.9.0
126
+ */
127
+ function get_saved_currency_symbol( $currency, $default_symbol ) {
128
+ if ( false === ( $saved_currency_symbol = get_option( 'wcj_currency_' . $currency, false ) ) ) {
129
+ return ( in_array( $currency, array_keys( $this->get_additional_currencies() ) ) ? $this->get_additional_currency_symbol( $currency ) : $default_symbol );
130
+ } else {
131
+ return $saved_currency_symbol;
132
+ }
133
+ }
134
+
135
+ /**
136
+ * change_currency_symbol.
137
+ *
138
+ * @version 3.9.0
139
+ */
140
+ function change_currency_symbol( $currency_symbol, $currency ) {
141
+ // Maybe return saved value
142
+ if ( isset( $this->saved_symbol[ $currency ] ) ) {
143
+ return $this->saved_symbol[ $currency ];
144
+ }
145
+ // Maybe hide symbol
146
+ if ( 'yes' === get_option( 'wcj_currency_hide_symbol', 'no' ) ) {
147
+ return '';
148
+ }
149
+ // Custom currencies
150
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_currency_custom_currency_total_number', 1 ) ); $i++ ) {
151
+ $custom_currency_code = get_option( 'wcj_currency_custom_currency_code_' . $i, '' );
152
+ $custom_currency_name = get_option( 'wcj_currency_custom_currency_name_' . $i, '' );
153
+ if ( '' != $custom_currency_code && '' != $custom_currency_name && $currency === $custom_currency_code ) {
154
+ $this->saved_symbol[ $currency ] = do_shortcode( get_option( 'wcj_currency_custom_currency_symbol_' . $i, '' ) );
155
+ return $this->saved_symbol[ $currency ];
156
+ }
157
+ }
158
+ // List
159
+ $this->saved_symbol[ $currency ] = apply_filters( 'booster_option', $currency_symbol, do_shortcode( $this->get_saved_currency_symbol( $currency, $currency_symbol ) ) );
160
+ return $this->saved_symbol[ $currency ];
161
+ }
162
+
163
+ /**
164
+ * add_edit_currency_symbol_field.
165
+ *
166
+ * @version 3.9.0
167
+ * @todo [dev] (maybe) remove this
168
+ */
169
+ function add_edit_currency_symbol_field( $settings ) {
170
+ $updated_settings = array();
171
+ foreach ( $settings as $section ) {
172
+ if ( isset( $section['id'] ) && 'woocommerce_currency_pos' == $section['id'] ) {
173
+ $updated_settings[] = array(
174
+ 'name' => __( 'Booster: Currency Symbol', 'woocommerce-jetpack' ),
175
+ 'desc_tip' => __( 'This sets the currency symbol.', 'woocommerce-jetpack' ),
176
+ 'id' => 'wcj_currency_' . get_woocommerce_currency(),
177
+ 'type' => 'text',
178
+ 'default' => get_woocommerce_currency_symbol(),
179
+ 'desc' => apply_filters( 'booster_message', '', 'desc' ),
180
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'readonly' ),
181
+ );
182
+ }
183
+ $updated_settings[] = $section;
184
+ }
185
+ return $updated_settings;
186
+ }
187
+
188
+ }
189
+
190
+ endif;
191
+
192
+ return new WCJ_Currencies();
includes/class-wcj-custom-css.php CHANGED
@@ -1,91 +1,91 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Custom CSS
4
- *
5
- * @version 4.0.0
6
- * @since 2.7.0
7
- * @author Algoritmika Ltd.
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 ( '' != get_option( 'wcj_general_custom_css', '' ) ) {
36
- add_action( 'wp_' . get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'hook_custom_css' ) );
37
- }
38
- // Admin
39
- if ( '' != get_option( 'wcj_general_custom_admin_css', '' ) ) {
40
- add_action( 'admin_' . get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'hook_custom_admin_css' ) );
41
- }
42
- // Per product
43
- if ( 'yes' === get_option( 'wcj_custom_css_per_product', 'no' ) ) {
44
- add_action( 'wp_' . 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>' . 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>' . get_option( 'wcj_general_custom_admin_css', '' ) . '</style>';
85
- }
86
-
87
- }
88
-
89
- endif;
90
-
91
- return new WCJ_Custom_CSS();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Custom CSS
4
+ *
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 ( '' != get_option( 'wcj_general_custom_css', '' ) ) {
36
+ add_action( 'wp_' . get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'hook_custom_css' ) );
37
+ }
38
+ // Admin
39
+ if ( '' != get_option( 'wcj_general_custom_admin_css', '' ) ) {
40
+ add_action( 'admin_' . get_option( 'wcj_custom_css_hook', 'head' ), array( $this, 'hook_custom_admin_css' ) );
41
+ }
42
+ // Per product
43
+ if ( 'yes' === get_option( 'wcj_custom_css_per_product', 'no' ) ) {
44
+ add_action( 'wp_' . 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>' . 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>' . get_option( 'wcj_general_custom_admin_css', '' ) . '</style>';
85
+ }
86
+
87
+ }
88
+
89
+ endif;
90
+
91
+ return new WCJ_Custom_CSS();
includes/class-wcj-custom-js.php CHANGED
@@ -1,66 +1,66 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Custom JS
4
- *
5
- * @version 4.0.0
6
- * @since 2.8.0
7
- * @author Algoritmika Ltd.
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 ( '' != get_option( 'wcj_custom_js_frontend', '' ) ) {
34
- add_action( 'wp_' . get_option( 'wcj_custom_js_hook', 'head' ), array( $this, 'custom_frontend_js' ) );
35
- }
36
- if ( '' != get_option( 'wcj_custom_js_backend', '' ) ) {
37
- add_action( 'admin_' . 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( 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( get_option( 'wcj_custom_js_backend', '' ) ) . '</script>';
60
- }
61
-
62
- }
63
-
64
- endif;
65
-
66
- return new WCJ_Custom_JS();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Custom JS
4
+ *
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 ( '' != get_option( 'wcj_custom_js_frontend', '' ) ) {
34
+ add_action( 'wp_' . get_option( 'wcj_custom_js_hook', 'head' ), array( $this, 'custom_frontend_js' ) );
35
+ }
36
+ if ( '' != get_option( 'wcj_custom_js_backend', '' ) ) {
37
+ add_action( 'admin_' . 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( 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( get_option( 'wcj_custom_js_backend', '' ) ) . '</script>';
60
+ }
61
+
62
+ }
63
+
64
+ endif;
65
+
66
+ return new WCJ_Custom_JS();
includes/class-wcj-custom-php.php CHANGED
@@ -1,90 +1,90 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Custom PHP
4
- *
5
- * @version 4.0.1
6
- * @since 4.0.0
7
- * @author Algoritmika Ltd.
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 = 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
-
90
- return new WCJ_Custom_PHP();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Custom PHP
4
+ *
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 = 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
+
90
+ return new WCJ_Custom_PHP();
includes/class-wcj-debug-tools.php CHANGED
@@ -1,107 +1,107 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Debug Tools
4
- *
5
- * @version 4.1.0
6
- * @version 4.1.0
7
- * @author Algoritmika Ltd.
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 4.1.0
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 .= $this->get_tool_header_html( 'debug_tools' );
55
- $the_tools .= '<p><a href="' . add_query_arg( 'wcj_delete_log', '1' ) . '">' . __( 'Delete Log', 'woocommerce-jetpack' ) . '</a></p>';
56
- // Log
57
- $the_log = '';
58
- $the_log .= '<p style="font-style:italic;color:gray;">' . sprintf( __( 'Now: %s', 'woocommerce-jetpack' ), date( 'Y-m-d H:i:s' ) ) . '</p>';
59
- if ( '' != ( $log = get_option( 'wcj_log', '' ) ) ) {
60
- $the_log .= '<pre style="color:green;background-color:black;padding:5px;">' . $log . '</pre>';
61
- } else {
62
- $the_log .= '<p style="font-style:italic;color:gray;">' . __( 'Log is empty.', 'woocommerce-jetpack' ) . '</p>';
63
- }
64
- // Final output
65
- $html = '';
66
- $html .= '<div class="wrap">';
67
- $html .= '<p>' . $the_tools . '</p>';
68
- $html .= '<p>' . $the_log . '</p>';
69
- $html .= '</div>';
70
- echo $html;
71
- }
72
-
73
- /**
74
- * get_system_info_table_array.
75
- *
76
- * @version 4.1.0
77
- * @since 2.5.7
78
- * @todo [feature] (maybe) 'DB_NAME', 'DB_USER', 'DB_PASSWORD', 'DB_HOST', 'DB_CHARSET', 'DB_COLLATE'
79
- */
80
- function get_system_info_table_array() {
81
- $system_info = array();
82
- $constants_array = array(
83
- 'WP_MEMORY_LIMIT',
84
- 'WP_MAX_MEMORY_LIMIT',
85
- 'WP_DEBUG',
86
- 'ABSPATH',
87
- 'DISABLE_WP_CRON',
88
- 'WP_CRON_LOCK_TIMEOUT',
89
- 'WCJ_WC_VERSION',
90
- 'WCJ_SESSION_TYPE',
91
- );
92
- foreach ( $constants_array as $the_constant ) {
93
- $system_info[] = array( $the_constant, ( defined( $the_constant ) ? constant( $the_constant ) : __( 'NOT DEFINED', 'woocommerce-jetpack' ) ) );
94
- }
95
- if ( isset( $_GET['wcj_debug'] ) ) {
96
- foreach ( $_SERVER as $server_var_id => $server_var_value ) {
97
- $system_info[] = array( $server_var_id, esc_html( $server_var_value ) );
98
- }
99
- }
100
- return $system_info;
101
- }
102
-
103
- }
104
-
105
- endif;
106
-
107
- return new WCJ_Debug_Tools();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Debug Tools
4
+ *
5
+ * @version 4.1.0
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 4.1.0
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 .= $this->get_tool_header_html( 'debug_tools' );
55
+ $the_tools .= '<p><a href="' . add_query_arg( 'wcj_delete_log', '1' ) . '">' . __( 'Delete Log', 'woocommerce-jetpack' ) . '</a></p>';
56
+ // Log
57
+ $the_log = '';
58
+ $the_log .= '<p style="font-style:italic;color:gray;">' . sprintf( __( 'Now: %s', 'woocommerce-jetpack' ), date( 'Y-m-d H:i:s' ) ) . '</p>';
59
+ if ( '' != ( $log = get_option( 'wcj_log', '' ) ) ) {
60
+ $the_log .= '<pre style="color:green;background-color:black;padding:5px;">' . $log . '</pre>';
61
+ } else {
62
+ $the_log .= '<p style="font-style:italic;color:gray;">' . __( 'Log is empty.', 'woocommerce-jetpack' ) . '</p>';
63
+ }
64
+ // Final output
65
+ $html = '';
66
+ $html .= '<div class="wrap">';
67
+ $html .= '<p>' . $the_tools . '</p>';
68
+ $html .= '<p>' . $the_log . '</p>';
69
+ $html .= '</div>';
70
+ echo $html;
71
+ }
72
+
73
+ /**
74
+ * get_system_info_table_array.
75
+ *
76
+ * @version 4.1.0
77
+ * @since 2.5.7
78
+ * @todo [feature] (maybe) 'DB_NAME', 'DB_USER', 'DB_PASSWORD', 'DB_HOST', 'DB_CHARSET', 'DB_COLLATE'
79
+ */
80
+ function get_system_info_table_array() {
81
+ $system_info = array();
82
+ $constants_array = array(
83
+ 'WP_MEMORY_LIMIT',
84
+ 'WP_MAX_MEMORY_LIMIT',
85
+ 'WP_DEBUG',
86
+ 'ABSPATH',
87
+ 'DISABLE_WP_CRON',
88
+ 'WP_CRON_LOCK_TIMEOUT',
89
+ 'WCJ_WC_VERSION',
90
+ 'WCJ_SESSION_TYPE',
91
+ );
92
+ foreach ( $constants_array as $the_constant ) {
93
+ $system_info[] = array( $the_constant, ( defined( $the_constant ) ? constant( $the_constant ) : __( 'NOT DEFINED', 'woocommerce-jetpack' ) ) );
94
+ }
95
+ if ( isset( $_GET['wcj_debug'] ) ) {
96
+ foreach ( $_SERVER as $server_var_id => $server_var_value ) {
97
+ $system_info[] = array( $server_var_id, esc_html( $server_var_value ) );
98
+ }
99
+ }
100
+ return $system_info;
101
+ }
102
+
103
+ }
104
+
105
+ endif;
106
+
107
+ return new WCJ_Debug_Tools();
includes/class-wcj-email-options.php CHANGED
@@ -1,169 +1,169 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Email Options
4
- *
5
- * @version 3.7.0
6
- * @since 2.9.1
7
- * @author Algoritmika Ltd.
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 ( '' != get_option( 'wcj_emails_bcc_email', '' ) ) {
34
- add_filter( 'woocommerce_email_headers', array( $this, 'add_bcc_email' ), PHP_INT_MAX, 3 );
35
- }
36
- if ( '' != 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' === 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( 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', '', 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: " . 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: " . 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
-
169
- return new WCJ_Email_Options();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Email Options
4
+ *
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 ( '' != get_option( 'wcj_emails_bcc_email', '' ) ) {
34
+ add_filter( 'woocommerce_email_headers', array( $this, 'add_bcc_email' ), PHP_INT_MAX, 3 );
35
+ }
36
+ if ( '' != 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' === 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( 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', '', 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: " . 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: " . 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
+
169
+ return new WCJ_Email_Options();
includes/class-wcj-emails-verification.php CHANGED
@@ -1,212 +1,212 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Email Verification
4
- *
5
- * @version 4.4.0
6
- * @since 2.8.0
7
- * @author Algoritmika Ltd.
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 4.4.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.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-email-verification';
28
- parent::__construct();
29
-
30
- if ( $this->is_enabled() ) {
31
- add_action( 'init', array( $this, 'process_email_verification' ), PHP_INT_MAX );
32
- add_filter( 'woocommerce_registration_redirect', array( $this, 'prevent_user_login_automatically_after_register' ), PHP_INT_MAX );
33
- add_filter( 'wp_authenticate_user', array( $this, 'check_if_user_email_is_verified' ), PHP_INT_MAX );
34
- add_action( 'user_register', array( $this, 'reset_and_mail_activation_link' ), PHP_INT_MAX );
35
- add_filter( 'manage_users_columns', array( $this, 'add_verified_email_column' ) );
36
- add_filter( 'manage_users_custom_column', array( $this, 'render_verified_email_column' ), 10, 3 );
37
- add_action( 'set_current_user', array( $this, 'prevent_user_login') );
38
- }
39
- }
40
-
41
- /**
42
- * Prevents user login.
43
- *
44
- * @version 4.4.0
45
- * @since 4.4.0
46
- */
47
- function prevent_user_login() {
48
- global $current_user;
49
- if (
50
- 'yes' === get_option( 'wcj_emails_verification_prevent_user_login', 'no' ) &&
51
- 0 != $current_user->ID
52
- ) {
53
- setup_userdata( $current_user->ID );
54
- $user_data = get_userdata( $current_user->ID );
55
- $response = $this->check_if_user_email_is_verified( $user_data );
56
- if ( is_wp_error( $response ) ) {
57
- wp_logout();
58
- }
59
- }
60
- }
61
-
62
- /**
63
- * add_verified_email_column.
64
- *
65
- * @version 3.1.0
66
- * @since 3.1.0
67
- * @todo (maybe) add option to enable/disable the column
68
- */
69
- function add_verified_email_column( $columns ) {
70
- $columns['wcj_is_verified_email'] = __( 'Verified', 'woocommerce-jetpack' );
71
- return $columns;
72
- }
73
-
74
- /**
75
- * render_verified_email_column.
76
- *
77
- * @version 3.1.0
78
- * @since 3.1.0
79
- */
80
- function render_verified_email_column( $output, $column_name, $user_id ) {
81
- if ( 'wcj_is_verified_email' === $column_name ) {
82
- $replaced_values = array(
83
- '1' => '<span title="' . __( 'Email verified', 'woocommerce-jetpack' ) . '">&#9745;</span>',
84
- '0' => '<span title="' . __( 'Email not verified', 'woocommerce-jetpack' ) . '">&#10006;</span>',
85
- );
86
- return str_replace( array_keys( $replaced_values ), array_values( $replaced_values ), get_user_meta( $user_id, 'wcj_is_activated', true ) );
87
- }
88
- return $output;
89
- }
90
-
91
- /**
92
- * prevent_user_login_automatically_after_register.
93
- *
94
- * @version 2.8.0
95
- * @since 2.8.0
96
- */
97
- function prevent_user_login_automatically_after_register( $redirect_to ) {
98
- wp_logout();
99
- return add_query_arg( 'wcj_activate_account_message', '', $redirect_to );
100
- }
101
-
102
- /**
103
- * check_if_user_email_is_verified.
104
- *
105
- * @version 3.6.0
106
- * @since 2.8.0
107
- */
108
- function check_if_user_email_is_verified( $userdata ) {
109
- if (
110
- ( 'yes' === get_option( 'wcj_emails_verification_already_registered_enabled', 'no' ) && ! get_user_meta( $userdata->ID, 'wcj_is_activated', true ) ) ||
111
- ( 'no' === get_option( 'wcj_emails_verification_already_registered_enabled', 'no' ) && '0' === get_user_meta( $userdata->ID, 'wcj_is_activated', true ) )
112
- ) {
113
- if ( isset( $userdata->roles ) && ! empty( $userdata->roles ) ) {
114
- $userdata_roles = wcj_get_array( $userdata->roles );
115
- $skip_user_roles = wcj_get_array( get_option( 'wcj_emails_verification_skip_user_roles', array( 'administrator' ) ) );
116
- $_intersect = array_intersect( $userdata_roles, $skip_user_roles );
117
- if ( ! empty( $_intersect ) ) {
118
- return $userdata;
119
- }
120
- }
121
- $error_message = do_shortcode( get_option( 'wcj_emails_verification_error_message',
122
- __( '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' )
123
- ) );
124
- $error_message = str_replace( '%resend_verification_url%', add_query_arg( 'wcj_user_id', $userdata->ID, wc_get_page_permalink( 'myaccount' ) ), $error_message );
125
- $userdata = new WP_Error( 'booster_email_verified_error', $error_message );
126
- }
127
- return $userdata;
128
- }
129
-
130
- /**
131
- * reset_and_mail_activation_link.
132
- *
133
- * @version 3.1.0
134
- * @since 2.8.0
135
- * @todo %site_name% etc. in `wcj_emails_verification_email_subject`
136
- */
137
- function reset_and_mail_activation_link( $user_id ) {
138
- $user_info = get_userdata( $user_id );
139
- $code = md5( time() );
140
- $url = add_query_arg( 'wcj_verify_email', base64_encode( json_encode( array( 'id' => $user_id, 'code' => $code ) ) ), wc_get_page_permalink( 'myaccount' ) );
141
- $email_content = do_shortcode( apply_filters( 'booster_option',
142
- __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ),
143
- get_option( 'wcj_emails_verification_email_content',
144
- __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ) ) ) );
145
- $email_content = str_replace( '%verification_url%', $url, $email_content );
146
- $email_subject = do_shortcode( apply_filters( 'booster_option',
147
- __( 'Please activate your account', 'woocommerce-jetpack' ),
148
- get_option( 'wcj_emails_verification_email_subject',
149
- __( 'Please activate your account', 'woocommerce-jetpack' ) ) ) );
150
- update_user_meta( $user_id, 'wcj_is_activated', '0' );
151
- update_user_meta( $user_id, 'wcj_activation_code', $code );
152
- if ( 'wc' === apply_filters( 'booster_option', 'plain', get_option( 'wcj_emails_verification_email_template', 'plain' ) ) ) {
153
- $email_content = wcj_wrap_in_wc_email_template( $email_content,
154
- get_option( 'wcj_emails_verification_email_template_wc_heading', __( 'Activate your account', 'woocommerce-jetpack' ) ) );
155
- }
156
- wc_mail( $user_info->user_email, $email_subject, $email_content );
157
- }
158
-
159
- /**
160
- * process_email_verification.
161
- *
162
- * @version 3.9.0
163
- * @since 2.8.0
164
- */
165
- function process_email_verification() {
166
- if ( isset( $_GET['wcj_verified_email'] ) ) {
167
- if ( function_exists( 'wc_add_notice' ) ) {
168
- $data = json_decode( base64_decode( $_GET['wcj_verified_email'] ), true );
169
- if ( ! empty( $data['id'] ) && ! empty( $data['code'] ) && get_user_meta( $data['id'], 'wcj_activation_code', true ) == $data['code'] ) {
170
- wc_add_notice( do_shortcode( get_option( 'wcj_emails_verification_success_message',
171
- __( '<strong>Success:</strong> Your account has been activated!', 'woocommerce-jetpack' ) ) ) );
172
- }
173
- }
174
- } elseif ( isset( $_GET['wcj_verify_email'] ) ) {
175
- $data = json_decode( base64_decode( $_GET['wcj_verify_email'] ), true );
176
- if ( ! empty( $data['id'] ) && ! empty( $data['code'] ) && get_user_meta( $data['id'], 'wcj_activation_code', true ) == $data['code'] ) {
177
- update_user_meta( $data['id'], 'wcj_is_activated', '1' );
178
- if ( 'yes' === get_option( 'wcj_emails_verification_redirect_on_success', 'yes' ) ) {
179
- wp_set_current_user( $data['id'] );
180
- wp_set_auth_cookie( $data['id'] );
181
- }
182
- $url = ( '' != ( $custom_url = get_option( 'wcj_emails_verification_redirect_on_success_custom_url', '' ) ) ? $custom_url : wc_get_page_permalink( 'myaccount' ) );
183
- wp_safe_redirect( add_query_arg( 'wcj_verified_email', $_GET['wcj_verify_email'], $url ) );
184
- exit;
185
- } elseif ( ! empty( $data['id'] ) ) {
186
- $_notice = do_shortcode(
187
- get_option( 'wcj_emails_verification_failed_message',
188
- __( '<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' )
189
- )
190
- );
191
- $_notice = str_replace( '%resend_verification_url%', add_query_arg( 'wcj_user_id', $data['id'], wc_get_page_permalink( 'myaccount' ) ), $_notice );
192
- wc_add_notice( $_notice, 'error' );
193
- } else {
194
- $_notice = get_option( 'wcj_emails_verification_failed_message_no_user_id',
195
- __( '<strong>Error:</strong> Activation failed, please contact our administrator.', 'woocommerce-jetpack' ) );
196
- wc_add_notice( $_notice, 'error' );
197
- }
198
- } elseif ( isset( $_GET['wcj_activate_account_message'] ) ) {
199
- wc_add_notice( do_shortcode( get_option( 'wcj_emails_verification_activation_message',
200
- __( 'Thank you for your registration. Your account has to be activated before you can login. Please check your email.', 'woocommerce-jetpack' ) ) ) );
201
- } elseif ( isset( $_GET['wcj_user_id'] ) ) {
202
- $this->reset_and_mail_activation_link( $_GET['wcj_user_id'] );
203
- wc_add_notice( do_shortcode( get_option( 'wcj_emails_verification_email_resend_message',
204
- __( '<strong>Success:</strong> Your activation email has been resent. Please check your email.', 'woocommerce-jetpack' ) ) ) );
205
- }
206
- }
207
-
208
- }
209
-
210
- endif;
211
-
212
- return new WCJ_Email_Verification();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Email Verification
4
+ *
5
+ * @version 4.4.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_Email_Verification' ) ) :
13
+
14
+ class WCJ_Email_Verification extends WCJ_Module {
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 4.4.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.', 'woocommerce-jetpack' );
27
+ $this->link_slug = 'woocommerce-email-verification';
28
+ parent::__construct();
29
+
30
+ if ( $this->is_enabled() ) {
31
+ add_action( 'init', array( $this, 'process_email_verification' ), PHP_INT_MAX );
32
+ add_filter( 'woocommerce_registration_redirect', array( $this, 'prevent_user_login_automatically_after_register' ), PHP_INT_MAX );
33
+ add_filter( 'wp_authenticate_user', array( $this, 'check_if_user_email_is_verified' ), PHP_INT_MAX );
34
+ add_action( 'user_register', array( $this, 'reset_and_mail_activation_link' ), PHP_INT_MAX );
35
+ add_filter( 'manage_users_columns', array( $this, 'add_verified_email_column' ) );
36
+ add_filter( 'manage_users_custom_column', array( $this, 'render_verified_email_column' ), 10, 3 );
37
+ add_action( 'set_current_user', array( $this, 'prevent_user_login') );
38
+ }
39
+ }
40
+
41
+ /**
42
+ * Prevents user login.
43
+ *
44
+ * @version 4.4.0
45
+ * @since 4.4.0
46
+ */
47
+ function prevent_user_login() {
48
+ global $current_user;
49
+ if (
50
+ 'yes' === get_option( 'wcj_emails_verification_prevent_user_login', 'no' ) &&
51
+ 0 != $current_user->ID
52
+ ) {
53
+ setup_userdata( $current_user->ID );
54
+ $user_data = get_userdata( $current_user->ID );
55
+ $response = $this->check_if_user_email_is_verified( $user_data );
56
+ if ( is_wp_error( $response ) ) {
57
+ wp_logout();
58
+ }
59
+ }
60
+ }
61
+
62
+ /**
63
+ * add_verified_email_column.
64
+ *
65
+ * @version 3.1.0
66
+ * @since 3.1.0
67
+ * @todo (maybe) add option to enable/disable the column
68
+ */
69
+ function add_verified_email_column( $columns ) {
70
+ $columns['wcj_is_verified_email'] = __( 'Verified', 'woocommerce-jetpack' );
71
+ return $columns;
72
+ }
73
+
74
+ /**
75
+ * render_verified_email_column.
76
+ *
77
+ * @version 3.1.0
78
+ * @since 3.1.0
79
+ */
80
+ function render_verified_email_column( $output, $column_name, $user_id ) {
81
+ if ( 'wcj_is_verified_email' === $column_name ) {
82
+ $replaced_values = array(
83
+ '1' => '<span title="' . __( 'Email verified', 'woocommerce-jetpack' ) . '">&#9745;</span>',
84
+ '0' => '<span title="' . __( 'Email not verified', 'woocommerce-jetpack' ) . '">&#10006;</span>',
85
+ );
86
+ return str_replace( array_keys( $replaced_values ), array_values( $replaced_values ), get_user_meta( $user_id, 'wcj_is_activated', true ) );
87
+ }
88
+ return $output;
89
+ }
90
+
91
+ /**
92
+ * prevent_user_login_automatically_after_register.
93
+ *
94
+ * @version 2.8.0
95
+ * @since 2.8.0
96
+ */
97
+ function prevent_user_login_automatically_after_register( $redirect_to ) {
98
+ wp_logout();
99
+ return add_query_arg( 'wcj_activate_account_message', '', $redirect_to );
100
+ }
101
+
102
+ /**
103
+ * check_if_user_email_is_verified.
104
+ *
105
+ * @version 3.6.0
106
+ * @since 2.8.0
107
+ */
108
+ function check_if_user_email_is_verified( $userdata ) {
109
+ if (
110
+ ( 'yes' === get_option( 'wcj_emails_verification_already_registered_enabled', 'no' ) && ! get_user_meta( $userdata->ID, 'wcj_is_activated', true ) ) ||
111
+ ( 'no' === get_option( 'wcj_emails_verification_already_registered_enabled', 'no' ) && '0' === get_user_meta( $userdata->ID, 'wcj_is_activated', true ) )
112
+ ) {
113
+ if ( isset( $userdata->roles ) && ! empty( $userdata->roles ) ) {
114
+ $userdata_roles = wcj_get_array( $userdata->roles );
115
+ $skip_user_roles = wcj_get_array( get_option( 'wcj_emails_verification_skip_user_roles', array( 'administrator' ) ) );
116
+ $_intersect = array_intersect( $userdata_roles, $skip_user_roles );
117
+ if ( ! empty( $_intersect ) ) {
118
+ return $userdata;
119
+ }
120
+ }
121
+ $error_message = do_shortcode( get_option( 'wcj_emails_verification_error_message',
122
+ __( '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' )
123
+ ) );
124
+ $error_message = str_replace( '%resend_verification_url%', add_query_arg( 'wcj_user_id', $userdata->ID, wc_get_page_permalink( 'myaccount' ) ), $error_message );
125
+ $userdata = new WP_Error( 'booster_email_verified_error', $error_message );
126
+ }
127
+ return $userdata;
128
+ }
129
+
130
+ /**
131
+ * reset_and_mail_activation_link.
132
+ *
133
+ * @version 3.1.0
134
+ * @since 2.8.0
135
+ * @todo %site_name% etc. in `wcj_emails_verification_email_subject`
136
+ */
137
+ function reset_and_mail_activation_link( $user_id ) {
138
+ $user_info = get_userdata( $user_id );
139
+ $code = md5( time() );
140
+ $url = add_query_arg( 'wcj_verify_email', base64_encode( json_encode( array( 'id' => $user_id, 'code' => $code ) ) ), wc_get_page_permalink( 'myaccount' ) );
141
+ $email_content = do_shortcode( apply_filters( 'booster_option',
142
+ __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ),
143
+ get_option( 'wcj_emails_verification_email_content',
144
+ __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ) ) ) );
145
+ $email_content = str_replace( '%verification_url%', $url, $email_content );
146
+ $email_subject = do_shortcode( apply_filters( 'booster_option',
147
+ __( 'Please activate your account', 'woocommerce-jetpack' ),
148
+ get_option( 'wcj_emails_verification_email_subject',
149
+ __( 'Please activate your account', 'woocommerce-jetpack' ) ) ) );
150
+ update_user_meta( $user_id, 'wcj_is_activated', '0' );
151
+ update_user_meta( $user_id, 'wcj_activation_code', $code );
152
+ if ( 'wc' === apply_filters( 'booster_option', 'plain', get_option( 'wcj_emails_verification_email_template', 'plain' ) ) ) {
153
+ $email_content = wcj_wrap_in_wc_email_template( $email_content,
154
+ get_option( 'wcj_emails_verification_email_template_wc_heading', __( 'Activate your account', 'woocommerce-jetpack' ) ) );
155
+ }
156
+ wc_mail( $user_info->user_email, $email_subject, $email_content );
157
+ }
158
+
159
+ /**
160
+ * process_email_verification.
161
+ *
162
+ * @version 3.9.0
163
+ * @since 2.8.0
164
+ */
165
+ function process_email_verification() {
166
+ if ( isset( $_GET['wcj_verified_email'] ) ) {
167
+ if ( function_exists( 'wc_add_notice' ) ) {
168
+ $data = json_decode( base64_decode( $_GET['wcj_verified_email'] ), true );
169
+ if ( ! empty( $data['id'] ) && ! empty( $data['code'] ) && get_user_meta( $data['id'], 'wcj_activation_code', true ) == $data['code'] ) {
170
+ wc_add_notice( do_shortcode( get_option( 'wcj_emails_verification_success_message',
171
+ __( '<strong>Success:</strong> Your account has been activated!', 'woocommerce-jetpack' ) ) ) );
172
+ }
173
+ }
174
+ } elseif ( isset( $_GET['wcj_verify_email'] ) ) {
175
+ $data = json_decode( base64_decode( $_GET['wcj_verify_email'] ), true );
176
+ if ( ! empty( $data['id'] ) && ! empty( $data['code'] ) && get_user_meta( $data['id'], 'wcj_activation_code', true ) == $data['code'] ) {
177
+ update_user_meta( $data['id'], 'wcj_is_activated', '1' );
178
+ if ( 'yes' === get_option( 'wcj_emails_verification_redirect_on_success', 'yes' ) ) {
179
+ wp_set_current_user( $data['id'] );
180
+ wp_set_auth_cookie( $data['id'] );
181
+ }
182
+ $url = ( '' != ( $custom_url = get_option( 'wcj_emails_verification_redirect_on_success_custom_url', '' ) ) ? $custom_url : wc_get_page_permalink( 'myaccount' ) );
183
+ wp_safe_redirect( add_query_arg( 'wcj_verified_email', $_GET['wcj_verify_email'], $url ) );
184
+ exit;
185
+ } elseif ( ! empty( $data['id'] ) ) {
186
+ $_notice = do_shortcode(
187
+ get_option( 'wcj_emails_verification_failed_message',
188
+ __( '<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' )
189
+ )
190
+ );
191
+ $_notice = str_replace( '%resend_verification_url%', add_query_arg( 'wcj_user_id', $data['id'], wc_get_page_permalink( 'myaccount' ) ), $_notice );
192
+ wc_add_notice( $_notice, 'error' );
193
+ } else {
194
+ $_notice = get_option( 'wcj_emails_verification_failed_message_no_user_id',
195
+ __( '<strong>Error:</strong> Activation failed, please contact our administrator.', 'woocommerce-jetpack' ) );
196
+ wc_add_notice( $_notice, 'error' );
197
+ }
198
+ } elseif ( isset( $_GET['wcj_activate_account_message'] ) ) {
199
+ wc_add_notice( do_shortcode( get_option( 'wcj_emails_verification_activation_message',
200
+ __( 'Thank you for your registration. Your account has to be activated before you can login. Please check your email.', 'woocommerce-jetpack' ) ) ) );
201
+ } elseif ( isset( $_GET['wcj_user_id'] ) ) {
202
+ $this->reset_and_mail_activation_link( $_GET['wcj_user_id'] );
203
+ wc_add_notice( do_shortcode( get_option( 'wcj_emails_verification_email_resend_message',
204
+ __( '<strong>Success:</strong> Your activation email has been resent. Please check your email.', 'woocommerce-jetpack' ) ) ) );
205
+ }
206
+ }
207
+
208
+ }
209
+
210
+ endif;
211
+
212
+ return new WCJ_Email_Verification();
includes/class-wcj-emails.php CHANGED
@@ -1,135 +1,135 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Custom Emails
4
- *
5
- * @version 3.2.0
6
- * @author Algoritmika Ltd.
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 3.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.', 'woocommerce-jetpack' );
25
- $this->link_slug = 'woocommerce-custom-emails';
26
- parent::__construct();
27
-
28
- if ( $this->is_enabled() ) {
29
- add_filter( 'woocommerce_email_actions', array( $this, 'add_custom_woocommerce_email_actions' ) );
30
- add_filter( 'woocommerce_email_classes', array( $this, 'add_custom_emails_to_wc' ) );
31
- add_filter( 'woocommerce_resend_order_emails_available', array( $this, 'add_custom_emails_to_wc_resend_order_emails' ) );
32
- if ( ! WCJ_IS_WC_VERSION_BELOW_3_2_0 ) {
33
- add_filter( 'woocommerce_order_actions', array( $this, 'add_custom_emails_order_actions' ), PHP_INT_MAX, 1 );
34
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
35
- add_action( 'woocommerce_order_action_' . 'wcj_send_email_custom' . '_' . $i,
36
- array( $this, 'do_custom_emails_order_actions' ), PHP_INT_MAX, 1 );
37
- }
38
- }
39
- }
40
- }
41
-
42
- /**
43
- * do_custom_emails_order_actions.
44
- *
45
- * @version 3.2.0
46
- * @since 3.2.0
47
- */
48
- function do_custom_emails_order_actions( $order ) {
49
- $booster_action_prefix = 'woocommerce_order_action_' . 'wcj_send_email_custom' . '_';
50
- $_current_filter = current_filter();
51
- if ( substr( $_current_filter, 0, strlen( $booster_action_prefix ) ) === $booster_action_prefix ) {
52
- $email_nr = substr( $_current_filter, strlen( $booster_action_prefix ) );
53
- WC()->payment_gateways();
54
- WC()->shipping();
55
- WC()->mailer()->emails[ 'WC_Email_WCJ_Custom_' . $email_nr ]->trigger( $order->get_id(), $order );
56
- $order->add_order_note(
57
- sprintf( __( 'Booster: Emails: %s manually sent.', 'woocommerce-jetpack' ),
58
- get_option( 'wcj_emails_custom_emails_admin_title_' . $email_nr, __( 'Custom', 'woocommerce-jetpack' ) . ' #' . $email_nr ) ),
59
- false,
60
- true
61
- );
62
- }
63
- }
64
-
65
- /**
66
- * add_custom_emails_order_actions.
67
- *
68
- * @version 3.2.0
69
- * @since 3.2.0
70
- * @todo (maybe) add "Add Custom Email(s) to Order Actions" option (in WC >= 3.2.0); same to `woocommerce_order_action_`
71
- */
72
- function add_custom_emails_order_actions( $actions ) {
73
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
74
- $actions[ 'wcj_send_email_custom' . '_' . $i ] = sprintf( apply_filters( 'wcj_emails_custom_emails_order_action_text',
75
- __( 'Booster: Send Email: %s', 'woocommerce-jetpack' ), $i ),
76
- get_option( 'wcj_emails_custom_emails_admin_title_' . $i, __( 'Custom', 'woocommerce-jetpack' ) . ' #' . $i )
77
- );
78
- }
79
- return $actions;
80
- }
81
-
82
- /**
83
- * add_custom_woocommerce_email_actions.
84
- *
85
- * @version 2.9.1
86
- * @since 2.4.5
87
- */
88
- function add_custom_woocommerce_email_actions( $email_actions ) {
89
- $email_actions[] = 'woocommerce_checkout_order_processed';
90
- $order_statuses = wcj_get_order_statuses();
91
- foreach ( $order_statuses as $slug => $name ) {
92
- $email_actions[] = 'woocommerce_order_status_' . $slug;
93
- foreach ( $order_statuses as $slug2 => $name2 ) {
94
- if ( $slug != $slug2 ) {
95
- $email_actions[] = 'woocommerce_order_status_' . $slug . '_to_' . $slug2;
96
- }
97
- }
98
- }
99
- return $email_actions;
100
- }
101
-
102
- /**
103
- * add_custom_emails_to_wc_resend_order_emails.
104
- *
105
- * @version 2.3.9
106
- * @since 2.3.9
107
- */
108
- function add_custom_emails_to_wc_resend_order_emails( $emails ) {
109
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
110
- $emails[] = 'wcj_custom' . '_' . $i;
111
- }
112
- return $emails;
113
- }
114
-
115
- /**
116
- * add_custom_emails_to_wc.
117
- *
118
- * @version 2.3.9
119
- * @since 2.3.9
120
- */
121
- function add_custom_emails_to_wc( $emails ) {
122
- if ( ! class_exists( 'WC_Email_WCJ_Custom' ) ) {
123
- require_once( 'emails/class-wc-email-wcj-custom.php' );
124
- }
125
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
126
- $emails[ 'WC_Email_WCJ_Custom_' . $i ] = new WC_Email_WCJ_Custom( $i );
127
- }
128
- return $emails;
129
- }
130
-
131
- }
132
-
133
- endif;
134
-
135
- return new WCJ_Emails();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Custom Emails
4
+ *
5
+ * @version 3.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 3.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.', 'woocommerce-jetpack' );
25
+ $this->link_slug = 'woocommerce-custom-emails';
26
+ parent::__construct();
27
+
28
+ if ( $this->is_enabled() ) {
29
+ add_filter( 'woocommerce_email_actions', array( $this, 'add_custom_woocommerce_email_actions' ) );
30
+ add_filter( 'woocommerce_email_classes', array( $this, 'add_custom_emails_to_wc' ) );
31
+ add_filter( 'woocommerce_resend_order_emails_available', array( $this, 'add_custom_emails_to_wc_resend_order_emails' ) );
32
+ if ( ! WCJ_IS_WC_VERSION_BELOW_3_2_0 ) {
33
+ add_filter( 'woocommerce_order_actions', array( $this, 'add_custom_emails_order_actions' ), PHP_INT_MAX, 1 );
34
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
35
+ add_action( 'woocommerce_order_action_' . 'wcj_send_email_custom' . '_' . $i,
36
+ array( $this, 'do_custom_emails_order_actions' ), PHP_INT_MAX, 1 );
37
+ }
38
+ }
39
+ }
40
+ }
41
+
42
+ /**
43
+ * do_custom_emails_order_actions.
44
+ *
45
+ * @version 3.2.0
46
+ * @since 3.2.0
47
+ */
48
+ function do_custom_emails_order_actions( $order ) {
49
+ $booster_action_prefix = 'woocommerce_order_action_' . 'wcj_send_email_custom' . '_';
50
+ $_current_filter = current_filter();
51
+ if ( substr( $_current_filter, 0, strlen( $booster_action_prefix ) ) === $booster_action_prefix ) {
52
+ $email_nr = substr( $_current_filter, strlen( $booster_action_prefix ) );
53
+ WC()->payment_gateways();
54
+ WC()->shipping();
55
+ WC()->mailer()->emails[ 'WC_Email_WCJ_Custom_' . $email_nr ]->trigger( $order->get_id(), $order );
56
+ $order->add_order_note(
57
+ sprintf( __( 'Booster: Emails: %s manually sent.', 'woocommerce-jetpack' ),
58
+ get_option( 'wcj_emails_custom_emails_admin_title_' . $email_nr, __( 'Custom', 'woocommerce-jetpack' ) . ' #' . $email_nr ) ),
59
+ false,
60
+ true
61
+ );
62
+ }
63
+ }
64
+
65
+ /**
66
+ * add_custom_emails_order_actions.
67
+ *
68
+ * @version 3.2.0
69
+ * @since 3.2.0
70
+ * @todo (maybe) add "Add Custom Email(s) to Order Actions" option (in WC >= 3.2.0); same to `woocommerce_order_action_`
71
+ */
72
+ function add_custom_emails_order_actions( $actions ) {
73
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
74
+ $actions[ 'wcj_send_email_custom' . '_' . $i ] = sprintf( apply_filters( 'wcj_emails_custom_emails_order_action_text',
75
+ __( 'Booster: Send Email: %s', 'woocommerce-jetpack' ), $i ),
76
+ get_option( 'wcj_emails_custom_emails_admin_title_' . $i, __( 'Custom', 'woocommerce-jetpack' ) . ' #' . $i )
77
+ );
78
+ }
79
+ return $actions;
80
+ }
81
+
82
+ /**
83
+ * add_custom_woocommerce_email_actions.
84
+ *
85
+ * @version 2.9.1
86
+ * @since 2.4.5
87
+ */
88
+ function add_custom_woocommerce_email_actions( $email_actions ) {
89
+ $email_actions[] = 'woocommerce_checkout_order_processed';
90
+ $order_statuses = wcj_get_order_statuses();
91
+ foreach ( $order_statuses as $slug => $name ) {
92
+ $email_actions[] = 'woocommerce_order_status_' . $slug;
93
+ foreach ( $order_statuses as $slug2 => $name2 ) {
94
+ if ( $slug != $slug2 ) {
95
+ $email_actions[] = 'woocommerce_order_status_' . $slug . '_to_' . $slug2;
96
+ }
97
+ }
98
+ }
99
+ return $email_actions;
100
+ }
101
+
102
+ /**
103
+ * add_custom_emails_to_wc_resend_order_emails.
104
+ *
105
+ * @version 2.3.9
106
+ * @since 2.3.9
107
+ */
108
+ function add_custom_emails_to_wc_resend_order_emails( $emails ) {
109
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
110
+ $emails[] = 'wcj_custom' . '_' . $i;
111
+ }
112
+ return $emails;
113
+ }
114
+
115
+ /**
116
+ * add_custom_emails_to_wc.
117
+ *
118
+ * @version 2.3.9
119
+ * @since 2.3.9
120
+ */
121
+ function add_custom_emails_to_wc( $emails ) {
122
+ if ( ! class_exists( 'WC_Email_WCJ_Custom' ) ) {
123
+ require_once( 'emails/class-wc-email-wcj-custom.php' );
124
+ }
125
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
126
+ $emails[ 'WC_Email_WCJ_Custom_' . $i ] = new WC_Email_WCJ_Custom( $i );
127
+ }
128
+ return $emails;
129
+ }
130
+
131
+ }
132
+
133
+ endif;
134
+
135
+ return new WCJ_Emails();
includes/class-wcj-empty-cart-button.php CHANGED
@@ -1,80 +1,80 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Empty Cart Button
4
- *
5
- * @version 3.5.3
6
- * @since 2.2.1
7
- * @author Algoritmika Ltd.
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 3.5.3
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.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-empty-cart-button';
28
- parent::__construct();
29
-
30
- if ( $this->is_enabled() ) {
31
- add_action( 'init', array( $this, 'maybe_empty_cart' ) );
32
- if ( 'disable' != ( $empty_cart_cart_position = apply_filters( 'booster_option', 'woocommerce_after_cart',
33
- get_option( 'wcj_empty_cart_position', 'woocommerce_after_cart' ) ) )
34
- ) {
35
- add_action( $empty_cart_cart_position, array( $this, 'add_empty_cart_link' ) );
36
- }
37
- if ( 'disable' != ( $empty_cart_checkout_position = get_option( 'wcj_empty_cart_checkout_position', 'disable' ) ) ) {
38
- $deprecated_hooks = array(
39
- 'woocommerce_checkout_before_customer_details' => 'woocommerce_before_checkout_form',
40
- 'woocommerce_checkout_billing' => 'woocommerce_before_checkout_form',
41
- 'woocommerce_checkout_shipping' => 'woocommerce_before_checkout_form',
42
- 'woocommerce_checkout_after_customer_details' => 'woocommerce_after_checkout_form',
43
- 'woocommerce_checkout_before_order_review' => 'woocommerce_after_checkout_form',
44
- 'woocommerce_checkout_order_review' => 'woocommerce_after_checkout_form',
45
- 'woocommerce_checkout_after_order_review' => 'woocommerce_after_checkout_form',
46
- );
47
- if ( isset( $deprecated_hooks[ $empty_cart_checkout_position ] ) ) {
48
- $empty_cart_checkout_position = $deprecated_hooks[ $empty_cart_checkout_position ];
49
- update_option( 'wcj_empty_cart_checkout_position', $empty_cart_checkout_position );
50
- }
51
- add_action( $empty_cart_checkout_position, array( $this, 'add_empty_cart_link' ) );
52
- }
53
- }
54
- }
55
-
56
- /**
57
- * add_empty_cart_link.
58
- *
59
- * @version 2.8.0
60
- */
61
- function add_empty_cart_link() {
62
- echo wcj_empty_cart_button_html();
63
- }
64
-
65
- /**
66
- * maybe_empty_cart.
67
- *
68
- * @version 2.8.0
69
- */
70
- function maybe_empty_cart() {
71
- if ( isset( $_POST['wcj_empty_cart'] ) && isset( WC()->cart ) ) {
72
- WC()->cart->empty_cart();
73
- }
74
- }
75
-
76
- }
77
-
78
- endif;
79
-
80
- return new WCJ_Empty_Cart_Button();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Empty Cart Button
4
+ *
5
+ * @version 3.5.3
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 3.5.3
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.', 'woocommerce-jetpack' );
27
+ $this->link_slug = 'woocommerce-empty-cart-button';
28
+ parent::__construct();
29
+
30
+ if ( $this->is_enabled() ) {
31
+ add_action( 'init', array( $this, 'maybe_empty_cart' ) );
32
+ if ( 'disable' != ( $empty_cart_cart_position = apply_filters( 'booster_option', 'woocommerce_after_cart',
33
+ get_option( 'wcj_empty_cart_position', 'woocommerce_after_cart' ) ) )
34
+ ) {
35
+ add_action( $empty_cart_cart_position, array( $this, 'add_empty_cart_link' ) );
36
+ }
37
+ if ( 'disable' != ( $empty_cart_checkout_position = get_option( 'wcj_empty_cart_checkout_position', 'disable' ) ) ) {
38
+ $deprecated_hooks = array(
39
+ 'woocommerce_checkout_before_customer_details' => 'woocommerce_before_checkout_form',
40
+ 'woocommerce_checkout_billing' => 'woocommerce_before_checkout_form',
41
+ 'woocommerce_checkout_shipping' => 'woocommerce_before_checkout_form',
42
+ 'woocommerce_checkout_after_customer_details' => 'woocommerce_after_checkout_form',
43
+ 'woocommerce_checkout_before_order_review' => 'woocommerce_after_checkout_form',
44
+ 'woocommerce_checkout_order_review' => 'woocommerce_after_checkout_form',
45
+ 'woocommerce_checkout_after_order_review' => 'woocommerce_after_checkout_form',
46
+ );
47
+ if ( isset( $deprecated_hooks[ $empty_cart_checkout_position ] ) ) {
48
+ $empty_cart_checkout_position = $deprecated_hooks[ $empty_cart_checkout_position ];
49
+ update_option( 'wcj_empty_cart_checkout_position', $empty_cart_checkout_position );
50
+ }
51
+ add_action( $empty_cart_checkout_position, array( $this, 'add_empty_cart_link' ) );
52
+ }
53
+ }
54
+ }
55
+
56
+ /**
57
+ * add_empty_cart_link.
58
+ *
59
+ * @version 2.8.0
60
+ */
61
+ function add_empty_cart_link() {
62
+ echo wcj_empty_cart_button_html();
63
+ }
64
+
65
+ /**
66
+ * maybe_empty_cart.
67
+ *
68
+ * @version 2.8.0
69
+ */
70
+ function maybe_empty_cart() {
71
+ if ( isset( $_POST['wcj_empty_cart'] ) && isset( WC()->cart ) ) {
72
+ WC()->cart->empty_cart();
73
+ }
74
+ }
75
+
76
+ }
77
+
78
+ endif;
79
+
80
+ return new WCJ_Empty_Cart_Button();
includes/class-wcj-eu-vat-number.php CHANGED
@@ -1,600 +1,600 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - EU VAT Number
4
- *
5
- * @version 4.9.0
6
- * @since 2.3.9
7
- * @author Algoritmika Ltd.
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 4.7.1
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.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-eu-vat-number';
28
- parent::__construct();
29
-
30
- $this->add_tools( array(
31
- 'eu_countries_vat_rates' => array(
32
- 'title' => __( 'EU Countries VAT Rates', 'woocommerce-jetpack' ),
33
- 'desc' => __( 'Add all EU countries VAT standard rates to WooCommerce.', 'woocommerce-jetpack' ),
34
- ),
35
- ) );
36
-
37
- if ( $this->is_enabled() ) {
38
- add_action( 'init', array( $this, 'start_session' ) );
39
- add_filter( 'woocommerce_checkout_fields', array( $this, 'add_eu_vat_number_checkout_field_to_frontend' ), PHP_INT_MAX );
40
- add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_billing_eu_vat_number_field_to_admin_order_display' ), PHP_INT_MAX );
41
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
42
- add_action( 'wp_ajax_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
43
- add_action( 'wp_ajax_nopriv_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
44
- add_filter( 'wp', array( $this, 'maybe_exclude_vat' ), PHP_INT_MAX );
45
- add_filter( 'woocommerce_cart_tax_totals', array( $this, 'maybe_remove_tax_totals' ), 1 );
46
- add_filter( 'woocommerce_calculated_total', array( $this, 'maybe_recalculate_tax_totals' ), 1, 2 );
47
- add_action( 'woocommerce_after_checkout_validation', array( $this, 'checkout_validate_vat' ), PHP_INT_MAX );
48
- add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_eu_vat_number_customer_meta_field' ) );
49
- add_filter( 'default_checkout_billing_eu_vat_number', array( $this, 'add_default_checkout_billing_eu_vat_number' ), PHP_INT_MAX, 2 );
50
-
51
- if ( 'after_order_table' === get_option( 'wcj_eu_vat_number_display_position', 'after_order_table' ) ) {
52
- add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
53
- add_action( 'woocommerce_email_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
54
- } else {
55
- add_filter( 'woocommerce_order_formatted_billing_address', array( $this, 'add_eu_vat_number_to_order_billing_address' ), PHP_INT_MAX, 2 );
56
- add_filter( 'woocommerce_my_account_my_address_formatted_address', array( $this, 'add_eu_vat_number_to_my_account_billing_address' ), PHP_INT_MAX, 3 );
57
- add_filter( 'woocommerce_localisation_address_formats', array( $this, 'add_eu_vat_number_to_address_formats' ) );
58
- add_filter( 'woocommerce_formatted_address_replacements', array( $this, 'replace_eu_vat_number_in_address_formats' ), PHP_INT_MAX, 2 );
59
- }
60
-
61
- $this->eu_countries_vat_rates_tool = include_once( 'tools/class-wcj-eu-countries-vat-rates-tool.php' );
62
-
63
- // EU VAT number summary on order edit page
64
- if ( 'yes' === get_option( 'wcj_eu_vat_number_add_order_edit_metabox', 'no' ) ) {
65
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
66
- // "Validate VAT and remove taxes" button
67
- add_action( 'admin_init', array( $this, 'admin_validate_vat_and_maybe_remove_taxes' ), PHP_INT_MAX );
68
- }
69
-
70
- // Admin order edit - "Load billing address" button
71
- add_filter( 'woocommerce_ajax_get_customer_details', array( $this, 'add_billing_eu_vat_number_to_ajax_get_customer_details' ), PHP_INT_MAX, 3 );
72
- }
73
- }
74
-
75
- /**
76
- * maybe_recalculate_tax_totals.
77
- *
78
- * @version 4.6.0
79
- * @since 4.6.0
80
- *
81
- * @see https://gist.github.com/TimBHowe/fe9418b9224d8b8cb339
82
- * @param $total
83
- * @param $cart
84
- *
85
- * @return mixed
86
- */
87
- function maybe_recalculate_tax_totals( $total, $cart ) {
88
- if ( 'yes' === get_option( 'wcj_eu_vat_number_disable_for_valid_on_cart', 'no' ) && $this->need_to_exclude_vat() ) {
89
- return $total - $cart->get_taxes_total();
90
- }
91
- return $total;
92
- }
93
-
94
- /**
95
- * maybe_remove_tax_totals.
96
- *
97
- * @version 4.6.0
98
- * @since 4.6.0
99
- *
100
- * @see https://gist.github.com/TimBHowe/fe9418b9224d8b8cb339
101
- * @param $tax_totals
102
- *
103
- * @return array
104
- */
105
- function maybe_remove_tax_totals( $tax_totals ) {
106
- if ( 'yes' === get_option( 'wcj_eu_vat_number_disable_for_valid_on_cart', 'no' ) && $this->need_to_exclude_vat() ) {
107
- $tax_totals = array();
108
- }
109
- return $tax_totals;
110
- }
111
-
112
- /**
113
- * admin_validate_vat_and_maybe_remove_taxes.
114
- *
115
- * @version 3.3.0
116
- * @since 3.3.0
117
- */
118
- function admin_validate_vat_and_maybe_remove_taxes() {
119
- if ( isset( $_GET['validate_vat_and_maybe_remove_taxes'] ) ) {
120
- $order_id = $_GET['validate_vat_and_maybe_remove_taxes'];
121
- $order = wc_get_order( $order_id );
122
- if ( $order ) {
123
- $vat_id = get_post_meta( $order_id, '_billing_eu_vat_number', true );
124
- if ( '' != $vat_id && strlen( $vat_id ) > 2 ) {
125
- if ( wcj_validate_vat( substr( $vat_id, 0, 2 ), substr( $vat_id, 2 ) ) ) {
126
- foreach ( $order->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) {
127
- $item->set_taxes( false );
128
- }
129
- foreach ( $order->get_shipping_methods() as $item_id => $item ) {
130
- $item->set_taxes( false );
131
- }
132
- $order->update_taxes();
133
- $order->calculate_totals( false );
134
- }
135
- }
136
- }
137
- wp_safe_redirect( remove_query_arg( 'validate_vat_and_maybe_remove_taxes' ) );
138
- exit;
139
- }
140
- }
141
-
142
- /**
143
- * add_billing_eu_vat_number_to_ajax_get_customer_details.
144
- *
145
- * @version 3.3.0
146
- * @since 3.3.0
147
- */
148
- function add_billing_eu_vat_number_to_ajax_get_customer_details( $data, $customer, $user_id ) {
149
- $data['billing']['eu_vat_number'] = get_user_meta( $user_id, 'billing_eu_vat_number', true );
150
- return $data;
151
- }
152
-
153
- /**
154
- * add_meta_box.
155
- *
156
- * @version 2.6.0
157
- * @since 2.6.0
158
- */
159
- function add_meta_box() {
160
- $screen = ( isset( $this->meta_box_screen ) ) ? $this->meta_box_screen : 'shop_order';
161
- $context = ( isset( $this->meta_box_context ) ) ? $this->meta_box_context : 'side';
162
- $priority = ( isset( $this->meta_box_priority ) ) ? $this->meta_box_priority : 'low';
163
- add_meta_box(
164
- 'wc-jetpack-' . $this->id,
165
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . $this->short_desc,
166
- array( $this, 'create_meta_box' ),
167
- $screen,
168
- $context,
169
- $priority
170
- );
171
- }
172
-
173
- /**
174
- * create_meta_box.
175
- *
176
- * @version 3.3.0
177
- * @since 2.6.0
178
- */
179
- function create_meta_box() {
180
- $order_id = get_the_ID();
181
- $_order = wc_get_order( $order_id );
182
- $_customer_ip_address = ( WCJ_IS_WC_VERSION_BELOW_3 ? $_order->customer_ip_address : $_order->get_customer_ip_address() );
183
-
184
- // Country by IP
185
- if ( class_exists( 'WC_Geolocation' ) ) {
186
- // Get the country by IP
187
- $location = WC_Geolocation::geolocate_ip( $_customer_ip_address );
188
- // Base fallback
189
- if ( empty( $location['country'] ) ) {
190
- $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
191
- }
192
- $customer_country = ( isset( $location['country'] ) ) ? $location['country'] : '';
193
- } else {
194
- $customer_country = '';
195
- }
196
-
197
- // Customer EU VAT number
198
- $customer_eu_vat_number = get_post_meta( $order_id, '_billing_eu_vat_number', true );
199
- if ( '' == $customer_eu_vat_number ) {
200
- $customer_eu_vat_number = '-';
201
- }
202
-
203
- // Taxes
204
- $taxes = '';
205
- $taxes_array = $_order->get_tax_totals();
206
- if ( empty( $taxes_array ) ) {
207
- $taxes = '-';
208
- } else {
209
- foreach ( $taxes_array as $tax ) {
210
- $taxes .= $tax->label . ': ' . $tax->formatted_amount . '<br>';
211
- }
212
- }
213
-
214
- // Results table
215
- $table_data = array(
216
- array(
217
- __( 'Customer IP', 'woocommerce-jetpack' ),
218
- $_customer_ip_address
219
- ),
220
- array(
221
- __( 'Country by IP', 'woocommerce-jetpack' ),
222
- wcj_get_country_flag_by_code( $customer_country ) . ' ' . wcj_get_country_name_by_code( $customer_country ) . ' [' . $customer_country . ']'
223
- ),
224
- array(
225
- __( 'Customer EU VAT Number', 'woocommerce-jetpack' ),
226
- $customer_eu_vat_number
227
- ),
228
- array(
229
- __( 'Taxes', 'woocommerce-jetpack' ),
230
- $taxes,
231
- ),
232
- );
233
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
234
- echo '<p>' . '<a href="' . add_query_arg( 'validate_vat_and_maybe_remove_taxes', $order_id ) . '">' .
235
- __( 'Validate VAT and remove taxes', 'woocommerce-jetpack' ) . '</a>' . '</p>';
236
- }
237
-
238
- /**
239
- * replace_eu_vat_number_in_address_formats.
240
- *
241
- * @version 2.5.2
242
- * @since 2.5.2
243
- */
244
- function replace_eu_vat_number_in_address_formats( $replacements, $args ) {
245
- $field_name = 'billing_' . $this->id;
246
- $replacements['{' . $field_name . '}'] = ( isset( $args[ $field_name ] ) ) ? $args[ $field_name ] : '';
247
- return $replacements;
248
- }
249
-
250
- /**
251
- * add_eu_vat_number_to_address_formats.
252
- *
253
- * @version 2.5.2
254
- * @since 2.5.2
255
- */
256
- function add_eu_vat_number_to_address_formats( $address_formats ) {
257
- $field_name = 'billing_' . $this->id;
258
- $modified_address_formats = array();
259
- foreach ( $address_formats as $country => $address_format ) {
260
- $modified_address_formats[ $country ] = $address_format . "\n{" . $field_name . '}';
261
- }
262
- return $modified_address_formats;
263
- }
264
-
265
- /**
266
- * add_eu_vat_number_to_my_account_billing_address.
267
- *
268
- * @version 2.5.2
269
- * @since 2.5.2
270
- */
271
- function add_eu_vat_number_to_my_account_billing_address( $fields, $customer_id, $name ) {
272
- if ( 'billing' === $name ) {
273
- $field_name = 'billing_' . $this->id;
274
- $fields[ $field_name ] = get_user_meta( $customer_id, $field_name, true );
275
- }
276
- return $fields;
277
- }
278
-
279
- /**
280
- * add_eu_vat_number_to_order_billing_address.
281
- *
282
- * @version 2.7.0
283
- * @since 2.5.2
284
- */
285
- function add_eu_vat_number_to_order_billing_address( $fields, $_order ) {
286
- $field_name = 'billing_' . $this->id;
287
- $fields[ $field_name ] = get_post_meta( wcj_get_order_id( $_order ), '_' . $field_name, true );
288
- return $fields;
289
- }
290
-
291
- /**
292
- * add_eu_vat_number_to_order_display.
293
- *
294
- * @version 3.2.2
295
- * @since 2.4.7
296
- */
297
- function add_eu_vat_number_to_order_display( $order ) {
298
- $order_id = wcj_get_order_id( $order );
299
- $html = '';
300
- $option_name = '_billing_' . $this->id;
301
- $the_eu_vat_number = get_post_meta( $order_id, $option_name, true );
302
- if ( '' != $the_eu_vat_number ) {
303
- $the_label = get_option( 'wcj_eu_vat_number_field_label', __( 'EU VAT Number', 'woocommerce-jetpack' ) );
304
- $html .= '<p>' . '<strong>' . $the_label . '</strong>: ' . $the_eu_vat_number . '</p>';
305
- }
306
- echo $html;
307
- }
308
-
309
- /**
310
- * create_eu_countries_vat_rates_tool.
311
- *
312
- * @version 2.3.10
313
- * @since 2.3.10
314
- */
315
- function create_eu_countries_vat_rates_tool() {
316
- return $this->eu_countries_vat_rates_tool->create_eu_countries_vat_rates_tool( $this->get_tool_header_html( 'eu_countries_vat_rates' ) );
317
- }
318
-
319
- /**
320
- * add_default_checkout_billing_eu_vat_number.
321
- *
322
- * @version 4.3.0
323
- */
324
- function add_default_checkout_billing_eu_vat_number( $default_value, $field_key ) {
325
- if ( '' != ( $eu_vat_number_to_check = wcj_session_get( 'wcj_eu_vat_number_to_check' ) ) ) {
326
- return $eu_vat_number_to_check;
327
- } elseif ( is_user_logged_in() ) {
328
- $current_user = wp_get_current_user();
329
- if ( $meta = get_user_meta( $current_user->ID, 'billing_eu_vat_number', true ) ) {
330
- return $meta;
331
- }
332
- }
333
- return $default_value;
334
- }
335
-
336
- /**
337
- * add_eu_vat_number_customer_meta_field.
338
- */
339
- function add_eu_vat_number_customer_meta_field( $fields ) {
340
- $fields['billing']['fields']['billing_eu_vat_number'] = array(
341
- 'label' => get_option( 'wcj_eu_vat_number_field_label' ),
342
- 'description' => ''
343
- );
344
- return $fields;
345
- }
346
-
347
- /**
348
- * start_session.
349
- *
350
- * @version 4.9.0
351
- */
352
- function start_session() {
353
- if ( is_admin() ) {
354
- return;
355
- }
356
- wcj_session_maybe_start();
357
- $args = array();
358
- if ( isset( $_POST['post_data'] ) ) {
359
- parse_str( $_POST['post_data'], $args );
360
- if ( isset( $args['billing_eu_vat_number'] ) && wcj_session_get( 'wcj_eu_vat_number_to_check' ) != $args['billing_eu_vat_number'] ) {
361
- wcj_session_set( 'wcj_is_eu_vat_number_valid', null );
362
- wcj_session_set( 'wcj_eu_vat_number_to_check', null );
363
- }
364
- }
365
- }
366
-
367
- /**
368
- * restrictive_loading_valid.
369
- *
370
- * @version 4.9.0
371
- * @since 4.9.0
372
- *
373
- * @return bool
374
- */
375
- function restrictive_loading_valid() {
376
- if ( empty( $restrictive_loading_conditions = get_option( 'wcj_eu_vat_number_restrictive_loading', array() ) ) ) {
377
- return true;
378
- }
379
- foreach ( $restrictive_loading_conditions as $condition ) {
380
- if ( $condition() ) {
381
- return true;
382
- }
383
- }
384
- return false;
385
- }
386
-
387
- /**
388
- * enqueue_scripts.
389
- *
390
- * @version 4.9.0
391
- */
392
- function enqueue_scripts() {
393
- if (
394
- 'no' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ||
395
- ! $this->restrictive_loading_valid()
396
- ) {
397
- return;
398
- }
399
- wp_enqueue_script( 'wcj-eu-vat-number', wcj_plugin_url() . '/includes/js/wcj-eu-vat-number.js', array(), WCJ()->version, true );
400
- wp_localize_script( 'wcj-eu-vat-number', 'ajax_object', array(
401
- 'ajax_url' => admin_url( 'admin-ajax.php' ),
402
- 'eu_countries' => wcj_get_european_union_countries(),
403
- 'show_vat_field_for_eu_only' => get_option( 'wcj_eu_vat_number_show_vat_field_for_eu_only', 'no' ),
404
- 'add_progress_text' => get_option( 'wcj_eu_vat_number_add_progress_text', 'no' ),
405
- 'progress_text_validating' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_validating', __( 'Validating VAT. Please wait...', 'woocommerce-jetpack' ) ) ),
406
- 'progress_text_valid' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_valid', __( 'VAT is valid.', 'woocommerce-jetpack' ) ) ),
407
- 'progress_text_not_valid' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_not_valid', __( 'VAT is not valid.', 'woocommerce-jetpack' ) ) ),
408
- 'progress_text_validation_failed' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_validation_failed', __( 'Validation failed. Please try again.', 'woocommerce-jetpack' ) ) ),
409
- ) );
410
- }
411
-
412
- /**
413
- * wcj_validate_eu_vat_number.
414
- *
415
- * @version 4.6.1
416
- */
417
- function wcj_validate_eu_vat_number( $param ) {
418
- $param = wp_parse_args( $param, array(
419
- 'wcj_eu_vat_number_to_check' => '',
420
- 'echo' => true
421
- ) );
422
- $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'] : '';
423
- $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;
424
- if ( ! empty( $eu_vat_number ) ) {
425
- $eu_vat_number_to_check = substr( $eu_vat_number, 2 );
426
- $eu_vat_number_country_to_check = substr( $eu_vat_number, 0, 2 );
427
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_eu_vat_number_check_ip_location_country', 'no' ) ) ) {
428
- $location = WC_Geolocation::geolocate_ip();
429
- if ( empty( $location['country'] ) ) {
430
- $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
431
- }
432
- $is_valid = ( $location['country'] === $eu_vat_number_country_to_check ) ?
433
- wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check ) :
434
- false;
435
- } else {
436
- $is_valid = wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check );
437
- }
438
- } else {
439
- $is_valid = null;
440
- }
441
- wcj_session_set( 'wcj_is_eu_vat_number_valid', $is_valid );
442
- wcj_session_set( 'wcj_eu_vat_number_to_check', $eu_vat_number );
443
- $response = '3';
444
- if ( false === $is_valid ) {
445
- $response = '0';
446
- } elseif ( true === $is_valid ) {
447
- $response = '1';
448
- } elseif ( null === $is_valid ) {
449
- $response = '2';
450
- }
451
- if ( $param['echo'] ) {
452
- wp_send_json( array( 'result' => $response ) );
453
- } else {
454
- return $response;
455
- }
456
- }
457
-
458
- /**
459
- * need_to_exclude_vat.
460
- *
461
- * @version 4.7.1
462
- * @since 4.6.0
463
- *
464
- * @return bool
465
- */
466
- function need_to_exclude_vat() {
467
- if (
468
- (
469
- ( function_exists( 'is_checkout' ) && is_checkout() ) ||
470
- ( function_exists( 'is_cart' ) && is_cart() ) ||
471
- defined( 'WOOCOMMERCE_CHECKOUT' ) || defined( 'WOOCOMMERCE_CART' ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX )
472
- ) &&
473
- ! empty( WC()->customer ) &&
474
- 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) &&
475
- 'yes' === get_option( 'wcj_eu_vat_number_disable_for_valid', 'yes' ) &&
476
- (
477
- ( true === wcj_session_get( 'wcj_is_eu_vat_number_valid' ) && null !== ( $eu_vat_number = wcj_session_get( 'wcj_eu_vat_number_to_check' ) ) ) ||
478
- ( 'yes' === 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 ) ) )
479
- )
480
- ) {
481
- $preserve_base_country_check_passed = true;
482
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_eu_vat_number_preserve_in_base_country', 'no' ) ) ) {
483
- $location = wc_get_base_location();
484
- if ( empty( $location['country'] ) ) {
485
- $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
486
- }
487
- $selected_country = substr( $eu_vat_number, 0, 2 );
488
- if ( 'EL' === $selected_country ) {
489
- $selected_country = 'GR';
490
- }
491
- $preserve_base_country_check_passed = ( strtoupper( $location['country'] ) !== strtoupper( $selected_country ) );
492
- }
493
- if ( $preserve_base_country_check_passed ) {
494
- return true;
495
- } else {
496
- return false;
497
- }
498
- } else {
499
- if ( ! function_exists( 'WC' ) || ! empty( WC()->customer ) ) {
500
- return false;
501
- }
502
- }
503
- return false;
504
- }
505
-
506
- /**
507
- * maybe_exclude_vat.
508
- *
509
- * @version 4.6.0
510
- */
511
- function maybe_exclude_vat() {
512
- if ( $this->need_to_exclude_vat() ) {
513
- WC()->customer->set_is_vat_exempt( true );
514
- } else {
515
- if ( ! empty( WC()->customer ) ) {
516
- WC()->customer->set_is_vat_exempt( false );
517
- }
518
- }
519
- }
520
-
521
- /**
522
- * checkout_validate_vat.
523
- *
524
- * @version 4.6.1
525
- */
526
- function checkout_validate_vat( $_posted ) {
527
- if ( 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) {
528
- if (
529
- ( 'yes' === get_option( 'wcj_eu_vat_number_field_required', 'no' ) && '' == $_posted['billing_eu_vat_number'] ) ||
530
- (
531
- '' != $_posted['billing_eu_vat_number'] ) &&
532
- '1' !== $this->wcj_validate_eu_vat_number( array( 'wcj_eu_vat_number_to_check' => $_posted['billing_eu_vat_number'], 'echo' => false )
533
- )
534
- ) {
535
- wc_add_notice(
536
- get_option( 'wcj_eu_vat_number_not_valid_message', __( '<strong>EU VAT Number</strong> is not valid.', 'woocommerce-jetpack' ) ),
537
- 'error'
538
- );
539
- }
540
- }
541
- }
542
-
543
- /**
544
- * add_billing_eu_vat_number_field_to_admin_order_display.
545
- *
546
- * @version 4.6.0
547
- */
548
- function add_billing_eu_vat_number_field_to_admin_order_display( $fields ) {
549
- $vat_number = '';
550
-
551
- $fields[ $this->id ] = array(
552
- 'type' => 'text',
553
- 'label' => get_option( 'wcj_eu_vat_number_field_label' ),
554
- 'show' => true
555
- );
556
-
557
- // Try to read meta from 'vat_number' if '_billing_eu_vat_number' is empty
558
- if ( 'yes' === get_option( 'wcj_eu_vat_number_read_vat_number_meta', 'no' ) ) {
559
- global $post;
560
- $order = wc_get_order( $post->ID );
561
- if ( is_a( $order, 'WC_Order' ) ) {
562
- $metas = array( '_billing_eu_vat_number', '_vat_number', '_billing_vat_number' );
563
- foreach ( $metas as $meta ) {
564
- $vat_number = get_post_meta( $order->get_id(), $meta, true );
565
- if ( ! empty( $vat_number ) ) {
566
- break;
567
- }
568
- }
569
- $fields[ $this->id ]['value'] = $vat_number;
570
- }
571
- }
572
-
573
- return $fields;
574
- }
575
-
576
- /**
577
- * add_eu_vat_number_checkout_field_to_frontend.
578
- *
579
- * @version 3.9.0
580
- */
581
- function add_eu_vat_number_checkout_field_to_frontend( $fields ) {
582
- $fields['billing'][ 'billing_' . $this->id ] = array(
583
- 'type' => 'text',
584
- 'label' => get_option( 'wcj_eu_vat_number_field_label' ),
585
- 'description' => get_option( 'wcj_eu_vat_number_field_description' ),
586
- 'placeholder' => get_option( 'wcj_eu_vat_number_field_placeholder' ),
587
- 'required' => ( 'yes' === get_option( 'wcj_eu_vat_number_field_required', 'no' ) ),
588
- 'custom_attributes' => array(),
589
- 'clear' => ( 'yes' === get_option( 'wcj_eu_vat_number_field_clear', 'yes' ) ),
590
- 'class' => array( get_option( 'wcj_eu_vat_number_field_class', 'form-row-wide' ) ),
591
- 'validate' => ( 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) ? array( 'eu-vat-number' ) : array(),
592
- );
593
- return $fields;
594
- }
595
-
596
- }
597
-
598
- endif;
599
-
600
- return new WCJ_EU_VAT_Number();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - EU VAT Number
4
+ *
5
+ * @version 4.9.0
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 4.7.1
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.', 'woocommerce-jetpack' );
27
+ $this->link_slug = 'woocommerce-eu-vat-number';
28
+ parent::__construct();
29
+
30
+ $this->add_tools( array(
31
+ 'eu_countries_vat_rates' => array(
32
+ 'title' => __( 'EU Countries VAT Rates', 'woocommerce-jetpack' ),
33
+ 'desc' => __( 'Add all EU countries VAT standard rates to WooCommerce.', 'woocommerce-jetpack' ),
34
+ ),
35
+ ) );
36
+
37
+ if ( $this->is_enabled() ) {
38
+ add_action( 'init', array( $this, 'start_session' ) );
39
+ add_filter( 'woocommerce_checkout_fields', array( $this, 'add_eu_vat_number_checkout_field_to_frontend' ), PHP_INT_MAX );
40
+ add_filter( 'woocommerce_admin_billing_fields', array( $this, 'add_billing_eu_vat_number_field_to_admin_order_display' ), PHP_INT_MAX );
41
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
42
+ add_action( 'wp_ajax_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
43
+ add_action( 'wp_ajax_nopriv_wcj_validate_eu_vat_number', array( $this, 'wcj_validate_eu_vat_number' ) );
44
+ add_filter( 'wp', array( $this, 'maybe_exclude_vat' ), PHP_INT_MAX );
45
+ add_filter( 'woocommerce_cart_tax_totals', array( $this, 'maybe_remove_tax_totals' ), 1 );
46
+ add_filter( 'woocommerce_calculated_total', array( $this, 'maybe_recalculate_tax_totals' ), 1, 2 );
47
+ add_action( 'woocommerce_after_checkout_validation', array( $this, 'checkout_validate_vat' ), PHP_INT_MAX );
48
+ add_filter( 'woocommerce_customer_meta_fields', array( $this, 'add_eu_vat_number_customer_meta_field' ) );
49
+ add_filter( 'default_checkout_billing_eu_vat_number', array( $this, 'add_default_checkout_billing_eu_vat_number' ), PHP_INT_MAX, 2 );
50
+
51
+ if ( 'after_order_table' === get_option( 'wcj_eu_vat_number_display_position', 'after_order_table' ) ) {
52
+ add_action( 'woocommerce_order_details_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
53
+ add_action( 'woocommerce_email_after_order_table', array( $this, 'add_eu_vat_number_to_order_display' ), PHP_INT_MAX );
54
+ } else {
55
+ add_filter( 'woocommerce_order_formatted_billing_address', array( $this, 'add_eu_vat_number_to_order_billing_address' ), PHP_INT_MAX, 2 );
56
+ add_filter( 'woocommerce_my_account_my_address_formatted_address', array( $this, 'add_eu_vat_number_to_my_account_billing_address' ), PHP_INT_MAX, 3 );
57
+ add_filter( 'woocommerce_localisation_address_formats', array( $this, 'add_eu_vat_number_to_address_formats' ) );
58
+ add_filter( 'woocommerce_formatted_address_replacements', array( $this, 'replace_eu_vat_number_in_address_formats' ), PHP_INT_MAX, 2 );
59
+ }
60
+
61
+ $this->eu_countries_vat_rates_tool = include_once( 'tools/class-wcj-eu-countries-vat-rates-tool.php' );
62
+
63
+ // EU VAT number summary on order edit page
64
+ if ( 'yes' === get_option( 'wcj_eu_vat_number_add_order_edit_metabox', 'no' ) ) {
65
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
66
+ // "Validate VAT and remove taxes" button
67
+ add_action( 'admin_init', array( $this, 'admin_validate_vat_and_maybe_remove_taxes' ), PHP_INT_MAX );
68
+ }
69
+
70
+ // Admin order edit - "Load billing address" button
71
+ add_filter( 'woocommerce_ajax_get_customer_details', array( $this, 'add_billing_eu_vat_number_to_ajax_get_customer_details' ), PHP_INT_MAX, 3 );
72
+ }
73
+ }
74
+
75
+ /**
76
+ * maybe_recalculate_tax_totals.
77
+ *
78
+ * @version 4.6.0
79
+ * @since 4.6.0
80
+ *
81
+ * @see https://gist.github.com/TimBHowe/fe9418b9224d8b8cb339
82
+ * @param $total
83
+ * @param $cart
84
+ *
85
+ * @return mixed
86
+ */
87
+ function maybe_recalculate_tax_totals( $total, $cart ) {
88
+ if ( 'yes' === get_option( 'wcj_eu_vat_number_disable_for_valid_on_cart', 'no' ) && $this->need_to_exclude_vat() ) {
89
+ return $total - $cart->get_taxes_total();
90
+ }
91
+ return $total;
92
+ }
93
+
94
+ /**
95
+ * maybe_remove_tax_totals.
96
+ *
97
+ * @version 4.6.0
98
+ * @since 4.6.0
99
+ *
100
+ * @see https://gist.github.com/TimBHowe/fe9418b9224d8b8cb339
101
+ * @param $tax_totals
102
+ *
103
+ * @return array
104
+ */
105
+ function maybe_remove_tax_totals( $tax_totals ) {
106
+ if ( 'yes' === get_option( 'wcj_eu_vat_number_disable_for_valid_on_cart', 'no' ) && $this->need_to_exclude_vat() ) {
107
+ $tax_totals = array();
108
+ }
109
+ return $tax_totals;
110
+ }
111
+
112
+ /**
113
+ * admin_validate_vat_and_maybe_remove_taxes.
114
+ *
115
+ * @version 3.3.0
116
+ * @since 3.3.0
117
+ */
118
+ function admin_validate_vat_and_maybe_remove_taxes() {
119
+ if ( isset( $_GET['validate_vat_and_maybe_remove_taxes'] ) ) {
120
+ $order_id = $_GET['validate_vat_and_maybe_remove_taxes'];
121
+ $order = wc_get_order( $order_id );
122
+ if ( $order ) {
123
+ $vat_id = get_post_meta( $order_id, '_billing_eu_vat_number', true );
124
+ if ( '' != $vat_id && strlen( $vat_id ) > 2 ) {
125
+ if ( wcj_validate_vat( substr( $vat_id, 0, 2 ), substr( $vat_id, 2 ) ) ) {
126
+ foreach ( $order->get_items( array( 'line_item', 'fee' ) ) as $item_id => $item ) {
127
+ $item->set_taxes( false );
128
+ }
129
+ foreach ( $order->get_shipping_methods() as $item_id => $item ) {
130
+ $item->set_taxes( false );
131
+ }
132
+ $order->update_taxes();
133
+ $order->calculate_totals( false );
134
+ }
135
+ }
136
+ }
137
+ wp_safe_redirect( remove_query_arg( 'validate_vat_and_maybe_remove_taxes' ) );
138
+ exit;
139
+ }
140
+ }
141
+
142
+ /**
143
+ * add_billing_eu_vat_number_to_ajax_get_customer_details.
144
+ *
145
+ * @version 3.3.0
146
+ * @since 3.3.0
147
+ */
148
+ function add_billing_eu_vat_number_to_ajax_get_customer_details( $data, $customer, $user_id ) {
149
+ $data['billing']['eu_vat_number'] = get_user_meta( $user_id, 'billing_eu_vat_number', true );
150
+ return $data;
151
+ }
152
+
153
+ /**
154
+ * add_meta_box.
155
+ *
156
+ * @version 2.6.0
157
+ * @since 2.6.0
158
+ */
159
+ function add_meta_box() {
160
+ $screen = ( isset( $this->meta_box_screen ) ) ? $this->meta_box_screen : 'shop_order';
161
+ $context = ( isset( $this->meta_box_context ) ) ? $this->meta_box_context : 'side';
162
+ $priority = ( isset( $this->meta_box_priority ) ) ? $this->meta_box_priority : 'low';
163
+ add_meta_box(
164
+ 'wc-jetpack-' . $this->id,
165
+ __( 'Booster', 'woocommerce-jetpack' ) . ': ' . $this->short_desc,
166
+ array( $this, 'create_meta_box' ),
167
+ $screen,
168
+ $context,
169
+ $priority
170
+ );
171
+ }
172
+
173
+ /**
174
+ * create_meta_box.
175
+ *
176
+ * @version 3.3.0
177
+ * @since 2.6.0
178
+ */
179
+ function create_meta_box() {
180
+ $order_id = get_the_ID();
181
+ $_order = wc_get_order( $order_id );
182
+ $_customer_ip_address = ( WCJ_IS_WC_VERSION_BELOW_3 ? $_order->customer_ip_address : $_order->get_customer_ip_address() );
183
+
184
+ // Country by IP
185
+ if ( class_exists( 'WC_Geolocation' ) ) {
186
+ // Get the country by IP
187
+ $location = WC_Geolocation::geolocate_ip( $_customer_ip_address );
188
+ // Base fallback
189
+ if ( empty( $location['country'] ) ) {
190
+ $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
191
+ }
192
+ $customer_country = ( isset( $location['country'] ) ) ? $location['country'] : '';
193
+ } else {
194
+ $customer_country = '';
195
+ }
196
+
197
+ // Customer EU VAT number
198
+ $customer_eu_vat_number = get_post_meta( $order_id, '_billing_eu_vat_number', true );
199
+ if ( '' == $customer_eu_vat_number ) {
200
+ $customer_eu_vat_number = '-';
201
+ }
202
+
203
+ // Taxes
204
+ $taxes = '';
205
+ $taxes_array = $_order->get_tax_totals();
206
+ if ( empty( $taxes_array ) ) {
207
+ $taxes = '-';
208
+ } else {
209
+ foreach ( $taxes_array as $tax ) {
210
+ $taxes .= $tax->label . ': ' . $tax->formatted_amount . '<br>';
211
+ }
212
+ }
213
+
214
+ // Results table
215
+ $table_data = array(
216
+ array(
217
+ __( 'Customer IP', 'woocommerce-jetpack' ),
218
+ $_customer_ip_address
219
+ ),
220
+ array(
221
+ __( 'Country by IP', 'woocommerce-jetpack' ),
222
+ wcj_get_country_flag_by_code( $customer_country ) . ' ' . wcj_get_country_name_by_code( $customer_country ) . ' [' . $customer_country . ']'
223
+ ),
224
+ array(
225
+ __( 'Customer EU VAT Number', 'woocommerce-jetpack' ),
226
+ $customer_eu_vat_number
227
+ ),
228
+ array(
229
+ __( 'Taxes', 'woocommerce-jetpack' ),
230
+ $taxes,
231
+ ),
232
+ );
233
+ echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
234
+ echo '<p>' . '<a href="' . add_query_arg( 'validate_vat_and_maybe_remove_taxes', $order_id ) . '">' .
235
+ __( 'Validate VAT and remove taxes', 'woocommerce-jetpack' ) . '</a>' . '</p>';
236
+ }
237
+
238
+ /**
239
+ * replace_eu_vat_number_in_address_formats.
240
+ *
241
+ * @version 2.5.2
242
+ * @since 2.5.2
243
+ */
244
+ function replace_eu_vat_number_in_address_formats( $replacements, $args ) {
245
+ $field_name = 'billing_' . $this->id;
246
+ $replacements['{' . $field_name . '}'] = ( isset( $args[ $field_name ] ) ) ? $args[ $field_name ] : '';
247
+ return $replacements;
248
+ }
249
+
250
+ /**
251
+ * add_eu_vat_number_to_address_formats.
252
+ *
253
+ * @version 2.5.2
254
+ * @since 2.5.2
255
+ */
256
+ function add_eu_vat_number_to_address_formats( $address_formats ) {
257
+ $field_name = 'billing_' . $this->id;
258
+ $modified_address_formats = array();
259
+ foreach ( $address_formats as $country => $address_format ) {
260
+ $modified_address_formats[ $country ] = $address_format . "\n{" . $field_name . '}';
261
+ }
262
+ return $modified_address_formats;
263
+ }
264
+
265
+ /**
266
+ * add_eu_vat_number_to_my_account_billing_address.
267
+ *
268
+ * @version 2.5.2
269
+ * @since 2.5.2
270
+ */
271
+ function add_eu_vat_number_to_my_account_billing_address( $fields, $customer_id, $name ) {
272
+ if ( 'billing' === $name ) {
273
+ $field_name = 'billing_' . $this->id;
274
+ $fields[ $field_name ] = get_user_meta( $customer_id, $field_name, true );
275
+ }
276
+ return $fields;
277
+ }
278
+
279
+ /**
280
+ * add_eu_vat_number_to_order_billing_address.
281
+ *
282
+ * @version 2.7.0
283
+ * @since 2.5.2
284
+ */
285
+ function add_eu_vat_number_to_order_billing_address( $fields, $_order ) {
286
+ $field_name = 'billing_' . $this->id;
287
+ $fields[ $field_name ] = get_post_meta( wcj_get_order_id( $_order ), '_' . $field_name, true );
288
+ return $fields;
289
+ }
290
+
291
+ /**
292
+ * add_eu_vat_number_to_order_display.
293
+ *
294
+ * @version 3.2.2
295
+ * @since 2.4.7
296
+ */
297
+ function add_eu_vat_number_to_order_display( $order ) {
298
+ $order_id = wcj_get_order_id( $order );
299
+ $html = '';
300
+ $option_name = '_billing_' . $this->id;
301
+ $the_eu_vat_number = get_post_meta( $order_id, $option_name, true );
302
+ if ( '' != $the_eu_vat_number ) {
303
+ $the_label = get_option( 'wcj_eu_vat_number_field_label', __( 'EU VAT Number', 'woocommerce-jetpack' ) );
304
+ $html .= '<p>' . '<strong>' . $the_label . '</strong>: ' . $the_eu_vat_number . '</p>';
305
+ }
306
+ echo $html;
307
+ }
308
+
309
+ /**
310
+ * create_eu_countries_vat_rates_tool.
311
+ *
312
+ * @version 2.3.10
313
+ * @since 2.3.10
314
+ */
315
+ function create_eu_countries_vat_rates_tool() {
316
+ return $this->eu_countries_vat_rates_tool->create_eu_countries_vat_rates_tool( $this->get_tool_header_html( 'eu_countries_vat_rates' ) );
317
+ }
318
+
319
+ /**
320
+ * add_default_checkout_billing_eu_vat_number.
321
+ *
322
+ * @version 4.3.0
323
+ */
324
+ function add_default_checkout_billing_eu_vat_number( $default_value, $field_key ) {
325
+ if ( '' != ( $eu_vat_number_to_check = wcj_session_get( 'wcj_eu_vat_number_to_check' ) ) ) {
326
+ return $eu_vat_number_to_check;
327
+ } elseif ( is_user_logged_in() ) {
328
+ $current_user = wp_get_current_user();
329
+ if ( $meta = get_user_meta( $current_user->ID, 'billing_eu_vat_number', true ) ) {
330
+ return $meta;
331
+ }
332
+ }
333
+ return $default_value;
334
+ }
335
+
336
+ /**
337
+ * add_eu_vat_number_customer_meta_field.
338
+ */
339
+ function add_eu_vat_number_customer_meta_field( $fields ) {
340
+ $fields['billing']['fields']['billing_eu_vat_number'] = array(
341
+ 'label' => get_option( 'wcj_eu_vat_number_field_label' ),
342
+ 'description' => ''
343
+ );
344
+ return $fields;
345
+ }
346
+
347
+ /**
348
+ * start_session.
349
+ *
350
+ * @version 4.9.0
351
+ */
352
+ function start_session() {
353
+ if ( is_admin() ) {
354
+ return;
355
+ }
356
+ wcj_session_maybe_start();
357
+ $args = array();
358
+ if ( isset( $_POST['post_data'] ) ) {
359
+ parse_str( $_POST['post_data'], $args );
360
+ if ( isset( $args['billing_eu_vat_number'] ) && wcj_session_get( 'wcj_eu_vat_number_to_check' ) != $args['billing_eu_vat_number'] ) {
361
+ wcj_session_set( 'wcj_is_eu_vat_number_valid', null );
362
+ wcj_session_set( 'wcj_eu_vat_number_to_check', null );
363
+ }
364
+ }
365
+ }
366
+
367
+ /**
368
+ * restrictive_loading_valid.
369
+ *
370
+ * @version 4.9.0
371
+ * @since 4.9.0
372
+ *
373
+ * @return bool
374
+ */
375
+ function restrictive_loading_valid() {
376
+ if ( empty( $restrictive_loading_conditions = get_option( 'wcj_eu_vat_number_restrictive_loading', array() ) ) ) {
377
+ return true;
378
+ }
379
+ foreach ( $restrictive_loading_conditions as $condition ) {
380
+ if ( $condition() ) {
381
+ return true;
382
+ }
383
+ }
384
+ return false;
385
+ }
386
+
387
+ /**
388
+ * enqueue_scripts.
389
+ *
390
+ * @version 4.9.0
391
+ */
392
+ function enqueue_scripts() {
393
+ if (
394
+ 'no' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ||
395
+ ! $this->restrictive_loading_valid()
396
+ ) {
397
+ return;
398
+ }
399
+ wp_enqueue_script( 'wcj-eu-vat-number', wcj_plugin_url() . '/includes/js/wcj-eu-vat-number.js', array(), WCJ()->version, true );
400
+ wp_localize_script( 'wcj-eu-vat-number', 'ajax_object', array(
401
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
402
+ 'eu_countries' => wcj_get_european_union_countries(),
403
+ 'show_vat_field_for_eu_only' => get_option( 'wcj_eu_vat_number_show_vat_field_for_eu_only', 'no' ),
404
+ 'add_progress_text' => get_option( 'wcj_eu_vat_number_add_progress_text', 'no' ),
405
+ 'progress_text_validating' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_validating', __( 'Validating VAT. Please wait...', 'woocommerce-jetpack' ) ) ),
406
+ 'progress_text_valid' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_valid', __( 'VAT is valid.', 'woocommerce-jetpack' ) ) ),
407
+ 'progress_text_not_valid' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_not_valid', __( 'VAT is not valid.', 'woocommerce-jetpack' ) ) ),
408
+ 'progress_text_validation_failed' => do_shortcode( get_option( 'wcj_eu_vat_number_progress_text_validation_failed', __( 'Validation failed. Please try again.', 'woocommerce-jetpack' ) ) ),
409
+ ) );
410
+ }
411
+
412
+ /**
413
+ * wcj_validate_eu_vat_number.
414
+ *
415
+ * @version 4.6.1
416
+ */
417
+ function wcj_validate_eu_vat_number( $param ) {
418
+ $param = wp_parse_args( $param, array(
419
+ 'wcj_eu_vat_number_to_check' => '',
420
+ 'echo' => true
421
+ ) );
422
+ $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'] : '';
423
+ $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;
424
+ if ( ! empty( $eu_vat_number ) ) {
425
+ $eu_vat_number_to_check = substr( $eu_vat_number, 2 );
426
+ $eu_vat_number_country_to_check = substr( $eu_vat_number, 0, 2 );
427
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_eu_vat_number_check_ip_location_country', 'no' ) ) ) {
428
+ $location = WC_Geolocation::geolocate_ip();
429
+ if ( empty( $location['country'] ) ) {
430
+ $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
431
+ }
432
+ $is_valid = ( $location['country'] === $eu_vat_number_country_to_check ) ?
433
+ wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check ) :
434
+ false;
435
+ } else {
436
+ $is_valid = wcj_validate_vat( $eu_vat_number_country_to_check, $eu_vat_number_to_check );
437
+ }
438
+ } else {
439
+ $is_valid = null;
440
+ }
441
+ wcj_session_set( 'wcj_is_eu_vat_number_valid', $is_valid );
442
+ wcj_session_set( 'wcj_eu_vat_number_to_check', $eu_vat_number );
443
+ $response = '3';
444
+ if ( false === $is_valid ) {
445
+ $response = '0';
446
+ } elseif ( true === $is_valid ) {
447
+ $response = '1';
448
+ } elseif ( null === $is_valid ) {
449
+ $response = '2';
450
+ }
451
+ if ( $param['echo'] ) {
452
+ wp_send_json( array( 'result' => $response ) );
453
+ } else {
454
+ return $response;
455
+ }
456
+ }
457
+
458
+ /**
459
+ * need_to_exclude_vat.
460
+ *
461
+ * @version 4.7.1
462
+ * @since 4.6.0
463
+ *
464
+ * @return bool
465
+ */
466
+ function need_to_exclude_vat() {
467
+ if (
468
+ (
469
+ ( function_exists( 'is_checkout' ) && is_checkout() ) ||
470
+ ( function_exists( 'is_cart' ) && is_cart() ) ||
471
+ defined( 'WOOCOMMERCE_CHECKOUT' ) || defined( 'WOOCOMMERCE_CART' ) || ( defined( 'DOING_AJAX' ) && DOING_AJAX )
472
+ ) &&
473
+ ! empty( WC()->customer ) &&
474
+ 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) &&
475
+ 'yes' === get_option( 'wcj_eu_vat_number_disable_for_valid', 'yes' ) &&
476
+ (
477
+ ( true === wcj_session_get( 'wcj_is_eu_vat_number_valid' ) && null !== ( $eu_vat_number = wcj_session_get( 'wcj_eu_vat_number_to_check' ) ) ) ||
478
+ ( 'yes' === 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 ) ) )
479
+ )
480
+ ) {
481
+ $preserve_base_country_check_passed = true;
482
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_eu_vat_number_preserve_in_base_country', 'no' ) ) ) {
483
+ $location = wc_get_base_location();
484
+ if ( empty( $location['country'] ) ) {
485
+ $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
486
+ }
487
+ $selected_country = substr( $eu_vat_number, 0, 2 );
488
+ if ( 'EL' === $selected_country ) {
489
+ $selected_country = 'GR';
490
+ }
491
+ $preserve_base_country_check_passed = ( strtoupper( $location['country'] ) !== strtoupper( $selected_country ) );
492
+ }
493
+ if ( $preserve_base_country_check_passed ) {
494
+ return true;
495
+ } else {
496
+ return false;
497
+ }
498
+ } else {
499
+ if ( ! function_exists( 'WC' ) || ! empty( WC()->customer ) ) {
500
+ return false;
501
+ }
502
+ }
503
+ return false;
504
+ }
505
+
506
+ /**
507
+ * maybe_exclude_vat.
508
+ *
509
+ * @version 4.6.0
510
+ */
511
+ function maybe_exclude_vat() {
512
+ if ( $this->need_to_exclude_vat() ) {
513
+ WC()->customer->set_is_vat_exempt( true );
514
+ } else {
515
+ if ( ! empty( WC()->customer ) ) {
516
+ WC()->customer->set_is_vat_exempt( false );
517
+ }
518
+ }
519
+ }
520
+
521
+ /**
522
+ * checkout_validate_vat.
523
+ *
524
+ * @version 4.6.1
525
+ */
526
+ function checkout_validate_vat( $_posted ) {
527
+ if ( 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) {
528
+ if (
529
+ ( 'yes' === get_option( 'wcj_eu_vat_number_field_required', 'no' ) && '' == $_posted['billing_eu_vat_number'] ) ||
530
+ (
531
+ '' != $_posted['billing_eu_vat_number'] ) &&
532
+ '1' !== $this->wcj_validate_eu_vat_number( array( 'wcj_eu_vat_number_to_check' => $_posted['billing_eu_vat_number'], 'echo' => false )
533
+ )
534
+ ) {
535
+ wc_add_notice(
536
+ get_option( 'wcj_eu_vat_number_not_valid_message', __( '<strong>EU VAT Number</strong> is not valid.', 'woocommerce-jetpack' ) ),
537
+ 'error'
538
+ );
539
+ }
540
+ }
541
+ }
542
+
543
+ /**
544
+ * add_billing_eu_vat_number_field_to_admin_order_display.
545
+ *
546
+ * @version 4.6.0
547
+ */
548
+ function add_billing_eu_vat_number_field_to_admin_order_display( $fields ) {
549
+ $vat_number = '';
550
+
551
+ $fields[ $this->id ] = array(
552
+ 'type' => 'text',
553
+ 'label' => get_option( 'wcj_eu_vat_number_field_label' ),
554
+ 'show' => true
555
+ );
556
+
557
+ // Try to read meta from 'vat_number' if '_billing_eu_vat_number' is empty
558
+ if ( 'yes' === get_option( 'wcj_eu_vat_number_read_vat_number_meta', 'no' ) ) {
559
+ global $post;
560
+ $order = wc_get_order( $post->ID );
561
+ if ( is_a( $order, 'WC_Order' ) ) {
562
+ $metas = array( '_billing_eu_vat_number', '_vat_number', '_billing_vat_number' );
563
+ foreach ( $metas as $meta ) {
564
+ $vat_number = get_post_meta( $order->get_id(), $meta, true );
565
+ if ( ! empty( $vat_number ) ) {
566
+ break;
567
+ }
568
+ }
569
+ $fields[ $this->id ]['value'] = $vat_number;
570
+ }
571
+ }
572
+
573
+ return $fields;
574
+ }
575
+
576
+ /**
577
+ * add_eu_vat_number_checkout_field_to_frontend.
578
+ *
579
+ * @version 3.9.0
580
+ */
581
+ function add_eu_vat_number_checkout_field_to_frontend( $fields ) {
582
+ $fields['billing'][ 'billing_' . $this->id ] = array(
583
+ 'type' => 'text',
584
+ 'label' => get_option( 'wcj_eu_vat_number_field_label' ),
585
+ 'description' => get_option( 'wcj_eu_vat_number_field_description' ),
586
+ 'placeholder' => get_option( 'wcj_eu_vat_number_field_placeholder' ),
587
+ 'required' => ( 'yes' === get_option( 'wcj_eu_vat_number_field_required', 'no' ) ),
588
+ 'custom_attributes' => array(),
589
+ 'clear' => ( 'yes' === get_option( 'wcj_eu_vat_number_field_clear', 'yes' ) ),
590
+ 'class' => array( get_option( 'wcj_eu_vat_number_field_class', 'form-row-wide' ) ),
591
+ 'validate' => ( 'yes' === get_option( 'wcj_eu_vat_number_validate', 'yes' ) ) ? array( 'eu-vat-number' ) : array(),
592
+ );
593
+ return $fields;
594
+ }
595
+
596
+ }
597
+
598
+ endif;
599
+
600
+ return new WCJ_EU_VAT_Number();
includes/class-wcj-export-import.php CHANGED
@@ -1,339 +1,339 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Export
4
- *
5
- * @version 4.4.0
6
- * @since 2.5.4
7
- * @author Algoritmika Ltd.
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 2.8.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.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-export-tools';
29
- parent::__construct();
30
-
31
- $this->add_tools( array(
32
- 'export_customers' => array(
33
- 'title' => __( 'Export Customers', 'woocommerce-jetpack' ),
34
- 'desc' => __( 'Export Customers.', 'woocommerce-jetpack' ),
35
- ),
36
- 'export_customers_from_orders' => array(
37
- 'title' => __( 'Export Customers from Orders', 'woocommerce-jetpack' ),
38
- 'desc' => __( 'Export Customers (extracted from orders).', 'woocommerce-jetpack' ) . ' ' .
39
- __( 'Customers are identified by billing email.', 'woocommerce-jetpack' ),
40
- ),
41
- 'export_orders' => array(
42
- 'title' => __( 'Export Orders', 'woocommerce-jetpack' ),
43
- 'desc' => __( 'Export Orders.', 'woocommerce-jetpack' ),
44
- ),
45
- 'export_orders_items' => array(
46
- 'title' => __( 'Export Orders Items', 'woocommerce-jetpack' ),
47
- 'desc' => __( 'Export Orders Items.', 'woocommerce-jetpack' ),
48
- ),
49
- 'export_products' => array(
50
- 'title' => __( 'Export Products', 'woocommerce-jetpack' ),
51
- 'desc' => __( 'Export Products.', 'woocommerce-jetpack' ),
52
- ),
53
- ) );
54
-
55
- $this->fields_helper = require_once( 'export/class-wcj-fields-helper.php' );
56
-
57
- if ( $this->is_enabled() ) {
58
- add_action( 'init', array( $this, 'export_csv' ) );
59
- add_action( 'init', array( $this, 'export_xml' ) );
60
- }
61
- }
62
-
63
- /**
64
- * export.
65
- *
66
- * @version 2.5.9
67
- * @since 2.4.8
68
- * @todo [dev] when filtering now using `strpos`, but other options would be `stripos` (case-insensitive) or strict equality
69
- * @todo [dev] (maybe) do filtering directly in WP_Query
70
- */
71
- function export( $tool_id ) {
72
- $data = array();
73
- switch ( $tool_id ) {
74
- case 'customers':
75
- $exporter = require_once( 'export/class-wcj-exporter-customers.php' );
76
- $data = $exporter->export_customers( $this->fields_helper );
77
- break;
78
- case 'customers_from_orders':
79
- $exporter = require_once( 'export/class-wcj-exporter-customers.php' );
80
- $data = $exporter->export_customers_from_orders( $this->fields_helper );
81
- break;
82
- case 'orders':
83
- $exporter = require_once( 'export/class-wcj-exporter-orders.php' );
84
- $data = $exporter->export_orders( $this->fields_helper );
85
- break;
86
- case 'orders_items':
87
- $exporter = require_once( 'export/class-wcj-exporter-orders.php' );
88
- $data = $exporter->export_orders_items( $this->fields_helper );
89
- break;
90
- case 'products':
91
- $exporter = require_once( 'export/class-wcj-exporter-products.php' );
92
- $data = $exporter->export_products( $this->fields_helper );
93
- break;
94
- }
95
- if ( isset( $_POST['wcj_export_filter_all_columns'] ) && '' != $_POST['wcj_export_filter_all_columns'] ) {
96
- foreach ( $data as $row_id => $row ) {
97
- if ( 0 == $row_id ) {
98
- continue;
99
- }
100
- $is_filtered = false;
101
- foreach ( $row as $cell ) {
102
- if ( false !== strpos( $cell, $_POST['wcj_export_filter_all_columns'] ) ) {
103
- $is_filtered = true;
104
- break;
105
- }
106
- }
107
- if ( ! $is_filtered ) {
108
- unset( $data[ $row_id ] );
109
- }
110
- }
111
- }
112
- return $data;
113
- }
114
-
115
- /**
116
- * export_xml.
117
- *
118
- * @version 2.5.9
119
- * @since 2.5.9
120
- * @todo [dev] templates for xml_start, xml_end, xml_item.
121
- * @todo [dev] `strip_tags`
122
- */
123
- function export_xml() {
124
- if ( isset( $_POST['wcj_export_xml'] ) ) {
125
- $data = $this->export( $_POST['wcj_export_xml'] );
126
- if ( is_array( $data ) ) {
127
- $xml = '';
128
- $xml .= '<?xml version = "1.0" encoding = "utf-8" ?>' . PHP_EOL . '<root>' . PHP_EOL;
129
- foreach ( $data as $row_num => $row ) {
130
- if ( 0 == $row_num ) {
131
- foreach ( $row as $cell_id => $cell_value ) {
132
- $cell_ids[ $cell_id ] = sanitize_title_with_dashes( $cell_value );
133
- }
134
- continue;
135
- }
136
- $xml .= '<item>' . PHP_EOL;
137
- foreach ( $row as $cell_id => $cell_value ) {
138
- $xml .= "\t" . '<' . $cell_ids[ $cell_id ] . '>' . $cell_value . '</' . $cell_ids[ $cell_id ] . '>' . PHP_EOL;
139
- }
140
- $xml .= '</item>' . PHP_EOL;
141
- }
142
- $xml .= '</root>';
143
- header( "Content-Disposition: attachment; filename=" . $_POST['wcj_export_xml'] . ".xml" );
144
- header( "Content-Type: Content-Type: text/html; charset=utf-8" );
145
- header( "Content-Description: File Transfer" );
146
- header( "Content-Length: " . strlen( $xml ) );
147
- echo $xml;
148
- die();
149
- }
150
- }
151
- }
152
-
153
- /**
154
- * export_csv.
155
- *
156
- * @version 2.5.9
157
- * @since 2.4.8
158
- */
159
- function export_csv() {
160
- if ( isset( $_POST['wcj_export'] ) ) {
161
- $data = $this->export( $_POST['wcj_export'] );
162
- if ( is_array( $data ) ) {
163
- $csv = '';
164
- foreach ( $data as $row ) {
165
- $csv .= implode( get_option( 'wcj_export_csv_separator', ',' ), $row ) . PHP_EOL;
166
- }
167
- if ( 'yes' === get_option( 'wcj_export_csv_add_utf_8_bom', 'yes' ) ) {
168
- $csv = "\xEF\xBB\xBF" . $csv; // UTF-8 BOM
169
- }
170
- header( "Content-Disposition: attachment; filename=" . $_POST['wcj_export'] . ".csv" );
171
- header( "Content-Type: Content-Type: text/html; charset=utf-8" );
172
- header( "Content-Description: File Transfer" );
173
- header( "Content-Length: " . strlen( $csv ) );
174
- echo $csv;
175
- die();
176
- }
177
- }
178
- }
179
-
180
- /**
181
- * export_filter_fields.
182
- *
183
- * @version 2.5.9
184
- * @since 2.5.5
185
- * @todo [dev] filter each field separately
186
- */
187
- function export_filter_fields( $tool_id ) {
188
- $fields = array();
189
- switch ( $tool_id ) {
190
- case 'orders':
191
- $fields = array(
192
- 'wcj_filter_by_order_billing_country' => __( 'Filter by Billing Country', 'woocommerce-jetpack' ),
193
- 'wcj_filter_by_product_title' => __( 'Filter by Product Title', 'woocommerce-jetpack' ),
194
- );
195
- break;
196
- case 'orders_items':
197
- $fields = array(
198
- 'wcj_filter_by_order_billing_country' => __( 'Filter by Billing Country', 'woocommerce-jetpack' ),
199
- );
200
- break;
201
- }
202
- if ( ! empty( $fields ) ) {
203
- $data = array();
204
- foreach( $fields as $field_id => $field_desc ) {
205
- $field_value = ( isset( $_POST[ $field_id ] ) ) ? $_POST[ $field_id ] : '';
206
- $data[] = array(
207
- '<label for="' . $field_id . '">' . $field_desc . '</label>',
208
- '<input name="' . $field_id . '" id="' . $field_id . '" type="text" value="' . $field_value . '">',
209
- );
210
- }
211
- $data[] = array(
212
- '<button class="button-primary" type="submit" name="wcj_export_filter" value="' . $tool_id . '">' . __( 'Filter', 'woocommerce-jetpack' ) . '</button>',
213
- '',
214
- );
215
- return wcj_get_table_html( $data, array( 'table_class' => 'widefat', 'table_style' => 'width:50%;min-width:300px;', 'table_heading_type' => 'vertical' ) );
216
- }
217
- }
218
-
219
- /**
220
- * export_date_fields.
221
- *
222
- * @version 4.4.0
223
- * @since 3.0.0
224
- * @todo [dev] maybe make `$dateformat` optional
225
- * @todo [dev] mark current (i.e. active) link (if exists)
226
- */
227
- function export_date_fields( $tool_id ) {
228
- $current_start_date = ( isset( $_GET['start_date'] ) ? $_GET['start_date'] : '' );
229
- $current_end_date = ( isset( $_GET['end_date'] ) ? $_GET['end_date'] : '' );
230
- $predefined_ranges = array();
231
- $predefined_ranges[] = '<a href="' . add_query_arg( 'range', 'all_time', remove_query_arg( array( 'start_date', 'end_date' ) ) ) . '">' .
232
- __( 'All time', 'woocommerce-jetpack' ) . '</a>';
233
- foreach ( array_merge( wcj_get_reports_standard_ranges(), wcj_get_reports_custom_ranges() ) as $range_id => $range_data ) {
234
- $link = add_query_arg( array(
235
- 'start_date' => $range_data['start_date'],
236
- 'end_date' => $range_data['end_date'],
237
- 'range' => $range_id,
238
- ) );
239
- $predefined_ranges[] = '<a href="' . $link . '">' . $range_data['title'] . '</a>';
240
- }
241
- $predefined_ranges = implode( ' | ', $predefined_ranges );
242
- $dateformat = ' dateformat="yy-mm-dd"';
243
- $date_input_fields = '<form method="get" action="">' .
244
- '<input type="hidden" name="page" value="wcj-tools">' .
245
- '<input type="hidden" name="tab" value="export_' . $tool_id . '">' .
246
- '<strong>' . __( 'Custom:', 'woocommerce-jetpack' ) . '</strong>' . ' ' .
247
- '<input name="start_date" id="start_date" type="text" display="date"' . $dateformat . ' value="' . $current_start_date . '">' .
248
- '<strong>' . ' - ' . '</strong>' .
249
- '<input name="end_date" id="end_date" type="text" display="date"' . $dateformat . ' value="' . $current_end_date . '">' .
250
- ' ' .
251
- '<button class="button-primary" name="range" id="range" type="submit" value="custom">' . __( 'Go', 'woocommerce-jetpack' ) . '</button>' .
252
- '</form>';
253
- return $predefined_ranges . '<br>' . $date_input_fields;
254
- }
255
-
256
- /**
257
- * create_export_tool.
258
- *
259
- * @version 3.0.0
260
- * @since 2.4.8
261
- */
262
- function create_export_tool( $tool_id ) {
263
- echo $this->get_tool_header_html( 'export_' . $tool_id );
264
- echo '<p>' . $this->export_date_fields( $tool_id ) . '</p>';
265
- if ( ! isset( $_GET['range'] ) ) {
266
- return;
267
- }
268
- echo '<form method="post" action="">';
269
- echo '<p>' . $this->export_filter_fields( $tool_id ) . '</p>';
270
- echo '<p>';
271
- echo '<button class="button-primary" type="submit" name="wcj_export" value="' . $tool_id . '">' . __( 'Download CSV', 'woocommerce-jetpack' ) . '</button>';
272
- echo ' ';
273
- echo '<button class="button-primary" type="submit" name="wcj_export_xml" value="' . $tool_id . '">' .
274
- __( 'Download XML', 'woocommerce-jetpack' ) . '</button>';
275
- echo '<button style="float:right;margin-right:10px;" class="button-primary" type="submit" name="wcj_export_filter" value="' . $tool_id . '">' .
276
- __( 'Filter by All Fields', 'woocommerce-jetpack' ) . '</button>';
277
- echo '<input style="float:right;margin-right:10px;" type="text" name="wcj_export_filter_all_columns" value="' .
278
- ( isset( $_POST['wcj_export_filter_all_columns'] ) ? $_POST['wcj_export_filter_all_columns'] : '' ) . '">';
279
- echo '</p>';
280
- echo '</form>';
281
- $data = $this->export( $tool_id );
282
- echo ( is_array( $data ) ) ? wcj_get_table_html( $data, array( 'table_class' => 'widefat striped' ) ) : $data;
283
- }
284
-
285
- /**
286
- * create_export_customers_tool.
287
- *
288
- * @version 2.4.8
289
- * @since 2.4.8
290
- */
291
- function create_export_customers_tool() {
292
- $this->create_export_tool( 'customers' );
293
- }
294
-
295
- /**
296
- * create_export_orders_tool.
297
- *
298
- * @version 2.4.8
299
- * @since 2.4.8
300
- */
301
- function create_export_orders_tool() {
302
- $this->create_export_tool( 'orders' );
303
- }
304
-
305
- /**
306
- * create_export_orders_items_tool.
307
- *
308
- * @version 2.5.9
309
- * @since 2.5.9
310
- */
311
- function create_export_orders_items_tool() {
312
- $this->create_export_tool( 'orders_items' );
313
- }
314
-
315
- /**
316
- * create_export_products_tool.
317
- *
318
- * @version 2.5.3
319
- * @since 2.5.3
320
- */
321
- function create_export_products_tool() {
322
- $this->create_export_tool( 'products' );
323
- }
324
-
325
- /**
326
- * create_export_customers_from_orders_tool.
327
- *
328
- * @version 2.4.8
329
- * @since 2.3.9
330
- */
331
- function create_export_customers_from_orders_tool() {
332
- $this->create_export_tool( 'customers_from_orders' );
333
- }
334
-
335
- }
336
-
337
- endif;
338
-
339
- return new WCJ_Export_Import();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Export
4
+ *
5
+ * @version 4.4.0
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 2.8.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.', 'woocommerce-jetpack' );
28
+ $this->link_slug = 'woocommerce-export-tools';
29
+ parent::__construct();
30
+
31
+ $this->add_tools( array(
32
+ 'export_customers' => array(
33
+ 'title' => __( 'Export Customers', 'woocommerce-jetpack' ),
34
+ 'desc' => __( 'Export Customers.', 'woocommerce-jetpack' ),
35
+ ),
36
+ 'export_customers_from_orders' => array(
37
+ 'title' => __( 'Export Customers from Orders', 'woocommerce-jetpack' ),
38
+ 'desc' => __( 'Export Customers (extracted from orders).', 'woocommerce-jetpack' ) . ' ' .
39
+ __( 'Customers are identified by billing email.', 'woocommerce-jetpack' ),
40
+ ),
41
+ 'export_orders' => array(
42
+ 'title' => __( 'Export Orders', 'woocommerce-jetpack' ),
43
+ 'desc' => __( 'Export Orders.', 'woocommerce-jetpack' ),
44
+ ),
45
+ 'export_orders_items' => array(
46
+ 'title' => __( 'Export Orders Items', 'woocommerce-jetpack' ),
47
+ 'desc' => __( 'Export Orders Items.', 'woocommerce-jetpack' ),
48
+ ),
49
+ 'export_products' => array(
50
+ 'title' => __( 'Export Products', 'woocommerce-jetpack' ),
51
+ 'desc' => __( 'Export Products.', 'woocommerce-jetpack' ),
52
+ ),
53
+ ) );
54
+
55
+ $this->fields_helper = require_once( 'export/class-wcj-fields-helper.php' );
56
+
57
+ if ( $this->is_enabled() ) {
58
+ add_action( 'init', array( $this, 'export_csv' ) );
59
+ add_action( 'init', array( $this, 'export_xml' ) );
60
+ }
61
+ }
62
+
63
+ /**
64
+ * export.
65
+ *
66
+ * @version 2.5.9
67
+ * @since 2.4.8
68
+ * @todo [dev] when filtering now using `strpos`, but other options would be `stripos` (case-insensitive) or strict equality
69
+ * @todo [dev] (maybe) do filtering directly in WP_Query
70
+ */
71
+ function export( $tool_id ) {
72
+ $data = array();
73
+ switch ( $tool_id ) {
74
+ case 'customers':
75
+ $exporter = require_once( 'export/class-wcj-exporter-customers.php' );
76
+ $data = $exporter->export_customers( $this->fields_helper );
77
+ break;
78
+ case 'customers_from_orders':
79
+ $exporter = require_once( 'export/class-wcj-exporter-customers.php' );
80
+ $data = $exporter->export_customers_from_orders( $this->fields_helper );
81
+ break;
82
+ case 'orders':
83
+ $exporter = require_once( 'export/class-wcj-exporter-orders.php' );
84
+ $data = $exporter->export_orders( $this->fields_helper );
85
+ break;
86
+ case 'orders_items':
87
+ $exporter = require_once( 'export/class-wcj-exporter-orders.php' );
88
+ $data = $exporter->export_orders_items( $this->fields_helper );
89
+ break;
90
+ case 'products':
91
+ $exporter = require_once( 'export/class-wcj-exporter-products.php' );
92
+ $data = $exporter->export_products( $this->fields_helper );
93
+ break;
94
+ }
95
+ if ( isset( $_POST['wcj_export_filter_all_columns'] ) && '' != $_POST['wcj_export_filter_all_columns'] ) {
96
+ foreach ( $data as $row_id => $row ) {
97
+ if ( 0 == $row_id ) {
98
+ continue;
99
+ }
100
+ $is_filtered = false;
101
+ foreach ( $row as $cell ) {
102
+ if ( false !== strpos( $cell, $_POST['wcj_export_filter_all_columns'] ) ) {
103
+ $is_filtered = true;
104
+ break;
105
+ }
106
+ }
107
+ if ( ! $is_filtered ) {
108
+ unset( $data[ $row_id ] );
109
+ }
110
+ }
111
+ }
112
+ return $data;
113
+ }
114
+
115
+ /**
116
+ * export_xml.
117
+ *
118
+ * @version 2.5.9
119
+ * @since 2.5.9
120
+ * @todo [dev] templates for xml_start, xml_end, xml_item.
121
+ * @todo [dev] `strip_tags`
122
+ */
123
+ function export_xml() {
124
+ if ( isset( $_POST['wcj_export_xml'] ) ) {
125
+ $data = $this->export( $_POST['wcj_export_xml'] );
126
+ if ( is_array( $data ) ) {
127
+ $xml = '';
128
+ $xml .= '<?xml version = "1.0" encoding = "utf-8" ?>' . PHP_EOL . '<root>' . PHP_EOL;
129
+ foreach ( $data as $row_num => $row ) {
130
+ if ( 0 == $row_num ) {
131
+ foreach ( $row as $cell_id => $cell_value ) {
132
+ $cell_ids[ $cell_id ] = sanitize_title_with_dashes( $cell_value );
133
+ }
134
+ continue;
135
+ }
136
+ $xml .= '<item>' . PHP_EOL;
137
+ foreach ( $row as $cell_id => $cell_value ) {
138
+ $xml .= "\t" . '<' . $cell_ids[ $cell_id ] . '>' . $cell_value . '</' . $cell_ids[ $cell_id ] . '>' . PHP_EOL;
139
+ }
140
+ $xml .= '</item>' . PHP_EOL;
141
+ }
142
+ $xml .= '</root>';
143
+ header( "Content-Disposition: attachment; filename=" . $_POST['wcj_export_xml'] . ".xml" );
144
+ header( "Content-Type: Content-Type: text/html; charset=utf-8" );
145
+ header( "Content-Description: File Transfer" );
146
+ header( "Content-Length: " . strlen( $xml ) );
147
+ echo $xml;
148
+ die();
149
+ }
150
+ }
151
+ }
152
+
153
+ /**
154
+ * export_csv.
155
+ *
156
+ * @version 2.5.9
157
+ * @since 2.4.8
158
+ */
159
+ function export_csv() {
160
+ if ( isset( $_POST['wcj_export'] ) ) {
161
+ $data = $this->export( $_POST['wcj_export'] );
162
+ if ( is_array( $data ) ) {
163
+ $csv = '';
164
+ foreach ( $data as $row ) {
165
+ $csv .= implode( get_option( 'wcj_export_csv_separator', ',' ), $row ) . PHP_EOL;
166
+ }
167
+ if ( 'yes' === get_option( 'wcj_export_csv_add_utf_8_bom', 'yes' ) ) {
168
+ $csv = "\xEF\xBB\xBF" . $csv; // UTF-8 BOM
169
+ }
170
+ header( "Content-Disposition: attachment; filename=" . $_POST['wcj_export'] . ".csv" );
171
+ header( "Content-Type: Content-Type: text/html; charset=utf-8" );
172
+ header( "Content-Description: File Transfer" );
173
+ header( "Content-Length: " . strlen( $csv ) );
174
+ echo $csv;
175
+ die();
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ * export_filter_fields.
182
+ *
183
+ * @version 2.5.9
184
+ * @since 2.5.5
185
+ * @todo [dev] filter each field separately
186
+ */
187
+ function export_filter_fields( $tool_id ) {
188
+ $fields = array();
189
+ switch ( $tool_id ) {
190
+ case 'orders':
191
+ $fields = array(
192
+ 'wcj_filter_by_order_billing_country' => __( 'Filter by Billing Country', 'woocommerce-jetpack' ),
193
+ 'wcj_filter_by_product_title' => __( 'Filter by Product Title', 'woocommerce-jetpack' ),
194
+ );
195
+ break;
196
+ case 'orders_items':
197
+ $fields = array(
198
+ 'wcj_filter_by_order_billing_country' => __( 'Filter by Billing Country', 'woocommerce-jetpack' ),
199
+ );
200
+ break;
201
+ }
202
+ if ( ! empty( $fields ) ) {
203
+ $data = array();
204
+ foreach( $fields as $field_id => $field_desc ) {
205
+ $field_value = ( isset( $_POST[ $field_id ] ) ) ? $_POST[ $field_id ] : '';
206
+ $data[] = array(
207
+ '<label for="' . $field_id . '">' . $field_desc . '</label>',
208
+ '<input name="' . $field_id . '" id="' . $field_id . '" type="text" value="' . $field_value . '">',
209
+ );
210
+ }
211
+ $data[] = array(
212
+ '<button class="button-primary" type="submit" name="wcj_export_filter" value="' . $tool_id . '">' . __( 'Filter', 'woocommerce-jetpack' ) . '</button>',
213
+ '',
214
+ );
215
+ return wcj_get_table_html( $data, array( 'table_class' => 'widefat', 'table_style' => 'width:50%;min-width:300px;', 'table_heading_type' => 'vertical' ) );
216
+ }
217
+ }
218
+
219
+ /**
220
+ * export_date_fields.
221
+ *
222
+ * @version 4.4.0
223
+ * @since 3.0.0
224
+ * @todo [dev] maybe make `$dateformat` optional
225
+ * @todo [dev] mark current (i.e. active) link (if exists)
226
+ */
227
+ function export_date_fields( $tool_id ) {
228
+ $current_start_date = ( isset( $_GET['start_date'] ) ? $_GET['start_date'] : '' );
229
+ $current_end_date = ( isset( $_GET['end_date'] ) ? $_GET['end_date'] : '' );
230
+ $predefined_ranges = array();
231
+ $predefined_ranges[] = '<a href="' . add_query_arg( 'range', 'all_time', remove_query_arg( array( 'start_date', 'end_date' ) ) ) . '">' .
232
+ __( 'All time', 'woocommerce-jetpack' ) . '</a>';
233
+ foreach ( array_merge( wcj_get_reports_standard_ranges(), wcj_get_reports_custom_ranges() ) as $range_id => $range_data ) {
234
+ $link = add_query_arg( array(
235
+ 'start_date' => $range_data['start_date'],
236
+ 'end_date' => $range_data['end_date'],
237
+ 'range' => $range_id,
238
+ ) );
239
+ $predefined_ranges[] = '<a href="' . $link . '">' . $range_data['title'] . '</a>';
240
+ }
241
+ $predefined_ranges = implode( ' | ', $predefined_ranges );
242
+ $dateformat = ' dateformat="yy-mm-dd"';
243
+ $date_input_fields = '<form method="get" action="">' .
244
+ '<input type="hidden" name="page" value="wcj-tools">' .
245
+ '<input type="hidden" name="tab" value="export_' . $tool_id . '">' .
246
+ '<strong>' . __( 'Custom:', 'woocommerce-jetpack' ) . '</strong>' . ' ' .
247
+ '<input name="start_date" id="start_date" type="text" display="date"' . $dateformat . ' value="' . $current_start_date . '">' .
248
+ '<strong>' . ' - ' . '</strong>' .
249
+ '<input name="end_date" id="end_date" type="text" display="date"' . $dateformat . ' value="' . $current_end_date . '">' .
250
+ ' ' .
251
+ '<button class="button-primary" name="range" id="range" type="submit" value="custom">' . __( 'Go', 'woocommerce-jetpack' ) . '</button>' .
252
+ '</form>';
253
+ return $predefined_ranges . '<br>' . $date_input_fields;
254
+ }
255
+
256
+ /**
257
+ * create_export_tool.
258
+ *
259
+ * @version 3.0.0
260
+ * @since 2.4.8
261
+ */
262
+ function create_export_tool( $tool_id ) {
263
+ echo $this->get_tool_header_html( 'export_' . $tool_id );
264
+ echo '<p>' . $this->export_date_fields( $tool_id ) . '</p>';
265
+ if ( ! isset( $_GET['range'] ) ) {
266
+ return;
267
+ }
268
+ echo '<form method="post" action="">';
269
+ echo '<p>' . $this->export_filter_fields( $tool_id ) . '</p>';
270
+ echo '<p>';
271
+ echo '<button class="button-primary" type="submit" name="wcj_export" value="' . $tool_id . '">' . __( 'Download CSV', 'woocommerce-jetpack' ) . '</button>';
272
+ echo ' ';
273
+ echo '<button class="button-primary" type="submit" name="wcj_export_xml" value="' . $tool_id . '">' .
274
+ __( 'Download XML', 'woocommerce-jetpack' ) . '</button>';
275
+ echo '<button style="float:right;margin-right:10px;" class="button-primary" type="submit" name="wcj_export_filter" value="' . $tool_id . '">' .
276
+ __( 'Filter by All Fields', 'woocommerce-jetpack' ) . '</button>';
277
+ echo '<input style="float:right;margin-right:10px;" type="text" name="wcj_export_filter_all_columns" value="' .
278
+ ( isset( $_POST['wcj_export_filter_all_columns'] ) ? $_POST['wcj_export_filter_all_columns'] : '' ) . '">';
279
+ echo '</p>';
280
+ echo '</form>';
281
+ $data = $this->export( $tool_id );
282
+ echo ( is_array( $data ) ) ? wcj_get_table_html( $data, array( 'table_class' => 'widefat striped' ) ) : $data;
283
+ }
284
+
285
+ /**
286
+ * create_export_customers_tool.
287
+ *
288
+ * @version 2.4.8
289
+ * @since 2.4.8
290
+ */
291
+ function create_export_customers_tool() {
292
+ $this->create_export_tool( 'customers' );
293
+ }
294
+
295
+ /**
296
+ * create_export_orders_tool.
297
+ *
298
+ * @version 2.4.8
299
+ * @since 2.4.8
300
+ */
301
+ function create_export_orders_tool() {
302
+ $this->create_export_tool( 'orders' );
303
+ }
304
+
305
+ /**
306
+ * create_export_orders_items_tool.
307
+ *
308
+ * @version 2.5.9
309
+ * @since 2.5.9
310
+ */
311
+ function create_export_orders_items_tool() {
312
+ $this->create_export_tool( 'orders_items' );
313
+ }
314
+
315
+ /**
316
+ * create_export_products_tool.
317
+ *
318
+ * @version 2.5.3
319
+ * @since 2.5.3
320
+ */
321
+ function create_export_products_tool() {
322
+ $this->create_export_tool( 'products' );
323
+ }
324
+
325
+ /**
326
+ * create_export_customers_from_orders_tool.
327
+ *
328
+ * @version 2.4.8
329
+ * @since 2.3.9
330
+ */
331
+ function create_export_customers_from_orders_tool() {
332
+ $this->create_export_tool( 'customers_from_orders' );
333
+ }
334
+
335
+ }
336
+
337
+ endif;
338
+
339
+ return new WCJ_Export_Import();
includes/class-wcj-free-price.php CHANGED
@@ -1,171 +1,171 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Free Price
4
- *
5
- * @version 2.8.0
6
- * @since 2.5.9
7
- * @author Algoritmika Ltd.
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 2.8.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.', 'woocommerce-jetpack' );
28
- $this->link_slug = 'woocommerce-free-price-labels';
29
- parent::__construct();
30
-
31
- if ( $this->is_enabled() ) {
32
- if ( WCJ_IS_WC_VERSION_BELOW_3 ) {
33
- add_filter( 'woocommerce_free_price_html', array( $this, 'modify_free_price_simple_external_custom' ), PHP_INT_MAX, 2 );
34
- add_filter( 'woocommerce_grouped_free_price_html', array( $this, 'modify_free_price_grouped' ), PHP_INT_MAX, 2 );
35
- add_filter( 'woocommerce_variable_free_price_html', array( $this, 'modify_free_price_variable' ), PHP_INT_MAX, 2 );
36
- add_filter( 'woocommerce_variation_free_price_html', array( $this, 'modify_free_price_variation' ), PHP_INT_MAX, 2 );
37
- } else {
38
- add_filter( 'woocommerce_get_price_html', array( $this, 'maybe_modify_price' ), PHP_INT_MAX, 2 );
39
- }
40
- }
41
- }
42
-
43
- /**
44
- * are_all_prices_free
45
- *
46
- * @version 2.7.0
47
- * @since 2.7.0
48
- */
49
- function are_all_prices_free( $_product, $type ) {
50
- if ( 'variable' === $type ) {
51
- $prices = $_product->get_variation_prices( true );
52
- $min_price = current( $prices['price'] );
53
- $max_price = end( $prices['price'] );
54
- if ( '' !== $min_price && '' !== $max_price ) {
55
- return ( 0 == $min_price && 0 == $max_price );
56
- }
57
- } elseif ( 'variable' === $type ) {
58
- $child_prices = array();
59
- foreach ( $_product->get_children() as $child_id ) {
60
- $child = wc_get_product( $child_id );
61
- if ( '' !== $child->get_price() ) {
62
- $child_prices[] = wcj_get_product_display_price( $child );
63
- }
64
- }
65
- if ( ! empty( $child_prices ) ) {
66
- $min_price = min( $child_prices );
67
- $max_price = max( $child_prices );
68
- } else {
69
- $min_price = '';
70
- $max_price = '';
71
- }
72
- if ( '' !== $min_price && '' !== $max_price ) {
73
- return ( 0 == $min_price && 0 == $max_price );
74
- }
75
- }
76
- return false;
77
- }
78
-
79
- /**
80
- * maybe_modify_price
81
- *
82
- * @version 2.7.0
83
- * @since 2.7.0
84
- */
85
- function maybe_modify_price( $price, $_product ) {
86
- if ( '' !== $price ) {
87
- if ( 0 == $_product->get_price() ) {
88
- if ( $_product->is_type( 'grouped' ) ) {
89
- return ( $this->are_all_prices_free( $_product, 'grouped' ) ) ? $this->modify_free_price_grouped( $price, $_product ) : $price;
90
- } elseif ( $_product->is_type( 'variable' ) ) {
91
- return ( $this->are_all_prices_free( $_product, 'variable' ) ) ? $this->modify_free_price_variable( $price, $_product ) : $price;
92
- } elseif ( $_product->is_type( 'variation' ) ) {
93
- return $this->modify_free_price_variation( $price, $_product );
94
- } else {
95
- return $this->modify_free_price_simple_external_custom( $price, $_product );
96
- }
97
- }
98
- }
99
- return $price;
100
- }
101
-
102
- /**
103
- * get_view_id
104
- *
105
- * @version 2.5.9
106
- * @since 2.5.9
107
- */
108
- function get_view_id( $product_id ) {
109
- $view = 'single'; // default
110
- if ( is_single( $product_id ) ) {
111
- $view = 'single';
112
- } elseif ( is_single() ) {
113
- $view = 'related';
114
- } elseif ( is_front_page() ) {
115
- $view = 'home';
116
- } elseif ( is_page() ) {
117
- $view = 'page';
118
- } elseif ( is_archive() ) {
119
- $view = 'archive';
120
- }
121
- return $view;
122
- }
123
-
124
- /**
125
- * modify_free_price_simple_external_custom.
126
- *
127
- * @version 2.7.0
128
- * @since 2.5.9
129
- */
130
- function modify_free_price_simple_external_custom( $price, $_product ) {
131
- $default = '<span class="amount">' . __( 'Free!', 'woocommerce' ) . '</span>';
132
- return ( $_product->is_type( 'external' ) ) ?
133
- do_shortcode( get_option( 'wcj_free_price_external_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), $default ) ) :
134
- do_shortcode( get_option( 'wcj_free_price_simple_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), $default ) );
135
- }
136
-
137
- /**
138
- * modify_free_price_grouped.
139
- *
140
- * @version 2.7.0
141
- * @since 2.5.9
142
- */
143
- function modify_free_price_grouped( $price, $_product ) {
144
- return do_shortcode( get_option( 'wcj_free_price_grouped_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), __( 'Free!', 'woocommerce' ) ) );
145
- }
146
-
147
- /**
148
- * modify_free_price_variable.
149
- *
150
- * @version 2.7.0
151
- * @since 2.5.9
152
- */
153
- function modify_free_price_variable( $price, $_product ) {
154
- return do_shortcode( apply_filters( 'booster_option', __( 'Free!', 'woocommerce' ), get_option( 'wcj_free_price_variable_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), __( 'Free!', 'woocommerce' ) ) ) );
155
- }
156
-
157
- /**
158
- * modify_free_price_variation.
159
- *
160
- * @version 2.5.9
161
- * @since 2.5.9
162
- */
163
- function modify_free_price_variation( $price, $_product ) {
164
- return do_shortcode( apply_filters( 'booster_option', __( 'Free!', 'woocommerce' ), get_option( 'wcj_free_price_variable_variation', __( 'Free!', 'woocommerce' ) ) ) );
165
- }
166
-
167
- }
168
-
169
- endif;
170
-
171
- return new WCJ_Free_Price();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Free Price
4
+ *
5
+ * @version 2.8.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 2.8.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.', 'woocommerce-jetpack' );
28
+ $this->link_slug = 'woocommerce-free-price-labels';
29
+ parent::__construct();
30
+
31
+ if ( $this->is_enabled() ) {
32
+ if ( WCJ_IS_WC_VERSION_BELOW_3 ) {
33
+ add_filter( 'woocommerce_free_price_html', array( $this, 'modify_free_price_simple_external_custom' ), PHP_INT_MAX, 2 );
34
+ add_filter( 'woocommerce_grouped_free_price_html', array( $this, 'modify_free_price_grouped' ), PHP_INT_MAX, 2 );
35
+ add_filter( 'woocommerce_variable_free_price_html', array( $this, 'modify_free_price_variable' ), PHP_INT_MAX, 2 );
36
+ add_filter( 'woocommerce_variation_free_price_html', array( $this, 'modify_free_price_variation' ), PHP_INT_MAX, 2 );
37
+ } else {
38
+ add_filter( 'woocommerce_get_price_html', array( $this, 'maybe_modify_price' ), PHP_INT_MAX, 2 );
39
+ }
40
+ }
41
+ }
42
+
43
+ /**
44
+ * are_all_prices_free
45
+ *
46
+ * @version 2.7.0
47
+ * @since 2.7.0
48
+ */
49
+ function are_all_prices_free( $_product, $type ) {
50
+ if ( 'variable' === $type ) {
51
+ $prices = $_product->get_variation_prices( true );
52
+ $min_price = current( $prices['price'] );
53
+ $max_price = end( $prices['price'] );
54
+ if ( '' !== $min_price && '' !== $max_price ) {
55
+ return ( 0 == $min_price && 0 == $max_price );
56
+ }
57
+ } elseif ( 'variable' === $type ) {
58
+ $child_prices = array();
59
+ foreach ( $_product->get_children() as $child_id ) {
60
+ $child = wc_get_product( $child_id );
61
+ if ( '' !== $child->get_price() ) {
62
+ $child_prices[] = wcj_get_product_display_price( $child );
63
+ }
64
+ }
65
+ if ( ! empty( $child_prices ) ) {
66
+ $min_price = min( $child_prices );
67
+ $max_price = max( $child_prices );
68
+ } else {
69
+ $min_price = '';
70
+ $max_price = '';
71
+ }
72
+ if ( '' !== $min_price && '' !== $max_price ) {
73
+ return ( 0 == $min_price && 0 == $max_price );
74
+ }
75
+ }
76
+ return false;
77
+ }
78
+
79
+ /**
80
+ * maybe_modify_price
81
+ *
82
+ * @version 2.7.0
83
+ * @since 2.7.0
84
+ */
85
+ function maybe_modify_price( $price, $_product ) {
86
+ if ( '' !== $price ) {
87
+ if ( 0 == $_product->get_price() ) {
88
+ if ( $_product->is_type( 'grouped' ) ) {
89
+ return ( $this->are_all_prices_free( $_product, 'grouped' ) ) ? $this->modify_free_price_grouped( $price, $_product ) : $price;
90
+ } elseif ( $_product->is_type( 'variable' ) ) {
91
+ return ( $this->are_all_prices_free( $_product, 'variable' ) ) ? $this->modify_free_price_variable( $price, $_product ) : $price;
92
+ } elseif ( $_product->is_type( 'variation' ) ) {
93
+ return $this->modify_free_price_variation( $price, $_product );
94
+ } else {
95
+ return $this->modify_free_price_simple_external_custom( $price, $_product );
96
+ }
97
+ }
98
+ }
99
+ return $price;
100
+ }
101
+
102
+ /**
103
+ * get_view_id
104
+ *
105
+ * @version 2.5.9
106
+ * @since 2.5.9
107
+ */
108
+ function get_view_id( $product_id ) {
109
+ $view = 'single'; // default
110
+ if ( is_single( $product_id ) ) {
111
+ $view = 'single';
112
+ } elseif ( is_single() ) {
113
+ $view = 'related';
114
+ } elseif ( is_front_page() ) {
115
+ $view = 'home';
116
+ } elseif ( is_page() ) {
117
+ $view = 'page';
118
+ } elseif ( is_archive() ) {
119
+ $view = 'archive';
120
+ }
121
+ return $view;
122
+ }
123
+
124
+ /**
125
+ * modify_free_price_simple_external_custom.
126
+ *
127
+ * @version 2.7.0
128
+ * @since 2.5.9
129
+ */
130
+ function modify_free_price_simple_external_custom( $price, $_product ) {
131
+ $default = '<span class="amount">' . __( 'Free!', 'woocommerce' ) . '</span>';
132
+ return ( $_product->is_type( 'external' ) ) ?
133
+ do_shortcode( get_option( 'wcj_free_price_external_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), $default ) ) :
134
+ do_shortcode( get_option( 'wcj_free_price_simple_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), $default ) );
135
+ }
136
+
137
+ /**
138
+ * modify_free_price_grouped.
139
+ *
140
+ * @version 2.7.0
141
+ * @since 2.5.9
142
+ */
143
+ function modify_free_price_grouped( $price, $_product ) {
144
+ return do_shortcode( get_option( 'wcj_free_price_grouped_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), __( 'Free!', 'woocommerce' ) ) );
145
+ }
146
+
147
+ /**
148
+ * modify_free_price_variable.
149
+ *
150
+ * @version 2.7.0
151
+ * @since 2.5.9
152
+ */
153
+ function modify_free_price_variable( $price, $_product ) {
154
+ return do_shortcode( apply_filters( 'booster_option', __( 'Free!', 'woocommerce' ), get_option( 'wcj_free_price_variable_' . $this->get_view_id( wcj_get_product_id_or_variation_parent_id( $_product ) ), __( 'Free!', 'woocommerce' ) ) ) );
155
+ }
156
+
157
+ /**
158
+ * modify_free_price_variation.
159
+ *
160
+ * @version 2.5.9
161
+ * @since 2.5.9
162
+ */
163
+ function modify_free_price_variation( $price, $_product ) {
164
+ return do_shortcode( apply_filters( 'booster_option', __( 'Free!', 'woocommerce' ), get_option( 'wcj_free_price_variable_variation', __( 'Free!', 'woocommerce' ) ) ) );
165
+ }
166
+
167
+ }
168
+
169
+ endif;
170
+
171
+ return new WCJ_Free_Price();
includes/class-wcj-general.php CHANGED
@@ -1,271 +1,271 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - General
4
- *
5
- * @version 4.5.0
6
- * @author Algoritmika Ltd.
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 = 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 = 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' === 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' === 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' === 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' === 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' === 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 2.9.0
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' => 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 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 get_option( 'wcj_session_expiration', 48 * 60 * 60 );
173
- }
174
-
175
- /**
176
- * create_custom_roles_tool.
177
- *
178
- * @version 4.0.0
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 = 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 = 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'), $_GET['wcj_delete_role'] ) . '</p>';
213
- }
214
-
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 = 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="' . 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', '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
- }
242
-
243
- /**
244
- * maybe_change_paypal_email.
245
- *
246
- * @version 2.5.2
247
- * @since 2.5.2
248
- */
249
- function maybe_change_paypal_email( $load_gateways ) {
250
- if ( isset( WC()->cart ) ) {
251
- foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
252
- if ( '' != ( $email = get_post_meta( $values['product_id'], '_' . 'wcj_paypal_per_product_email', true ) ) ) {
253
- foreach ( $load_gateways as $key => $gateway ) {
254
- if ( is_string( $gateway ) && 'WC_Gateway_Paypal' === $gateway ) {
255
- $load_gateway = new $gateway();
256
- $load_gateway->receiver_email = $load_gateway->email = $load_gateway->settings['receiver_email'] = $load_gateway->settings['email'] = $email;
257
- $load_gateways[ $key ] = $load_gateway;
258
- }
259
- }
260
- break;
261
- }
262
- }
263
- }
264
- return $load_gateways;
265
- }
266
-
267
- }
268
-
269
- endif;
270
-
271
- return new WCJ_General();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - General
4
+ *
5
+ * @version 4.5.0
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 = 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 = 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' === 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' === 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' === 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' === 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' === 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 2.9.0
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' => 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 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 get_option( 'wcj_session_expiration', 48 * 60 * 60 );
173
+ }
174
+
175
+ /**
176
+ * create_custom_roles_tool.
177
+ *
178
+ * @version 4.0.0
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 = 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 = 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'), $_GET['wcj_delete_role'] ) . '</p>';
213
+ }
214
+
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 = 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="' . 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', '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
+ }
242
+
243
+ /**
244
+ * maybe_change_paypal_email.
245
+ *
246
+ * @version 2.5.2
247
+ * @since 2.5.2
248
+ */
249
+ function maybe_change_paypal_email( $load_gateways ) {
250
+ if ( isset( WC()->cart ) ) {
251
+ foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
252
+ if ( '' != ( $email = get_post_meta( $values['product_id'], '_' . 'wcj_paypal_per_product_email', true ) ) ) {
253
+ foreach ( $load_gateways as $key => $gateway ) {
254
+ if ( is_string( $gateway ) && 'WC_Gateway_Paypal' === $gateway ) {
255
+ $load_gateway = new $gateway();
256
+ $load_gateway->receiver_email = $load_gateway->email = $load_gateway->settings['receiver_email'] = $load_gateway->settings['email'] = $email;
257
+ $load_gateways[ $key ] = $load_gateway;
258
+ }
259
+ }
260
+ break;
261
+ }
262
+ }
263
+ }
264
+ return $load_gateways;
265
+ }
266
+
267
+ }
268
+
269
+ endif;
270
+
271
+ return new WCJ_General();
includes/class-wcj-global-discount.php CHANGED
@@ -1,427 +1,427 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Global Discount
4
- *
5
- * @version 4.9.0
6
- * @since 2.5.7
7
- * @author Algoritmika Ltd.
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 4.8.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.', 'woocommerce-jetpack' );
31
- $this->link_slug = 'woocommerce-shop-global-discount';
32
- parent::__construct();
33
-
34
- if ( $this->is_enabled() ) {
35
- $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'global_discount' );
36
- if ( 'yes' === get_option( 'wcj_global_discount_enabled_in_admin', 'no' ) || wcj_is_frontend() ) {
37
- wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
38
- }
39
-
40
- add_action( 'admin_init', array( $this, 'regenerate_wcj_sale_products_in_cache' ) );
41
- add_filter( 'woocommerce_shortcode_products_query', array( $this, 'add_wcj_sale_ids_to_products_shortcode' ), 10, 3 );
42
- }
43
-
44
- }
45
-
46
- /**
47
- * add_wcj_sale_ids_to_products_shortcode.
48
- *
49
- * @version 4.8.0
50
- * @since 4.8.0
51
- *
52
- * @param $args
53
- * @param $atts
54
- * @param $type
55
- *
56
- * @return mixed
57
- */
58
- function add_wcj_sale_ids_to_products_shortcode( $args, $atts, $type ) {
59
- if (
60
- 'sale_products' != $type ||
61
- 'yes' != get_option( 'wcj_global_discount_products_shortcode_compatibility', 'no' )
62
- ) {
63
- return $args;
64
- }
65
-
66
- $prev_post__in = isset( $args['post__in'] ) ? $args['post__in'] : array();
67
- $args['post__in'] = array_merge( $prev_post__in, $this->get_wcj_sale_products() );
68
- return $args;
69
- }
70
-
71
- /**
72
- * regenerate_wcj_sale_products_in_cache.
73
- *
74
- * @version 4.8.0
75
- * @since 4.8.0
76
- */
77
- function regenerate_wcj_sale_products_in_cache() {
78
- if (
79
- 'yes' != get_option( 'wcj_global_discount_products_shortcode_compatibility', 'no' ) ||
80
- ! isset( $_REQUEST['page'] ) || 'wc-settings' !== $_REQUEST['page'] ||
81
- ! isset( $_REQUEST['tab'] ) || 'jetpack' !== $_REQUEST['tab'] ||
82
- ! isset( $_REQUEST['wcj-cat'] ) || 'prices_and_currencies' !== $_REQUEST['wcj-cat'] ||
83
- ! isset( $_REQUEST['section'] ) || 'global_discount' !== $_REQUEST['section'] ||
84
- ! isset( $_POST['save'] )
85
- ) {
86
- return;
87
- }
88
- $this->clear_wcj_sale_products_from_cache();
89
- $this->get_wcj_sale_products();
90
- }
91
-
92
- /**
93
- * get_wcj_sale_products.
94
- *
95
- * @version 4.8.0
96
- * @since 4.8.0
97
- *
98
- * @return array|mixed
99
- */
100
- function get_wcj_sale_products() {
101
- $transient_name = 'wcj_global_discount_sale_products';
102
- $sale_products = get_transient( $transient_name );
103
- if ( false === $sale_products ) {
104
- $args = array(
105
- 'post_type' => 'product',
106
- 'posts_per_page' => - 1,
107
- 'fields' => 'ids',
108
- );
109
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
110
- for ( $i = 1; $i <= $total_number; $i ++ ) {
111
- $enabled = get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
112
- if ( 'yes' !== $enabled ) {
113
- continue;
114
- }
115
-
116
- // Categories
117
- $include_cats = get_option( 'wcj_global_discount_sale_categories_incl_' . $i, array() );
118
- $exclude_cats = get_option( 'wcj_global_discount_sale_categories_excl_' . $i, array() );
119
- $cats = array();
120
- if ( ! empty( $include_cats ) || ! empty( $exclude_cats ) ) {
121
- $cats = array(
122
- 'relation' => 'AND',
123
- );
124
- if ( ! empty( $include_cats ) ) {
125
- $cats[] = array(
126
- 'taxonomy' => 'product_cat',
127
- 'field' => 'term_id',
128
- 'include_children' => false,
129
- 'terms' => $include_cats
130
- );
131
- }
132
- if ( ! empty( $exclude_cats ) ) {
133
- $cats[] = array(
134
- 'taxonomy' => 'product_cat',
135
- 'field' => 'term_id',
136
- 'include_children' => false,
137
- 'terms' => $exclude_cats,
138
- 'operator' => 'NOT IN'
139
- );
140
- }
141
- }
142
-
143
- // Tags
144
- $include_tags = get_option( 'wcj_global_discount_sale_tags_incl_' . $i, array() );
145
- $exclude_tags = get_option( 'wcj_global_discount_sale_tags_excl_' . $i, array() );
146
- $tags = array();
147
- if ( ! empty( $include_tags ) || ! empty( $exclude_tags ) ) {
148
- $tags = array(
149
- 'relation' => 'AND',
150
- );
151
- if ( ! empty( $include_tags ) ) {
152
- $tags[] = array(
153
- 'taxonomy' => 'product_tag',
154
- 'field' => 'term_id',
155
- 'terms' => $include_tags
156
- );
157
- }
158
- if ( ! empty( $exclude_tags ) ) {
159
- $tags[] = array(
160
- 'taxonomy' => 'product_tag',
161
- 'field' => 'term_id',
162
- 'terms' => $exclude_tags,
163
- 'operator' => 'NOT IN'
164
- );
165
- }
166
- }
167
-
168
- // Tax Query
169
- if ( ! empty( $cats ) || ! empty( $tags ) ) {
170
- $args['tax_query'] = array(
171
- 'relation' => 'AND'
172
- );
173
- if ( ! empty( $cats ) ) {
174
- $args['tax_query'][] = $cats;
175
- }
176
- if ( ! empty( $tags ) ) {
177
- $args['tax_query'][] = $tags;
178
- }
179
- }
180
-
181
- // Products
182
- $products_incl = get_option( 'wcj_global_discount_sale_products_incl_' . $i, array() );
183
- $products_excl = get_option( 'wcj_global_discount_sale_products_excl_' . $i, array() );
184
- if ( ! empty( $products_incl ) || ! empty( $products_excl ) ) {
185
- if ( ! empty( $products_incl ) ) {
186
- $args['post__in'] = $products_incl;
187
- }
188
- if ( ! empty( $products_excl ) ) {
189
- $args['post__not_in'] = $products_excl;
190
- }
191
- }
192
-
193
- // Scope
194
- $scope = get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
195
- if ( 'all' != $scope ) {
196
- $wc_sale_products = wc_get_product_ids_on_sale();
197
- if ( 'only_on_sale' == $scope ) {
198
- $args['post__in'] = $wc_sale_products;
199
- if ( empty( $wc_sale_products ) ) {
200
- $args['post_type'] = 'do_not_search';
201
- }
202
- } elseif ( 'only_not_on_sale' == $scope ) {
203
- $args['post__not_in'] = $wc_sale_products;
204
- }
205
- }
206
-
207
- $query = new WP_Query( $args );
208
- $sale_products = array_unique( $query->posts );
209
- $prev_group_sale_products = get_transient( $transient_name );
210
- if ( false !== $prev_group_sale_products ) {
211
- $sale_products = array_unique( array_merge( $prev_group_sale_products, $sale_products ) );
212
- }
213
-
214
- set_transient( $transient_name, $sale_products, YEAR_IN_SECONDS );
215
- }
216
- }
217
- return $sale_products;
218
- }
219
-
220
- /**
221
- * clear_wcj_sale_products_from_cache.
222
- *
223
- * @version 4.8.0
224
- * @since 4.8.0
225
- */
226
- function clear_wcj_sale_products_from_cache() {
227
- delete_transient( 'wcj_global_discount_sale_products' );
228
- }
229
-
230
- /**
231
- * change_price.
232
- *
233
- * @version 3.1.0
234
- * @since 3.1.0
235
- * @todo `WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER, 'woocommerce_variation_prices_regular_price', 'woocommerce_product_variation_get_regular_price'`
236
- */
237
- function change_price( $price, $_product ) {
238
- $_current_filter = current_filter();
239
- if ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_PRICE_FILTER, 'woocommerce_variation_prices_price', 'woocommerce_product_variation_get_price' ) ) ) {
240
- return $this->add_global_discount( $price, $_product, 'price' );
241
- } elseif ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_SALE_PRICE_FILTER, 'woocommerce_variation_prices_sale_price', 'woocommerce_product_variation_get_sale_price' ) ) ) {
242
- return $this->add_global_discount( $price, $_product, 'sale_price' );
243
- } else {
244
- return $price;
245
- }
246
- }
247
-
248
- /**
249
- * change_price_grouped.
250
- *
251
- * @version 3.1.0
252
- * @since 2.5.7
253
- */
254
- function change_price_grouped( $price, $qty, $_product ) {
255
- if ( $_product->is_type( 'grouped' ) ) {
256
- foreach ( $_product->get_children() as $child_id ) {
257
- $the_price = get_post_meta( $child_id, '_price', true );
258
- $the_product = wc_get_product( $child_id );
259
- $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
260
- if ( $the_price == $price ) {
261
- return $this->add_global_discount( $price, $the_product, 'price' );
262
- }
263
- }
264
- }
265
- return $price;
266
- }
267
-
268
- /**
269
- * calculate_price.
270
- *
271
- * @version 3.8.0
272
- * @since 2.5.7
273
- */
274
- function calculate_price( $price, $coefficient, $group ) {
275
- if ( '' === $price ) {
276
- return $price;
277
- }
278
- $return_price = ( 'percent' === get_option( 'wcj_global_discount_sale_coefficient_type_' . $group, 'percent' ) ) ?
279
- ( $price + $price * ( $coefficient / 100 ) ) :
280
- ( $price + $coefficient );
281
- $return_price = ( $return_price >= 0 ? $return_price : 0 );
282
- if ( 'none' != ( $final_correction_function = get_option( 'wcj_global_discount_sale_final_correction_func_' . $group, 'none' ) ) ) {
283
- $final_correction_coef = get_option( 'wcj_global_discount_sale_final_correction_coef_' . $group, 1 );
284
- $return_price = $final_correction_function( $return_price / $final_correction_coef ) * $final_correction_coef;
285
- }
286
- return $return_price;
287
- }
288
-
289
- /**
290
- * check_if_applicable.
291
- *
292
- * @version 3.1.0
293
- * @since 2.5.7
294
- * @return bool
295
- */
296
- function check_if_applicable( $_product, $group ) {
297
- return ( 'yes' === get_option( 'wcj_global_discount_sale_enabled_' . $group, 'yes' ) && $this->is_enabled_for_product( $_product, $group ) );
298
- }
299
-
300
- /**
301
- * is_enabled_for_product.
302
- *
303
- * @version 3.1.0
304
- * @since 3.1.0
305
- */
306
- function is_enabled_for_product( $_product, $group ) {
307
- $product_id = wcj_get_product_id_or_variation_parent_id( $_product );
308
- return wcj_is_enabled_for_product( $product_id, array(
309
- 'include_products' => get_option( 'wcj_global_discount_sale_products_incl_' . $group, '' ),
310
- 'exclude_products' => get_option( 'wcj_global_discount_sale_products_excl_' . $group, '' ),
311
- 'include_categories' => get_option( 'wcj_global_discount_sale_categories_incl_' . $group, '' ),
312
- 'exclude_categories' => get_option( 'wcj_global_discount_sale_categories_excl_' . $group, '' ),
313
- 'include_tags' => get_option( 'wcj_global_discount_sale_tags_incl_' . $group, '' ),
314
- 'exclude_tags' => get_option( 'wcj_global_discount_sale_tags_excl_' . $group, '' ),
315
- ) );
316
- }
317
-
318
- /**
319
- * check_if_applicable_by_product_scope.
320
- *
321
- * @version 3.9.0
322
- * @since 3.1.0
323
- */
324
- function check_if_applicable_by_product_scope( $_product, $price, $price_type, $scope ) {
325
- $return = true;
326
- if ( 'sale_price' === $price_type ) {
327
- if ( 0 == $price ) {
328
- // The product is currently not on sale
329
- if ( 'only_on_sale' === $scope ) {
330
- $return = false;
331
- }
332
- } else {
333
- // The product is currently on sale
334
- if ( 'only_not_on_sale' === $scope ) {
335
- $return = false;
336
- }
337
- }
338
- } else { // if ( 'price' === $price_type )
339
- wcj_remove_change_price_hooks( $this, $this->price_hooks_priority, false );
340
- if ( 'only_on_sale' === $scope && 0 == $_product->get_sale_price() ) {
341
- $return = false;
342
- } elseif ( 'only_not_on_sale' === $scope && 0 != $_product->get_sale_price() ) {
343
- $return = false;
344
- }
345
- wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
346
- }
347
- return $return;
348
- }
349
-
350
- /**
351
- * add_global_discount.
352
- *
353
- * @version 3.1.0
354
- * @since 2.5.7
355
- */
356
- function add_global_discount( $price, $_product, $price_type ) {
357
- if ( 'price' === $price_type && '' === $price ) {
358
- return $price; // no changes
359
- }
360
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
361
- for ( $i = 1; $i <= $total_number; $i++ ) {
362
- if ( ! $this->check_if_applicable( $_product, $i ) ) {
363
- continue; // no changes by current discount group
364
- }
365
- $coefficient = get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
366
- if ( 0 != $coefficient ) {
367
- if ( ! $this->check_if_applicable_by_product_scope( $_product, $price, $price_type, get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' ) ) ) {
368
- continue; // no changes by current discount group
369
- }
370
- if ( 'sale_price' === $price_type && 0 == $price ) {
371
- $price = $_product->get_regular_price();
372
- }
373
- return $this->calculate_price( $price, $coefficient, $i ); // discount applied
374
- }
375
- }
376
- return $price; // no changes
377
- }
378
-
379
- /**
380
- * get_global_discount_options.
381
- *
382
- * @version 4.8.0
383
- * @since 4.8.0
384
- *
385
- * @return array
386
- */
387
- function get_global_discount_options() {
388
- $options = $this->wcj_global_options;
389
- if ( empty( $options ) ) {
390
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
391
- $options['total_number'] = $total_number;
392
- for ( $i = 1; $i <= $total_number; $i ++ ) {
393
- $options['enabled'][ $i ] = get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
394
- $options['type'][ $i ] = get_option( 'wcj_global_discount_sale_coefficient_type_' . $i, 'percent' );
395
- $options['value'][ $i ] = get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
396
- $options['scope'][ $i ] = get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
397
- $options['cats_in'][ $i ] = get_option( 'wcj_global_discount_sale_categories_incl_' . $i, array() );
398
- $options['cats_ex'][ $i ] = get_option( 'wcj_global_discount_sale_categories_excl_' . $i, array() );
399
- $options['tags_in'][ $i ] = get_option( 'wcj_global_discount_sale_tags_incl_' . $i, array() );
400
- $options['tags_ex'][ $i ] = get_option( 'wcj_global_discount_sale_tags_excl_' . $i, array() );
401
- $options['products_in'][ $i ] = get_option( 'wcj_global_discount_sale_products_incl_' . $i, array() );
402
- $options['products_ex'][ $i ] = get_option( 'wcj_global_discount_sale_products_excl_' . $i, array() );
403
- }
404
- $this->wcj_global_options = $options;
405
- }
406
- return $options;
407
- }
408
-
409
- /**
410
- * get_variation_prices_hash.
411
- *
412
- * @version 4.9.0
413
- * @since 2.5.7
414
- */
415
- function get_variation_prices_hash( $price_hash, $_product, $display ) {
416
- $options = $this->get_global_discount_options();
417
- if ( is_array( $price_hash ) ) {
418
- $price_hash['wcj_global_discount_price_hash'] = $options;
419
- }
420
- return $price_hash;
421
- }
422
-
423
- }
424
-
425
- endif;
426
-
427
- return new WCJ_Global_Discount();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Global Discount
4
+ *
5
+ * @version 4.9.0
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 4.8.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.', 'woocommerce-jetpack' );
31
+ $this->link_slug = 'woocommerce-shop-global-discount';
32
+ parent::__construct();
33
+
34
+ if ( $this->is_enabled() ) {
35
+ $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'global_discount' );
36
+ if ( 'yes' === get_option( 'wcj_global_discount_enabled_in_admin', 'no' ) || wcj_is_frontend() ) {
37
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
38
+ }
39
+
40
+ add_action( 'admin_init', array( $this, 'regenerate_wcj_sale_products_in_cache' ) );
41
+ add_filter( 'woocommerce_shortcode_products_query', array( $this, 'add_wcj_sale_ids_to_products_shortcode' ), 10, 3 );
42
+ }
43
+
44
+ }
45
+
46
+ /**
47
+ * add_wcj_sale_ids_to_products_shortcode.
48
+ *
49
+ * @version 4.8.0
50
+ * @since 4.8.0
51
+ *
52
+ * @param $args
53
+ * @param $atts
54
+ * @param $type
55
+ *
56
+ * @return mixed
57
+ */
58
+ function add_wcj_sale_ids_to_products_shortcode( $args, $atts, $type ) {
59
+ if (
60
+ 'sale_products' != $type ||
61
+ 'yes' != get_option( 'wcj_global_discount_products_shortcode_compatibility', 'no' )
62
+ ) {
63
+ return $args;
64
+ }
65
+
66
+ $prev_post__in = isset( $args['post__in'] ) ? $args['post__in'] : array();
67
+ $args['post__in'] = array_merge( $prev_post__in, $this->get_wcj_sale_products() );
68
+ return $args;
69
+ }
70
+
71
+ /**
72
+ * regenerate_wcj_sale_products_in_cache.
73
+ *
74
+ * @version 4.8.0
75
+ * @since 4.8.0
76
+ */
77
+ function regenerate_wcj_sale_products_in_cache() {
78
+ if (
79
+ 'yes' != get_option( 'wcj_global_discount_products_shortcode_compatibility', 'no' ) ||
80
+ ! isset( $_REQUEST['page'] ) || 'wc-settings' !== $_REQUEST['page'] ||
81
+ ! isset( $_REQUEST['tab'] ) || 'jetpack' !== $_REQUEST['tab'] ||
82
+ ! isset( $_REQUEST['wcj-cat'] ) || 'prices_and_currencies' !== $_REQUEST['wcj-cat'] ||
83
+ ! isset( $_REQUEST['section'] ) || 'global_discount' !== $_REQUEST['section'] ||
84
+ ! isset( $_POST['save'] )
85
+ ) {
86
+ return;
87
+ }
88
+ $this->clear_wcj_sale_products_from_cache();
89
+ $this->get_wcj_sale_products();
90
+ }
91
+
92
+ /**
93
+ * get_wcj_sale_products.
94
+ *
95
+ * @version 4.8.0
96
+ * @since 4.8.0
97
+ *
98
+ * @return array|mixed
99
+ */
100
+ function get_wcj_sale_products() {
101
+ $transient_name = 'wcj_global_discount_sale_products';
102
+ $sale_products = get_transient( $transient_name );
103
+ if ( false === $sale_products ) {
104
+ $args = array(
105
+ 'post_type' => 'product',
106
+ 'posts_per_page' => - 1,
107
+ 'fields' => 'ids',
108
+ );
109
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
110
+ for ( $i = 1; $i <= $total_number; $i ++ ) {
111
+ $enabled = get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
112
+ if ( 'yes' !== $enabled ) {
113
+ continue;
114
+ }
115
+
116
+ // Categories
117
+ $include_cats = get_option( 'wcj_global_discount_sale_categories_incl_' . $i, array() );
118
+ $exclude_cats = get_option( 'wcj_global_discount_sale_categories_excl_' . $i, array() );
119
+ $cats = array();
120
+ if ( ! empty( $include_cats ) || ! empty( $exclude_cats ) ) {
121
+ $cats = array(
122
+ 'relation' => 'AND',
123
+ );
124
+ if ( ! empty( $include_cats ) ) {
125
+ $cats[] = array(
126
+ 'taxonomy' => 'product_cat',
127
+ 'field' => 'term_id',
128
+ 'include_children' => false,
129
+ 'terms' => $include_cats
130
+ );
131
+ }
132
+ if ( ! empty( $exclude_cats ) ) {
133
+ $cats[] = array(
134
+ 'taxonomy' => 'product_cat',
135
+ 'field' => 'term_id',
136
+ 'include_children' => false,
137
+ 'terms' => $exclude_cats,
138
+ 'operator' => 'NOT IN'
139
+ );
140
+ }
141
+ }
142
+
143
+ // Tags
144
+ $include_tags = get_option( 'wcj_global_discount_sale_tags_incl_' . $i, array() );
145
+ $exclude_tags = get_option( 'wcj_global_discount_sale_tags_excl_' . $i, array() );
146
+ $tags = array();
147
+ if ( ! empty( $include_tags ) || ! empty( $exclude_tags ) ) {
148
+ $tags = array(
149
+ 'relation' => 'AND',
150
+ );
151
+ if ( ! empty( $include_tags ) ) {
152
+ $tags[] = array(
153
+ 'taxonomy' => 'product_tag',
154
+ 'field' => 'term_id',
155
+ 'terms' => $include_tags
156
+ );
157
+ }
158
+ if ( ! empty( $exclude_tags ) ) {
159
+ $tags[] = array(
160
+ 'taxonomy' => 'product_tag',
161
+ 'field' => 'term_id',
162
+ 'terms' => $exclude_tags,
163
+ 'operator' => 'NOT IN'
164
+ );
165
+ }
166
+ }
167
+
168
+ // Tax Query
169
+ if ( ! empty( $cats ) || ! empty( $tags ) ) {
170
+ $args['tax_query'] = array(
171
+ 'relation' => 'AND'
172
+ );
173
+ if ( ! empty( $cats ) ) {
174
+ $args['tax_query'][] = $cats;
175
+ }
176
+ if ( ! empty( $tags ) ) {
177
+ $args['tax_query'][] = $tags;
178
+ }
179
+ }
180
+
181
+ // Products
182
+ $products_incl = get_option( 'wcj_global_discount_sale_products_incl_' . $i, array() );
183
+ $products_excl = get_option( 'wcj_global_discount_sale_products_excl_' . $i, array() );
184
+ if ( ! empty( $products_incl ) || ! empty( $products_excl ) ) {
185
+ if ( ! empty( $products_incl ) ) {
186
+ $args['post__in'] = $products_incl;
187
+ }
188
+ if ( ! empty( $products_excl ) ) {
189
+ $args['post__not_in'] = $products_excl;
190
+ }
191
+ }
192
+
193
+ // Scope
194
+ $scope = get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
195
+ if ( 'all' != $scope ) {
196
+ $wc_sale_products = wc_get_product_ids_on_sale();
197
+ if ( 'only_on_sale' == $scope ) {
198
+ $args['post__in'] = $wc_sale_products;
199
+ if ( empty( $wc_sale_products ) ) {
200
+ $args['post_type'] = 'do_not_search';
201
+ }
202
+ } elseif ( 'only_not_on_sale' == $scope ) {
203
+ $args['post__not_in'] = $wc_sale_products;
204
+ }
205
+ }
206
+
207
+ $query = new WP_Query( $args );
208
+ $sale_products = array_unique( $query->posts );
209
+ $prev_group_sale_products = get_transient( $transient_name );
210
+ if ( false !== $prev_group_sale_products ) {
211
+ $sale_products = array_unique( array_merge( $prev_group_sale_products, $sale_products ) );
212
+ }
213
+
214
+ set_transient( $transient_name, $sale_products, YEAR_IN_SECONDS );
215
+ }
216
+ }
217
+ return $sale_products;
218
+ }
219
+
220
+ /**
221
+ * clear_wcj_sale_products_from_cache.
222
+ *
223
+ * @version 4.8.0
224
+ * @since 4.8.0
225
+ */
226
+ function clear_wcj_sale_products_from_cache() {
227
+ delete_transient( 'wcj_global_discount_sale_products' );
228
+ }
229
+
230
+ /**
231
+ * change_price.
232
+ *
233
+ * @version 3.1.0
234
+ * @since 3.1.0
235
+ * @todo `WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER, 'woocommerce_variation_prices_regular_price', 'woocommerce_product_variation_get_regular_price'`
236
+ */
237
+ function change_price( $price, $_product ) {
238
+ $_current_filter = current_filter();
239
+ if ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_PRICE_FILTER, 'woocommerce_variation_prices_price', 'woocommerce_product_variation_get_price' ) ) ) {
240
+ return $this->add_global_discount( $price, $_product, 'price' );
241
+ } elseif ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_SALE_PRICE_FILTER, 'woocommerce_variation_prices_sale_price', 'woocommerce_product_variation_get_sale_price' ) ) ) {
242
+ return $this->add_global_discount( $price, $_product, 'sale_price' );
243
+ } else {
244
+ return $price;
245
+ }
246
+ }
247
+
248
+ /**
249
+ * change_price_grouped.
250
+ *
251
+ * @version 3.1.0
252
+ * @since 2.5.7
253
+ */
254
+ function change_price_grouped( $price, $qty, $_product ) {
255
+ if ( $_product->is_type( 'grouped' ) ) {
256
+ foreach ( $_product->get_children() as $child_id ) {
257
+ $the_price = get_post_meta( $child_id, '_price', true );
258
+ $the_product = wc_get_product( $child_id );
259
+ $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
260
+ if ( $the_price == $price ) {
261
+ return $this->add_global_discount( $price, $the_product, 'price' );
262
+ }
263
+ }
264
+ }
265
+ return $price;
266
+ }
267
+
268
+ /**
269
+ * calculate_price.
270
+ *
271
+ * @version 3.8.0
272
+ * @since 2.5.7
273
+ */
274
+ function calculate_price( $price, $coefficient, $group ) {
275
+ if ( '' === $price ) {
276
+ return $price;
277
+ }
278
+ $return_price = ( 'percent' === get_option( 'wcj_global_discount_sale_coefficient_type_' . $group, 'percent' ) ) ?
279
+ ( $price + $price * ( $coefficient / 100 ) ) :
280
+ ( $price + $coefficient );
281
+ $return_price = ( $return_price >= 0 ? $return_price : 0 );
282
+ if ( 'none' != ( $final_correction_function = get_option( 'wcj_global_discount_sale_final_correction_func_' . $group, 'none' ) ) ) {
283
+ $final_correction_coef = get_option( 'wcj_global_discount_sale_final_correction_coef_' . $group, 1 );
284
+ $return_price = $final_correction_function( $return_price / $final_correction_coef ) * $final_correction_coef;
285
+ }
286
+ return $return_price;
287
+ }
288
+
289
+ /**
290
+ * check_if_applicable.
291
+ *
292
+ * @version 3.1.0
293
+ * @since 2.5.7
294
+ * @return bool
295
+ */
296
+ function check_if_applicable( $_product, $group ) {
297
+ return ( 'yes' === get_option( 'wcj_global_discount_sale_enabled_' . $group, 'yes' ) && $this->is_enabled_for_product( $_product, $group ) );
298
+ }
299
+
300
+ /**
301
+ * is_enabled_for_product.
302
+ *
303
+ * @version 3.1.0
304
+ * @since 3.1.0
305
+ */
306
+ function is_enabled_for_product( $_product, $group ) {
307
+ $product_id = wcj_get_product_id_or_variation_parent_id( $_product );
308
+ return wcj_is_enabled_for_product( $product_id, array(
309
+ 'include_products' => get_option( 'wcj_global_discount_sale_products_incl_' . $group, '' ),
310
+ 'exclude_products' => get_option( 'wcj_global_discount_sale_products_excl_' . $group, '' ),
311
+ 'include_categories' => get_option( 'wcj_global_discount_sale_categories_incl_' . $group, '' ),
312
+ 'exclude_categories' => get_option( 'wcj_global_discount_sale_categories_excl_' . $group, '' ),
313
+ 'include_tags' => get_option( 'wcj_global_discount_sale_tags_incl_' . $group, '' ),
314
+ 'exclude_tags' => get_option( 'wcj_global_discount_sale_tags_excl_' . $group, '' ),
315
+ ) );
316
+ }
317
+
318
+ /**
319
+ * check_if_applicable_by_product_scope.
320
+ *
321
+ * @version 3.9.0
322
+ * @since 3.1.0
323
+ */
324
+ function check_if_applicable_by_product_scope( $_product, $price, $price_type, $scope ) {
325
+ $return = true;
326
+ if ( 'sale_price' === $price_type ) {
327
+ if ( 0 == $price ) {
328
+ // The product is currently not on sale
329
+ if ( 'only_on_sale' === $scope ) {
330
+ $return = false;
331
+ }
332
+ } else {
333
+ // The product is currently on sale
334
+ if ( 'only_not_on_sale' === $scope ) {
335
+ $return = false;
336
+ }
337
+ }
338
+ } else { // if ( 'price' === $price_type )
339
+ wcj_remove_change_price_hooks( $this, $this->price_hooks_priority, false );
340
+ if ( 'only_on_sale' === $scope && 0 == $_product->get_sale_price() ) {
341
+ $return = false;
342
+ } elseif ( 'only_not_on_sale' === $scope && 0 != $_product->get_sale_price() ) {
343
+ $return = false;
344
+ }
345
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
346
+ }
347
+ return $return;
348
+ }
349
+
350
+ /**
351
+ * add_global_discount.
352
+ *
353
+ * @version 3.1.0
354
+ * @since 2.5.7
355
+ */
356
+ function add_global_discount( $price, $_product, $price_type ) {
357
+ if ( 'price' === $price_type && '' === $price ) {
358
+ return $price; // no changes
359
+ }
360
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
361
+ for ( $i = 1; $i <= $total_number; $i++ ) {
362
+ if ( ! $this->check_if_applicable( $_product, $i ) ) {
363
+ continue; // no changes by current discount group
364
+ }
365
+ $coefficient = get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
366
+ if ( 0 != $coefficient ) {
367
+ if ( ! $this->check_if_applicable_by_product_scope( $_product, $price, $price_type, get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' ) ) ) {
368
+ continue; // no changes by current discount group
369
+ }
370
+ if ( 'sale_price' === $price_type && 0 == $price ) {
371
+ $price = $_product->get_regular_price();
372
+ }
373
+ return $this->calculate_price( $price, $coefficient, $i ); // discount applied
374
+ }
375
+ }
376
+ return $price; // no changes
377
+ }
378
+
379
+ /**
380
+ * get_global_discount_options.
381
+ *
382
+ * @version 4.8.0
383
+ * @since 4.8.0
384
+ *
385
+ * @return array
386
+ */
387
+ function get_global_discount_options() {
388
+ $options = $this->wcj_global_options;
389
+ if ( empty( $options ) ) {
390
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
391
+ $options['total_number'] = $total_number;
392
+ for ( $i = 1; $i <= $total_number; $i ++ ) {
393
+ $options['enabled'][ $i ] = get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
394
+ $options['type'][ $i ] = get_option( 'wcj_global_discount_sale_coefficient_type_' . $i, 'percent' );
395
+ $options['value'][ $i ] = get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
396
+ $options['scope'][ $i ] = get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
397
+ $options['cats_in'][ $i ] = get_option( 'wcj_global_discount_sale_categories_incl_' . $i, array() );
398
+ $options['cats_ex'][ $i ] = get_option( 'wcj_global_discount_sale_categories_excl_' . $i, array() );
399
+ $options['tags_in'][ $i ] = get_option( 'wcj_global_discount_sale_tags_incl_' . $i, array() );
400
+ $options['tags_ex'][ $i ] = get_option( 'wcj_global_discount_sale_tags_excl_' . $i, array() );
401
+ $options['products_in'][ $i ] = get_option( 'wcj_global_discount_sale_products_incl_' . $i, array() );
402
+ $options['products_ex'][ $i ] = get_option( 'wcj_global_discount_sale_products_excl_' . $i, array() );
403
+ }
404
+ $this->wcj_global_options = $options;
405
+ }
406
+ return $options;
407
+ }
408
+
409
+ /**
410
+ * get_variation_prices_hash.
411
+ *
412
+ * @version 4.9.0
413
+ * @since 2.5.7
414
+ */
415
+ function get_variation_prices_hash( $price_hash, $_product, $display ) {
416
+ $options = $this->get_global_discount_options();
417
+ if ( is_array( $price_hash ) ) {
418
+ $price_hash['wcj_global_discount_price_hash'] = $options;
419
+ }
420
+ return $price_hash;
421
+ }
422
+
423
+ }
424
+
425
+ endif;
426
+
427
+ return new WCJ_Global_Discount();
includes/class-wcj-left-to-free-shipping.php CHANGED
@@ -1,99 +1,99 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Left to Free Shipping
4
- *
5
- * @version 2.8.0
6
- * @since 2.5.8
7
- * @author Algoritmika Ltd.
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' === 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', 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', 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( 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( 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( 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
-
99
- return new WCJ_Left_To_Free_Shipping();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Left to Free Shipping
4
+ *
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' === 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', 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', 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( 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( 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( 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
+
99
+ return new WCJ_Left_To_Free_Shipping();
includes/class-wcj-max-products-per-user.php CHANGED
@@ -1,351 +1,351 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Max Products per User
4
- *
5
- * @version 4.2.0
6
- * @since 3.5.0
7
- * @author Algoritmika Ltd.
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 4.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.', 'woocommerce-jetpack' );
32
- $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' );
33
- $this->link_slug = 'woocommerce-maximum-products-per-user';
34
- parent::__construct();
35
-
36
- if ( $this->is_enabled() ) {
37
- if ( 'yes' === get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) || 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
38
- add_action( 'woocommerce_checkout_process', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
39
- add_action( 'woocommerce_before_cart', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
40
- if ( 'yes' === get_option( 'wcj_max_products_per_user_stop_from_adding_to_cart', 'no' ) ) {
41
- add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_on_add_to_cart' ), PHP_INT_MAX, 3 );
42
- }
43
- if ( 'yes' === get_option( 'wcj_max_products_per_user_stop_from_seeing_checkout', 'no' ) ) {
44
- add_action( 'wp', array( $this, 'stop_from_seeing_checkout' ), PHP_INT_MAX );
45
- }
46
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
47
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
48
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
49
- }
50
- }
51
- $this->order_status = get_option( 'wcj_max_products_per_user_order_status', array( 'wc-completed' ) );
52
- if ( empty( $this->order_status ) ) {
53
- $this->order_status = array( 'wc-completed' );
54
- }
55
- foreach ( $this->order_status as $status ) {
56
- $status = substr( $status, 3 );
57
- add_action( 'woocommerce_order_status_' . $status, array( $this, 'save_quantities' ), PHP_INT_MAX );
58
- }
59
- add_action( 'add_meta_boxes', array( $this, 'add_report_meta_box' ) );
60
- add_action( 'admin_init', array( $this, 'calculate_data' ) );
61
- add_action( 'admin_notices', array( $this, 'calculate_data_notice' ) );
62
- }
63
- }
64
-
65
- /**
66
- * validate_on_add_to_cart.
67
- *
68
- * @version 4.2.0
69
- * @since 4.2.0
70
- * @todo [dev] code refactoring (this function is very similar to `$this->check_quantities()`)
71
- * @todo [dev] (maybe) recheck `wc_add_notice()` or `wc_print_notice()`
72
- * @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 )`
73
- * @todo [feature] add replaced value `%qty_already_in_cart%` (same in `$this->check_quantities()`)
74
- * @todo [feature] add replaced value `%current_add_to_cart_qty%`
75
- * @todo [feature] (maybe) add replaced value `%remaining_qty_incl_qty_already_in_cart%`
76
- * @todo [feature] (maybe) option to choose `wc_add_notice( $message, 'error' );` or `wc_add_notice( $message, 'notice' );`
77
- */
78
- function validate_on_add_to_cart( $passed, $product_id, $quantity ) {
79
- // Get max quantity (for current product)
80
- if ( 0 == ( $max_qty = $this->get_max_qty( $product_id ) ) ) {
81
- return $passed; // no max qty set for current product
82
- }
83
- // Get quantity already bought (for current user / current product)
84
- if ( 0 == ( $current_user_id = wcj_get_current_user_id() ) ) {
85
- return $passed; // unlogged (i.e. guest) user
86
- }
87
- $user_already_bought = 0;
88
- if ( ( $users_quantities = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', true ) ) && isset( $users_quantities[ $current_user_id ] ) ) {
89
- $user_already_bought = $users_quantities[ $current_user_id ];
90
- }
91
- // Get quantity in cart (for current product)
92
- $currently_in_cart = 0;
93
- if ( isset( WC()->cart ) ) {
94
- $cart_item_quantities = WC()->cart->get_cart_item_quantities();
95
- if ( ! empty( $cart_item_quantities ) && is_array( $cart_item_quantities ) ) {
96
- foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
97
- if ( $_product_id == $product_id ) {
98
- $currently_in_cart += $cart_item_quantity;
99
- }
100
- }
101
- }
102
- }
103
- // Validate
104
- if ( ( $currently_in_cart + $user_already_bought + $quantity ) > $max_qty ) {
105
- $product = wc_get_product( $product_id );
106
- $replaced_values = array(
107
- '%max_qty%' => $max_qty,
108
- '%product_title%' => $product->get_title(),
109
- '%qty_already_bought%' => $user_already_bought,
110
- '%remaining_qty%' => max( ( $max_qty - $user_already_bought ), 0 ),
111
- );
112
- $message = get_option( 'wcj_max_products_per_user_message',
113
- __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' ) );
114
- $message = str_replace( array_keys( $replaced_values ), $replaced_values, $message );
115
- wc_add_notice( $message, 'error' );
116
- return false;
117
- }
118
- // Passed
119
- return $passed;
120
- }
121
-
122
- /**
123
- * calculate_data_notice.
124
- *
125
- * @version 3.5.0
126
- * @since 3.5.0
127
- */
128
- function calculate_data_notice() {
129
- if ( isset( $_GET['wcj_max_products_per_user_calculate_data_finished'] ) ) {
130
- $class = 'notice notice-info';
131
- $message = __( 'Data re-calculated.', 'woocommerce-jetpack' ) . ' ' .
132
- sprintf( __( '%s order(s) processed.', 'woocommerce-jetpack' ), $_GET['wcj_max_products_per_user_calculate_data_finished'] );
133
- printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
134
- }
135
- }
136
-
137
- /**
138
- * calculate_data.
139
- *
140
- * @version 4.1.0
141
- * @since 3.5.0
142
- * @todo reset `wcj_max_products_per_user_report` and `wcj_max_products_per_user_saved` meta
143
- */
144
- function calculate_data() {
145
- if ( isset( $_GET['wcj_max_products_per_user_calculate_data'] ) ) {
146
- $offset = 0;
147
- $block_size = 512;
148
- $total_orders = 0;
149
- while( true ) {
150
- $args = array(
151
- 'post_type' => 'shop_order',
152
- 'post_status' => $this->order_status,
153
- 'posts_per_page' => $block_size,
154
- 'orderby' => 'ID',
155
- 'order' => 'DESC',
156
- 'offset' => $offset,
157
- 'fields' => 'ids',
158
- );
159
- $loop = new WP_Query( $args );
160
- if ( ! $loop->have_posts() ) {
161
- break;
162
- }
163
- foreach ( $loop->posts as $_order_id ) {
164
- $this->save_quantities( $_order_id );
165
- $total_orders++;
166
- }
167
- $offset += $block_size;
168
- }
169
- wp_safe_redirect( add_query_arg( 'wcj_max_products_per_user_calculate_data_finished', $total_orders,
170
- remove_query_arg( 'wcj_max_products_per_user_calculate_data' ) ) );
171
- exit;
172
- }
173
- }
174
-
175
- /**
176
- * add_report_meta_box.
177
- *
178
- * @version 3.5.0
179
- * @since 3.5.0
180
- */
181
- function add_report_meta_box() {
182
- add_meta_box(
183
- 'wc-jetpack-' . $this->id . '-report',
184
- __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Maximum Products per User: Sales Data', 'woocommerce-jetpack' ),
185
- array( $this, 'create_report_meta_box' ),
186
- 'product',
187
- 'normal',
188
- 'high'
189
- );
190
- }
191
-
192
- /**
193
- * create_report_meta_box.
194
- *
195
- * @version 3.5.0
196
- * @since 3.5.0
197
- */
198
- function create_report_meta_box() {
199
- if ( $users_quantities = get_post_meta( get_the_ID(), '_' . 'wcj_max_products_per_user_report', true ) ) {
200
- $table_data = array();
201
- $table_data[] = array( __( 'User ID', 'woocommerce-jetpack' ), __( 'User Name', 'woocommerce-jetpack' ), __( 'Qty Bought', 'woocommerce-jetpack' ) );
202
- foreach ( $users_quantities as $user_id => $qty_bought ) {
203
- if ( 0 == $user_id ) {
204
- $user = __( 'Guest', 'woocommerce-jetpack' );
205
- } else {
206
- $user = get_user_by( 'id', $user_id );
207
- $user = ( isset( $user->data->user_nicename ) ? $user->data->user_nicename : '-' );
208
- }
209
- $table_data[] = array( $user_id, $user, $qty_bought );
210
- }
211
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal' ) );
212
- } else {
213
- echo '<em>' . __( 'No data yet.', 'woocommerce-jetpack' ) . '</em>';
214
- }
215
- }
216
-
217
- /**
218
- * save_quantities.
219
- *
220
- * @version 3.5.0
221
- * @since 3.5.0
222
- */
223
- function save_quantities( $order_id ) {
224
- if ( $order = wc_get_order( $order_id ) ) {
225
- if ( 'yes' !== get_post_meta( $order_id, '_' . 'wcj_max_products_per_user_saved', true ) ) {
226
- if ( sizeof( $order->get_items() ) > 0 ) {
227
- $user_id = ( WCJ_IS_WC_VERSION_BELOW_3 ? $order->customer_user : $order->get_customer_id() );
228
- foreach ( $order->get_items() as $item ) {
229
- if ( $item->is_type( 'line_item' ) && ( $product = $item->get_product() ) ) {
230
- $product_id = wcj_get_product_id_or_variation_parent_id( $product );
231
- $product_qty = $item->get_quantity();
232
- if ( '' == ( $users_quantities = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', true ) ) ) {
233
- $users_quantities = array();
234
- }
235
- if ( isset( $users_quantities[ $user_id ] ) ) {
236
- $product_qty += $users_quantities[ $user_id ];
237
- }
238
- $users_quantities[ $user_id ] = $product_qty;
239
- update_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', $users_quantities );
240
- }
241
- }
242
- }
243
- update_post_meta( $order_id, '_' . 'wcj_max_products_per_user_saved', 'yes' );
244
- }
245
- }
246
- }
247
-
248
- /**
249
- * get_max_qty.
250
- *
251
- * @version 3.5.0
252
- * @since 3.5.0
253
- * @todo (maybe) local - add "enabled/disabled" option
254
- * @todo (maybe) global - apply only to selected products (i.e. include/exclude products, cats, tags)
255
- * @todo (maybe) per user and/or per user role (both global and local)
256
- */
257
- function get_max_qty( $product_id ) {
258
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) && 0 != ( $qty = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_qty', true ) ) ) {
259
- return $qty;
260
- } elseif ( 'yes' === get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) ) {
261
- return get_option( 'wcj_max_products_per_user_global_max_qty', 1 );
262
- } else {
263
- return 0;
264
- }
265
- }
266
-
267
- /**
268
- * stop_from_seeing_checkout.
269
- *
270
- * @version 3.5.0
271
- * @since 3.5.0
272
- */
273
- function stop_from_seeing_checkout() {
274
- if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
275
- return;
276
- }
277
- if ( ! $this->check_quantities( false ) ) {
278
- wp_safe_redirect( wc_get_cart_url() );
279
- exit;
280
- }
281
- }
282
-
283
- /**
284
- * check_cart_quantities.
285
- *
286
- * @version 3.5.0
287
- * @since 3.5.0
288
- */
289
- function check_cart_quantities() {
290
- $this->check_quantities();
291
- }
292
-
293
- /**
294
- * check_quantities.
295
- *
296
- * @version 3.5.0
297
- * @since 3.5.0
298
- * @todo [dev] recheck `$cart_item_quantity` (maybe should be calculated same as `$currently_in_cart` in `$this->validate_on_add_to_cart()`)
299
- */
300
- function check_quantities( $add_notices = true ) {
301
- $result = true;
302
- if ( ! isset( WC()->cart ) ) {
303
- return $result;
304
- }
305
- if ( 0 == ( $current_user_id = wcj_get_current_user_id() ) ) {
306
- return $result;
307
- }
308
- $cart_item_quantities = WC()->cart->get_cart_item_quantities();
309
- if ( empty( $cart_item_quantities ) || ! is_array( $cart_item_quantities ) ) {
310
- return $result;
311
- }
312
- $is_cart = ( function_exists( 'is_cart' ) && is_cart() );
313
- foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
314
- if ( 0 == ( $max_qty = $this->get_max_qty( $_product_id ) ) ) {
315
- continue;
316
- }
317
- $user_already_bought = 0;
318
- if ( ( $users_quantities = get_post_meta( $_product_id, '_' . 'wcj_max_products_per_user_report', true ) ) && isset( $users_quantities[ $current_user_id ] ) ) {
319
- $user_already_bought = $users_quantities[ $current_user_id ];
320
- }
321
- if ( ( $user_already_bought + $cart_item_quantity ) > $max_qty ) {
322
- if ( $add_notices ) {
323
- $result = false;
324
- $product = wc_get_product( $_product_id );
325
- $replaced_values = array(
326
- '%max_qty%' => $max_qty,
327
- '%product_title%' => $product->get_title(),
328
- '%qty_already_bought%' => $user_already_bought,
329
- '%remaining_qty%' => max( ( $max_qty - $user_already_bought ), 0 ),
330
- );
331
- $message = get_option( 'wcj_max_products_per_user_message',
332
- __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' ) );
333
- $message = str_replace( array_keys( $replaced_values ), $replaced_values, $message );
334
- if ( $is_cart ) {
335
- wc_print_notice( $message, 'notice' );
336
- } else {
337
- wc_add_notice( $message, 'error' );
338
- }
339
- } else {
340
- return false;
341
- }
342
- }
343
- }
344
- return $result;
345
- }
346
-
347
- }
348
-
349
- endif;
350
-
351
- return new WCJ_Max_products_Per_User();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Max Products per User
4
+ *
5
+ * @version 4.2.0
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 4.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.', 'woocommerce-jetpack' );
32
+ $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' );
33
+ $this->link_slug = 'woocommerce-maximum-products-per-user';
34
+ parent::__construct();
35
+
36
+ if ( $this->is_enabled() ) {
37
+ if ( 'yes' === get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) || 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
38
+ add_action( 'woocommerce_checkout_process', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
39
+ add_action( 'woocommerce_before_cart', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
40
+ if ( 'yes' === get_option( 'wcj_max_products_per_user_stop_from_adding_to_cart', 'no' ) ) {
41
+ add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_on_add_to_cart' ), PHP_INT_MAX, 3 );
42
+ }
43
+ if ( 'yes' === get_option( 'wcj_max_products_per_user_stop_from_seeing_checkout', 'no' ) ) {
44
+ add_action( 'wp', array( $this, 'stop_from_seeing_checkout' ), PHP_INT_MAX );
45
+ }
46
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
47
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
48
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
49
+ }
50
+ }
51
+ $this->order_status = get_option( 'wcj_max_products_per_user_order_status', array( 'wc-completed' ) );
52
+ if ( empty( $this->order_status ) ) {
53
+ $this->order_status = array( 'wc-completed' );
54
+ }
55
+ foreach ( $this->order_status as $status ) {
56
+ $status = substr( $status, 3 );
57
+ add_action( 'woocommerce_order_status_' . $status, array( $this, 'save_quantities' ), PHP_INT_MAX );
58
+ }
59
+ add_action( 'add_meta_boxes', array( $this, 'add_report_meta_box' ) );
60
+ add_action( 'admin_init', array( $this, 'calculate_data' ) );
61
+ add_action( 'admin_notices', array( $this, 'calculate_data_notice' ) );
62
+ }
63
+ }
64
+
65
+ /**
66
+ * validate_on_add_to_cart.
67
+ *
68
+ * @version 4.2.0
69
+ * @since 4.2.0
70
+ * @todo [dev] code refactoring (this function is very similar to `$this->check_quantities()`)
71
+ * @todo [dev] (maybe) recheck `wc_add_notice()` or `wc_print_notice()`
72
+ * @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 )`
73
+ * @todo [feature] add replaced value `%qty_already_in_cart%` (same in `$this->check_quantities()`)
74
+ * @todo [feature] add replaced value `%current_add_to_cart_qty%`
75
+ * @todo [feature] (maybe) add replaced value `%remaining_qty_incl_qty_already_in_cart%`
76
+ * @todo [feature] (maybe) option to choose `wc_add_notice( $message, 'error' );` or `wc_add_notice( $message, 'notice' );`
77
+ */
78
+ function validate_on_add_to_cart( $passed, $product_id, $quantity ) {
79
+ // Get max quantity (for current product)
80
+ if ( 0 == ( $max_qty = $this->get_max_qty( $product_id ) ) ) {
81
+ return $passed; // no max qty set for current product
82
+ }
83
+ // Get quantity already bought (for current user / current product)
84
+ if ( 0 == ( $current_user_id = wcj_get_current_user_id() ) ) {
85
+ return $passed; // unlogged (i.e. guest) user
86
+ }
87
+ $user_already_bought = 0;
88
+ if ( ( $users_quantities = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', true ) ) && isset( $users_quantities[ $current_user_id ] ) ) {
89
+ $user_already_bought = $users_quantities[ $current_user_id ];
90
+ }
91
+ // Get quantity in cart (for current product)
92
+ $currently_in_cart = 0;
93
+ if ( isset( WC()->cart ) ) {
94
+ $cart_item_quantities = WC()->cart->get_cart_item_quantities();
95
+ if ( ! empty( $cart_item_quantities ) && is_array( $cart_item_quantities ) ) {
96
+ foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
97
+ if ( $_product_id == $product_id ) {
98
+ $currently_in_cart += $cart_item_quantity;
99
+ }
100
+ }
101
+ }
102
+ }
103
+ // Validate
104
+ if ( ( $currently_in_cart + $user_already_bought + $quantity ) > $max_qty ) {
105
+ $product = wc_get_product( $product_id );
106
+ $replaced_values = array(
107
+ '%max_qty%' => $max_qty,
108
+ '%product_title%' => $product->get_title(),
109
+ '%qty_already_bought%' => $user_already_bought,
110
+ '%remaining_qty%' => max( ( $max_qty - $user_already_bought ), 0 ),
111
+ );
112
+ $message = get_option( 'wcj_max_products_per_user_message',
113
+ __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' ) );
114
+ $message = str_replace( array_keys( $replaced_values ), $replaced_values, $message );
115
+ wc_add_notice( $message, 'error' );
116
+ return false;
117
+ }
118
+ // Passed
119
+ return $passed;
120
+ }
121
+
122
+ /**
123
+ * calculate_data_notice.
124
+ *
125
+ * @version 3.5.0
126
+ * @since 3.5.0
127
+ */
128
+ function calculate_data_notice() {
129
+ if ( isset( $_GET['wcj_max_products_per_user_calculate_data_finished'] ) ) {
130
+ $class = 'notice notice-info';
131
+ $message = __( 'Data re-calculated.', 'woocommerce-jetpack' ) . ' ' .
132
+ sprintf( __( '%s order(s) processed.', 'woocommerce-jetpack' ), $_GET['wcj_max_products_per_user_calculate_data_finished'] );
133
+ printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
134
+ }
135
+ }
136
+
137
+ /**
138
+ * calculate_data.
139
+ *
140
+ * @version 4.1.0
141
+ * @since 3.5.0
142
+ * @todo reset `wcj_max_products_per_user_report` and `wcj_max_products_per_user_saved` meta
143
+ */
144
+ function calculate_data() {
145
+ if ( isset( $_GET['wcj_max_products_per_user_calculate_data'] ) ) {
146
+ $offset = 0;
147
+ $block_size = 512;
148
+ $total_orders = 0;
149
+ while( true ) {
150
+ $args = array(
151
+ 'post_type' => 'shop_order',
152
+ 'post_status' => $this->order_status,
153
+ 'posts_per_page' => $block_size,
154
+ 'orderby' => 'ID',
155
+ 'order' => 'DESC',
156
+ 'offset' => $offset,
157
+ 'fields' => 'ids',
158
+ );
159
+ $loop = new WP_Query( $args );
160
+ if ( ! $loop->have_posts() ) {
161
+ break;
162
+ }
163
+ foreach ( $loop->posts as $_order_id ) {
164
+ $this->save_quantities( $_order_id );
165
+ $total_orders++;
166
+ }
167
+ $offset += $block_size;
168
+ }
169
+ wp_safe_redirect( add_query_arg( 'wcj_max_products_per_user_calculate_data_finished', $total_orders,
170
+ remove_query_arg( 'wcj_max_products_per_user_calculate_data' ) ) );
171
+ exit;
172
+ }
173
+ }
174
+
175
+ /**
176
+ * add_report_meta_box.
177
+ *
178
+ * @version 3.5.0
179
+ * @since 3.5.0
180
+ */
181
+ function add_report_meta_box() {
182
+ add_meta_box(
183
+ 'wc-jetpack-' . $this->id . '-report',
184
+ __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Maximum Products per User: Sales Data', 'woocommerce-jetpack' ),
185
+ array( $this, 'create_report_meta_box' ),
186
+ 'product',
187
+ 'normal',
188
+ 'high'
189
+ );
190
+ }
191
+
192
+ /**
193
+ * create_report_meta_box.
194
+ *
195
+ * @version 3.5.0
196
+ * @since 3.5.0
197
+ */
198
+ function create_report_meta_box() {
199
+ if ( $users_quantities = get_post_meta( get_the_ID(), '_' . 'wcj_max_products_per_user_report', true ) ) {
200
+ $table_data = array();
201
+ $table_data[] = array( __( 'User ID', 'woocommerce-jetpack' ), __( 'User Name', 'woocommerce-jetpack' ), __( 'Qty Bought', 'woocommerce-jetpack' ) );
202
+ foreach ( $users_quantities as $user_id => $qty_bought ) {
203
+ if ( 0 == $user_id ) {
204
+ $user = __( 'Guest', 'woocommerce-jetpack' );
205
+ } else {
206
+ $user = get_user_by( 'id', $user_id );
207
+ $user = ( isset( $user->data->user_nicename ) ? $user->data->user_nicename : '-' );
208
+ }
209
+ $table_data[] = array( $user_id, $user, $qty_bought );
210
+ }
211
+ echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal' ) );
212
+ } else {
213
+ echo '<em>' . __( 'No data yet.', 'woocommerce-jetpack' ) . '</em>';
214
+ }
215
+ }
216
+
217
+ /**
218
+ * save_quantities.
219
+ *
220
+ * @version 3.5.0
221
+ * @since 3.5.0
222
+ */
223
+ function save_quantities( $order_id ) {
224
+ if ( $order = wc_get_order( $order_id ) ) {
225
+ if ( 'yes' !== get_post_meta( $order_id, '_' . 'wcj_max_products_per_user_saved', true ) ) {
226
+ if ( sizeof( $order->get_items() ) > 0 ) {
227
+ $user_id = ( WCJ_IS_WC_VERSION_BELOW_3 ? $order->customer_user : $order->get_customer_id() );
228
+ foreach ( $order->get_items() as $item ) {
229
+ if ( $item->is_type( 'line_item' ) && ( $product = $item->get_product() ) ) {
230
+ $product_id = wcj_get_product_id_or_variation_parent_id( $product );
231
+ $product_qty = $item->get_quantity();
232
+ if ( '' == ( $users_quantities = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', true ) ) ) {
233
+ $users_quantities = array();
234
+ }
235
+ if ( isset( $users_quantities[ $user_id ] ) ) {
236
+ $product_qty += $users_quantities[ $user_id ];
237
+ }
238
+ $users_quantities[ $user_id ] = $product_qty;
239
+ update_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', $users_quantities );
240
+ }
241
+ }
242
+ }
243
+ update_post_meta( $order_id, '_' . 'wcj_max_products_per_user_saved', 'yes' );
244
+ }
245
+ }
246
+ }
247
+
248
+ /**
249
+ * get_max_qty.
250
+ *
251
+ * @version 3.5.0
252
+ * @since 3.5.0
253
+ * @todo (maybe) local - add "enabled/disabled" option
254
+ * @todo (maybe) global - apply only to selected products (i.e. include/exclude products, cats, tags)
255
+ * @todo (maybe) per user and/or per user role (both global and local)
256
+ */
257
+ function get_max_qty( $product_id ) {
258
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) && 0 != ( $qty = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_qty', true ) ) ) {
259
+ return $qty;
260
+ } elseif ( 'yes' === get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) ) {
261
+ return get_option( 'wcj_max_products_per_user_global_max_qty', 1 );
262
+ } else {
263
+ return 0;
264
+ }
265
+ }
266
+
267
+ /**
268
+ * stop_from_seeing_checkout.
269
+ *
270
+ * @version 3.5.0
271
+ * @since 3.5.0
272
+ */
273
+ function stop_from_seeing_checkout() {
274
+ if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
275
+ return;
276
+ }
277
+ if ( ! $this->check_quantities( false ) ) {
278
+ wp_safe_redirect( wc_get_cart_url() );
279
+ exit;
280
+ }
281
+ }
282
+
283
+ /**
284
+ * check_cart_quantities.
285
+ *
286
+ * @version 3.5.0
287
+ * @since 3.5.0
288
+ */
289
+ function check_cart_quantities() {
290
+ $this->check_quantities();
291
+ }
292
+
293
+ /**
294
+ * check_quantities.
295
+ *
296
+ * @version 3.5.0
297
+ * @since 3.5.0
298
+ * @todo [dev] recheck `$cart_item_quantity` (maybe should be calculated same as `$currently_in_cart` in `$this->validate_on_add_to_cart()`)
299
+ */
300
+ function check_quantities( $add_notices = true ) {
301
+ $result = true;
302
+ if ( ! isset( WC()->cart ) ) {
303
+ return $result;
304
+ }
305
+ if ( 0 == ( $current_user_id = wcj_get_current_user_id() ) ) {
306
+ return $result;
307
+ }
308
+ $cart_item_quantities = WC()->cart->get_cart_item_quantities();
309
+ if ( empty( $cart_item_quantities ) || ! is_array( $cart_item_quantities ) ) {
310
+ return $result;
311
+ }
312
+ $is_cart = ( function_exists( 'is_cart' ) && is_cart() );
313
+ foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
314
+ if ( 0 == ( $max_qty = $this->get_max_qty( $_product_id ) ) ) {
315
+ continue;
316
+ }
317
+ $user_already_bought = 0;
318
+ if ( ( $users_quantities = get_post_meta( $_product_id, '_' . 'wcj_max_products_per_user_report', true ) ) && isset( $users_quantities[ $current_user_id ] ) ) {
319
+ $user_already_bought = $users_quantities[ $current_user_id ];
320
+ }
321
+ if ( ( $user_already_bought + $cart_item_quantity ) > $max_qty ) {
322
+ if ( $add_notices ) {
323
+ $result = false;
324
+ $product = wc_get_product( $_product_id );
325
+ $replaced_values = array(
326
+ '%max_qty%' => $max_qty,
327
+ '%product_title%' => $product->get_title(),
328
+ '%qty_already_bought%' => $user_already_bought,
329
+ '%remaining_qty%' => max( ( $max_qty - $user_already_bought ), 0 ),
330
+ );
331
+ $message = get_option( 'wcj_max_products_per_user_message',
332
+ __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' ) );
333
+ $message = str_replace( array_keys( $replaced_values ), $replaced_values, $message );
334
+ if ( $is_cart ) {
335
+ wc_print_notice( $message, 'notice' );
336
+ } else {
337
+ wc_add_notice( $message, 'error' );
338
+ }
339
+ } else {
340
+ return false;
341
+ }
342
+ }
343
+ }
344
+ return $result;
345
+ }
346
+
347
+ }
348
+
349
+ endif;
350
+
351
+ return new WCJ_Max_products_Per_User();
includes/class-wcj-mini-cart.php CHANGED
@@ -1,65 +1,65 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Mini Cart Custom Info
4
- *
5
- * @version 2.8.0
6
- * @since 2.2.0
7
- * @author Algoritmika Ltd.
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 2.8.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.', 'woocommerce-jetpack' );
26
- $this->link_slug = 'woocommerce-mini-cart';
27
- parent::__construct();
28
-
29
- if ( $this->is_enabled() ) {
30
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_mini_cart_custom_info_total_number', 1 ) );
31
- for ( $i = 1; $i <= $total_number; $i++ ) {
32
- add_action(
33
- get_option( 'wcj_mini_cart_custom_info_hook_' . $i, 'woocommerce_after_mini_cart' ),
34
- array( $this, 'add_mini_cart_custom_info' ),
35
- get_option( 'wcj_mini_cart_custom_info_priority_' . $i, 10 )
36
- );
37
- }
38
- }
39
- }
40
-
41
- /**
42
- * add_mini_cart_custom_info.
43
- *
44
- * @version 2.4.6
45
- */
46
- function add_mini_cart_custom_info() {
47
- $current_filter = current_filter();
48
- $current_filter_priority = wcj_current_filter_priority();
49
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_mini_cart_custom_info_total_number', 1 ) );
50
- for ( $i = 1; $i <= $total_number; $i++ ) {
51
- if (
52
- '' != get_option( 'wcj_mini_cart_custom_info_content_' . $i ) &&
53
- $current_filter === get_option( 'wcj_mini_cart_custom_info_hook_' . $i, 'woocommerce_after_mini_cart' ) &&
54
- $current_filter_priority == get_option( 'wcj_mini_cart_custom_info_priority_' . $i, 10 )
55
- ) {
56
- echo do_shortcode( get_option( 'wcj_mini_cart_custom_info_content_' . $i ) );
57
- }
58
- }
59
- }
60
-
61
- }
62
-
63
- endif;
64
-
65
- return new WCJ_Mini_Cart();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Mini Cart Custom Info
4
+ *
5
+ * @version 2.8.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 2.8.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.', 'woocommerce-jetpack' );
26
+ $this->link_slug = 'woocommerce-mini-cart';
27
+ parent::__construct();
28
+
29
+ if ( $this->is_enabled() ) {
30
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_mini_cart_custom_info_total_number', 1 ) );
31
+ for ( $i = 1; $i <= $total_number; $i++ ) {
32
+ add_action(
33
+ get_option( 'wcj_mini_cart_custom_info_hook_' . $i, 'woocommerce_after_mini_cart' ),
34
+ array( $this, 'add_mini_cart_custom_info' ),
35
+ get_option( 'wcj_mini_cart_custom_info_priority_' . $i, 10 )
36
+ );
37
+ }
38
+ }
39
+ }
40
+
41
+ /**
42
+ * add_mini_cart_custom_info.
43
+ *
44
+ * @version 2.4.6
45
+ */
46
+ function add_mini_cart_custom_info() {
47
+ $current_filter = current_filter();
48
+ $current_filter_priority = wcj_current_filter_priority();
49
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_mini_cart_custom_info_total_number', 1 ) );
50
+ for ( $i = 1; $i <= $total_number; $i++ ) {
51
+ if (
52
+ '' != get_option( 'wcj_mini_cart_custom_info_content_' . $i ) &&
53
+ $current_filter === get_option( 'wcj_mini_cart_custom_info_hook_' . $i, 'woocommerce_after_mini_cart' ) &&
54
+ $current_filter_priority == get_option( 'wcj_mini_cart_custom_info_priority_' . $i, 10 )
55
+ ) {
56
+ echo do_shortcode( get_option( 'wcj_mini_cart_custom_info_content_' . $i ) );
57
+ }
58
+ }
59
+ }
60
+
61
+ }
62
+
63
+ endif;
64
+
65
+ return new WCJ_Mini_Cart();
includes/class-wcj-modules-by-user-roles.php CHANGED
@@ -1,35 +1,35 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Modules By User Roles
4
- *
5
- * @version 3.3.0
6
- * @since 3.3.0
7
- * @author Algoritmika Ltd.
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
-
35
- return new WCJ_Modules_By_User_Roles();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Modules By User Roles
4
+ *
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
+
35
+ return new WCJ_Modules_By_User_Roles();
includes/class-wcj-more-button-labels.php CHANGED
@@ -1,64 +1,64 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - More Button Labels
4
- *
5
- * @version 3.3.0
6
- * @since 2.2.0
7
- * @author Algoritmika Ltd.
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' === 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 = get_option( 'wcj_checkout_place_order_button_text', '' ) ) ) ? $new_text : $current_text;
58
- }
59
-
60
- }
61
-
62
- endif;
63
-
64
- return new WCJ_More_Button_Labels();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - More Button Labels
4
+ *
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' === 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 = get_option( 'wcj_checkout_place_order_button_text', '' ) ) ) ? $new_text : $current_text;
58
+ }
59
+
60
+ }
61
+
62
+ endif;
63
+
64
+ return new WCJ_More_Button_Labels();
includes/class-wcj-multicurrency-product-base-price.php CHANGED
@@ -1,476 +1,507 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Multicurrency Product Base Price
4
- *
5
- * @version 4.8.0
6
- * @since 2.4.8
7
- * @author Algoritmika Ltd.
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
- /**
17
- * Constructor.
18
- *
19
- * @version 4.3.1
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' );
26
- $this->desc = __( 'Enter prices for products in different currencies.', 'woocommerce-jetpack' );
27
- $this->link_slug = 'woocommerce-multicurrency-product-base-price';
28
- parent::__construct();
29
-
30
- if ( $this->is_enabled() ) {
31
-
32
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
33
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
34
- add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
35
-
36
- $this->do_convert_in_back_end = ( 'yes' === get_option( 'wcj_multicurrency_base_price_do_convert_in_back_end', 'no' ) );
37
-
38
- if ( $this->do_convert_in_back_end || wcj_is_frontend() ) {
39
- $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'multicurrency_base_price' );
40
- wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
41
- }
42
-
43
- // Compatibility with WooCommerce Price Filter Widget
44
- $this->handle_price_filter_widget_compatibility();
45
- }
46
- }
47
-
48
- /**
49
- * Adds Compatibility with WooCommerce Price Filter Widget.
50
- *
51
- * @version 4.8.0
52
- * @since 4.3.1
53
- */
54
- function handle_price_filter_widget_compatibility() {
55
- add_action( 'updated_post_meta', array( $this, 'update_base_price_meta_on_price_update' ), 10, 3 );
56
- add_action( 'updated_post_meta', array( $this, 'update_base_price_meta_on_base_price_currency_update' ), 10, 3 );
57
- add_action( 'added_post_meta', array( $this, 'update_base_price_meta_on_base_price_currency_update' ), 10, 3 );
58
- add_action( 'updated_option', array( $this, 'update_products_base_price_on_exchange_rate_change' ), 10, 3 );
59
- add_action( 'updated_post_meta', array( $this, 'handle_price_filter_compatibility_flag_on_base_price_update' ), 10, 4 );
60
- add_action( 'updated_post_meta', array( $this, 'handle_price_filter_compatibility_flag_on_base_price_currency_update' ), 10, 4 );
61
- add_filter( 'woocommerce_price_filter_sql', array( $this, 'change_woocommerce_price_filter_sql' ) );
62
- add_action( 'woocommerce_product_query', array( $this, 'modify_default_price_filter_hook' ), PHP_INT_MAX );
63
- }
64
-
65
- /**
66
- * modify_default_price_filter_hook.
67
- *
68
- * @version 4.8.0
69
- * @since 4.8.0
70
- *
71
- * @param $query
72
- *
73
- * @return mixed
74
- */
75
- function modify_default_price_filter_hook( $query ) {
76
- if (
77
- 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
78
- ! isset( $_GET['min_price'] ) ||
79
- ! isset( $_GET['max_price'] )
80
- ) {
81
- return $query;
82
- }
83
-
84
- // Remove Price Filter Meta Query
85
- $meta_query = $query->get( 'meta_query' );
86
- $meta_query = empty( $meta_query ) ? array() : $meta_query;
87
- foreach ( $meta_query as $key => $value ) {
88
- if ( is_array( $value ) ) {
89
- if ( isset( $value['price_filter'] ) ) {
90
- unset( $meta_query[ $key ]['price_filter'] );
91
- }
92
- }
93
- }
94
- $query->set( 'meta_query', $meta_query );
95
-
96
- // Remove Price Filter Hooks
97
- wcj_remove_class_filter( 'posts_clauses', 'WC_Query', 'price_filter_post_clauses' );
98
-
99
- // Remove Price Filter hooks from "Product Filter for WooCommerce" plugin
100
- if ( class_exists( 'XforWC_Product_Filters_Frontend' ) ) {
101
- remove_filter( 'posts_clauses', 'XforWC_Product_Filters_Frontend::price_filter_post_clauses', 10, 2 );
102
- }
103
-
104
- // Add Price Filter Hook
105
- add_filter( 'posts_clauses', array( $this, 'price_filter_post_clauses' ), 10, 2 );
106
- }
107
-
108
- /**
109
- * price_filter_post_clauses.
110
- *
111
- * @version 4.8.0
112
- * @since 4.8.0
113
- *
114
- * @see WC_Query::price_filter_post_clauses
115
- *
116
- * @param $args
117
- * @param $wp_query
118
- *
119
- * @return mixed
120
- */
121
- function price_filter_post_clauses( $args, $wp_query ) {
122
- global $wpdb;
123
- if ( ! $wp_query->is_main_query() || ( ! isset( $_GET['max_price'] ) && ! isset( $_GET['min_price'] ) ) ) {
124
- return $args;
125
- }
126
- $current_min_price = isset( $_GET['min_price'] ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0; // WPCS: input var ok, CSRF ok.
127
- $current_max_price = isset( $_GET['max_price'] ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : PHP_INT_MAX; // WPCS: input var ok, CSRF ok.
128
- if ( wc_tax_enabled() && 'incl' === get_option( 'woocommerce_tax_display_shop' ) && ! wc_prices_include_tax() ) {
129
- $tax_class = apply_filters( 'woocommerce_price_filter_widget_tax_class', '' ); // Uses standard tax class.
130
- $tax_rates = WC_Tax::get_rates( $tax_class );
131
- if ( $tax_rates ) {
132
- $current_min_price -= WC_Tax::get_tax_total( WC_Tax::calc_inclusive_tax( $current_min_price, $tax_rates ) );
133
- $current_max_price -= WC_Tax::get_tax_total( WC_Tax::calc_inclusive_tax( $current_max_price, $tax_rates ) );
134
- }
135
- }
136
- $args['where'] .= $wpdb->prepare(
137
- "
138
- AND {$wpdb->posts}.ID IN (
139
- SELECT p.ID
140
- FROM {$wpdb->posts} as p
141
- LEFT JOIN {$wpdb->postmeta} as pm ON p.ID = pm.post_id AND pm.meta_key = '_wcj_multicurrency_base_price'
142
- LEFT JOIN {$wpdb->postmeta} as pm2 ON (pm2.post_id=p.ID) AND (pm2.meta_key = '_price')
143
- WHERE p.post_type = 'product' AND p.post_status = 'publish'
144
- AND ( (pm.meta_value <= %f AND pm.meta_value >= %f) OR (pm2.meta_value <= %f AND pm2.meta_value >= %f) )
145
- GROUP BY p.ID
146
- )
147
- ",
148
- $current_max_price,
149
- $current_min_price,
150
- $current_max_price,
151
- $current_min_price
152
- );
153
- return $args;
154
- }
155
-
156
- /**
157
- * Changes WooCommerce Price Filter Widget SQL.
158
- *
159
- * All in all, it creates the min and max from '_price' meta, and from '_wcj_multicurrency_base_price' if there is the '_wcj_multicurrency_base_price_comp_pf' meta
160
- *
161
- * @version 4.8.0
162
- * @since 4.3.1
163
- *
164
- * @see WC_Widget_Price_Filter::get_filtered_price()
165
- * @param $sql
166
- *
167
- * @return string
168
- */
169
- function change_woocommerce_price_filter_sql($sql){
170
- if (
171
- is_admin() ||
172
- ( ! is_shop() && ! is_product_taxonomy() ) ||
173
- 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' )
174
- ) {
175
- return $sql;
176
- }
177
-
178
- global $wpdb;
179
- $args = wc()->query->get_main_query()->query_vars;
180
- $tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
181
- $meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
182
- if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
183
- $tax_query[] = array(
184
- 'taxonomy' => $args['taxonomy'],
185
- 'terms' => array( $args['term'] ),
186
- 'field' => 'slug',
187
- );
188
- }
189
- foreach ( $meta_query + $tax_query as $key => $query ) {
190
- if ( ! empty( $query['price_filter'] ) || ! empty( $query['rating_filter'] ) ) {
191
- unset( $meta_query[ $key ] );
192
- }
193
- }
194
- $meta_query = new WP_Meta_Query( $meta_query );
195
- $tax_query = new WP_Tax_Query( $tax_query );
196
- $meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
197
- $tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' );
198
- $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}";
199
- $sql .= " JOIN {$wpdb->postmeta} as pm ON {$wpdb->posts}.ID = pm.post_id " . $tax_query_sql['join'] . $meta_query_sql['join'];
200
- $sql .= " LEFT JOIN {$wpdb->postmeta} as pm2 ON {$wpdb->posts}.ID = pm2.post_id AND pm2.meta_key = '_wcj_multicurrency_base_price_comp_pf' ";
201
- $sql .= " LEFT JOIN {$wpdb->postmeta} as pm3 ON {$wpdb->posts}.ID = pm3.post_id AND pm3.meta_key = '_wcj_multicurrency_base_price' ";
202
- $sql .= " WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_post_type', array( 'product' ) ) ) ) . "')
203
- AND {$wpdb->posts}.post_status = 'publish'
204
- AND pm.meta_key IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_meta_keys', array( '_price' ) ) ) ) . "')
205
- AND pm.meta_value > '' ";
206
- $sql .= $tax_query_sql['where'] . $meta_query_sql['where'];
207
- $search = WC_Query::get_main_search_query_sql();
208
- if ( $search ) {
209
- $sql .= ' AND ' . $search;
210
- }
211
- return $sql;
212
- }
213
-
214
- /**
215
- * Updates '_wcj_multicurrency_base_price' when '_wcj_multicurrency_base_price_currency' changes.
216
- *
217
- * @version 4.3.1
218
- * @since 4.3.1
219
- *
220
- * @param $meta_id
221
- * @param $object_id
222
- * @param $meta_key
223
- */
224
- function update_base_price_meta_on_base_price_currency_update( $meta_id, $object_id, $meta_key ) {
225
- if (
226
- 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
227
- ! function_exists( 'wc_get_product' ) ||
228
- '_wcj_multicurrency_base_price_currency' !== $meta_key ||
229
- ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
230
- ) {
231
- return;
232
- }
233
- $this->update_wcj_multicurrency_base_price_meta( $product );
234
- }
235
-
236
- /**
237
- * Updates '_wcj_multicurrency_base_price' when '_price' meta is updated.
238
- *
239
- * @version 4.3.1
240
- * @since 4.3.1
241
- *
242
- * @param $meta_id
243
- * @param $object_id
244
- * @param $meta_key
245
- */
246
- function update_base_price_meta_on_price_update( $meta_id, $object_id, $meta_key ){
247
- if (
248
- 'no' === get_option('wcj_multicurrency_base_price_advanced_price_filter_comp') ||
249
- ! function_exists( 'wc_get_product' ) ||
250
- '_price' !== $meta_key ||
251
- ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
252
- ) {
253
- return;
254
- }
255
- $this->update_wcj_multicurrency_base_price_meta( $product );
256
- }
257
-
258
- /**
259
- * Updates '_wcj_multicurrency_base_price' meta on products by currency when exchange rate changes inside 'Multicurrency Product Base Price' module.
260
- *
261
- * @version 4.3.1
262
- * @since 4.3.1
263
- *
264
- * @param $option_name
265
- * @param $old_value
266
- * @param $option_value
267
- */
268
- function update_products_base_price_on_exchange_rate_change( $option_name, $old_value, $option_value ){
269
- if (
270
- 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
271
- false === strpos( $option_name, 'wcj_multicurrency_base_price_exchange_rate_' )
272
- ) {
273
- return;
274
- }
275
- $currency_number = substr( $option_name, strrpos( $option_name, '_' ) + 1 );
276
- $currency = get_option( 'wcj_multicurrency_base_price_currency_' . $currency_number );
277
- $the_query = $this->get_products_by_base_price_currency( '=', $currency );
278
- if ( $the_query->have_posts() ) {
279
- foreach ( $the_query->posts as $post_id ) {
280
- $this->update_wcj_multicurrency_base_price_meta( $post_id );
281
- }
282
- wp_reset_postdata();
283
- }
284
- }
285
-
286
- /**
287
- * Flags a product with '_wcj_multicurrency_base_price_comp_pf' if its '_wcj_multicurrency_base_price_currency' is different from base woocommerce currency.
288
- *
289
- * @version 4.3.1
290
- * @since 4.3.1
291
- *
292
- * @param $meta_id
293
- * @param $object_id
294
- * @param $meta_key
295
- * @param $meta_value
296
- */
297
- function handle_price_filter_compatibility_flag_on_base_price_currency_update( $meta_id, $object_id, $meta_key, $meta_value ) {
298
- if (
299
- 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
300
- ! function_exists( 'wc_get_product' ) ||
301
- '_wcj_multicurrency_base_price_currency' !== $meta_key ||
302
- ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
303
- ) {
304
- return;
305
- }
306
- if ( $meta_value === get_option( 'woocommerce_currency' ) ) {
307
- delete_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf' );
308
- } else {
309
- update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf', true );
310
- }
311
- }
312
-
313
- /**
314
- * Flags a product with '_wcj_multicurrency_base_price_comp_pf' if its '_price' is != '_wcj_multicurrency_base_price'
315
- *
316
- * @version 4.3.1
317
- * @since 4.3.1
318
- *
319
- * @param $meta_id
320
- * @param $object_id
321
- * @param $meta_key
322
- * @param $meta_value
323
- */
324
- function handle_price_filter_compatibility_flag_on_base_price_update( $meta_id, $object_id, $meta_key, $meta_value ) {
325
- if (
326
- 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
327
- ! function_exists( 'wc_get_product' ) ||
328
- '_wcj_multicurrency_base_price' !== $meta_key ||
329
- ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
330
- ) {
331
- return;
332
- }
333
- if ( $meta_value === get_post_meta( $product->get_id(), '_price', true ) ) {
334
- delete_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf' );
335
- } else {
336
- update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf', true );
337
- }
338
- }
339
-
340
- /**
341
- * Gets products by base price currency.
342
- *
343
- * @version 4.3.1
344
- * @since 4.3.1
345
- *
346
- * @param string $compare
347
- * @param string $currency
348
- *
349
- * @return WP_Query
350
- */
351
- function get_products_by_base_price_currency( $compare = '=', $currency = '' ) {
352
- if ( empty( $currency ) ) {
353
- $currency = get_option( 'woocommerce_currency' );
354
- }
355
- $args = array(
356
- 'post_type' => 'product',
357
- 'posts_per_page' => - 1,
358
- 'no_found_rows' => true,
359
- 'update_post_meta_cache' => false,
360
- 'update_post_term_cache' => false,
361
- 'fields' => 'ids',
362
- 'meta_query' => array(
363
- array(
364
- 'key' => '_wcj_multicurrency_base_price_currency',
365
- 'value' => $currency,
366
- 'compare' => $compare
367
- )
368
- )
369
- );
370
- $query = new WP_Query( $args );
371
- return $query;
372
- }
373
-
374
- /**
375
- * Updates '_wcj_multicurrency_base_price' meta.
376
- *
377
- * @version 4.4.0
378
- * @since 4.3.1
379
- *
380
- * @param $product
381
- * @param null $price
382
- *
383
- * @return bool
384
- */
385
- function update_wcj_multicurrency_base_price_meta( $product, $price = null ) {
386
- if ( filter_var( $product, FILTER_VALIDATE_INT ) ) {
387
- $product = wc_get_product( $product );
388
- }
389
- if ( ! is_a( $product, 'WC_Product' ) ) {
390
- return false;
391
- }
392
- if ( ! $price ) {
393
- $price = $this->change_price( get_post_meta( $product->get_id(), '_price', true ), $product );
394
- }
395
- update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price', $price );
396
- return true;
397
- }
398
-
399
- /**
400
- * change_price_grouped.
401
- *
402
- * @version 2.7.0
403
- * @since 2.5.0
404
- */
405
- function change_price_grouped( $price, $qty, $_product ) {
406
- if ( $_product->is_type( 'grouped' ) ) {
407
- foreach ( $_product->get_children() as $child_id ) {
408
- $the_price = get_post_meta( $child_id, '_price', true );
409
- $the_product = wc_get_product( $child_id );
410
- $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
411
- if ( $the_price == $price ) {
412
- return $this->change_price( $price, $the_product );
413
- }
414
- }
415
- }
416
- return $price;
417
- }
418
-
419
- /**
420
- * change_price.
421
- *
422
- * @version 2.7.0
423
- * @since 2.4.8
424
- */
425
- function change_price( $price, $_product ) {
426
- return wcj_price_by_product_base_currency( $price, wcj_get_product_id_or_variation_parent_id( $_product ) );
427
- }
428
-
429
- /**
430
- * get_variation_prices_hash.
431
- *
432
- * @version 3.5.0
433
- * @since 2.4.8
434
- */
435
- function get_variation_prices_hash( $price_hash, $_product, $display ) {
436
- $multicurrency_base_price_currency = get_post_meta( wcj_get_product_id_or_variation_parent_id( $_product, true ), '_' . 'wcj_multicurrency_base_price_currency', true );
437
- $price_hash['wcj_multicurrency_base_price'] = array(
438
- 'currency' => $multicurrency_base_price_currency,
439
- 'exchange_rate' => wcj_get_currency_exchange_rate_product_base_currency( $multicurrency_base_price_currency ),
440
- 'rounding' => get_option( 'wcj_multicurrency_base_price_round_enabled', 'no' ),
441
- 'rounding_precision' => get_option( 'wcj_multicurrency_base_price_round_precision', get_option( 'woocommerce_price_num_decimals' ) ),
442
- 'save_prices' => get_option( 'wcj_multicurrency_base_price_save_prices', 'no' ),
443
- );
444
- return $price_hash;
445
- }
446
-
447
- /**
448
- * change_currency_symbol_on_product_edit.
449
- *
450
- * @version 3.9.0
451
- * @since 2.4.8
452
- */
453
- function change_currency_symbol_on_product_edit( $currency_symbol, $currency ) {
454
- if ( is_admin() ) {
455
- global $pagenow;
456
- if (
457
- ( 'post.php' === $pagenow && isset( $_GET['action'] ) && 'edit' === $_GET['action'] ) || // admin product edit page
458
- ( ! $this->do_convert_in_back_end && 'edit.php' === $pagenow && isset( $_GET['post_type'] ) && 'product' === $_GET['post_type'] ) // admin products list
459
- ) {
460
- $multicurrency_base_price_currency = get_post_meta( get_the_ID(), '_' . 'wcj_multicurrency_base_price_currency', true );
461
- if ( '' != $multicurrency_base_price_currency ) {
462
- remove_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
463
- $return = get_woocommerce_currency_symbol( $multicurrency_base_price_currency );
464
- add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
465
- return $return;
466
- }
467
- }
468
- }
469
- return $currency_symbol;
470
- }
471
-
472
- }
473
-
474
- endif;
475
-
476
- return new WCJ_Multicurrency_Base_Price();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Multicurrency Product Base Price
4
+ *
5
+ * @version 5.0.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
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 5.0.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' );
26
+ $this->desc = __( 'Enter prices for products in different currencies.', 'woocommerce-jetpack' );
27
+ $this->link_slug = 'woocommerce-multicurrency-product-base-price';
28
+ parent::__construct();
29
+
30
+ if ( $this->is_enabled() ) {
31
+
32
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
33
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
34
+ add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
35
+
36
+ $this->do_convert_in_back_end = ( 'yes' === get_option( 'wcj_multicurrency_base_price_do_convert_in_back_end', 'no' ) );
37
+
38
+ if ( $this->do_convert_in_back_end || wcj_is_frontend() ) {
39
+ $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'multicurrency_base_price' );
40
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority, false );
41
+ }
42
+
43
+ // Compatibility with WooCommerce Price Filter Widget
44
+ $this->handle_price_filter_widget_compatibility();
45
+
46
+ // Compatibility with WooCommerce Ordering
47
+ $this->handle_wc_price_sorting();
48
+ }
49
+ }
50
+
51
+ /**
52
+ * handle_wc_ordering.
53
+ *
54
+ * @version 5.0.0
55
+ * @since 5.0.0
56
+ */
57
+ function handle_wc_price_sorting() {
58
+ add_filter( 'woocommerce_get_catalog_ordering_args', function ( $args, $orderby, $order ) {
59
+ if (
60
+ 'no' === get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ||
61
+ is_admin()
62
+ ) {
63
+ return $args;
64
+ }
65
+ add_filter( 'posts_clauses', function ( $args ) use ( $order ) {
66
+ if ( false === strpos( $args['orderby'], 'wc_product_meta_lookup' ) ) {
67
+ return $args;
68
+ }
69
+ $order_sql = 'DESC' === $order ? 'DESC' : 'ASC';
70
+ global $wpdb;
71
+ $args['join'] .= " LEFT JOIN {$wpdb->postmeta} AS pm ON ({$wpdb->posts}.ID = pm.post_id and pm.meta_key='_wcj_multicurrency_base_price')";
72
+ $args['orderby'] = " pm.meta_value + 0 {$order_sql}, wc_product_meta_lookup.product_id {$order_sql} ";
73
+ return $args;
74
+ } );
75
+ return $args;
76
+ }, 10, 3 );
77
+ }
78
+
79
+ /**
80
+ * Adds Compatibility with WooCommerce Price Filter Widget.
81
+ *
82
+ * @version 4.8.0
83
+ * @since 4.3.1
84
+ */
85
+ function handle_price_filter_widget_compatibility() {
86
+ add_action( 'updated_post_meta', array( $this, 'update_base_price_meta_on_price_update' ), 10, 3 );
87
+ add_action( 'updated_post_meta', array( $this, 'update_base_price_meta_on_base_price_currency_update' ), 10, 3 );
88
+ add_action( 'added_post_meta', array( $this, 'update_base_price_meta_on_base_price_currency_update' ), 10, 3 );
89
+ add_action( 'updated_option', array( $this, 'update_products_base_price_on_exchange_rate_change' ), 10, 3 );
90
+ add_action( 'updated_post_meta', array( $this, 'handle_price_filter_compatibility_flag_on_base_price_update' ), 10, 4 );
91
+ add_action( 'updated_post_meta', array( $this, 'handle_price_filter_compatibility_flag_on_base_price_currency_update' ), 10, 4 );
92
+ add_filter( 'woocommerce_price_filter_sql', array( $this, 'change_woocommerce_price_filter_sql' ) );
93
+ add_action( 'woocommerce_product_query', array( $this, 'modify_default_price_filter_hook' ), PHP_INT_MAX );
94
+ }
95
+
96
+ /**
97
+ * modify_default_price_filter_hook.
98
+ *
99
+ * @version 4.8.0
100
+ * @since 4.8.0
101
+ *
102
+ * @param $query
103
+ *
104
+ * @return mixed
105
+ */
106
+ function modify_default_price_filter_hook( $query ) {
107
+ if (
108
+ 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
109
+ ! isset( $_GET['min_price'] ) ||
110
+ ! isset( $_GET['max_price'] )
111
+ ) {
112
+ return $query;
113
+ }
114
+
115
+ // Remove Price Filter Meta Query
116
+ $meta_query = $query->get( 'meta_query' );
117
+ $meta_query = empty( $meta_query ) ? array() : $meta_query;
118
+ foreach ( $meta_query as $key => $value ) {
119
+ if ( is_array( $value ) ) {
120
+ if ( isset( $value['price_filter'] ) ) {
121
+ unset( $meta_query[ $key ]['price_filter'] );
122
+ }
123
+ }
124
+ }
125
+ $query->set( 'meta_query', $meta_query );
126
+
127
+ // Remove Price Filter Hooks
128
+ wcj_remove_class_filter( 'posts_clauses', 'WC_Query', 'price_filter_post_clauses' );
129
+
130
+ // Remove Price Filter hooks from "Product Filter for WooCommerce" plugin
131
+ if ( class_exists( 'XforWC_Product_Filters_Frontend' ) ) {
132
+ remove_filter( 'posts_clauses', 'XforWC_Product_Filters_Frontend::price_filter_post_clauses', 10, 2 );
133
+ }
134
+
135
+ // Add Price Filter Hook
136
+ add_filter( 'posts_clauses', array( $this, 'price_filter_post_clauses' ), 10, 2 );
137
+ }
138
+
139
+ /**
140
+ * price_filter_post_clauses.
141
+ *
142
+ * @version 4.8.0
143
+ * @since 4.8.0
144
+ *
145
+ * @see WC_Query::price_filter_post_clauses
146
+ *
147
+ * @param $args
148
+ * @param $wp_query
149
+ *
150
+ * @return mixed
151
+ */
152
+ function price_filter_post_clauses( $args, $wp_query ) {
153
+ global $wpdb;
154
+ if ( ! $wp_query->is_main_query() || ( ! isset( $_GET['max_price'] ) && ! isset( $_GET['min_price'] ) ) ) {
155
+ return $args;
156
+ }
157
+ $current_min_price = isset( $_GET['min_price'] ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0; // WPCS: input var ok, CSRF ok.
158
+ $current_max_price = isset( $_GET['max_price'] ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : PHP_INT_MAX; // WPCS: input var ok, CSRF ok.
159
+ if ( wc_tax_enabled() && 'incl' === get_option( 'woocommerce_tax_display_shop' ) && ! wc_prices_include_tax() ) {
160
+ $tax_class = apply_filters( 'woocommerce_price_filter_widget_tax_class', '' ); // Uses standard tax class.
161
+ $tax_rates = WC_Tax::get_rates( $tax_class );
162
+ if ( $tax_rates ) {
163
+ $current_min_price -= WC_Tax::get_tax_total( WC_Tax::calc_inclusive_tax( $current_min_price, $tax_rates ) );
164
+ $current_max_price -= WC_Tax::get_tax_total( WC_Tax::calc_inclusive_tax( $current_max_price, $tax_rates ) );
165
+ }
166
+ }
167
+ $args['where'] .= $wpdb->prepare(
168
+ "
169
+ AND {$wpdb->posts}.ID IN (
170
+ SELECT p.ID
171
+ FROM {$wpdb->posts} as p
172
+ LEFT JOIN {$wpdb->postmeta} as pm ON p.ID = pm.post_id AND pm.meta_key = '_wcj_multicurrency_base_price'
173
+ LEFT JOIN {$wpdb->postmeta} as pm2 ON (pm2.post_id=p.ID) AND (pm2.meta_key = '_price')
174
+ WHERE p.post_type = 'product' AND p.post_status = 'publish'
175
+ AND ( (pm.meta_value <= %f AND pm.meta_value >= %f) OR (pm2.meta_value <= %f AND pm2.meta_value >= %f) )
176
+ GROUP BY p.ID
177
+ )
178
+ ",
179
+ $current_max_price,
180
+ $current_min_price,
181
+ $current_max_price,
182
+ $current_min_price
183
+ );
184
+ return $args;
185
+ }
186
+
187
+ /**
188
+ * Changes WooCommerce Price Filter Widget SQL.
189
+ *
190
+ * All in all, it creates the min and max from '_price' meta, and from '_wcj_multicurrency_base_price' if there is the '_wcj_multicurrency_base_price_comp_pf' meta
191
+ *
192
+ * @version 4.8.0
193
+ * @since 4.3.1
194
+ *
195
+ * @see WC_Widget_Price_Filter::get_filtered_price()
196
+ * @param $sql
197
+ *
198
+ * @return string
199
+ */
200
+ function change_woocommerce_price_filter_sql($sql){
201
+ if (
202
+ is_admin() ||
203
+ ( ! is_shop() && ! is_product_taxonomy() ) ||
204
+ 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' )
205
+ ) {
206
+ return $sql;
207
+ }
208
+
209
+ global $wpdb;
210
+ $args = wc()->query->get_main_query()->query_vars;
211
+ $tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
212
+ $meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
213
+ if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
214
+ $tax_query[] = array(
215
+ 'taxonomy' => $args['taxonomy'],
216
+ 'terms' => array( $args['term'] ),
217
+ 'field' => 'slug',
218
+ );
219
+ }
220
+ foreach ( $meta_query + $tax_query as $key => $query ) {
221
+ if ( ! empty( $query['price_filter'] ) || ! empty( $query['rating_filter'] ) ) {
222
+ unset( $meta_query[ $key ] );
223
+ }
224
+ }
225
+ $meta_query = new WP_Meta_Query( $meta_query );
226
+ $tax_query = new WP_Tax_Query( $tax_query );
227
+ $meta_query_sql = $meta_query->get_sql( 'post', $wpdb->posts, 'ID' );
228
+ $tax_query_sql = $tax_query->get_sql( $wpdb->posts, 'ID' );
229
+ $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}";
230
+ $sql .= " JOIN {$wpdb->postmeta} as pm ON {$wpdb->posts}.ID = pm.post_id " . $tax_query_sql['join'] . $meta_query_sql['join'];
231
+ $sql .= " LEFT JOIN {$wpdb->postmeta} as pm2 ON {$wpdb->posts}.ID = pm2.post_id AND pm2.meta_key = '_wcj_multicurrency_base_price_comp_pf' ";
232
+ $sql .= " LEFT JOIN {$wpdb->postmeta} as pm3 ON {$wpdb->posts}.ID = pm3.post_id AND pm3.meta_key = '_wcj_multicurrency_base_price' ";
233
+ $sql .= " WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_post_type', array( 'product' ) ) ) ) . "')
234
+ AND {$wpdb->posts}.post_status = 'publish'
235
+ AND pm.meta_key IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_meta_keys', array( '_price' ) ) ) ) . "')
236
+ AND pm.meta_value > '' ";
237
+ $sql .= $tax_query_sql['where'] . $meta_query_sql['where'];
238
+ $search = WC_Query::get_main_search_query_sql();
239
+ if ( $search ) {
240
+ $sql .= ' AND ' . $search;
241
+ }
242
+ return $sql;
243
+ }
244
+
245
+ /**
246
+ * Updates '_wcj_multicurrency_base_price' when '_wcj_multicurrency_base_price_currency' changes.
247
+ *
248
+ * @version 5.0.0
249
+ * @since 4.3.1
250
+ *
251
+ * @param $meta_id
252
+ * @param $object_id
253
+ * @param $meta_key
254
+ */
255
+ function update_base_price_meta_on_base_price_currency_update( $meta_id, $object_id, $meta_key ) {
256
+ if (
257
+ ( 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp' ) && 'no' === get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ) ||
258
+ ! function_exists( 'wc_get_product' ) ||
259
+ '_wcj_multicurrency_base_price_currency' !== $meta_key ||
260
+ ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
261
+ ) {
262
+ return;
263
+ }
264
+ $this->update_wcj_multicurrency_base_price_meta( $product );
265
+ }
266
+
267
+ /**
268
+ * Updates '_wcj_multicurrency_base_price' when '_price' meta is updated.
269
+ *
270
+ * @version 5.0.0
271
+ * @since 4.3.1
272
+ *
273
+ * @param $meta_id
274
+ * @param $object_id
275
+ * @param $meta_key
276
+ */
277
+ function update_base_price_meta_on_price_update( $meta_id, $object_id, $meta_key ){
278
+ if (
279
+ ( 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp' ) && 'no' === get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ) ||
280
+ ! function_exists( 'wc_get_product' ) ||
281
+ '_price' !== $meta_key ||
282
+ ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
283
+ ) {
284
+ return;
285
+ }
286
+ $this->update_wcj_multicurrency_base_price_meta( $product );
287
+ }
288
+
289
+ /**
290
+ * Updates '_wcj_multicurrency_base_price' meta on products by currency when exchange rate changes inside 'Multicurrency Product Base Price' module.
291
+ *
292
+ * @version 5.0.0
293
+ * @since 4.3.1
294
+ *
295
+ * @param $option_name
296
+ * @param $old_value
297
+ * @param $option_value
298
+ */
299
+ function update_products_base_price_on_exchange_rate_change( $option_name, $old_value, $option_value ){
300
+ if (
301
+ ( 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp' ) && 'no' === get_option( 'wcj_multicurrency_base_price_comp_wc_price_sorting', 'no' ) ) ||
302
+ false === strpos( $option_name, 'wcj_multicurrency_base_price_exchange_rate_' )
303
+ ) {
304
+ return;
305
+ }
306
+ $currency_number = substr( $option_name, strrpos( $option_name, '_' ) + 1 );
307
+ $currency = get_option( 'wcj_multicurrency_base_price_currency_' . $currency_number );
308
+ $the_query = $this->get_products_by_base_price_currency( '=', $currency );
309
+ if ( $the_query->have_posts() ) {
310
+ foreach ( $the_query->posts as $post_id ) {
311
+ $this->update_wcj_multicurrency_base_price_meta( $post_id );
312
+ }
313
+ wp_reset_postdata();
314
+ }
315
+ }
316
+
317
+ /**
318
+ * Flags a product with '_wcj_multicurrency_base_price_comp_pf' if its '_wcj_multicurrency_base_price_currency' is different from base woocommerce currency.
319
+ *
320
+ * @version 4.3.1
321
+ * @since 4.3.1
322
+ *
323
+ * @param $meta_id
324
+ * @param $object_id
325
+ * @param $meta_key
326
+ * @param $meta_value
327
+ */
328
+ function handle_price_filter_compatibility_flag_on_base_price_currency_update( $meta_id, $object_id, $meta_key, $meta_value ) {
329
+ if (
330
+ 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
331
+ ! function_exists( 'wc_get_product' ) ||
332
+ '_wcj_multicurrency_base_price_currency' !== $meta_key ||
333
+ ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
334
+ ) {
335
+ return;
336
+ }
337
+ if ( $meta_value === get_option( 'woocommerce_currency' ) ) {
338
+ delete_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf' );
339
+ } else {
340
+ update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf', true );
341
+ }
342
+ }
343
+
344
+ /**
345
+ * Flags a product with '_wcj_multicurrency_base_price_comp_pf' if its '_price' is != '_wcj_multicurrency_base_price'
346
+ *
347
+ * @version 4.3.1
348
+ * @since 4.3.1
349
+ *
350
+ * @param $meta_id
351
+ * @param $object_id
352
+ * @param $meta_key
353
+ * @param $meta_value
354
+ */
355
+ function handle_price_filter_compatibility_flag_on_base_price_update( $meta_id, $object_id, $meta_key, $meta_value ) {
356
+ if (
357
+ 'no' === get_option( 'wcj_multicurrency_base_price_advanced_price_filter_comp', 'no' ) ||
358
+ ! function_exists( 'wc_get_product' ) ||
359
+ '_wcj_multicurrency_base_price' !== $meta_key ||
360
+ ! is_a( $product = wc_get_product( $object_id ), 'WC_Product' )
361
+ ) {
362
+ return;
363
+ }
364
+ if ( $meta_value === get_post_meta( $product->get_id(), '_price', true ) ) {
365
+ delete_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf' );
366
+ } else {
367
+ update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price_comp_pf', true );
368
+ }
369
+ }
370
+
371
+ /**
372
+ * Gets products by base price currency.
373
+ *
374
+ * @version 4.3.1
375
+ * @since 4.3.1
376
+ *
377
+ * @param string $compare
378
+ * @param string $currency
379
+ *
380
+ * @return WP_Query
381
+ */
382
+ function get_products_by_base_price_currency( $compare = '=', $currency = '' ) {
383
+ if ( empty( $currency ) ) {
384
+ $currency = get_option( 'woocommerce_currency' );
385
+ }
386
+ $args = array(
387
+ 'post_type' => 'product',
388
+ 'posts_per_page' => - 1,
389
+ 'no_found_rows' => true,
390
+ 'update_post_meta_cache' => false,
391
+ 'update_post_term_cache' => false,
392
+ 'fields' => 'ids',
393
+ 'meta_query' => array(
394
+ array(
395
+ 'key' => '_wcj_multicurrency_base_price_currency',
396
+ 'value' => $currency,
397
+ 'compare' => $compare
398
+ )
399
+ )
400
+ );
401
+ $query = new WP_Query( $args );
402
+ return $query;
403
+ }
404
+
405
+ /**
406
+ * Updates '_wcj_multicurrency_base_price' meta.
407
+ *
408
+ * @version 4.4.0
409
+ * @since 4.3.1
410
+ *
411
+ * @param $product
412
+ * @param null $price
413
+ *
414
+ * @return bool
415
+ */
416
+ function update_wcj_multicurrency_base_price_meta( $product, $price = null ) {
417
+ if ( filter_var( $product, FILTER_VALIDATE_INT ) ) {
418
+ $product = wc_get_product( $product );
419
+ }
420
+ if ( ! is_a( $product, 'WC_Product' ) ) {
421
+ return false;
422
+ }
423
+ if ( ! $price ) {
424
+ $price = $this->change_price( get_post_meta( $product->get_id(), '_price', true ), $product );
425
+ }
426
+ update_post_meta( $product->get_id(), '_wcj_multicurrency_base_price', $price );
427
+ return true;
428
+ }
429
+
430
+ /**
431
+ * change_price_grouped.
432
+ *
433
+ * @version 2.7.0
434
+ * @since 2.5.0
435
+ */
436
+ function change_price_grouped( $price, $qty, $_product ) {
437
+ if ( $_product->is_type( 'grouped' ) ) {
438
+ foreach ( $_product->get_children() as $child_id ) {
439
+ $the_price = get_post_meta( $child_id, '_price', true );
440
+ $the_product = wc_get_product( $child_id );
441
+ $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
442
+ if ( $the_price == $price ) {
443
+ return $this->change_price( $price, $the_product );
444
+ }
445
+ }
446
+ }
447
+ return $price;
448
+ }
449
+
450
+ /**
451
+ * change_price.
452
+ *
453
+ * @version 2.7.0
454
+ * @since 2.4.8
455
+ */
456
+ function change_price( $price, $_product ) {
457
+ return wcj_price_by_product_base_currency( $price, wcj_get_product_id_or_variation_parent_id( $_product ) );
458
+ }
459
+
460
+ /**
461
+ * get_variation_prices_hash.
462
+ *
463
+ * @version 3.5.0
464
+ * @since 2.4.8
465
+ */
466
+ function get_variation_prices_hash( $price_hash, $_product, $display ) {
467
+ $multicurrency_base_price_currency = get_post_meta( wcj_get_product_id_or_variation_parent_id( $_product, true ), '_' . 'wcj_multicurrency_base_price_currency', true );
468
+ $price_hash['wcj_multicurrency_base_price'] = array(
469
+ 'currency' => $multicurrency_base_price_currency,
470
+ 'exchange_rate' => wcj_get_currency_exchange_rate_product_base_currency( $multicurrency_base_price_currency ),
471
+ 'rounding' => get_option( 'wcj_multicurrency_base_price_round_enabled', 'no' ),
472
+ 'rounding_precision' => get_option( 'wcj_multicurrency_base_price_round_precision', get_option( 'woocommerce_price_num_decimals' ) ),
473
+ 'save_prices' => get_option( 'wcj_multicurrency_base_price_save_prices', 'no' ),
474
+ );
475
+ return $price_hash;
476
+ }
477
+
478
+ /**
479
+ * change_currency_symbol_on_product_edit.
480
+ *
481
+ * @version 3.9.0
482
+ * @since 2.4.8
483
+ */
484
+ function change_currency_symbol_on_product_edit( $currency_symbol, $currency ) {
485
+ if ( is_admin() ) {
486
+ global $pagenow;
487
+ if (
488
+ ( 'post.php' === $pagenow && isset( $_GET['action'] ) && 'edit' === $_GET['action'] ) || // admin product edit page
489
+ ( ! $this->do_convert_in_back_end && 'edit.php' === $pagenow && isset( $_GET['post_type'] ) && 'product' === $_GET['post_type'] ) // admin products list
490
+ ) {
491
+ $multicurrency_base_price_currency = get_post_meta( get_the_ID(), '_' . 'wcj_multicurrency_base_price_currency', true );
492
+ if ( '' != $multicurrency_base_price_currency ) {
493
+ remove_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
494
+ $return = get_woocommerce_currency_symbol( $multicurrency_base_price_currency );
495
+ add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol_on_product_edit' ), PHP_INT_MAX, 2 );
496
+ return $return;
497
+ }
498
+ }
499
+ }
500
+ return $currency_symbol;
501
+ }
502
+
503
+ }
504
+
505
+ endif;
506
+
507
+ return new WCJ_Multicurrency_Base_Price();
includes/class-wcj-multicurrency.php CHANGED
@@ -1,1154 +1,1203 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Multicurrency (Currency Switcher)
4
- *
5
- * @version 4.9.0
6
- * @since 2.4.3
7
- * @author Algoritmika Ltd.
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 4.5.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.', 'woocommerce-jetpack' );
32
- $this->link_slug = 'woocommerce-multicurrency-currency-switcher';
33
- $this->extra_desc = sprintf( __( 'After setting currencies in the Currencies Options section below, you can add switcher to the frontend with: %s', 'woocommerce-jetpack' ),
34
- '<ol>' .
35
- '<li>' . sprintf( __( '<strong>Widget:</strong> "%s"', 'woocommerce-jetpack' ),
36
- __( 'Booster - Multicurrency Switcher', 'woocommerce-jetpack' ) ) .
37
- '</li>' .
38
- '<li>' . sprintf( __( '<strong>Shortcodes:</strong> %s', 'woocommerce-jetpack' ),
39
- '<code>[wcj_currency_select_drop_down_list]</code>, <code>[wcj_currency_select_radio_list]</code>, <code>[wcj_currency_select_link_list]</code>' ) .
40
- '</li>' .
41
- '<li>' . sprintf( __( '<strong>PHP code:</strong> by using %s function, e.g.: %s', 'woocommerce-jetpack' ),
42
- '<code>do_shortcode()</code>',
43
- '<code>echo&nbsp;do_shortcode(&nbsp;\'[wcj_currency_select_drop_down_list]\'&nbsp;);</code>' ) .
44
- '</li>' .
45
- '</ol>' );
46
- parent::__construct();
47
-
48
- if ( $this->is_enabled() ) {
49
- $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'multicurrency' );
50
-
51
- // Session
52
- if ( 'wc' === WCJ_SESSION_TYPE ) {
53
- // `init()` executed on `init` hook because we need to use `WC()->session`
54
- add_action( 'init', array( $this, 'init' ) );
55
- } else {
56
- $this->init();
57
- }
58
-
59
- $this->add_hooks();
60
-
61
- if ( 'yes' === get_option( 'wcj_multicurrency_per_product_enabled' , 'yes' ) ) {
62
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
63
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
64
- }
65
-
66
- if ( is_admin() ) {
67
- include_once( 'reports/class-wcj-currency-reports.php' );
68
- }
69
-
70
- if ( 'init' === current_filter() ) {
71
- $this->init_bkg_process_class();
72
- } else {
73
- add_action( 'plugins_loaded', array( $this, 'init_bkg_process_class' ) );
74
- }
75
- }
76
- }
77
-
78
- /**
79
- * init_bkg_process_class.
80
- *
81
- * @version 4.5.0
82
- * @since 4.5.0
83
- */
84
- function init_bkg_process_class() {
85
- if ( 'yes' === get_option( 'wcj_multicurrency_update_prices_on_exch_update', 'no' ) ) {
86
- require_once( wcj_plugin_path() . '/includes/background-process/class-wcj-multicurrency-price-updater.php' );
87
- $this->bkg_process_price_updater = new WCJ_Multicurrency_Price_Updater();
88
- }
89
- }
90
-
91
- /**
92
- * Handles third party compatibility
93
- *
94
- * @version 4.9.0
95
- * @since 4.3.0
96
- */
97
- function handle_third_party_compatibility(){
98
- // "WooCommerce Smart Coupons" Compatibility
99
- if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_wc_smart_coupons' , 'yes' ) ) {
100
- add_filter( 'woocommerce_coupon_get_amount', array( $this, 'smart_coupons_get_amount' ), 10, 2 );
101
- }
102
-
103
- // WooCommerce Coupons
104
- add_filter( 'woocommerce_coupon_is_valid', array( $this, 'check_woocommerce_coupon_min_max_amount' ), 10, 3 );
105
- add_action( 'woocommerce_coupon_get_discount_amount', array( $this, 'fix_wc_coupon_currency' ), 10, 5 );
106
-
107
- // WooCommerce Price Filter Widget
108
- if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_wc_price_filter' , 'no' ) ) {
109
- add_action( 'wp_footer', array( $this, 'add_compatibility_with_price_filter_widget' ) );
110
- add_action( 'wp_footer', array( $this, 'fix_price_filter_widget_currency_format' ) );
111
- add_filter( 'woocommerce_price_filter_sql', array( $this, 'get_price_filter_sql_compatible' ), 10, 3 );
112
- add_filter( 'posts_clauses', array( $this, 'posts_clauses_price_filter_compatible' ), 11, 2 );
113
- add_filter( 'woocommerce_price_filter_widget_step', function ( $step ) {
114
- $step = 1;
115
- return $step;
116
- } );
117
- }
118
-
119
- // Sort by Price
120
- if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_price_sorting_per_product', 'no' ) ) {
121
- add_filter( 'woocommerce_get_catalog_ordering_args', array( $this, 'handle_per_product_opt_with_sort_by_price' ), 29, 3 );
122
- }
123
-
124
- // Fix WooCommerce Import
125
- if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_wc_import' , 'no' ) ) {
126
- add_filter( 'woocommerce_product_importer_parsed_data', array( $this, 'fix_wc_product_import' ), 10, 2 );
127
- }
128
-
129
- // WPC Product Bundles plugin
130
- add_action( 'woocommerce_init', function () {
131
- if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_wpc_product_bundle', 'no' ) ) {
132
- wcj_remove_class_filter( 'woocommerce_add_to_cart', 'WPcleverWoosb', 'woosb_add_to_cart' );
133
- }
134
- }, 99 );
135
-
136
- // WooCommerce Tree Table Rate Shipping (https://tablerateshipping.com/)
137
- $this->wc_tree_table_rate_shipping_compatibility();
138
-
139
- // Flexible Shipping plugin https://flexibleshipping.com/
140
- add_filter( 'flexible_shipping_value_in_currency', array( $this, 'flexible_shipping_compatibility' ) );
141
- }
142
-
143
- /**
144
- * wcj_multicurrency_compatibility_flexible_shipping.
145
- *
146
- * @see https://flexibleshipping.com
147
- *
148
- * @version 4.9.0
149
- * @since 4.9.0
150
- *
151
- */
152
- function flexible_shipping_compatibility( $value ) {
153
- if ( 'yes' !== get_option( 'wcj_multicurrency_compatibility_flexible_shipping', 'no' ) ) {
154
- return $value;
155
- }
156
- $value *= $this->get_currency_exchange_rate( $this->get_current_currency_code() );
157
- return $value;
158
- }
159
-
160
- /**
161
- * wc_tree_table_rate_shipping_compatibility.
162
- *
163
- * @see https://tablerateshipping.com/
164
- *
165
- * @version 4.9.0
166
- * @since 4.9.0
167
- */
168
- function wc_tree_table_rate_shipping_compatibility() {
169
- $shipping_instance_max = apply_filters( 'wcj_multicurrency_compatibility_wc_ttrs_instances', 90 );
170
- for ( $i = 1; $i <= $shipping_instance_max; $i ++ ) {
171
- add_filter( 'option_' . 'woocommerce_tree_table_rate_' . $i . '_settings', array( $this, 'convert_wc_tree_table_rate_settings' ) );
172
- }
173
- }
174
-
175
- /**
176
- * get_wc_tree_table_rate_settings.
177
- *
178
- * @version 4.9.0
179
- * @since 4.9.0
180
- *
181
- * @param $option
182
- *
183
- * @return mixed
184
- */
185
- function convert_wc_tree_table_rate_settings( $option ) {
186
- if ( 'no' === get_option( 'wcj_multicurrency_compatibility_wc_ttrs', 'no' ) ) {
187
- return $option;
188
- }
189
- $rule = json_decode( $option['rule'] );
190
- $modified_rule = $this->recursively_convert_wc_tree_settings( $rule, array(
191
- 'change_keys' => array( 'value', 'min', 'max' ),
192
- 'exchange_rate' => $this->get_currency_exchange_rate( $this->get_current_currency_code() )
193
- ) );
194
- $option['rule'] = json_encode( $modified_rule );
195
- return $option;
196
- }
197
-
198
- /**
199
- * recursively_convert_wc_tree_settings.
200
- *
201
- * @version 4.9.0
202
- * @since 4.9.0
203
- *
204
- * @param $array
205
- * @param null $args
206
- *
207
- * @return array
208
- */
209
- function recursively_convert_wc_tree_settings( $array, $args = null ) {
210
- $args = wp_parse_args( $args, array(
211
- 'change_keys' => array(),
212
- 'exchange_rate' => 1,
213
- ) );
214
- $change_keys = $args['change_keys'];
215
- $exchange_rate = $args['exchange_rate'];
216
- foreach ( $array as $key => $value ) {
217
- $array_test = is_array( $array ) ? $array : get_object_vars( $array );
218
- if (
219
- in_array( $key, $change_keys ) &&
220
- ( isset( $array_test['condition'] ) && ( 'price' == $array_test['condition'] ) )
221
- ) {
222
- if ( is_array( $array ) ) {
223
- if ( ! empty( $value ) && is_numeric( $value ) ) {
224
- $array[ $key ] = $value * $exchange_rate;
225
- }
226
- } elseif ( is_a( $array, 'stdClass' ) ) {
227
- if ( ! empty( $value ) && is_numeric( $value ) ) {
228
- $array->$key = $value * $exchange_rate;
229
- }
230
- }
231
- }
232
- if ( is_array( $value ) || is_a( $value, 'stdClass' ) ) {
233
- $this->recursively_convert_wc_tree_settings( $value, $args );
234
- }
235
- }
236
- return $array;
237
- }
238
-
239
- /**
240
- * @version 4.9.0
241
- * @since 4.9.0
242
- *
243
- * @param $valid
244
- * @param WC_Coupon $coupon
245
- * @param WC_Discounts $wc_discounts
246
- *
247
- * @return bool
248
- * @throws Exception
249
- */
250
- function check_woocommerce_coupon_min_max_amount( $valid, WC_Coupon $coupon, WC_Discounts $wc_discounts ) {
251
- if ( 'yes' !== get_option( 'wcj_multicurrency_compatibility_wc_coupons', 'no' ) ) {
252
- return $valid;
253
- }
254
- remove_filter( 'woocommerce_coupon_is_valid', array( $this, 'check_woocommerce_coupon_min_max_amount' ), 10 );
255
- if ( ! empty( $minimum_amount = $coupon->get_minimum_amount() ) ) {
256
- $coupon->set_minimum_amount( $this->change_price( $minimum_amount, null ) );
257
- }
258
- if ( ! empty( $maximum_amount = $coupon->get_maximum_amount() ) ) {
259
- $coupon->set_maximum_amount( $this->change_price( $maximum_amount, null ) );
260
- }
261
- $is_coupon_valid = $wc_discounts->is_coupon_valid( $coupon );
262
- if ( is_wp_error( $is_coupon_valid ) ) {
263
- return false;
264
- }
265
- return $valid;
266
- }
267
-
268
- /**
269
- * fix_wc_coupon_currency.
270
- *
271
- * @version 4.5.0
272
- * @since 4.5.0
273
- *
274
- * @param $amount
275
- * @param $discount
276
- * @param $cart_item
277
- * @param $single
278
- * @param $wc_coupon
279
- *
280
- * @return float|int
281
- */
282
- function fix_wc_coupon_currency( $amount, $discount, $cart_item, $single, $wc_coupon ) {
283
- if (
284
- 'yes' !== get_option( 'wcj_multicurrency_compatibility_wc_coupons', 'no' ) ||
285
- 'fixed_cart' !== $wc_coupon->get_discount_type()
286
- ) {
287
- return $amount;
288
- }
289
- $amount = $this->change_price( $amount, null );
290
-
291
- return $amount;
292
- }
293
-
294
- /**
295
- * Fixes sort by price when `wcj_multicurrency_per_product_enabled` is enabled.
296
- *
297
- * @version 4.6.0
298
- * @since 4.5.0
299
- *
300
- * @param $args
301
- * @param $orderby
302
- * @param $order
303
- *
304
- * @return mixed
305
- */
306
- function handle_per_product_opt_with_sort_by_price( $args, $orderby, $order ) {
307
- if (
308
- $orderby != 'price' ||
309
- is_admin() ||
310
- ! is_main_query() ||
311
- 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
312
- get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
313
- 1 === $this->get_currency_exchange_rate( $this->get_current_currency_code()
314
- )
315
- ) {
316
- return $args;
317
- }
318
- $order = 'DESC' === $order ? $order : 'ASC';
319
- add_filter( 'posts_clauses', function ( $clauses ) use ( $order ) {
320
- global $wpdb;
321
- if (
322
- false === strpos( $clauses['orderby'], 'wc_product_meta_lookup.max_price DESC' ) &&
323
- false === strpos( $clauses['orderby'], 'wc_product_meta_lookup.min_price ASC' )
324
- ) {
325
- return $clauses;
326
- }
327
- $current_currency_code = $this->get_current_currency_code();
328
- $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
329
-
330
- $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!='')";
331
- if ( false === strpos( $clauses['join'], $min_max_join ) ) {
332
- $clauses['join'] .= " {$min_max_join} ";
333
- }
334
- if ( 'DESC' === $order ) {
335
- $clauses['fields'] .= ", (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) +0) AS wcj_price ";
336
- } else {
337
- $clauses['fields'] .= ", (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_price ";
338
- }
339
- $clauses['orderby'] = " wcj_price {$order}, wc_product_meta_lookup.product_id {$order} ";
340
-
341
- return $clauses;
342
- }, 99 );
343
- return $args;
344
- }
345
-
346
- /**
347
- * Makes Price Filter Widget filter correct products if Per product option `wcj_multicurrency_per_product_enabled` is enabled.
348
- *
349
- * First it removes products witch `_wcj_multicurrency_per_product_regular_price_{$current_currency_code}` meta don't match min and max.
350
- * Then it adds products witch `_wcj_multicurrency_per_product_regular_price_{$current_currency_code}` meta match min and max.
351
- *
352
- * @version 4.6.0
353
- * @since 4.5.0
354
- *
355
- * @see WC_Query::price_filter_post_clauses()
356
- *
357
- * @param $args
358
- * @param $query
359
- *
360
- * @return mixed
361
- */
362
- function posts_clauses_price_filter_compatible( $args, $query ) {
363
- if (
364
- is_admin() ||
365
- 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
366
- get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
367
- 1 === $this->get_currency_exchange_rate( $this->get_current_currency_code() ) ||
368
- ! isset( $args['where'] ) ||
369
- (
370
- false === strpos( $args['where'], 'wc_product_meta_lookup.min_price >=' ) &&
371
- false === strpos( $args['where'], 'wc_product_meta_lookup.max_price <=' )
372
- )
373
- ) {
374
- return $args;
375
- }
376
-
377
- global $wpdb;
378
- $current_currency_code = $this->get_current_currency_code();
379
- $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
380
-
381
- $min_price = isset( $_GET['min_price'] ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0;
382
- $max_price = isset( $_GET['max_price'] ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : PHP_INT_MAX;
383
- $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!='')";
384
- if ( false === strpos( $args['join'], $min_max_join ) ) {
385
- $args['join'] .= " {$min_max_join} ";
386
- }
387
- $args['fields'] .= ", (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_min_price ";
388
- $args['fields'] .= ", (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) +0) AS wcj_max_price ";
389
- $args['where'] = preg_replace( '/and wc_product_meta_lookup.min_price >= \d.* and wc_product_meta_lookup.max_price <= \d.*\s/i', '', $args['where'] );
390
- $args['groupby'] .= " having wcj_min_price >= $min_price AND wcj_min_price <= $max_price ";
391
- return $args;
392
- }
393
-
394
- /**
395
- * Makes Price Filter Widget show correct min and max values if Per product option `wcj_multicurrency_per_product_enabled` is enabled.
396
- *
397
- * 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
398
- *
399
- * @version 4.6.0
400
- * @since 4.5.0
401
- *
402
- * @see WC_Widget_Price_Filter::get_filtered_price()
403
- *
404
- * @param $sql
405
- *
406
- * @return mixed
407
- */
408
- function get_price_filter_sql_compatible( $sql, $meta_query_sql, $tax_query_sql ) {
409
- if (
410
- is_admin() ||
411
- 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
412
- get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
413
- 1 === $this->get_currency_exchange_rate( $this->get_current_currency_code() )
414
- ) {
415
- return $sql;
416
- }
417
-
418
- global $wpdb;
419
- $current_currency_code = $this->get_current_currency_code();
420
- $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
421
- $args = WC()->query->get_main_query()->query_vars;
422
- $tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
423
- $meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
424
-
425
- if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
426
- $tax_query[] = array(
427
- 'taxonomy' => $args['taxonomy'],
428
- 'terms' => array( $args['term'] ),
429
- 'field' => 'slug',
430
- );
431
- }
432
-
433
- foreach ( $meta_query + $tax_query as $key => $query ) {
434
- if ( ! empty( $query['price_filter'] ) || ! empty( $query['rating_filter'] ) ) {
435
- unset( $meta_query[ $key ] );
436
- }
437
- }
438
-
439
- $search = WC_Query::get_main_search_query_sql();
440
- $search_query_sql = $search ? ' AND ' . $search : '';
441
-
442
- $sql = "
443
- SELECT FLOOR(min(wcj_min_price)) as min_price, CEILING(max(wcj_max_price)) as max_price
444
- FROM(
445
- 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
446
- FROM {$wpdb->wc_product_meta_lookup}
447
- LEFT JOIN {$wpdb->postmeta} AS pm on pm.post_id = product_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!='')
448
- WHERE product_id IN (
449
- SELECT ID FROM {$wpdb->posts}
450
- " . $tax_query_sql['join'] . $meta_query_sql['join'] . "
451
- WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_post_type', array( 'product' ) ) ) ) . "')
452
- AND {$wpdb->posts}.post_status = 'publish'
453
- " . $tax_query_sql['where'] . $meta_query_sql['where'] . $search_query_sql . '
454
- )
455
- group by product_id
456
- ) as wcj_min_max_price
457
- ';
458
- return $sql;
459
- }
460
-
461
- /**
462
- * Fixes WooCommerce import.
463
- *
464
- * For now it converts '_wcj_%price%_{currency}' meta with lowercase currency to uppercase.
465
- *
466
- * @version 4.4.0
467
- * @since 4.4.0
468
- *
469
- * @param $parsed_data
470
- * @param $raw_data
471
- *
472
- * @return mixed
473
- */
474
- function fix_wc_product_import( $parsed_data, $raw_data ) {
475
- // Gets values
476
- $multicurrency_values = array_filter( $parsed_data['meta_data'], function ( $value ) {
477
- return preg_match( '/^_wcj_.+price.*_[a-z]{2,3}$/', $value['key'] );
478
- } );
479
-
480
- // Changes lowercase currency to uppercase
481
- $modified_values = array_map( function ( $value ) {
482
- $str = $value['key'];
483
- $last_underscore = strrpos( $str, '_' );
484
- $before = substr( $str, 0, $last_underscore );
485
- $currency = substr( $str, $last_underscore + 1 );
486
- $value['key'] = $before . '_' . strtoupper( $currency );
487
- return $value;
488
- }, $multicurrency_values );
489
-
490
- // Applies changes to the main data
491
- foreach ( $modified_values as $i => $value ) {
492
- $parsed_data['meta_data'][ $i ]['key'] = $value['key'];
493
- }
494
-
495
- return $parsed_data;
496
- }
497
-
498
- /**
499
- * Adds compatibility with WooCommerce Price Filter widget.
500
- *
501
- * @see price-slider.js, init_price_filter()
502
- *
503
- * @version 4.6.0
504
- * @since 4.3.0
505
- */
506
- function add_compatibility_with_price_filter_widget() {
507
- if ( ! is_active_widget( false, false, 'woocommerce_price_filter' ) ) {
508
- return;
509
- }
510
- ?>
511
- <?php
512
- $exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() );
513
- if ( $exchange_rate == 1 ) {
514
- return;
515
- }
516
- ?>
517
- <input type="hidden" id="wcj_mc_exchange_rate" value="<?php echo esc_html( $exchange_rate ) ?>"/>
518
- <script>
519
- var wcj_mc_pf_slider = {
520
- slider: null,
521
- convert_rate: 1,
522
- original_min: 1,
523
- original_max: 1,
524
- original_values: [],
525
- current_min: 1,
526
- current_max: 1,
527
- current_values: [],
528
- step: 1,
529
-
530
- init(slider, convert_rate, step) {
531
- this.step = step;
532
- this.slider = slider;
533
- this.convert_rate = convert_rate;
534
- this.original_min = jQuery(this.slider).slider("option", "min");
535
- this.original_max = jQuery(this.slider).slider("option", "max");
536
- if (this.original_min > jQuery(this.slider).parent().find('#min_price').val()) {
537
- jQuery(this.slider).parent().find('#min_price').attr('value', this.original_min);
538
- }
539
- if (this.original_max < jQuery(this.slider).parent().find('#max_price').val()) {
540
- jQuery(this.slider).parent().find('#max_price').attr('value', this.original_max);
541
- }
542
- this.original_values = jQuery(this.slider).slider("option", "values");
543
- this.current_min = this.original_min * this.convert_rate;
544
- this.current_max = this.original_max * this.convert_rate;
545
- this.current_values[0] = jQuery(this.slider).parent().find('#min_price').val() * wcj_mc_pf_slider.convert_rate;
546
- this.current_values[1] = jQuery(this.slider).parent().find('#max_price').val() * wcj_mc_pf_slider.convert_rate;
547
- this.update_slider();
548
- },
549
-
550
- update_slider() {
551
- jQuery(this.slider).slider("destroy");
552
- var current_min_price = Math.floor(this.current_min);
553
- var current_max_price = Math.ceil(this.current_max);
554
-
555
- jQuery(this.slider).slider({
556
- range: true,
557
- animate: true,
558
- min: current_min_price,
559
- max: current_max_price,
560
- step: parseFloat(this.step),
561
- values: wcj_mc_pf_slider.current_values,
562
- create: function () {
563
- jQuery(wcj_mc_pf_slider.slider).parent().find('.price_slider_amount #min_price').val(Math.floor(wcj_mc_pf_slider.current_values[0] / wcj_mc_pf_slider.convert_rate));
564
- jQuery(wcj_mc_pf_slider.slider).parent().find('.price_slider_amount #max_price').val(Math.ceil(wcj_mc_pf_slider.current_values[1] / wcj_mc_pf_slider.convert_rate));
565
- jQuery(document.body).trigger('price_slider_create', [Math.floor(wcj_mc_pf_slider.current_values[0]), Math.ceil(wcj_mc_pf_slider.current_values[1])]);
566
- },
567
- slide: function (event, ui) {
568
- jQuery(wcj_mc_pf_slider.slider).parent().find('.price_slider_amount #min_price').val(Math.floor(ui.values[0] / wcj_mc_pf_slider.convert_rate));
569
- jQuery(wcj_mc_pf_slider.slider).parent().find('.price_slider_amount #max_price').val(Math.ceil(ui.values[1] / wcj_mc_pf_slider.convert_rate));
570
- var the_min = ui.values[0] == Math.round(wcj_mc_pf_slider.current_values[0]) ? Math.floor(wcj_mc_pf_slider.current_values[0]) : ui.values[0];
571
- var the_max = ui.values[1] == Math.round(wcj_mc_pf_slider.current_values[1]) ? Math.ceil(wcj_mc_pf_slider.current_values[1]) : ui.values[1];
572
- jQuery(document.body).trigger('price_slider_slide', [the_min, the_max]);
573
- },
574
- change: function (event, ui) {
575
- jQuery(document.body).trigger('price_slider_change', [ui.values[0], ui.values[1]]);
576
- }
577
- });
578
- }
579
- };
580
- var wcj_mc_pf = {
581
- price_filters: null,
582
- rate: 1,
583
- step: 1,
584
- init: function (price_filters) {
585
- this.price_filters = price_filters;
586
- this.rate = document.getElementById('wcj_mc_exchange_rate').value;
587
- this.update_slider();
588
- },
589
- update_slider: function () {
590
- [].forEach.call(wcj_mc_pf.price_filters, function (el) {
591
- wcj_mc_pf_slider.init(el, wcj_mc_pf.rate, wcj_mc_pf.step);
592
- });
593
- }
594
- }
595
- document.addEventListener("DOMContentLoaded", function () {
596
- var price_filters = document.querySelectorAll('.price_slider.ui-slider');
597
- if (price_filters.length) {
598
- wcj_mc_pf.init(price_filters);
599
- }
600
- });
601
- </script>
602
- <?php
603
- }
604
-
605
- /**
606
- * Fixes price filter widget currency format
607
- *
608
- * @version 4.3.0
609
- * @since 4.3.0
610
- */
611
- function fix_price_filter_widget_currency_format() {
612
- $price_args = apply_filters( 'wc_price_args', array(
613
- 'ex_tax_label' => false,
614
- 'currency' => '',
615
- 'decimal_separator' => wc_get_price_decimal_separator(),
616
- 'thousand_separator' => wc_get_price_thousand_separator(),
617
- 'decimals' => wc_get_price_decimals(),
618
- 'price_format' => get_woocommerce_price_format(),
619
- ) );
620
- $symbol = apply_filters( 'woocommerce_currency_symbol', get_woocommerce_currency_symbol(), get_woocommerce_currency() );
621
- wp_localize_script(
622
- 'wc-price-slider', 'woocommerce_price_slider_params', array(
623
- 'currency_format_num_decimals' => $price_args['decimals'],
624
- 'currency_format_symbol' => $symbol,
625
- 'currency_format_decimal_sep' => esc_attr( $price_args['decimal_separator'] ),
626
- 'currency_format_thousand_sep' => esc_attr( $price_args['thousand_separator'] ),
627
- 'currency_format' => esc_attr( str_replace( array( '%1$s', '%2$s' ), array( '%s', '%v' ), $price_args['price_format'] ) ),
628
- )
629
- );
630
- }
631
-
632
- /**
633
- * add_hooks.
634
- *
635
- * @version 4.3.0
636
- */
637
- function add_hooks() {
638
- if ( wcj_is_frontend() ) {
639
-
640
- // Prices - Compatibility - "WooCommerce TM Extra Product Options" plugin
641
- 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 );
642
- add_filter( 'wc_epo_price', array( $this, 'change_price_by_currency_tm_extra_product_options_plugin' ), $this->price_hooks_priority, 3 );
643
-
644
- // Currency hooks
645
- add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), $this->price_hooks_priority, 1 );
646
-
647
- // Add "Change Price" hooks
648
- wcj_add_change_price_hooks( $this, $this->price_hooks_priority );
649
-
650
- // "WooCommerce Product Add-ons" plugin
651
- add_filter( 'woocommerce_get_item_data', array( $this, 'get_addons_item_data' ), 20, 2 );
652
- add_filter( 'woocommerce_product_addons_option_price_raw', array( $this, 'product_addons_option_price_raw' ), 10, 2 );
653
-
654
- // Third Party Compatibility
655
- $this->handle_third_party_compatibility();
656
-
657
- // Additional Price Filters
658
- $this->additional_price_filters = get_option( 'wcj_multicurrency_switcher_additional_price_filters', '' );
659
- if ( ! empty( $this->additional_price_filters ) ) {
660
- $this->additional_price_filters = array_map( 'trim', explode( PHP_EOL, $this->additional_price_filters ) );
661
- foreach ( $this->additional_price_filters as $additional_price_filter ) {
662
- add_filter( $additional_price_filter, array( $this, 'change_price' ), $this->price_hooks_priority, 2 );
663
- }
664
- } else {
665
- $this->additional_price_filters = array();
666
- }
667
-
668
- } else {
669
- // Saves min and max price when product is updated
670
- add_action( 'woocommerce_update_product', function ( $post_id ) {
671
- if ( 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ) ) {
672
- return;
673
- }
674
- $this->save_min_max_prices_per_product( $post_id );
675
- }, 99 );
676
-
677
- // Saves min and max price when exchange rate changes
678
- add_action( 'updated_option', array( $this, 'update_min_max_prices_on_exchange_rate_change' ), 10, 3 );
679
- }
680
- }
681
-
682
- /**
683
- * Updates min and max prices on exchange rate change.
684
- *
685
- * The update is done with background process.
686
- *
687
- * @version 4.5.0
688
- * @since 4.5.0
689
- *
690
- * @param $option_name
691
- * @param $old_value
692
- * @param $option_value
693
- */
694
- function update_min_max_prices_on_exchange_rate_change( $option_name, $old_value, $option_value ) {
695
- if (
696
- 'no' === get_option( 'wcj_multicurrency_update_prices_on_exch_update', 'no' ) ||
697
- 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ) ||
698
- false === strpos( $option_name, 'wcj_multicurrency_exchange_rate_' )
699
- ) {
700
- return;
701
- }
702
- $currency_number = substr( $option_name, strrpos( $option_name, '_' ) + 1 );
703
- $currency = get_option( 'wcj_multicurrency_currency_' . $currency_number );
704
- $product_ids = $this->get_products_by_per_product_currency( $currency );
705
- if ( is_array( $product_ids ) && count( $product_ids ) > 0 ) {
706
- $this->bkg_process_price_updater->cancel_process();
707
- foreach ( $product_ids as $post_id ) {
708
- $this->bkg_process_price_updater->push_to_queue( array( 'id' => $post_id, 'currency' => $currency ) );
709
- }
710
- $this->bkg_process_price_updater->save()->dispatch();
711
- }
712
- }
713
-
714
- /**
715
- * Gets all products, or products with variations containing meta '_wcj_multicurrency_per_product_regular_price_{currency}' or '_wcj_multicurrency_per_product_sale_price_{currency}'.
716
- *
717
- * @version 4.6.0
718
- * @since 4.5.0
719
- *
720
- * @param $currency
721
- *
722
- * @return array
723
- */
724
- function get_products_by_per_product_currency( $currency ) {
725
- if ( empty( $currency ) ) {
726
- $currency = get_option( 'woocommerce_currency' );
727
- }
728
-
729
- global $wpdb;
730
- $product_ids = $wpdb->get_col( "
731
- SELECT p.ID
732
- FROM {$wpdb->posts} AS p
733
- LEFT JOIN {$wpdb->posts} AS p2 ON p.ID = p2.ID OR (p2.post_parent = p.ID AND p2.post_type='product_variation')
734
- LEFT JOIN {$wpdb->postmeta} AS pm ON (p2.ID = pm.post_id) AND (pm.meta_key IN ('_wcj_multicurrency_per_product_regular_price_{$currency}','_wcj_multicurrency_per_product_sale_price_{$currency}') AND pm.meta_value!='')
735
- WHERE p.post_status = 'publish' AND p.post_type IN ('product')
736
- AND pm.meta_value != 'null'
737
- GROUP BY p.ID
738
- " );
739
-
740
- return $product_ids;
741
- }
742
-
743
- /**
744
- * Updates min and max prices.
745
- *
746
- * @version 4.5.0
747
- * @since 4.5.0
748
- *
749
- * @param $post_id
750
- * @param string $currency_code_param
751
- */
752
- function save_min_max_prices_per_product( $post_id, $currency_code_param = '' ) {
753
- $product = wc_get_product( $post_id );
754
- $products = array();
755
- if ( $product->is_type( 'variable' ) ) {
756
- $available_variations = $product->get_variation_prices()['price'];
757
- foreach ( $available_variations as $variation_id => $price ) {
758
- $products[ $variation_id ] = $price;
759
- }
760
- } else {
761
- $products[ $post_id ] = $product->get_price();
762
- }
763
- if ( empty( $currency_code_param ) ) {
764
- $total_number = apply_filters( 'booster_option', 2, get_option( 'wcj_multicurrency_total_number', 2 ) );
765
- } else {
766
- $total_number = 1;
767
- }
768
-
769
- $per_product_prices = array();
770
- for ( $i = 1; $i <= $total_number; $i ++ ) {
771
- $currency_code = empty( $currency_code_param ) ? get_option( 'wcj_multicurrency_currency_' . $i ) : $currency_code_param;
772
- $exchange_rate = $this->get_currency_exchange_rate( $currency_code );
773
- foreach ( $products as $product_id => $original_price ) {
774
- // Regular Price
775
- if ( isset( $_POST["wcj_multicurrency_per_product_regular_price_{$currency_code}_{$product_id}"] ) ) {
776
- $regular_price = $_POST["wcj_multicurrency_per_product_regular_price_{$currency_code}_{$product_id}"];
777
- } else {
778
- $regular_price = get_post_meta( $product_id, '_wcj_multicurrency_per_product_regular_price_' . $currency_code, true );
779
- }
780
-
781
- // Sale Price
782
- if ( isset( $_POST["wcj_multicurrency_per_product_sale_price_{$currency_code}_{$product_id}"] ) ) {
783
- $sale_price = $_POST["wcj_multicurrency_per_product_sale_price_{$currency_code}_{$product_id}"];
784
- } else {
785
- $sale_price = get_post_meta( $product_id, '_wcj_multicurrency_per_product_sale_price_' . $currency_code, true );
786
- }
787
- $prices = array_filter( array( $regular_price, $sale_price ) );
788
- $price = count( $prices ) > 0 ? min( $prices ) : $original_price * $exchange_rate;
789
- $per_product_prices[ $currency_code ][ $product_id ] = $price;
790
- }
791
- }
792
- foreach ( $per_product_prices as $currency => $values ) {
793
- update_post_meta( $post_id, '_wcj_multicurrency_per_product_min_price_' . $currency, min( $values ) );
794
- update_post_meta( $post_id, '_wcj_multicurrency_per_product_max_price_' . $currency, max( $values ) );
795
- }
796
- }
797
-
798
- /**
799
- * Converts Smart Coupon currency.
800
- *
801
- * @version 4.3.0
802
- * @since 4.3.0
803
- *
804
- * @param $value
805
- * @param $coupon
806
- *
807
- * @return float|int
808
- */
809
- function smart_coupons_get_amount( $value, $coupon ) {
810
- if (
811
- ! is_a( $coupon, 'WC_Coupon' ) ||
812
- 'smart_coupon' !== $coupon->get_discount_type()
813
- ) {
814
- return $value;
815
- }
816
- $value = $this->change_price( $value, null );
817
- return $value;
818
- }
819
-
820
- /**
821
- * init.
822
- *
823
- * @version 3.4.5
824
- * @since 3.4.5
825
- */
826
- function init() {
827
- wcj_session_maybe_start();
828
- if ( isset( $_REQUEST['wcj-currency'] ) ) {
829
- wcj_session_set( 'wcj-currency', $_REQUEST['wcj-currency'] );
830
- }
831
- }
832
-
833
- /**
834
- * Converts add-ons plugin prices.
835
- *
836
- * @version 4.3.0
837
- * @since 4.3.0
838
- *
839
- * @param $price
840
- * @param $option
841
- *
842
- * @return float|int
843
- */
844
- function product_addons_option_price_raw( $price, $option ) {
845
- $price = $this->change_price( $price, null );
846
- return $price;
847
- }
848
-
849
- /**
850
- * Finds old add-ons fields on cart and replace by correct price.
851
- *
852
- * @version 4.3.0
853
- * @since 4.3.0
854
- *
855
- * @param $other_data
856
- * @param $cart_item
857
- *
858
- * @return mixed
859
- */
860
- function get_addons_item_data( $other_data, $cart_item ) {
861
- if ( ! empty( $cart_item['addons'] ) ) {
862
- foreach ( $cart_item['addons'] as $addon ) {
863
- $price = isset( $cart_item['addons_price_before_calc'] ) ? $cart_item['addons_price_before_calc'] : $addon['price'];
864
- $name_old = $addon['name'];
865
-
866
- // Get old field name (with wrong currency price)
867
- if ( 0 == $addon['price'] ) {
868
- $name_old .= '';
869
- } elseif ( 'percentage_based' === $addon['price_type'] && 0 == $price ) {
870
- $name_old .= '';
871
- } elseif ( 'percentage_based' !== $addon['price_type'] && $addon['price'] && apply_filters( 'woocommerce_addons_add_price_to_name', '__return_true' ) ) {
872
- $name_old .= ' (' . wc_price( \WC_Product_Addons_Helper::get_product_addon_price_for_display( $addon['price'], $cart_item['data'], true ) ) . ')';
873
- } else {
874
- $_product = new WC_Product( $cart_item['product_id'] );
875
- $_product->set_price( $price * ( $addon['price'] / 100 ) );
876
- $name_old .= ' (' . WC()->cart->get_product_price( $_product ) . ')';
877
- }
878
-
879
- // Get new field name (with correct currency price)
880
- $name_new = $addon['name'];
881
- $addon['price'] = $this->change_price( $addon['price'], null );
882
- if ( 0 == $addon['price'] ) {
883
- $name_new .= '';
884
- } elseif ( 'percentage_based' === $addon['price_type'] && 0 == $price ) {
885
- $name_new .= '';
886
- } elseif ( 'percentage_based' !== $addon['price_type'] && $addon['price'] && apply_filters( 'woocommerce_addons_add_price_to_name', '__return_true' ) ) {
887
- $name_new .= ' (' . wc_price( \WC_Product_Addons_Helper::get_product_addon_price_for_display( $addon['price'], $cart_item['data'], true ) ) . ')';
888
- } else {
889
- $_product = new WC_Product( $cart_item['product_id'] );
890
- $_product->set_price( $price * ( $addon['price'] / 100 ) );
891
- $name_new .= ' (' . WC()->cart->get_product_price( $_product ) . ')';
892
- }
893
-
894
- // Find old field on cart and replace by correct price
895
- foreach ( $other_data as $key => $data ) {
896
- if ( $data['name'] == $name_old ) {
897
- $other_data[ $key ]['name'] = $name_new;
898
- }
899
- }
900
- }
901
- }
902
- return $other_data;
903
- }
904
-
905
- /**
906
- * change_price_by_currency_tm_extra_product_options_plugin_cart.
907
- *
908
- * @version 2.7.0
909
- * @since 2.5.7
910
- */
911
- function change_price_by_currency_tm_extra_product_options_plugin_cart( $price ) {
912
- return $this->change_price( $price, null );
913
- }
914
-
915
- /**
916
- * change_price_by_currency_tm_extra_product_options_plugin.
917
- *
918
- * @version 2.7.0
919
- * @since 2.5.7
920
- */
921
- function change_price_by_currency_tm_extra_product_options_plugin( $price, $type, $post_id ) {
922
- return $this->change_price( $price, null );
923
- }
924
-
925
- /**
926
- * change_price_grouped.
927
- *
928
- * @version 2.7.0
929
- * @since 2.5.0
930
- */
931
- function change_price_grouped( $price, $qty, $_product ) {
932
- if ( $_product->is_type( 'grouped' ) ) {
933
- if ( 'yes' === get_option( 'wcj_multicurrency_per_product_enabled' , 'yes' ) ) {
934
- foreach ( $_product->get_children() as $child_id ) {
935
- $the_price = get_post_meta( $child_id, '_price', true );
936
- $the_product = wc_get_product( $child_id );
937
- $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
938
- if ( $the_price == $price ) {
939
- return $this->change_price( $price, $the_product );
940
- }
941
- }
942
- } else {
943
- return $this->change_price( $price, null );
944
- }
945
- }
946
- return $price;
947
- }
948
-
949
- /**
950
- * get_variation_prices_hash.
951
- *
952
- * @version 3.8.0
953
- */
954
- function get_variation_prices_hash( $price_hash, $_product, $display ) {
955
- $currency_code = $this->get_current_currency_code();
956
- $price_hash['wcj_multicurrency'] = array(
957
- 'currency' => $currency_code,
958
- 'exchange_rate' => $this->get_currency_exchange_rate( $currency_code ),
959
- 'per_product' => get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ),
960
- 'per_product_make_empty' => get_option( 'wcj_multicurrency_per_product_make_empty', 'no' ),
961
- 'rounding' => get_option( 'wcj_multicurrency_rounding', 'no_round' ),
962
- 'rounding_precision' => get_option( 'wcj_multicurrency_rounding_precision', absint( get_option( 'woocommerce_price_num_decimals', 2 ) ) ),
963
- );
964
- return $price_hash;
965
- }
966
-
967
- /**
968
- * get_currency_exchange_rate.
969
- *
970
- * @version 2.4.3
971
- */
972
- function get_currency_exchange_rate( $currency_code ) {
973
- $currency_exchange_rate = 1;
974
- $total_number = apply_filters( 'booster_option', 2, get_option( 'wcj_multicurrency_total_number', 2 ) );
975
- for ( $i = 1; $i <= $total_number; $i++ ) {
976
- if ( $currency_code === get_option( 'wcj_multicurrency_currency_' . $i ) ) {
977
- $currency_exchange_rate = get_option( 'wcj_multicurrency_exchange_rate_' . $i );
978
- break;
979
- }
980
- }
981
- return $currency_exchange_rate;
982
- }
983
-
984
- /**
985
- * do_revert.
986
- *
987
- * @version 3.9.0
988
- * @since 2.5.0
989
- */
990
- function do_revert() {
991
- switch ( get_option( 'wcj_multicurrency_revert', 'no' ) ) {
992
- case 'cart_only':
993
- return is_cart();
994
- case 'yes': // checkout only
995
- return is_checkout();
996
- case 'cart_and_checkout':
997
- return ( is_cart() || is_checkout() );
998
- default: // 'no'
999
- return false;
1000
- }
1001
- }
1002
-
1003
- /**
1004
- * Saves price so it won't be necessary to calculate it multiple times.
1005
- * @version 4.6.0
1006
- * @since 4.6.0
1007
- *
1008
- * @param $price
1009
- * @param $product_id
1010
- * @param $filter
1011
- */
1012
- function save_price( $price, $product_id, $filter ) {
1013
- WCJ()->modules['multicurrency']->calculated_products_prices[ $product_id ][ $filter ] = $price;
1014
- }
1015
-
1016
- /**
1017
- * change_price.
1018
- *
1019
- * @version 4.9.0
1020
- */
1021
- function change_price( $price, $_product ) {
1022
- if ( '' === $price ) {
1023
- return $price;
1024
- }
1025
-
1026
- if ( $this->do_revert() ) {
1027
- return $price;
1028
- }
1029
-
1030
- $_product_id = wcj_get_product_id( $_product );
1031
- $do_save = ( 'yes' === get_option( 'wcj_multicurrency_multicurrency_save_prices', 'no' ) );
1032
- $_current_filter = current_filter();
1033
- if ( '' == $_current_filter ) {
1034
- $_current_filter = 'wcj_filter__none';
1035
- }
1036
- if ( $do_save && isset( WCJ()->modules['multicurrency']->calculated_products_prices[ $_product_id ][ $_current_filter ] ) ) {
1037
- return WCJ()->modules['multicurrency']->calculated_products_prices[ $_product_id ][ $_current_filter ];
1038
- }
1039
-
1040
- // Per product
1041
- if ( 'yes' === get_option( 'wcj_multicurrency_per_product_enabled' , 'yes' ) && null != $_product ) {
1042
- if (
1043
- 'yes' === get_option( 'wcj_multicurrency_per_product_make_empty', 'no' ) &&
1044
- 'yes' === get_post_meta( $_product_id, '_' . 'wcj_multicurrency_per_product_make_empty_' . $this->get_current_currency_code(), true )
1045
- ) {
1046
- $price = '';
1047
- $this->save_price( $price, $_product_id, $_current_filter );
1048
- return $price;
1049
- } elseif ( '' != ( $regular_price_per_product = get_post_meta( $_product_id, '_' . 'wcj_multicurrency_per_product_regular_price_' . $this->get_current_currency_code(), true ) ) ) {
1050
- if ( 'woocommerce_get_price_including_tax' == $_current_filter || 'woocommerce_get_price_excluding_tax' == $_current_filter ) {
1051
- $price = wcj_get_product_display_price( $_product );
1052
- $this->save_price( $price, $_product_id, $_current_filter );
1053
- return $price;
1054
- } elseif ( WCJ_PRODUCT_GET_PRICE_FILTER == $_current_filter || 'woocommerce_variation_prices_price' == $_current_filter || 'woocommerce_product_variation_get_price' == $_current_filter || in_array( $_current_filter, $this->additional_price_filters ) ) {
1055
- if ( $_product->is_on_sale() ) {
1056
- $sale_price_per_product = get_post_meta( $_product_id, '_' . 'wcj_multicurrency_per_product_sale_price_' . $this->get_current_currency_code(), true );
1057
- $price = ( '' != $sale_price_per_product && $sale_price_per_product < $regular_price_per_product ) ? $sale_price_per_product : $regular_price_per_product;
1058
- } else {
1059
- $price = $regular_price_per_product;
1060
- }
1061
- $this->save_price( $price, $_product_id, $_current_filter );
1062
- return $price;
1063
- } elseif ( WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER == $_current_filter || 'woocommerce_variation_prices_regular_price' == $_current_filter || 'woocommerce_product_variation_get_regular_price' == $_current_filter ) {
1064
- $price = $regular_price_per_product;
1065
- $this->save_price( $price, $_product_id, $_current_filter );
1066
- return $price;
1067
- } elseif ( WCJ_PRODUCT_GET_SALE_PRICE_FILTER == $_current_filter || 'woocommerce_variation_prices_sale_price' == $_current_filter || 'woocommerce_product_variation_get_sale_price' == $_current_filter ) {
1068
- $sale_price_per_product = get_post_meta( $_product_id, '_' . 'wcj_multicurrency_per_product_sale_price_' . $this->get_current_currency_code(), true );
1069
- $price = ( '' != $sale_price_per_product ) ? $sale_price_per_product : $price;
1070
- $this->save_price( $price, $_product_id, $_current_filter );
1071
- return $price;
1072
- }
1073
- }
1074
- }
1075
-
1076
- // Global
1077
- if ( 1 != ( $currency_exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() ) ) ) {
1078
- $price = (float) $price * (float) $currency_exchange_rate;
1079
- switch ( get_option( 'wcj_multicurrency_rounding', 'no_round' ) ) {
1080
- case 'round':
1081
- $price = round( $price, get_option( 'wcj_multicurrency_rounding_precision', absint( get_option( 'woocommerce_price_num_decimals', 2 ) ) ) );
1082
- break;
1083
- case 'round_up':
1084
- $price = ceil( $price );
1085
- break;
1086
- case 'round_down':
1087
- $price = floor( $price );
1088
- break;
1089
- }
1090
- $this->save_price( $price, $_product_id, $_current_filter );
1091
- return $price;
1092
- }
1093
-
1094
- // No changes
1095
- $this->save_price( $price, $_product_id, $_current_filter );
1096
- return $price;
1097
- }
1098
-
1099
- /**
1100
- * get_current_currency_code.
1101
- *
1102
- * @version 3.4.0
1103
- */
1104
- function get_current_currency_code( $default_currency = '' ) {
1105
- if ( null !== ( $session_value = wcj_session_get( 'wcj-currency' ) ) ) {
1106
- return $session_value;
1107
- } else {
1108
- $module_roles = get_option( 'wcj_multicurrency_role_defaults_roles', '' );
1109
- if ( ! empty( $module_roles ) ) {
1110
- $current_user_role = wcj_get_current_user_first_role();
1111
- if ( in_array( $current_user_role, $module_roles ) ) {
1112
- $roles_default_currency = get_option( 'wcj_multicurrency_role_defaults_' . $current_user_role, '' );
1113
- if ( '' != $roles_default_currency ) {
1114
- return $roles_default_currency;
1115
- }
1116
- }
1117
- }
1118
- }
1119
- return $default_currency;
1120
- }
1121
-
1122
- /**
1123
- * change_currency_code.
1124
- *
1125
- * @version 2.5.0
1126
- */
1127
- function change_currency_code( $currency ) {
1128
- if ( $this->do_revert() ) {
1129
- return $currency;
1130
- }
1131
- return $this->get_current_currency_code( $currency );
1132
- }
1133
-
1134
- /**
1135
- * change_price_shipping.
1136
- *
1137
- * @version 4.9.0
1138
- */
1139
- function change_price_shipping( $package_rates, $package ) {
1140
- if (
1141
- $this->do_revert() ||
1142
- 'no' === get_option( 'wcj_multicurrency_convert_shipping_values', 'yes' )
1143
- ) {
1144
- return $package_rates;
1145
- }
1146
- $currency_exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() );
1147
- return wcj_change_price_shipping_package_rates( $package_rates, $currency_exchange_rate );
1148
- }
1149
-
1150
- }
1151
-
1152
- endif;
1153
-
1154
- return new WCJ_Multicurrency();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Multicurrency (Currency Switcher)
4
+ *
5
+ * @version 5.0.0
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 4.5.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.', 'woocommerce-jetpack' );
32
+ $this->link_slug = 'woocommerce-multicurrency-currency-switcher';
33
+ $this->extra_desc = sprintf( __( 'After setting currencies in the Currencies Options section below, you can add switcher to the frontend with: %s', 'woocommerce-jetpack' ),
34
+ '<ol>' .
35
+ '<li>' . sprintf( __( '<strong>Widget:</strong> "%s"', 'woocommerce-jetpack' ),
36
+ __( 'Booster - Multicurrency Switcher', 'woocommerce-jetpack' ) ) .
37
+ '</li>' .
38
+ '<li>' . sprintf( __( '<strong>Shortcodes:</strong> %s', 'woocommerce-jetpack' ),
39
+ '<code>[wcj_currency_select_drop_down_list]</code>, <code>[wcj_currency_select_radio_list]</code>, <code>[wcj_currency_select_link_list]</code>' ) .
40
+ '</li>' .
41
+ '<li>' . sprintf( __( '<strong>PHP code:</strong> by using %s function, e.g.: %s', 'woocommerce-jetpack' ),
42
+ '<code>do_shortcode()</code>',
43
+ '<code>echo&nbsp;do_shortcode(&nbsp;\'[wcj_currency_select_drop_down_list]\'&nbsp;);</code>' ) .
44
+ '</li>' .
45
+ '</ol>' );
46
+ parent::__construct();
47
+
48
+ if ( $this->is_enabled() ) {
49
+ $this->price_hooks_priority = wcj_get_module_price_hooks_priority( 'multicurrency' );
50
+
51
+ // Session
52
+ if ( 'wc' === WCJ_SESSION_TYPE ) {
53
+ // `init()` executed on `init` hook because we need to use `WC()->session`
54
+ add_action( 'init', array( $this, 'init' ) );
55
+ } else {
56
+ $this->init();
57
+ }
58
+
59
+ $this->add_hooks();
60
+
61
+ if ( 'yes' === get_option( 'wcj_multicurrency_per_product_enabled' , 'yes' ) ) {
62
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
63
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
64
+ }
65
+
66
+ if ( is_admin() ) {
67
+ include_once( 'reports/class-wcj-currency-reports.php' );
68
+ }
69
+
70
+ if ( 'init' === current_filter() ) {
71
+ $this->init_bkg_process_class();
72
+ } else {
73
+ add_action( 'plugins_loaded', array( $this, 'init_bkg_process_class' ) );
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * init_bkg_process_class.
80
+ *
81
+ * @version 4.5.0
82
+ * @since 4.5.0
83
+ */
84
+ function init_bkg_process_class() {
85
+ if ( 'yes' === get_option( 'wcj_multicurrency_update_prices_on_exch_update', 'no' ) ) {
86
+ require_once( wcj_plugin_path() . '/includes/background-process/class-wcj-multicurrency-price-updater.php' );
87
+ $this->bkg_process_price_updater = new WCJ_Multicurrency_Price_Updater();
88
+ }
89
+ }
90
+
91
+ /**
92
+ * Handles third party compatibility
93
+ *
94
+ * @version 5.0.0
95
+ * @since 4.3.0
96
+ */
97
+ function handle_compatibility(){
98
+ // "WooCommerce Smart Coupons" Compatibility
99
+ if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_wc_smart_coupons' , 'yes' ) ) {
100
+ add_filter( 'woocommerce_coupon_get_amount', array( $this, 'smart_coupons_get_amount' ), 10, 2 );
101
+ }
102
+
103
+ // WooCommerce Coupons
104
+ add_filter( 'woocommerce_coupon_is_valid', array( $this, 'check_woocommerce_coupon_min_max_amount' ), 10, 3 );
105
+ add_action( 'woocommerce_coupon_get_discount_amount', array( $this, 'fix_wc_coupon_currency' ), 10, 5 );
106
+
107
+ // WooCommerce Price Filter Widget
108
+ if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_wc_price_filter' , 'no' ) ) {
109
+ add_action( 'wp_footer', array( $this, 'add_compatibility_with_price_filter_widget' ) );
110
+ add_action( 'wp_footer', array( $this, 'fix_price_filter_widget_currency_format' ) );
111
+ add_filter( 'woocommerce_price_filter_sql', array( $this, 'get_price_filter_sql_compatible' ), 10, 3 );
112
+ add_filter( 'posts_clauses', array( $this, 'posts_clauses_price_filter_compatible' ), 11, 2 );
113
+ add_filter( 'woocommerce_price_filter_widget_step', function ( $step ) {
114
+ $step = 1;
115
+ return $step;
116
+ } );
117
+ }
118
+
119
+ // Sort by Price
120
+ if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_price_sorting_per_product', 'no' ) ) {
121
+ add_filter( 'woocommerce_get_catalog_ordering_args', array( $this, 'handle_per_product_opt_with_sort_by_price' ), 29, 3 );
122
+ }
123
+
124
+ // Fix WooCommerce Import
125
+ if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_wc_import' , 'no' ) ) {
126
+ add_filter( 'woocommerce_product_importer_parsed_data', array( $this, 'fix_wc_product_import' ), 10, 2 );
127
+ }
128
+
129
+ // WPC Product Bundles plugin
130
+ add_action( 'woocommerce_init', function () {
131
+ if ( 'yes' === get_option( 'wcj_multicurrency_compatibility_wpc_product_bundle', 'no' ) ) {
132
+ wcj_remove_class_filter( 'woocommerce_add_to_cart', 'WPcleverWoosb', 'woosb_add_to_cart' );
133
+ }
134
+ }, 99 );
135
+
136
+ // WooCommerce Tree Table Rate Shipping (https://tablerateshipping.com/)
137
+ $this->wc_tree_table_rate_shipping_compatibility();
138
+
139
+ // Flexible Shipping plugin https://flexibleshipping.com/
140
+ add_filter( 'flexible_shipping_value_in_currency', array( $this, 'flexible_shipping_compatibility' ) );
141
+
142
+ // Compatibility with Price by Country module
143
+ add_action( 'wcj_price_by_country_set_country', array( $this, 'change_currency_by_country' ), 10, 2 );
144
+
145
+ // Compatibility with Pricing Deals
146
+ add_filter( 'option_' . 'vtprd_rules_set', array( $this, 'convert_pricing_deals_settings' ) );
147
+ }
148
+
149
+ /**
150
+ * convert_pricing_deals_settings.
151
+ *
152
+ * @version 5.0.0
153
+ * @since 5.0.0
154
+ *
155
+ * @param $option
156
+ *
157
+ * @return mixed
158
+ */
159
+ function convert_pricing_deals_settings( $option ) {
160
+ if ( 'no' === get_option( 'wcj_multicurrency_compatibility_pricing_deals', 'no' ) ) {
161
+ return $option;
162
+ }
163
+ foreach ( $option as $key => $value ) {
164
+ foreach ( $value->rule_deal_info as $deal_info_key => $deal_info_value ) {
165
+ if ( 'currency' === $deal_info_value['buy_amt_type'] ) {
166
+ $option[ $key ]->rule_deal_info[ $deal_info_key ]['buy_amt_count'] *= $this->get_currency_exchange_rate( $this->get_current_currency_code() );
167
+ }
168
+ }
169
+ }
170
+ return $option;
171
+ }
172
+
173
+ /**
174
+ * change_currency_by_country.
175
+ *
176
+ * @version 5.0.0
177
+ * @since 5.0.0
178
+ *
179
+ * @param $country
180
+ * @param $currency
181
+ */
182
+ function change_currency_by_country( $country, $currency ) {
183
+ if (
184
+ empty( $currency ) ||
185
+ 'no' === get_option( 'wcj_multicurrency_compatibility_price_by_country_module', 'no' )
186
+ ) {
187
+ return;
188
+ }
189
+ wcj_session_set( 'wcj-currency', $currency );
190
+ }
191
+
192
+ /**
193
+ * wcj_multicurrency_compatibility_flexible_shipping.
194
+ *
195
+ * @see https://flexibleshipping.com
196
+ *
197
+ * @version 4.9.0
198
+ * @since 4.9.0
199
+ *
200
+ */
201
+ function flexible_shipping_compatibility( $value ) {
202
+ if ( 'yes' !== get_option( 'wcj_multicurrency_compatibility_flexible_shipping', 'no' ) ) {
203
+ return $value;
204
+ }
205
+ $value *= $this->get_currency_exchange_rate( $this->get_current_currency_code() );
206
+ return $value;
207
+ }
208
+
209
+ /**
210
+ * wc_tree_table_rate_shipping_compatibility.
211
+ *
212
+ * @see https://tablerateshipping.com/
213
+ *
214
+ * @version 4.9.0
215
+ * @since 4.9.0
216
+ */
217
+ function wc_tree_table_rate_shipping_compatibility() {
218
+ $shipping_instance_max = apply_filters( 'wcj_multicurrency_compatibility_wc_ttrs_instances', 90 );
219
+ for ( $i = 1; $i <= $shipping_instance_max; $i ++ ) {
220
+ add_filter( 'option_' . 'woocommerce_tree_table_rate_' . $i . '_settings', array( $this, 'convert_wc_tree_table_rate_settings' ) );
221
+ }
222
+ }
223
+
224
+ /**
225
+ * get_wc_tree_table_rate_settings.
226
+ *
227
+ * @version 4.9.0
228
+ * @since 4.9.0
229
+ *
230
+ * @param $option
231
+ *
232
+ * @return mixed
233
+ */
234
+ function convert_wc_tree_table_rate_settings( $option ) {
235
+ if ( 'no' === get_option( 'wcj_multicurrency_compatibility_wc_ttrs', 'no' ) ) {
236
+ return $option;
237
+ }
238
+ $rule = json_decode( $option['rule'] );
239
+ $modified_rule = $this->recursively_convert_wc_tree_settings( $rule, array(
240
+ 'change_keys' => array( 'value', 'min', 'max' ),
241
+ 'exchange_rate' => $this->get_currency_exchange_rate( $this->get_current_currency_code() )
242
+ ) );
243
+ $option['rule'] = json_encode( $modified_rule );
244
+ return $option;
245
+ }
246
+
247
+ /**
248
+ * recursively_convert_wc_tree_settings.
249
+ *
250
+ * @version 4.9.0
251
+ * @since 4.9.0
252
+ *
253
+ * @param $array
254
+ * @param null $args
255
+ *
256
+ * @return array
257
+ */
258
+ function recursively_convert_wc_tree_settings( $array, $args = null ) {
259
+ $args = wp_parse_args( $args, array(
260
+ 'change_keys' => array(),
261
+ 'exchange_rate' => 1,
262
+ ) );
263
+ $change_keys = $args['change_keys'];
264
+ $exchange_rate = $args['exchange_rate'];
265
+ foreach ( $array as $key => $value ) {
266
+ $array_test = is_array( $array ) ? $array : get_object_vars( $array );
267
+ if (
268
+ in_array( $key, $change_keys ) &&
269
+ ( isset( $array_test['condition'] ) && ( 'price' == $array_test['condition'] ) )
270
+ ) {
271
+ if ( is_array( $array ) ) {
272
+ if ( ! empty( $value ) && is_numeric( $value ) ) {
273
+ $array[ $key ] = $value * $exchange_rate;
274
+ }
275
+ } elseif ( is_a( $array, 'stdClass' ) ) {
276
+ if ( ! empty( $value ) && is_numeric( $value ) ) {
277
+ $array->$key = $value * $exchange_rate;
278
+ }
279
+ }
280
+ }
281
+ if ( is_array( $value ) || is_a( $value, 'stdClass' ) ) {
282
+ $this->recursively_convert_wc_tree_settings( $value, $args );
283
+ }
284
+ }
285
+ return $array;
286
+ }
287
+
288
+ /**
289
+ * @version 4.9.0
290
+ * @since 4.9.0
291
+ *
292
+ * @param $valid
293
+ * @param WC_Coupon $coupon
294
+ * @param WC_Discounts $wc_discounts
295
+ *
296
+ * @return bool
297
+ * @throws Exception
298
+ */
299
+ function check_woocommerce_coupon_min_max_amount( $valid, WC_Coupon $coupon, WC_Discounts $wc_discounts ) {
300
+ if ( 'yes' !== get_option( 'wcj_multicurrency_compatibility_wc_coupons', 'no' ) ) {
301
+ return $valid;
302
+ }
303
+ remove_filter( 'woocommerce_coupon_is_valid', array( $this, 'check_woocommerce_coupon_min_max_amount' ), 10 );
304
+ if ( ! empty( $minimum_amount = $coupon->get_minimum_amount() ) ) {
305
+ $coupon->set_minimum_amount( $this->change_price( $minimum_amount, null ) );
306
+ }
307
+ if ( ! empty( $maximum_amount = $coupon->get_maximum_amount() ) ) {
308
+ $coupon->set_maximum_amount( $this->change_price( $maximum_amount, null ) );
309
+ }
310
+ $is_coupon_valid = $wc_discounts->is_coupon_valid( $coupon );
311
+ if ( is_wp_error( $is_coupon_valid ) ) {
312
+ return false;
313
+ }
314
+ return $valid;
315
+ }
316
+
317
+ /**
318
+ * fix_wc_coupon_currency.
319
+ *
320
+ * @version 4.5.0
321
+ * @since 4.5.0
322
+ *
323
+ * @param $amount
324
+ * @param $discount
325
+ * @param $cart_item
326
+ * @param $single
327
+ * @param $wc_coupon
328
+ *
329
+ * @return float|int
330
+ */
331
+ function fix_wc_coupon_currency( $amount, $discount, $cart_item, $single, $wc_coupon ) {
332
+ if (
333
+ 'yes' !== get_option( 'wcj_multicurrency_compatibility_wc_coupons', 'no' ) ||
334
+ 'fixed_cart' !== $wc_coupon->get_discount_type()
335
+ ) {
336
+ return $amount;
337
+ }
338
+ $amount = $this->change_price( $amount, null );
339
+
340
+ return $amount;
341
+ }
342
+
343
+ /**
344
+ * Fixes sort by price when `wcj_multicurrency_per_product_enabled` is enabled.
345
+ *
346
+ * @version 4.6.0
347
+ * @since 4.5.0
348
+ *
349
+ * @param $args
350
+ * @param $orderby
351
+ * @param $order
352
+ *
353
+ * @return mixed
354
+ */
355
+ function handle_per_product_opt_with_sort_by_price( $args, $orderby, $order ) {
356
+ if (
357
+ $orderby != 'price' ||
358
+ is_admin() ||
359
+ ! is_main_query() ||
360
+ 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
361
+ get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
362
+ 1 === $this->get_currency_exchange_rate( $this->get_current_currency_code()
363
+ )
364
+ ) {
365
+ return $args;
366
+ }
367
+ $order = 'DESC' === $order ? $order : 'ASC';
368
+ add_filter( 'posts_clauses', function ( $clauses ) use ( $order ) {
369
+ global $wpdb;
370
+ if (
371
+ false === strpos( $clauses['orderby'], 'wc_product_meta_lookup.max_price DESC' ) &&
372
+ false === strpos( $clauses['orderby'], 'wc_product_meta_lookup.min_price ASC' )
373
+ ) {
374
+ return $clauses;
375
+ }
376
+ $current_currency_code = $this->get_current_currency_code();
377
+ $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
378
+
379
+ $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!='')";
380
+ if ( false === strpos( $clauses['join'], $min_max_join ) ) {
381
+ $clauses['join'] .= " {$min_max_join} ";
382
+ }
383
+ if ( 'DESC' === $order ) {
384
+ $clauses['fields'] .= ", (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) +0) AS wcj_price ";
385
+ } else {
386
+ $clauses['fields'] .= ", (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_price ";
387
+ }
388
+ $clauses['orderby'] = " wcj_price {$order}, wc_product_meta_lookup.product_id {$order} ";
389
+
390
+ return $clauses;
391
+ }, 99 );
392
+ return $args;
393
+ }
394
+
395
+ /**
396
+ * Makes Price Filter Widget filter correct products if Per product option `wcj_multicurrency_per_product_enabled` is enabled.
397
+ *
398
+ * First it removes products witch `_wcj_multicurrency_per_product_regular_price_{$current_currency_code}` meta don't match min and max.
399
+ * Then it adds products witch `_wcj_multicurrency_per_product_regular_price_{$current_currency_code}` meta match min and max.
400
+ *
401
+ * @version 4.6.0
402
+ * @since 4.5.0
403
+ *
404
+ * @see WC_Query::price_filter_post_clauses()
405
+ *
406
+ * @param $args
407
+ * @param $query
408
+ *
409
+ * @return mixed
410
+ */
411
+ function posts_clauses_price_filter_compatible( $args, $query ) {
412
+ if (
413
+ is_admin() ||
414
+ 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
415
+ get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
416
+ 1 === $this->get_currency_exchange_rate( $this->get_current_currency_code() ) ||
417
+ ! isset( $args['where'] ) ||
418
+ (
419
+ false === strpos( $args['where'], 'wc_product_meta_lookup.min_price >=' ) &&
420
+ false === strpos( $args['where'], 'wc_product_meta_lookup.max_price <=' )
421
+ )
422
+ ) {
423
+ return $args;
424
+ }
425
+
426
+ global $wpdb;
427
+ $current_currency_code = $this->get_current_currency_code();
428
+ $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
429
+
430
+ $min_price = isset( $_GET['min_price'] ) ? floatval( wp_unslash( $_GET['min_price'] ) ) : 0;
431
+ $max_price = isset( $_GET['max_price'] ) ? floatval( wp_unslash( $_GET['max_price'] ) ) : PHP_INT_MAX;
432
+ $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!='')";
433
+ if ( false === strpos( $args['join'], $min_max_join ) ) {
434
+ $args['join'] .= " {$min_max_join} ";
435
+ }
436
+ $args['fields'] .= ", (IFNULL(MIN((pm.meta_value +0))/{$exchange_rate},min_price) +0) AS wcj_min_price ";
437
+ $args['fields'] .= ", (IFNULL(MAX((pm.meta_value +0))/{$exchange_rate},max_price) +0) AS wcj_max_price ";
438
+ $args['where'] = preg_replace( '/and wc_product_meta_lookup.min_price >= \d.* and wc_product_meta_lookup.max_price <= \d.*\s/i', '', $args['where'] );
439
+ $args['groupby'] .= " having wcj_min_price >= $min_price AND wcj_min_price <= $max_price ";
440
+ return $args;
441
+ }
442
+
443
+ /**
444
+ * Makes Price Filter Widget show correct min and max values if Per product option `wcj_multicurrency_per_product_enabled` is enabled.
445
+ *
446
+ * 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
447
+ *
448
+ * @version 4.6.0
449
+ * @since 4.5.0
450
+ *
451
+ * @see WC_Widget_Price_Filter::get_filtered_price()
452
+ *
453
+ * @param $sql
454
+ *
455
+ * @return mixed
456
+ */
457
+ function get_price_filter_sql_compatible( $sql, $meta_query_sql, $tax_query_sql ) {
458
+ if (
459
+ is_admin() ||
460
+ 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'no' ) ||
461
+ get_option( 'woocommerce_currency' ) === $this->get_current_currency_code() ||
462
+ 1 === $this->get_currency_exchange_rate( $this->get_current_currency_code() )
463
+ ) {
464
+ return $sql;
465
+ }
466
+
467
+ global $wpdb;
468
+ $current_currency_code = $this->get_current_currency_code();
469
+ $exchange_rate = $this->get_currency_exchange_rate( $current_currency_code );
470
+ $args = WC()->query->get_main_query()->query_vars;
471
+ $tax_query = isset( $args['tax_query'] ) ? $args['tax_query'] : array();
472
+ $meta_query = isset( $args['meta_query'] ) ? $args['meta_query'] : array();
473
+
474
+ if ( ! is_post_type_archive( 'product' ) && ! empty( $args['taxonomy'] ) && ! empty( $args['term'] ) ) {
475
+ $tax_query[] = array(
476
+ 'taxonomy' => $args['taxonomy'],
477
+ 'terms' => array( $args['term'] ),
478
+ 'field' => 'slug',
479
+ );
480
+ }
481
+
482
+ foreach ( $meta_query + $tax_query as $key => $query ) {
483
+ if ( ! empty( $query['price_filter'] ) || ! empty( $query['rating_filter'] ) ) {
484
+ unset( $meta_query[ $key ] );
485
+ }
486
+ }
487
+
488
+ $search = WC_Query::get_main_search_query_sql();
489
+ $search_query_sql = $search ? ' AND ' . $search : '';
490
+
491
+ $sql = "
492
+ SELECT FLOOR(min(wcj_min_price)) as min_price, CEILING(max(wcj_max_price)) as max_price
493
+ FROM(
494
+ 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
495
+ FROM {$wpdb->wc_product_meta_lookup}
496
+ LEFT JOIN {$wpdb->postmeta} AS pm on pm.post_id = product_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!='')
497
+ WHERE product_id IN (
498
+ SELECT ID FROM {$wpdb->posts}
499
+ " . $tax_query_sql['join'] . $meta_query_sql['join'] . "
500
+ WHERE {$wpdb->posts}.post_type IN ('" . implode( "','", array_map( 'esc_sql', apply_filters( 'woocommerce_price_filter_post_type', array( 'product' ) ) ) ) . "')
501
+ AND {$wpdb->posts}.post_status = 'publish'
502
+ " . $tax_query_sql['where'] . $meta_query_sql['where'] . $search_query_sql . '
503
+ )
504
+ group by product_id
505
+ ) as wcj_min_max_price
506
+ ';
507
+ return $sql;
508
+ }
509
+
510
+ /**
511
+ * Fixes WooCommerce import.
512
+ *
513
+ * For now it converts '_wcj_%price%_{currency}' meta with lowercase currency to uppercase.
514
+ *
515
+ * @version 4.4.0
516
+ * @since 4.4.0
517
+ *
518
+ * @param $parsed_data
519
+ * @param $raw_data
520
+ *
521
+ * @return mixed
522
+ */
523
+ function fix_wc_product_import( $parsed_data, $raw_data ) {
524
+ // Gets values
525
+ $multicurrency_values = array_filter( $parsed_data['meta_data'], function ( $value ) {
526
+ return preg_match( '/^_wcj_.+price.*_[a-z]{2,3}$/', $value['key'] );
527
+ } );
528
+
529
+ // Changes lowercase currency to uppercase
530
+ $modified_values = array_map( function ( $value ) {
531
+ $str = $value['key'];
532
+ $last_underscore = strrpos( $str, '_' );
533
+ $before = substr( $str, 0, $last_underscore );
534
+ $currency = substr( $str, $last_underscore + 1 );
535
+ $value['key'] = $before . '_' . strtoupper( $currency );
536
+ return $value;
537
+ }, $multicurrency_values );
538
+
539
+ // Applies changes to the main data
540
+ foreach ( $modified_values as $i => $value ) {
541
+ $parsed_data['meta_data'][ $i ]['key'] = $value['key'];
542
+ }
543
+
544
+ return $parsed_data;
545
+ }
546
+
547
+ /**
548
+ * Adds compatibility with WooCommerce Price Filter widget.
549
+ *
550
+ * @see price-slider.js, init_price_filter()
551
+ *
552
+ * @version 4.6.0
553
+ * @since 4.3.0
554
+ */
555
+ function add_compatibility_with_price_filter_widget() {
556
+ if ( ! is_active_widget( false, false, 'woocommerce_price_filter' ) ) {
557
+ return;
558
+ }
559
+ ?>
560
+ <?php
561
+ $exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() );
562
+ if ( $exchange_rate == 1 ) {
563
+ return;
564
+ }
565
+ ?>
566
+ <input type="hidden" id="wcj_mc_exchange_rate" value="<?php echo esc_html( $exchange_rate ) ?>"/>
567
+ <script>
568
+ var wcj_mc_pf_slider = {
569
+ slider: null,
570
+ convert_rate: 1,
571
+ original_min: 1,
572
+ original_max: 1,
573
+ original_values: [],
574
+ current_min: 1,
575
+ current_max: 1,
576
+ current_values: [],
577
+ step: 1,
578
+
579
+ init(slider, convert_rate, step) {
580
+ this.step = step;
581
+ this.slider = slider;
582
+ this.convert_rate = convert_rate;
583
+ this.original_min = jQuery(this.slider).slider("option", "min");
584
+ this.original_max = jQuery(this.slider).slider("option", "max");
585
+ if (this.original_min > jQuery(this.slider).parent().find('#min_price').val()) {
586
+ jQuery(this.slider).parent().find('#min_price').attr('value', this.original_min);
587
+ }
588
+ if (this.original_max < jQuery(this.slider).parent().find('#max_price').val()) {
589
+ jQuery(this.slider).parent().find('#max_price').attr('value', this.original_max);
590
+ }
591
+ this.original_values = jQuery(this.slider).slider("option", "values");
592
+ this.current_min = this.original_min * this.convert_rate;
593
+ this.current_max = this.original_max * this.convert_rate;
594
+ this.current_values[0] = jQuery(this.slider).parent().find('#min_price').val() * wcj_mc_pf_slider.convert_rate;
595
+ this.current_values[1] = jQuery(this.slider).parent().find('#max_price').val() * wcj_mc_pf_slider.convert_rate;
596
+ this.update_slider();
597
+ },
598
+
599
+ update_slider() {
600
+ jQuery(this.slider).slider("destroy");
601
+ var current_min_price = Math.floor(this.current_min);
602
+ var current_max_price = Math.ceil(this.current_max);
603
+
604
+ jQuery(this.slider).slider({
605
+ range: true,
606
+ animate: true,
607
+ min: current_min_price,
608
+ max: current_max_price,
609
+ step: parseFloat(this.step),
610
+ values: wcj_mc_pf_slider.current_values,
611
+ create: function () {
612
+ jQuery(wcj_mc_pf_slider.slider).parent().find('.price_slider_amount #min_price').val(Math.floor(wcj_mc_pf_slider.current_values[0] / wcj_mc_pf_slider.convert_rate));
613
+ jQuery(wcj_mc_pf_slider.slider).parent().find('.price_slider_amount #max_price').val(Math.ceil(wcj_mc_pf_slider.current_values[1] / wcj_mc_pf_slider.convert_rate));
614
+ jQuery(document.body).trigger('price_slider_create', [Math.floor(wcj_mc_pf_slider.current_values[0]), Math.ceil(wcj_mc_pf_slider.current_values[1])]);
615
+ },
616
+ slide: function (event, ui) {
617
+ jQuery(wcj_mc_pf_slider.slider).parent().find('.price_slider_amount #min_price').val(Math.floor(ui.values[0] / wcj_mc_pf_slider.convert_rate));
618
+ jQuery(wcj_mc_pf_slider.slider).parent().find('.price_slider_amount #max_price').val(Math.ceil(ui.values[1] / wcj_mc_pf_slider.convert_rate));
619
+ var the_min = ui.values[0] == Math.round(wcj_mc_pf_slider.current_values[0]) ? Math.floor(wcj_mc_pf_slider.current_values[0]) : ui.values[0];
620
+ var the_max = ui.values[1] == Math.round(wcj_mc_pf_slider.current_values[1]) ? Math.ceil(wcj_mc_pf_slider.current_values[1]) : ui.values[1];
621
+ jQuery(document.body).trigger('price_slider_slide', [the_min, the_max]);
622
+ },
623
+ change: function (event, ui) {
624
+ jQuery(document.body).trigger('price_slider_change', [ui.values[0], ui.values[1]]);
625
+ }
626
+ });
627
+ }
628
+ };
629
+ var wcj_mc_pf = {
630
+ price_filters: null,
631
+ rate: 1,
632
+ step: 1,
633
+ init: function (price_filters) {
634
+ this.price_filters = price_filters;
635
+ this.rate = document.getElementById('wcj_mc_exchange_rate').value;
636
+ this.update_slider();
637
+ },
638
+ update_slider: function () {
639
+ [].forEach.call(wcj_mc_pf.price_filters, function (el) {
640
+ wcj_mc_pf_slider.init(el, wcj_mc_pf.rate, wcj_mc_pf.step);
641
+ });
642
+ }
643
+ }
644
+ document.addEventListener("DOMContentLoaded", function () {
645
+ var price_filters = document.querySelectorAll('.price_slider.ui-slider');
646
+ if (price_filters.length) {
647
+ wcj_mc_pf.init(price_filters);
648
+ }
649
+ });
650
+ </script>
651
+ <?php
652
+ }
653
+
654
+ /**
655
+ * Fixes price filter widget currency format
656
+ *
657
+ * @version 4.3.0
658
+ * @since 4.3.0
659
+ */
660
+ function fix_price_filter_widget_currency_format() {
661
+ $price_args = apply_filters( 'wc_price_args', array(
662
+ 'ex_tax_label' => false,
663
+ 'currency' => '',
664
+ 'decimal_separator' => wc_get_price_decimal_separator(),
665
+ 'thousand_separator' => wc_get_price_thousand_separator(),
666
+ 'decimals' => wc_get_price_decimals(),
667
+ 'price_format' => get_woocommerce_price_format(),
668
+ ) );
669
+ $symbol = apply_filters( 'woocommerce_currency_symbol', get_woocommerce_currency_symbol(), get_woocommerce_currency() );
670
+ wp_localize_script(
671
+ 'wc-price-slider', 'woocommerce_price_slider_params', array(
672
+ 'currency_format_num_decimals' => $price_args['decimals'],
673
+ 'currency_format_symbol' => $symbol,
674
+ 'currency_format_decimal_sep' => esc_attr( $price_args['decimal_separator'] ),
675
+ 'currency_format_thousand_sep' => esc_attr( $price_args['thousand_separator'] ),
676
+ 'currency_format' => esc_attr( str_replace( array( '%1$s', '%2$s' ), array( '%s', '%v' ), $price_args['price_format'] ) ),
677
+ )
678
+ );
679
+ }
680
+
681
+ /**
682
+ * add_hooks.
683
+ *
684
+ * @version 5.0.0
685
+ */
686
+ function add_hooks() {
687
+ if ( wcj_is_frontend() ) {
688
+
689
+ // Prices - Compatibility - "WooCommerce TM Extra Product Options" plugin
690
+ 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 );
691
+ add_filter( 'wc_epo_price', array( $this, 'change_price_by_currency_tm_extra_product_options_plugin' ), $this->price_hooks_priority, 3 );
692
+
693
+ // Currency hooks
694
+ add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), $this->price_hooks_priority, 1 );
695
+
696
+ // Add "Change Price" hooks
697
+ wcj_add_change_price_hooks( $this, $this->price_hooks_priority );
698
+
699
+ // "WooCommerce Product Add-ons" plugin
700
+ add_filter( 'woocommerce_get_item_data', array( $this, 'get_addons_item_data' ), 20, 2 );
701
+ add_filter( 'woocommerce_product_addons_option_price_raw', array( $this, 'product_addons_option_price_raw' ), 10, 2 );
702
+
703
+ // Handle Compatibility
704
+ $this->handle_compatibility();
705
+
706
+ // Additional Price Filters
707
+ $this->additional_price_filters = get_option( 'wcj_multicurrency_switcher_additional_price_filters', '' );
708
+ if ( ! empty( $this->additional_price_filters ) ) {
709
+ $this->additional_price_filters = array_map( 'trim', explode( PHP_EOL, $this->additional_price_filters ) );
710
+ foreach ( $this->additional_price_filters as $additional_price_filter ) {
711
+ add_filter( $additional_price_filter, array( $this, 'change_price' ), $this->price_hooks_priority, 2 );
712
+ }
713
+ } else {
714
+ $this->additional_price_filters = array();
715
+ }
716
+
717
+ } else {
718
+ // Saves min and max price when product is updated
719
+ add_action( 'woocommerce_update_product', function ( $post_id ) {
720
+ if ( 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ) ) {
721
+ return;
722
+ }
723
+ $this->save_min_max_prices_per_product( $post_id );
724
+ }, 99 );
725
+
726
+ // Saves min and max price when exchange rate changes
727
+ add_action( 'updated_option', array( $this, 'update_min_max_prices_on_exchange_rate_change' ), 10, 3 );
728
+ }
729
+ }
730
+
731
+ /**
732
+ * Updates min and max prices on exchange rate change.
733
+ *
734
+ * The update is done with background process.
735
+ *
736
+ * @version 4.5.0
737
+ * @since 4.5.0
738
+ *
739
+ * @param $option_name
740
+ * @param $old_value
741
+ * @param $option_value
742
+ */
743
+ function update_min_max_prices_on_exchange_rate_change( $option_name, $old_value, $option_value ) {
744
+ if (
745
+ 'no' === get_option( 'wcj_multicurrency_update_prices_on_exch_update', 'no' ) ||
746
+ 'no' === get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ) ||
747
+ false === strpos( $option_name, 'wcj_multicurrency_exchange_rate_' )
748
+ ) {
749
+ return;
750
+ }
751
+ $currency_number = substr( $option_name, strrpos( $option_name, '_' ) + 1 );
752
+ $currency = get_option( 'wcj_multicurrency_currency_' . $currency_number );
753
+ $product_ids = $this->get_products_by_per_product_currency( $currency );
754
+ if ( is_array( $product_ids ) && count( $product_ids ) > 0 ) {
755
+ $this->bkg_process_price_updater->cancel_process();
756
+ foreach ( $product_ids as $post_id ) {
757
+ $this->bkg_process_price_updater->push_to_queue( array( 'id' => $post_id, 'currency' => $currency ) );
758
+ }
759
+ $this->bkg_process_price_updater->save()->dispatch();
760
+ }
761
+ }
762
+
763
+ /**
764
+ * Gets all products, or products with variations containing meta '_wcj_multicurrency_per_product_regular_price_{currency}' or '_wcj_multicurrency_per_product_sale_price_{currency}'.
765
+ *
766
+ * @version 4.6.0
767
+ * @since 4.5.0
768
+ *
769
+ * @param $currency
770
+ *
771
+ * @return array
772
+ */
773
+ function get_products_by_per_product_currency( $currency ) {
774
+ if ( empty( $currency ) ) {
775
+ $currency = get_option( 'woocommerce_currency' );
776
+ }
777
+
778
+ global $wpdb;
779
+ $product_ids = $wpdb->get_col( "
780
+ SELECT p.ID
781
+ FROM {$wpdb->posts} AS p
782
+ LEFT JOIN {$wpdb->posts} AS p2 ON p.ID = p2.ID OR (p2.post_parent = p.ID AND p2.post_type='product_variation')
783
+ LEFT JOIN {$wpdb->postmeta} AS pm ON (p2.ID = pm.post_id) AND (pm.meta_key IN ('_wcj_multicurrency_per_product_regular_price_{$currency}','_wcj_multicurrency_per_product_sale_price_{$currency}') AND pm.meta_value!='')
784
+ WHERE p.post_status = 'publish' AND p.post_type IN ('product')
785
+ AND pm.meta_value != 'null'
786
+ GROUP BY p.ID
787
+ " );
788
+
789
+ return $product_ids;
790
+ }
791
+
792
+ /**
793
+ * Updates min and max prices.
794
+ *
795
+ * @version 4.5.0
796
+ * @since 4.5.0
797
+ *
798
+ * @param $post_id
799
+ * @param string $currency_code_param
800
+ */
801
+ function save_min_max_prices_per_product( $post_id, $currency_code_param = '' ) {
802
+ $product = wc_get_product( $post_id );
803
+ $products = array();
804
+ if ( $product->is_type( 'variable' ) ) {
805
+ $available_variations = $product->get_variation_prices()['price'];
806
+ foreach ( $available_variations as $variation_id => $price ) {
807
+ $products[ $variation_id ] = $price;
808
+ }
809
+ } else {
810
+ $products[ $post_id ] = $product->get_price();
811
+ }
812
+ if ( empty( $currency_code_param ) ) {
813
+ $total_number = apply_filters( 'booster_option', 2, get_option( 'wcj_multicurrency_total_number', 2 ) );
814
+ } else {
815
+ $total_number = 1;
816
+ }
817
+
818
+ $per_product_prices = array();
819
+ for ( $i = 1; $i <= $total_number; $i ++ ) {
820
+ $currency_code = empty( $currency_code_param ) ? get_option( 'wcj_multicurrency_currency_' . $i ) : $currency_code_param;
821
+ $exchange_rate = $this->get_currency_exchange_rate( $currency_code );
822
+ foreach ( $products as $product_id => $original_price ) {
823
+ // Regular Price
824
+ if ( isset( $_POST["wcj_multicurrency_per_product_regular_price_{$currency_code}_{$product_id}"] ) ) {
825
+ $regular_price = $_POST["wcj_multicurrency_per_product_regular_price_{$currency_code}_{$product_id}"];
826
+ } else {
827
+ $regular_price = get_post_meta( $product_id, '_wcj_multicurrency_per_product_regular_price_' . $currency_code, true );
828
+ }
829
+
830
+ // Sale Price
831
+ if ( isset( $_POST["wcj_multicurrency_per_product_sale_price_{$currency_code}_{$product_id}"] ) ) {
832
+ $sale_price = $_POST["wcj_multicurrency_per_product_sale_price_{$currency_code}_{$product_id}"];
833
+ } else {
834
+ $sale_price = get_post_meta( $product_id, '_wcj_multicurrency_per_product_sale_price_' . $currency_code, true );
835
+ }
836
+ $prices = array_filter( array( $regular_price, $sale_price ) );
837
+ $price = count( $prices ) > 0 ? min( $prices ) : $original_price * $exchange_rate;
838
+ $per_product_prices[ $currency_code ][ $product_id ] = $price;
839
+ }
840
+ }
841
+ foreach ( $per_product_prices as $currency => $values ) {
842
+ update_post_meta( $post_id, '_wcj_multicurrency_per_product_min_price_' . $currency, min( $values ) );
843
+ update_post_meta( $post_id, '_wcj_multicurrency_per_product_max_price_' . $currency, max( $values ) );
844
+ }
845
+ }
846
+
847
+ /**
848
+ * Converts Smart Coupon currency.
849
+ *
850
+ * @version 4.3.0
851
+ * @since 4.3.0
852
+ *
853
+ * @param $value
854
+ * @param $coupon
855
+ *
856
+ * @return float|int
857
+ */
858
+ function smart_coupons_get_amount( $value, $coupon ) {
859
+ if (
860
+ ! is_a( $coupon, 'WC_Coupon' ) ||
861
+ 'smart_coupon' !== $coupon->get_discount_type()
862
+ ) {
863
+ return $value;
864
+ }
865
+ $value = $this->change_price( $value, null );
866
+ return $value;
867
+ }
868
+
869
+ /**
870
+ * init.
871
+ *
872
+ * @version 3.4.5
873
+ * @since 3.4.5
874
+ */
875
+ function init() {
876
+ wcj_session_maybe_start();
877
+ if ( isset( $_REQUEST['wcj-currency'] ) ) {
878
+ wcj_session_set( 'wcj-currency', $_REQUEST['wcj-currency'] );
879
+ }
880
+ }
881
+
882
+ /**
883
+ * Converts add-ons plugin prices.
884
+ *
885
+ * @version 4.3.0
886
+ * @since 4.3.0
887
+ *
888
+ * @param $price
889
+ * @param $option
890
+ *
891
+ * @return float|int
892
+ */
893
+ function product_addons_option_price_raw( $price, $option ) {
894
+ $price = $this->change_price( $price, null );
895
+ return $price;
896
+ }
897
+
898
+ /**
899
+ * Finds old add-ons fields on cart and replace by correct price.
900
+ *
901
+ * @version 4.3.0
902
+ * @since 4.3.0
903
+ *
904
+ * @param $other_data
905
+ * @param $cart_item
906
+ *
907
+ * @return mixed
908
+ */
909
+ function get_addons_item_data( $other_data, $cart_item ) {
910
+ if ( ! empty( $cart_item['addons'] ) ) {
911
+ foreach ( $cart_item['addons'] as $addon ) {
912
+ $price = isset( $cart_item['addons_price_before_calc'] ) ? $cart_item['addons_price_before_calc'] : $addon['price'];
913
+ $name_old = $addon['name'];
914
+
915
+ // Get old field name (with wrong currency price)
916
+ if ( 0 == $addon['price'] ) {
917
+ $name_old .= '';
918
+ } elseif ( 'percentage_based' === $addon['price_type'] && 0 == $price ) {
919
+ $name_old .= '';
920
+ } elseif ( 'percentage_based' !== $addon['price_type'] && $addon['price'] && apply_filters( 'woocommerce_addons_add_price_to_name', '__return_true' ) ) {
921
+ $name_old .= ' (' . wc_price( \WC_Product_Addons_Helper::get_product_addon_price_for_display( $addon['price'], $cart_item['data'], true ) ) . ')';
922
+ } else {
923
+ $_product = new WC_Product( $cart_item['product_id'] );
924
+ $_product->set_price( $price * ( $addon['price'] / 100 ) );
925
+ $name_old .= ' (' . WC()->cart->get_product_price( $_product ) . ')';
926
+ }
927
+
928
+ // Get new field name (with correct currency price)
929
+ $name_new = $addon['name'];
930
+ $addon['price'] = $this->change_price( $addon['price'], null );
931
+ if ( 0 == $addon['price'] ) {
932
+ $name_new .= '';
933
+ } elseif ( 'percentage_based' === $addon['price_type'] && 0 == $price ) {
934
+ $name_new .= '';
935
+ } elseif ( 'percentage_based' !== $addon['price_type'] && $addon['price'] && apply_filters( 'woocommerce_addons_add_price_to_name', '__return_true' ) ) {
936
+ $name_new .= ' (' . wc_price( \WC_Product_Addons_Helper::get_product_addon_price_for_display( $addon['price'], $cart_item['data'], true ) ) . ')';
937
+ } else {
938
+ $_product = new WC_Product( $cart_item['product_id'] );
939
+ $_product->set_price( $price * ( $addon['price'] / 100 ) );
940
+ $name_new .= ' (' . WC()->cart->get_product_price( $_product ) . ')';
941
+ }
942
+
943
+ // Find old field on cart and replace by correct price
944
+ foreach ( $other_data as $key => $data ) {
945
+ if ( $data['name'] == $name_old ) {
946
+ $other_data[ $key ]['name'] = $name_new;
947
+ }
948
+ }
949
+ }
950
+ }
951
+ return $other_data;
952
+ }
953
+
954
+ /**
955
+ * change_price_by_currency_tm_extra_product_options_plugin_cart.
956
+ *
957
+ * @version 2.7.0
958
+ * @since 2.5.7
959
+ */
960
+ function change_price_by_currency_tm_extra_product_options_plugin_cart( $price ) {
961
+ return $this->change_price( $price, null );
962
+ }
963
+
964
+ /**
965
+ * change_price_by_currency_tm_extra_product_options_plugin.
966
+ *
967
+ * @version 2.7.0
968
+ * @since 2.5.7
969
+ */
970
+ function change_price_by_currency_tm_extra_product_options_plugin( $price, $type, $post_id ) {
971
+ return $this->change_price( $price, null );
972
+ }
973
+
974
+ /**
975
+ * change_price_grouped.
976
+ *
977
+ * @version 2.7.0
978
+ * @since 2.5.0
979
+ */
980
+ function change_price_grouped( $price, $qty, $_product ) {
981
+ if ( $_product->is_type( 'grouped' ) ) {
982
+ if ( 'yes' === get_option( 'wcj_multicurrency_per_product_enabled' , 'yes' ) ) {
983
+ foreach ( $_product->get_children() as $child_id ) {
984
+ $the_price = get_post_meta( $child_id, '_price', true );
985
+ $the_product = wc_get_product( $child_id );
986
+ $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
987
+ if ( $the_price == $price ) {
988
+ return $this->change_price( $price, $the_product );
989
+ }
990
+ }
991
+ } else {
992
+ return $this->change_price( $price, null );
993
+ }
994
+ }
995
+ return $price;
996
+ }
997
+
998
+ /**
999
+ * get_variation_prices_hash.
1000
+ *
1001
+ * @version 3.8.0
1002
+ */
1003
+ function get_variation_prices_hash( $price_hash, $_product, $display ) {
1004
+ $currency_code = $this->get_current_currency_code();
1005
+ $price_hash['wcj_multicurrency'] = array(
1006
+ 'currency' => $currency_code,
1007
+ 'exchange_rate' => $this->get_currency_exchange_rate( $currency_code ),
1008
+ 'per_product' => get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ),
1009
+ 'per_product_make_empty' => get_option( 'wcj_multicurrency_per_product_make_empty', 'no' ),
1010
+ 'rounding' => get_option( 'wcj_multicurrency_rounding', 'no_round' ),
1011
+ 'rounding_precision' => get_option( 'wcj_multicurrency_rounding_precision', absint( get_option( 'woocommerce_price_num_decimals', 2 ) ) ),
1012
+ );
1013
+ return $price_hash;
1014
+ }
1015
+
1016
+ /**
1017
+ * get_currency_exchange_rate.
1018
+ *
1019
+ * @version 2.4.3
1020
+ */
1021
+ function get_currency_exchange_rate( $currency_code ) {
1022
+ $currency_exchange_rate = 1;
1023
+ $total_number = apply_filters( 'booster_option', 2, get_option( 'wcj_multicurrency_total_number', 2 ) );
1024
+ for ( $i = 1; $i <= $total_number; $i++ ) {
1025
+ if ( $currency_code === get_option( 'wcj_multicurrency_currency_' . $i ) ) {
1026
+ $currency_exchange_rate = get_option( 'wcj_multicurrency_exchange_rate_' . $i );
1027
+ break;
1028
+ }
1029
+ }
1030
+ return $currency_exchange_rate;
1031
+ }
1032
+
1033
+ /**
1034
+ * do_revert.
1035
+ *
1036
+ * @version 3.9.0
1037
+ * @since 2.5.0
1038
+ */
1039
+ function do_revert() {
1040
+ switch ( get_option( 'wcj_multicurrency_revert', 'no' ) ) {
1041
+ case 'cart_only':
1042
+ return is_cart();
1043
+ case 'yes': // checkout only
1044
+ return is_checkout();
1045
+ case 'cart_and_checkout':
1046
+ return ( is_cart() || is_checkout() );
1047
+ default: // 'no'
1048
+ return false;
1049
+ }
1050
+ }
1051
+
1052
+ /**
1053
+ * Saves price so it won't be necessary to calculate it multiple times.
1054
+ * @version 4.6.0
1055
+ * @since 4.6.0
1056
+ *
1057
+ * @param $price
1058
+ * @param $product_id
1059
+ * @param $filter
1060
+ */
1061
+ function save_price( $price, $product_id, $filter ) {
1062
+ WCJ()->modules['multicurrency']->calculated_products_prices[ $product_id ][ $filter ] = $price;
1063
+ }
1064
+
1065
+ /**
1066
+ * change_price.
1067
+ *
1068
+ * @version 4.9.0
1069
+ */
1070
+ function change_price( $price, $_product ) {
1071
+ if ( '' === $price ) {
1072
+ return $price;
1073
+ }
1074
+
1075
+ if ( $this->do_revert() ) {
1076
+ return $price;
1077
+ }
1078
+
1079
+ $_product_id = wcj_get_product_id( $_product );
1080
+ $do_save = ( 'yes' === get_option( 'wcj_multicurrency_multicurrency_save_prices', 'no' ) );
1081
+ $_current_filter = current_filter();
1082
+ if ( '' == $_current_filter ) {
1083
+ $_current_filter = 'wcj_filter__none';
1084
+ }
1085
+ if ( $do_save && isset( WCJ()->modules['multicurrency']->calculated_products_prices[ $_product_id ][ $_current_filter ] ) ) {
1086
+ return WCJ()->modules['multicurrency']->calculated_products_prices[ $_product_id ][ $_current_filter ];
1087
+ }
1088
+
1089
+ // Per product
1090
+ if ( 'yes' === get_option( 'wcj_multicurrency_per_product_enabled' , 'yes' ) && null != $_product ) {
1091
+ if (
1092
+ 'yes' === get_option( 'wcj_multicurrency_per_product_make_empty', 'no' ) &&
1093
+ 'yes' === get_post_meta( $_product_id, '_' . 'wcj_multicurrency_per_product_make_empty_' . $this->get_current_currency_code(), true )
1094
+ ) {
1095
+ $price = '';
1096
+ $this->save_price( $price, $_product_id, $_current_filter );
1097
+ return $price;
1098
+ } elseif ( '' != ( $regular_price_per_product = get_post_meta( $_product_id, '_' . 'wcj_multicurrency_per_product_regular_price_' . $this->get_current_currency_code(), true ) ) ) {
1099
+ if ( 'woocommerce_get_price_including_tax' == $_current_filter || 'woocommerce_get_price_excluding_tax' == $_current_filter ) {
1100
+ $price = wcj_get_product_display_price( $_product );
1101
+ $this->save_price( $price, $_product_id, $_current_filter );
1102
+ return $price;
1103
+ } elseif ( WCJ_PRODUCT_GET_PRICE_FILTER == $_current_filter || 'woocommerce_variation_prices_price' == $_current_filter || 'woocommerce_product_variation_get_price' == $_current_filter || in_array( $_current_filter, $this->additional_price_filters ) ) {
1104
+ if ( $_product->is_on_sale() ) {
1105
+ $sale_price_per_product = get_post_meta( $_product_id, '_' . 'wcj_multicurrency_per_product_sale_price_' . $this->get_current_currency_code(), true );
1106
+ $price = ( '' != $sale_price_per_product && $sale_price_per_product < $regular_price_per_product ) ? $sale_price_per_product : $regular_price_per_product;
1107
+ } else {
1108
+ $price = $regular_price_per_product;
1109
+ }
1110
+ $this->save_price( $price, $_product_id, $_current_filter );
1111
+ return $price;
1112
+ } elseif ( WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER == $_current_filter || 'woocommerce_variation_prices_regular_price' == $_current_filter || 'woocommerce_product_variation_get_regular_price' == $_current_filter ) {
1113
+ $price = $regular_price_per_product;
1114
+ $this->save_price( $price, $_product_id, $_current_filter );
1115
+ return $price;
1116
+ } elseif ( WCJ_PRODUCT_GET_SALE_PRICE_FILTER == $_current_filter || 'woocommerce_variation_prices_sale_price' == $_current_filter || 'woocommerce_product_variation_get_sale_price' == $_current_filter ) {
1117
+ $sale_price_per_product = get_post_meta( $_product_id, '_' . 'wcj_multicurrency_per_product_sale_price_' . $this->get_current_currency_code(), true );
1118
+ $price = ( '' != $sale_price_per_product ) ? $sale_price_per_product : $price;
1119
+ $this->save_price( $price, $_product_id, $_current_filter );
1120
+ return $price;
1121
+ }
1122
+ }
1123
+ }
1124
+
1125
+ // Global
1126
+ if ( 1 != ( $currency_exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() ) ) ) {
1127
+ $price = (float) $price * (float) $currency_exchange_rate;
1128
+ switch ( get_option( 'wcj_multicurrency_rounding', 'no_round' ) ) {
1129
+ case 'round':
1130
+ $price = round( $price, get_option( 'wcj_multicurrency_rounding_precision', absint( get_option( 'woocommerce_price_num_decimals', 2 ) ) ) );
1131
+ break;
1132
+ case 'round_up':
1133
+ $price = ceil( $price );
1134
+ break;
1135
+ case 'round_down':
1136
+ $price = floor( $price );
1137
+ break;
1138
+ }
1139
+ $this->save_price( $price, $_product_id, $_current_filter );
1140
+ return $price;
1141
+ }
1142
+
1143
+ // No changes
1144
+ $this->save_price( $price, $_product_id, $_current_filter );
1145
+ return $price;
1146
+ }
1147
+
1148
+ /**
1149
+ * get_current_currency_code.
1150
+ *
1151
+ * @version 3.4.0
1152
+ */
1153
+ function get_current_currency_code( $default_currency = '' ) {
1154
+ if ( null !== ( $session_value = wcj_session_get( 'wcj-currency' ) ) ) {
1155
+ return $session_value;
1156
+ } else {
1157
+ $module_roles = get_option( 'wcj_multicurrency_role_defaults_roles', '' );
1158
+ if ( ! empty( $module_roles ) ) {
1159
+ $current_user_role = wcj_get_current_user_first_role();
1160
+ if ( in_array( $current_user_role, $module_roles ) ) {
1161
+ $roles_default_currency = get_option( 'wcj_multicurrency_role_defaults_' . $current_user_role, '' );
1162
+ if ( '' != $roles_default_currency ) {
1163
+ return $roles_default_currency;
1164
+ }
1165
+ }
1166
+ }
1167
+ }
1168
+ return $default_currency;
1169
+ }
1170
+
1171
+ /**
1172
+ * change_currency_code.
1173
+ *
1174
+ * @version 2.5.0
1175
+ */
1176
+ function change_currency_code( $currency ) {
1177
+ if ( $this->do_revert() ) {
1178
+ return $currency;
1179
+ }
1180
+ return $this->get_current_currency_code( $currency );
1181
+ }
1182
+
1183
+ /**
1184
+ * change_price_shipping.
1185
+ *
1186
+ * @version 4.9.0
1187
+ */
1188
+ function change_price_shipping( $package_rates, $package ) {
1189
+ if (
1190
+ $this->do_revert() ||
1191
+ 'no' === get_option( 'wcj_multicurrency_convert_shipping_values', 'yes' )
1192
+ ) {
1193
+ return $package_rates;
1194
+ }
1195
+ $currency_exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() );
1196
+ return wcj_change_price_shipping_package_rates( $package_rates, $currency_exchange_rate );
1197
+ }
1198
+
1199
+ }
1200
+
1201
+ endif;
1202
+
1203
+ return new WCJ_Multicurrency();
includes/class-wcj-my-account.php CHANGED
@@ -1,532 +1,532 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - My Account
4
- *
5
- * @version 4.8.0
6
- * @since 2.9.0
7
- * @author Algoritmika Ltd.
8
- */
9
-
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
-
12
- if ( ! class_exists( 'WCJ_My_Account' ) ) :
13
-
14
- class WCJ_My_Account extends WCJ_Module {
15
-
16
- /**
17
- * Constructor.
18
- *
19
- * @version 4.8.0
20
- * @since 2.9.0
21
- * @todo [dev] Custom Menu Pages: add "Type" option with values: "param" (i.e. as it is now) or "endpoint"
22
- * @todo [dev] Custom Menu Pages: deprecate "Add Custom Menu Items" (and add "link" value in "Type" options)
23
- */
24
- function __construct() {
25
-
26
- $this->id = 'my_account';
27
- $this->short_desc = __( 'My Account', 'woocommerce-jetpack' );
28
- $this->desc = __( 'WooCommerce "My Account" page customization.', 'woocommerce-jetpack' );
29
- $this->link_slug = 'woocommerce-my-account';
30
- parent::__construct();
31
-
32
- $this->account_menu_items = array(
33
- 'dashboard' => __( 'Dashboard', 'woocommerce' ),
34
- 'orders' => __( 'Orders', 'woocommerce' ),
35
- 'downloads' => __( 'Downloads', 'woocommerce' ),
36
- 'edit-address' => __( 'Addresses', 'woocommerce' ),
37
- 'payment-methods' => __( 'Payment methods', 'woocommerce' ),
38
- 'edit-account' => __( 'Account details', 'woocommerce' ),
39
- 'customer-logout' => __( 'Logout', 'woocommerce' ),
40
- );
41
- $this->account_menu_endpoints = array(
42
- 'orders' => __( 'Orders', 'woocommerce' ),
43
- 'view-order' => __( 'View order', 'woocommerce' ),
44
- 'downloads' => __( 'Downloads', 'woocommerce' ),
45
- 'edit-account' => __( 'Edit account', 'woocommerce' ) . ' (' . __( 'Account details', 'woocommerce' ) . ')',
46
- 'edit-address' => __( 'Addresses', 'woocommerce' ),
47
- 'payment-methods' => __( 'Payment methods', 'woocommerce' ),
48
- 'lost-password' => __( 'Lost password', 'woocommerce' ),
49
- 'customer-logout' => __( 'Logout', 'woocommerce' ),
50
- );
51
- $this->menu_order_default = implode( PHP_EOL, array_keys( $this->account_menu_items ) );
52
-
53
- if ( $this->is_enabled() ) {
54
- add_filter( 'woocommerce_my_account_my_orders_actions', array( $this, 'maybe_add_my_account_order_actions' ), 10, 2 );
55
- add_action( 'wp_footer', array( $this, 'maybe_add_js_conformation' ) );
56
- add_action( 'init', array( $this, 'process_woocommerce_mark_order_status' ) );
57
- // Custom pages
58
- if ( 'yes' === get_option( 'wcj_my_account_custom_pages_enabled', 'no' ) ) {
59
- add_action( 'woocommerce_account_' . 'page' . '_endpoint', array( $this, 'customize_dashboard' ), PHP_INT_MAX );
60
- add_filter( 'the_title', array( $this, 'set_custom_page_title' ), PHP_INT_MAX );
61
- add_filter( 'the_title', array( $this, 'set_custom_page_title_with_endpoint' ) );
62
- add_filter( 'woocommerce_account_menu_items', array( $this, 'add_custom_page_menu_item' ), PHP_INT_MAX );
63
- add_filter( 'woocommerce_get_endpoint_url', array( $this, 'set_custom_page_url' ), PHP_INT_MAX, 4 );
64
- add_action( 'init', array( $this, 'add_endpoints' ) );
65
- $this->customize_dashboard_for_endpoints();
66
- }
67
- // Custom info
68
- if ( 'yes' === get_option( 'wcj_my_account_custom_info_enabled', 'no' ) ) {
69
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_my_account_custom_info_total_number', 1 ) );
70
- for ( $i = 1; $i <= $total_number; $i++ ) {
71
- add_action(
72
- get_option( 'wcj_my_account_custom_info_hook_' . $i, 'woocommerce_account_dashboard' ),
73
- array( $this, 'add_my_account_custom_info' ),
74
- get_option( 'wcj_my_account_custom_info_priority_' . $i, 10 )
75
- );
76
- }
77
- }
78
- // Registration extra fields
79
- if ( 'yes' === get_option( 'wcj_my_account_registration_extra_fields_user_role_enabled', 'no' ) ) {
80
- add_action( 'woocommerce_register_form', array( $this, 'add_registration_extra_fields' ), PHP_INT_MAX );
81
- add_action( 'woocommerce_created_customer', array( $this, 'process_registration_extra_fields' ), PHP_INT_MAX, 3 );
82
- }
83
- // Menu & Endpoints
84
- if ( 'yes' === get_option( 'wcj_my_account_menu_customize_enabled', 'no' ) ) {
85
- foreach ( $this->account_menu_endpoints as $account_menu_endpoint_id => $account_menu_endpoint_title ) {
86
- add_filter( 'woocommerce_endpoint_' . $account_menu_endpoint_id . '_title', array( $this, 'customize_endpoint_title' ), PHP_INT_MAX, 2 );
87
- }
88
- add_filter( 'woocommerce_account_menu_items', array( $this, 'customize_menu' ), PHP_INT_MAX );
89
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_my_account_menu_order_custom_items_enabled', 'no' ) ) ) {
90
- add_filter( 'woocommerce_get_endpoint_url', array( $this, 'customize_menu_custom_endpoints' ), PHP_INT_MAX, 4 );
91
- }
92
- }
93
- // Dashboard customization
94
- if ( 'yes' === get_option( 'wcj_my_account_custom_dashboard_enabled', 'no' ) ) {
95
- add_action( 'woocommerce_account_' . 'page' . '_endpoint', array( $this, 'customize_dashboard' ), PHP_INT_MAX );
96
- }
97
- }
98
- }
99
-
100
- /**
101
- * customize_dashboard_for_endpoints.
102
- *
103
- * @version 4.8.0
104
- * @since 4.8.0
105
- */
106
- function customize_dashboard_for_endpoints() {
107
- foreach ( $this->get_custom_pages() as $custom_menu_page_id => $custom_menu_page_data ) {
108
- if ( empty( $endpoint = $custom_menu_page_data['endpoint'] ) ) {
109
- continue;
110
- }
111
- add_action( 'woocommerce_account_' . $endpoint . '_endpoint', array( $this, 'customize_dashboard' ), PHP_INT_MAX );
112
- }
113
- }
114
-
115
- /**
116
- * Register new endpoint to use inside My Account page.
117
- *
118
- * @version 4.8.0
119
- * @since 4.8.0
120
- *
121
- * @see https://developer.wordpress.org/reference/functions/add_rewrite_endpoint/
122
- */
123
- public function add_endpoints() {
124
- foreach ( $this->get_custom_pages() as $custom_menu_page_id => $custom_menu_page_data ) {
125
- if ( empty( $endpoint = $custom_menu_page_data['endpoint'] ) ) {
126
- continue;
127
- }
128
- add_rewrite_endpoint( $endpoint, EP_ROOT | EP_PAGES );
129
- }
130
- }
131
-
132
- /**
133
- * get_custom_pages.
134
- *
135
- * @version 4.8.0
136
- * @since 4.3.0
137
- * @todo [dev] customizable ID (i.e. instead of `sanitize_title( $title[ $i ] )`)
138
- */
139
- function get_custom_pages() {
140
- if ( isset( $this->custom_pages ) ) {
141
- return $this->custom_pages;
142
- }
143
- $this->custom_pages = array();
144
- $title = get_option( 'wcj_my_account_custom_pages_title', array() );
145
- $content = get_option( 'wcj_my_account_custom_pages_content', array() );
146
- $endpoint = get_option( 'wcj_my_account_custom_pages_endpoint', array() );
147
- for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_my_account_custom_pages_total_number', 1 ) ); $i ++ ) {
148
- if ( ! empty( $title[ $i ] ) && ! empty( $content[ $i ] ) ) {
149
- $endpoint[ $i ] = isset( $endpoint[ $i ] ) ? $endpoint[ $i ] : '';
150
- $this->custom_pages[ sanitize_title( $title[ $i ] ) ] = array( 'endpoint' => $endpoint[ $i ], 'title' => $title[ $i ], 'content' => $content[ $i ] );
151
- }
152
- }
153
- return $this->custom_pages;
154
- }
155
-
156
- /**
157
- * set_custom_page_title.
158
- *
159
- * @version 4.5.0
160
- * @since 4.3.0
161
- */
162
- function set_custom_page_title( $title ) {
163
- if (
164
- ! isset( $_GET['section'] ) ||
165
- is_admin() ||
166
- ! in_the_loop() ||
167
- ! is_account_page()
168
- ) {
169
- return $title;
170
- }
171
- if ( ! isset( $this->custom_pages ) ) {
172
- $this->get_custom_pages();
173
- }
174
- $endpoint = $_GET['section'];
175
- return ( isset( $this->custom_pages[ $endpoint ] ) ? $this->custom_pages[ $endpoint ]['title'] : $title );
176
-
177
- return $title;
178
- }
179
-
180
- /**
181
- * Set endpoint title.
182
- *
183
- * @version 4.8.0
184
- * @since 4.8.0
185
- *
186
- * @param string $title
187
- * @return string
188
- */
189
- public function set_custom_page_title_with_endpoint( $title ) {
190
- if (
191
- is_admin() ||
192
- ! is_account_page() ||
193
- ! in_the_loop()
194
- ) {
195
- return $title;
196
- }
197
- global $wp_query;
198
-
199
- if ( ! isset( $this->custom_pages ) ) {
200
- $this->get_custom_pages();
201
- }
202
- $endpoints = wp_list_pluck( $this->custom_pages, 'endpoint' );
203
- $intersect = array_intersect_key( $wp_query->query_vars, array_flip( array_filter( $endpoints ) ) );
204
- if ( ! empty( $intersect ) ) {
205
- reset( $intersect );
206
- $filter = wp_list_filter( $this->custom_pages, array( 'endpoint' => key( $intersect ) ) );
207
- reset( $filter );
208
- $title = ( isset( $this->custom_pages[ key( $filter ) ] ) ? $this->custom_pages[ key( $filter ) ]['title'] : $title );
209
- }
210
- return $title;
211
- }
212
-
213
- /**
214
- * set_custom_page_url.
215
- *
216
- * @version 4.8.0
217
- * @since 4.3.0
218
- * @todo [dev] (maybe) customizable `section` (e.g. `wcj-section`)
219
- */
220
- function set_custom_page_url( $url, $endpoint, $value, $permalink ) {
221
- if ( ! isset( $this->custom_pages ) ) {
222
- $this->get_custom_pages();
223
- }
224
- return ( isset( $this->custom_pages[ $endpoint ] ) && empty( $this->custom_pages[ $endpoint ]['endpoint'] ) && ( $myaccount_page_id = get_option( 'woocommerce_myaccount_page_id' ) ) ? add_query_arg( 'section', $endpoint, get_permalink( $myaccount_page_id ) ) : $url );
225
- }
226
-
227
- /**
228
- * add_custom_page_menu_item.
229
- *
230
- * @version 4.8.0
231
- * @since 4.3.0
232
- */
233
- function add_custom_page_menu_item( $items ) {
234
- foreach ( $this->get_custom_pages() as $custom_menu_page_id => $custom_menu_page_data ) {
235
- $custom_menu_page_id = ! empty( $custom_menu_page_data['endpoint'] ) ? $custom_menu_page_data['endpoint'] : $custom_menu_page_id;
236
- $items[ $custom_menu_page_id ] = $custom_menu_page_data['title'];
237
- }
238
- return $items;
239
- }
240
-
241
- /**
242
- * customize_menu_custom_endpoints.
243
- *
244
- * @version 3.8.0
245
- * @since 3.8.0
246
- */
247
- function customize_menu_custom_endpoints( $url, $endpoint, $value, $permalink ) {
248
- $custom_items = array_map( 'trim', explode( PHP_EOL, get_option( 'wcj_my_account_menu_order_custom_items', '' ) ) );
249
- foreach ( $custom_items as $custom_item ) {
250
- $parts = array_map( 'trim', explode( '|', $custom_item, 3 ) );
251
- if ( 3 === count( $parts ) && $parts[0] === $endpoint ) {
252
- return $parts[2];
253
- }
254
- }
255
- return $url;
256
- }
257
-
258
- /**
259
- * customize_dashboard.
260
- *
261
- * @version 4.8.0
262
- * @since 3.8.0
263
- * @see woocommerce/templates/myaccount/dashboard.php
264
- */
265
- function customize_dashboard( $value ) {
266
-
267
- // Custom pages
268
- if ( 'yes' === get_option( 'wcj_my_account_custom_pages_enabled', 'no' ) ) {
269
- if ( isset( $_GET['section'] ) || 'woocommerce_account_page_endpoint' != current_filter() ) {
270
- if ( ! isset( $this->custom_pages ) ) {
271
- $this->get_custom_pages();
272
- }
273
- $endpoint = 'woocommerce_account_page_endpoint' != current_filter() ? str_replace( array( 'woocommerce_account_', '_endpoint' ), array( '' ), current_filter() ) : false;
274
- if ( false !== $endpoint ) {
275
- $endpoint_tab = wp_list_filter( $this->custom_pages, array( 'endpoint' => $endpoint ) );
276
- }
277
- $page_id = isset( $_GET['section'] ) ? $_GET['section'] : ( false !== $endpoint ? array_keys( wp_list_pluck( $endpoint_tab, 'endpoint' ) )[0] : '' );
278
- if ( isset( $this->custom_pages[ $page_id ] ) ) {
279
- echo do_shortcode( $this->custom_pages[ $page_id ]['content'] );
280
- return;
281
- }
282
- }
283
- if ( 'no' === get_option( 'wcj_my_account_custom_dashboard_enabled', 'no' ) ) {
284
- wc_get_template( 'myaccount/dashboard.php', array(
285
- 'current_user' => get_user_by( 'id', get_current_user_id() ),
286
- ) );
287
- return;
288
- }
289
- }
290
-
291
- // Dashboard customization
292
- $current_user = get_user_by( 'id', get_current_user_id() );
293
-
294
- if ( '' != ( $custom_content = get_option( 'wcj_my_account_custom_dashboard_content', '' ) ) ) {
295
- echo do_shortcode( $custom_content );
296
- }
297
-
298
- if ( 'no' === get_option( 'wcj_my_account_custom_dashboard_hide_hello', 'no' ) ) {
299
- echo '<p>';
300
- /* translators: 1: user display name 2: logout url */
301
- printf(
302
- __( 'Hello %1$s (not %1$s? <a href="%2$s">Log out</a>)', 'woocommerce' ),
303
- '<strong>' . esc_html( $current_user->display_name ) . '</strong>',
304
- esc_url( wc_logout_url( wc_get_page_permalink( 'myaccount' ) ) )
305
- );
306
- echo '</p>';
307
- }
308
-
309
- if ( 'no' === get_option( 'wcj_my_account_custom_dashboard_hide_info', 'no' ) ) {
310
- echo '<p>';
311
- printf(
312
- __( 'From your account dashboard you can view your <a href="%1$s">recent orders</a>, manage your <a href="%2$s">shipping and billing addresses</a>, and <a href="%3$s">edit your password and account details</a>.', 'woocommerce' ),
313
- esc_url( wc_get_endpoint_url( 'orders' ) ),
314
- esc_url( wc_get_endpoint_url( 'edit-address' ) ),
315
- esc_url( wc_get_endpoint_url( 'edit-account' ) )
316
- );
317
- echo '</p>';
318
- }
319
-
320
- /**
321
- * My Account dashboard.
322
- *
323
- * @since 2.6.0
324
- */
325
- do_action( 'woocommerce_account_dashboard' );
326
-
327
- /**
328
- * Deprecated woocommerce_before_my_account action.
329
- *
330
- * @deprecated 2.6.0
331
- */
332
- do_action( 'woocommerce_before_my_account' );
333
-
334
- /**
335
- * Deprecated woocommerce_after_my_account action.
336
- *
337
- * @deprecated 2.6.0
338
- */
339
- do_action( 'woocommerce_after_my_account' );
340
-
341
- }
342
-
343
- /**
344
- * customize_endpoint_title.
345
- *
346
- * @version 3.8.0
347
- * @since 3.8.0
348
- * @todo (maybe) 'orders': `if ( ! empty( $wp->query_vars['orders'] ) ) { $title = sprintf( __( 'Orders (page %d)', 'woocommerce' ), intval( $wp->query_vars['orders'] ) ); }`
349
- * @todo (maybe) 'view-order': `$title = ( $order = wc_get_order( $wp->query_vars['view-order'] ) ) ? sprintf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ) : '';`
350
- * @todo (maybe) 'order-pay' => __( 'Pay for order', 'woocommerce' )
351
- * @todo (maybe) 'order-received' => __( 'Order received', 'woocommerce' )
352
- */
353
- function customize_endpoint_title( $title, $endpoint ) {
354
- $menu_titles = get_option( 'wcj_my_account_menu_title', array() );
355
- if ( ! empty( $menu_titles[ $endpoint ] ) ) {
356
- return $menu_titles[ $endpoint ];
357
- }
358
- return $title;
359
- }
360
-
361
- /**
362
- * customize_menu.
363
- *
364
- * @version 3.8.0
365
- * @since 3.8.0
366
- * @todo (maybe) option to disable menu
367
- */
368
- function customize_menu( $items ) {
369
- $menu_titles = get_option( 'wcj_my_account_menu_title', array() );
370
- foreach ( $items as $item_id => $item_title ) {
371
- if ( ! empty( $menu_titles[ $item_id ] ) ) {
372
- $items[ $item_id ] = $menu_titles[ $item_id ];
373
- }
374
- }
375
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_my_account_menu_order_customize_enabled', 'no' ) ) ) {
376
- $menu_order = array_map( 'trim', explode( PHP_EOL, get_option( 'wcj_my_account_menu_order', $this->menu_order_default ) ) );
377
- $modified_menu = array();
378
- foreach ( $menu_order as $item_id ) {
379
- if ( isset( $items[ $item_id ] ) ) {
380
- $modified_menu[ $item_id ] = $items[ $item_id ];
381
- unset( $items[ $item_id ] );
382
- }
383
- }
384
- $items = array_merge( $modified_menu, $items );
385
- }
386
- if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_my_account_menu_order_custom_items_enabled', 'no' ) ) ) {
387
- $custom_items = array_map( 'trim', explode( PHP_EOL, get_option( 'wcj_my_account_menu_order_custom_items', '' ) ) );
388
- foreach ( $custom_items as $custom_item ) {
389
- $parts = array_map( 'trim', explode( '|', $custom_item, 3 ) );
390
- if ( 3 === count( $parts ) ) {
391
- $items[ $parts[0] ] = $parts[1];
392
- }
393
- }
394
- }
395
- return $items;
396
- }
397
-
398
- /**
399
- * add_registration_extra_fields.
400
- *
401
- * @version 3.6.0
402
- * @since 3.6.0
403
- * @todo (maybe) more fields to choose from (i.e. not only "user role" field)
404
- * @todo (maybe) customizable position (check for other hooks or at least customizable priority on `woocommerce_register_form`)
405
- * @todo (maybe) move to new module (e.g. "Registration Form")
406
- */
407
- function add_registration_extra_fields() {
408
- $user_roles_options_html = '';
409
- $current_user_role_input = ! empty( $_POST['wcj_user_role'] ) ? $_POST['wcj_user_role'] :
410
- get_option( 'wcj_my_account_registration_extra_fields_user_role_default', 'customer' );
411
- $user_roles_options = get_option( 'wcj_my_account_registration_extra_fields_user_role_options', array( 'customer' ) );
412
- $all_user_roles = wcj_get_user_roles_options();
413
- foreach ( $user_roles_options as $user_role_id ) {
414
- $user_roles_options_html .= '<option value="' . $user_role_id . '" ' . selected( $user_role_id, $current_user_role_input, false ) . '>' .
415
- ( isset( $all_user_roles[ $user_role_id ] ) ? $all_user_roles[ $user_role_id ] : $user_role_id ) . '</option>';
416
- }
417
- ?><p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
418
- <label for="reg_wcj_user_role"><?php esc_html_e( 'User role', 'woocommerce-jetpack' ); ?></label>
419
- <select name="wcj_user_role" id="reg_wcj_user_role"><?php echo $user_roles_options_html; ?></select>
420
- </p><?php
421
- }
422
-
423
- /**
424
- * process_registration_extra_fields.
425
- *
426
- * @version 3.6.0
427
- * @since 3.6.0
428
- * @todo (maybe) optional admin confirmation for some user roles (probably will need to create additional `...-pending` user roles)
429
- */
430
- function process_registration_extra_fields( $customer_id, $new_customer_data, $password_generated ) {
431
- if ( isset( $_POST['wcj_user_role'] ) && '' != $_POST['wcj_user_role'] ) {
432
- $user_roles_options = get_option( 'wcj_my_account_registration_extra_fields_user_role_options', array( 'customer' ) );
433
- if ( ! empty( $user_roles_options ) && in_array( $_POST['wcj_user_role'], $user_roles_options ) ) {
434
- wp_update_user( array( 'ID' => $customer_id, 'role' => $_POST['wcj_user_role'] ) );
435
- }
436
- }
437
- }
438
-
439
- /**
440
- * add_my_account_custom_info.
441
- *
442
- * @version 3.4.0
443
- * @since 3.4.0
444
- */
445
- function add_my_account_custom_info() {
446
- $current_filter = current_filter();
447
- $current_filter_priority = wcj_current_filter_priority();
448
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_my_account_custom_info_total_number', 1 ) );
449
- for ( $i = 1; $i <= $total_number; $i++ ) {
450
- if (
451
- '' != get_option( 'wcj_my_account_custom_info_content_' . $i ) &&
452
- $current_filter === get_option( 'wcj_my_account_custom_info_hook_' . $i, 'woocommerce_account_dashboard' ) &&
453
- $current_filter_priority == get_option( 'wcj_my_account_custom_info_priority_' . $i, 10 )
454
- ) {
455
- echo do_shortcode( get_option( 'wcj_my_account_custom_info_content_' . $i ) );
456
- }
457
- }
458
- }
459
-
460
- /*
461
- * maybe_add_my_account_order_actions.
462
- *
463
- * @version 2.9.0
464
- * @since 2.9.0
465
- * @see http://snippet.fm/snippets/add-order-complete-action-to-woocommerce-my-orders-customer-table/
466
- */
467
- function maybe_add_my_account_order_actions( $actions, $order ) {
468
- $statuses_to_add = get_option( 'wcj_my_account_add_order_status_actions', '' );
469
- if ( ! empty( $statuses_to_add ) ) {
470
- $all_statuses = wcj_get_order_statuses();
471
- foreach ( $statuses_to_add as $status_to_add ) {
472
- if ( $status_to_add != $order->get_status() ) {
473
- $actions[ 'wcj_mark_' . $status_to_add . '_by_customer' ] = array(
474
- 'url' => wp_nonce_url( add_query_arg( array(
475
- 'wcj_action' => 'wcj_woocommerce_mark_order_status',
476
- 'status' => $status_to_add,
477
- 'order_id' => $order->get_id() ) ), 'wcj-woocommerce-mark-order-status' ),
478
- 'name' => $all_statuses[ $status_to_add ],
479
- );
480
- }
481
- }
482
- }
483
- return $actions;
484
- }
485
-
486
- /*
487
- * maybe_add_js_conformation.
488
- *
489
- * @version 2.9.0
490
- * @since 2.9.0
491
- */
492
- function maybe_add_js_conformation() {
493
- $statuses_to_add = get_option( 'wcj_my_account_add_order_status_actions', '' );
494
- if ( ! empty( $statuses_to_add ) ) {
495
- echo '<script>';
496
- foreach ( $statuses_to_add as $status_to_add ) {
497
- echo 'jQuery("a.wcj_mark_' . $status_to_add . '_by_customer").each( function() { jQuery(this).attr("onclick", "return confirm(\'' .
498
- __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')") } );';
499
- }
500
- echo '</script>';
501
- }
502
- }
503
-
504
- /*
505
- * process_woocommerce_mark_order_status.
506
- *
507
- * @version 2.9.0
508
- * @since 2.9.0
509
- */
510
- function process_woocommerce_mark_order_status() {
511
- if (
512
- isset( $_GET['wcj_action'] ) && 'wcj_woocommerce_mark_order_status' === $_GET['wcj_action'] &&
513
- isset( $_GET['status'] ) &&
514
- isset( $_GET['order_id'] ) &&
515
- isset( $_GET['_wpnonce'] )
516
- ) {
517
- if ( wp_verify_nonce( $_GET['_wpnonce'], 'wcj-woocommerce-mark-order-status' ) ) {
518
- $_order = wc_get_order( $_GET['order_id'] );
519
- if ( $_order->get_customer_id() === get_current_user_id() ) {
520
- $_order->update_status( $_GET['status'] );
521
- wp_safe_redirect( remove_query_arg( array( 'wcj_action', 'status', 'order_id', '_wpnonce' ) ) );
522
- exit;
523
- }
524
- }
525
- }
526
- }
527
-
528
- }
529
-
530
- endif;
531
-
532
- return new WCJ_My_Account();
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - My Account
4
+ *
5
+ * @version 4.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_My_Account' ) ) :
13
+
14
+ class WCJ_My_Account extends WCJ_Module {
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 4.8.0
20
+ * @since 2.9.0
21
+ * @todo [dev] Custom Menu Pages: add "Type" option with values: "param" (i.e. as it is now) or "endpoint"
22
+ * @todo [dev] Custom Menu Pages: deprecate "Add Custom Menu Items" (and add "link" value in "Type" options)
23
+ */
24
+ function __construct() {
25
+
26
+ $this->id = 'my_account';
27
+ $this->short_desc = __( 'My Account', 'woocommerce-jetpack' );
28
+ $this->desc = __( 'WooCommerce "My Account" page customization.', 'woocommerce-jetpack' );
29
+ $this->link_slug = 'woocommerce-my-account';
30
+ parent::__construct();
31
+
32
+ $this->account_menu_items = array(
33
+ 'dashboard' => __( 'Dashboard', 'woocommerce' ),
34
+ 'orders' => __( 'Orders', 'woocommerce' ),
35
+ 'downloads' => __( 'Downloads', 'woocommerce' ),
36
+ 'edit-address' => __( 'Addresses', 'woocommerce' ),
37
+ 'payment-methods' => __( 'Payment methods', 'woocommerce' ),
38
+ 'edit-account' => __( 'Account details', 'woocommerce' ),
39
+ 'customer-logout' => __( 'Logout', 'woocommerce' ),
40
+ );
41
+ $this->account_menu_endpoints = array(
42
+ 'orders' => __( 'Orders', 'woocommerce' ),
43
+ 'view-order' => __( 'View order', 'woocommerce' ),
44
+ 'downloads' => __( 'Downloads', 'woocommerce' ),
45
+ 'edit-account' => __( 'Edit account', 'woocommerce' ) . ' (' . __( 'Account details', 'woocommerce' ) . ')',
46
+ 'edit-address' => __( 'Addresses', 'woocommerce' ),
47
+ 'payment-methods' => __( 'Payment methods', 'woocommerce' ),
48
+ 'lost-password' => __( 'Lost password', 'woocommerce' ),
49
+ 'customer-logout' => __( 'Logout', 'woocommerce' ),
50
+ );
51
+ $this->menu_order_default = implode( PHP_EOL, array_keys( $this->account_menu_items ) );
52
+
53
+ if ( $this->is_enabled() ) {
54
+ add_filter( 'woocommerce_my_account_my_orders_actions', array( $this, 'maybe_add_my_account_order_actions' ), 10, 2 );
55
+ add_action( 'wp_footer', array( $this, 'maybe_add_js_conformation' ) );
56
+ add_action( 'init', array( $this, 'process_woocommerce_mark_order_status' ) );
57
+ // Custom pages
58
+ if ( 'yes' === get_option( 'wcj_my_account_custom_pages_enabled', 'no' ) ) {
59
+ add_action( 'woocommerce_account_' . 'page' . '_endpoint', array( $this, 'customize_dashboard' ), PHP_INT_MAX );
60
+ add_filter( 'the_title', array( $this, 'set_custom_page_title' ), PHP_INT_MAX );
61
+ add_filter( 'the_title', array( $this, 'set_custom_page_title_with_endpoint' ) );
62
+ add_filter( 'woocommerce_account_menu_items', array( $this, 'add_custom_page_menu_item' ), PHP_INT_MAX );
63
+ add_filter( 'woocommerce_get_endpoint_url', array( $this, 'set_custom_page_url' ), PHP_INT_MAX, 4 );
64
+ add_action( 'init', array( $this, 'add_endpoints' ) );
65
+ $this->customize_dashboard_for_endpoints();
66
+ }
67
+ // Custom info
68
+ if ( 'yes' === get_option( 'wcj_my_account_custom_info_enabled', 'no' ) ) {
69
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_my_account_custom_info_total_number', 1 ) );
70
+ for ( $i = 1; $i <= $total_number; $i++ ) {
71
+ add_action(
72
+ get_option( 'wcj_my_account_custom_info_hook_' . $i, 'woocommerce_account_dashboard' ),
73
+ array( $this, 'add_my_account_custom_info' ),
74
+ get_option( 'wcj_my_account_custom_info_priority_' . $i, 10 )
75
+ );
76
+ }
77
+ }
78
+ // Registration extra fields
79
+ if ( 'yes' === get_option( 'wcj_my_account_registration_extra_fields_user_role_enabled', 'no' ) ) {
80
+ add_action( 'woocommerce_register_form', array( $this, 'add_registration_extra_fields' ), PHP_INT_MAX );
81
+ add_action( 'woocommerce_created_customer', array( $this, 'process_registration_extra_fields' ), PHP_INT_MAX, 3 );
82
+ }
83
+ // Menu & Endpoints
84
+ if ( 'yes' === get_option( 'wcj_my_account_menu_customize_enabled', 'no' ) ) {
85
+ foreach ( $this->account_menu_endpoints as $account_menu_endpoint_id => $account_menu_endpoint_title ) {
86
+ add_filter( 'woocommerce_endpoint_' . $account_menu_endpoint_id . '_title', array( $this, 'customize_endpoint_title' ), PHP_INT_MAX, 2 );
87
+ }
88
+ add_filter( 'woocommerce_account_menu_items', array( $this, 'customize_menu' ), PHP_INT_MAX );
89
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_my_account_menu_order_custom_items_enabled', 'no' ) ) ) {
90
+ add_filter( 'woocommerce_get_endpoint_url', array( $this, 'customize_menu_custom_endpoints' ), PHP_INT_MAX, 4 );
91
+ }
92
+ }
93
+ // Dashboard customization
94
+ if ( 'yes' === get_option( 'wcj_my_account_custom_dashboard_enabled', 'no' ) ) {
95
+ add_action( 'woocommerce_account_' . 'page' . '_endpoint', array( $this, 'customize_dashboard' ), PHP_INT_MAX );
96
+ }
97
+ }
98
+ }
99
+
100
+ /**
101
+ * customize_dashboard_for_endpoints.
102
+ *
103
+ * @version 4.8.0
104
+ * @since 4.8.0
105
+ */
106
+ function customize_dashboard_for_endpoints() {
107
+ foreach ( $this->get_custom_pages() as $custom_menu_page_id => $custom_menu_page_data ) {
108
+ if ( empty( $endpoint = $custom_menu_page_data['endpoint'] ) ) {
109
+ continue;
110
+ }
111
+ add_action( 'woocommerce_account_' . $endpoint . '_endpoint', array( $this, 'customize_dashboard' ), PHP_INT_MAX );
112
+ }
113
+ }
114
+
115
+ /**
116
+ * Register new endpoint to use inside My Account page.
117
+ *
118
+ * @version 4.8.0
119
+ * @since 4.8.0
120
+ *
121
+ * @see https://developer.wordpress.org/reference/functions/add_rewrite_endpoint/
122
+ */
123
+ public function add_endpoints() {
124
+ foreach ( $this->get_custom_pages() as $custom_menu_page_id => $custom_menu_page_data ) {
125
+ if ( empty( $endpoint = $custom_menu_page_data['endpoint'] ) ) {
126
+ continue;
127
+ }
128
+ add_rewrite_endpoint( $endpoint, EP_ROOT | EP_PAGES );
129
+ }
130
+ }
131
+
132
+ /**
133
+ * get_custom_pages.
134
+ *
135
+ * @version 4.8.0
136
+ * @since 4.3.0
137
+ * @todo [dev] customizable ID (i.e. instead of `sanitize_title( $title[ $i ] )`)
138
+ */
139
+ function get_custom_pages() {
140
+ if ( isset( $this->custom_pages ) ) {
141
+ return $this->custom_pages;
142
+ }
143
+ $this->custom_pages = array();
144
+ $title = get_option( 'wcj_my_account_custom_pages_title', array() );
145
+ $content = get_option( 'wcj_my_account_custom_pages_content', array() );
146
+ $endpoint = get_option( 'wcj_my_account_custom_pages_endpoint', array() );
147
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_my_account_custom_pages_total_number', 1 ) ); $i ++ ) {
148
+ if ( ! empty( $title[ $i ] ) && ! empty( $content[ $i ] ) ) {
149
+ $endpoint[ $i ] = isset( $endpoint[ $i ] ) ? $endpoint[ $i ] : '';
150
+ $this->custom_pages[ sanitize_title( $title[ $i ] ) ] = array( 'endpoint' => $endpoint[ $i ], 'title' => $title[ $i ], 'content' => $content[ $i ] );
151
+ }
152
+ }
153
+ return $this->custom_pages;
154
+ }
155
+
156
+ /**
157
+ * set_custom_page_title.
158
+ *
159
+ * @version 4.5.0
160
+ * @since 4.3.0
161
+ */
162
+ function set_custom_page_title( $title ) {
163
+ if (
164
+ ! isset( $_GET['section'] ) ||
165
+ is_admin() ||
166
+ ! in_the_loop() ||
167
+ ! is_account_page()
168
+ ) {
169
+ return $title;
170
+ }
171
+ if ( ! isset( $this->custom_pages ) ) {
172
+ $this->get_custom_pages();
173
+ }
174
+ $endpoint = $_GET['section'];
175
+ return ( isset( $this->custom_pages[ $endpoint ] ) ? $this->custom_pages[ $endpoint ]['title'] : $title );
176
+
177
+ return $title;
178
+ }
179
+
180
+ /**
181
+ * Set endpoint title.
182
+ *
183
+ * @version 4.8.0
184
+ * @since 4.8.0
185
+ *
186
+ * @param string $title
187
+ * @return string
188
+ */
189
+ public function set_custom_page_title_with_endpoint( $title ) {
190
+ if (
191
+ is_admin() ||
192
+ ! is_account_page() ||
193
+ ! in_the_loop()
194
+ ) {
195
+ return $title;
196
+ }
197
+ global $wp_query;
198
+
199
+ if ( ! isset( $this->custom_pages ) ) {
200
+ $this->get_custom_pages();
201
+ }
202
+ $endpoints = wp_list_pluck( $this->custom_pages, 'endpoint' );
203
+ $intersect = array_intersect_key( $wp_query->query_vars, array_flip( array_filter( $endpoints ) ) );
204
+ if ( ! empty( $intersect ) ) {
205
+ reset( $intersect );
206
+ $filter = wp_list_filter( $this->custom_pages, array( 'endpoint' => key( $intersect ) ) );
207
+ reset( $filter );
208
+ $title = ( isset( $this->custom_pages[ key( $filter ) ] ) ? $this->custom_pages[ key( $filter ) ]['title'] : $title );
209
+ }
210
+ return $title;
211
+ }
212
+
213
+ /**
214
+ * set_custom_page_url.
215
+ *
216
+ * @version 4.8.0
217
+ * @since 4.3.0
218
+ * @todo [dev] (maybe) customizable `section` (e.g. `wcj-section`)
219
+ */
220
+ function set_custom_page_url( $url, $endpoint, $value, $permalink ) {
221
+ if ( ! isset( $this->custom_pages ) ) {
222
+ $this->get_custom_pages();
223
+ }
224
+ return ( isset( $this->custom_pages[ $endpoint ] ) && empty( $this->custom_pages[ $endpoint ]['endpoint'] ) && ( $myaccount_page_id = get_option( 'woocommerce_myaccount_page_id' ) ) ? add_query_arg( 'section', $endpoint, get_permalink( $myaccount_page_id ) ) : $url );
225
+ }
226
+
227
+ /**
228
+ * add_custom_page_menu_item.
229
+ *
230
+ * @version 4.8.0
231
+ * @since 4.3.0
232
+ */
233
+ function add_custom_page_menu_item( $items ) {
234
+ foreach ( $this->get_custom_pages() as $custom_menu_page_id => $custom_menu_page_data ) {
235
+ $custom_menu_page_id = ! empty( $custom_menu_page_data['endpoint'] ) ? $custom_menu_page_data['endpoint'] : $custom_menu_page_id;
236
+ $items[ $custom_menu_page_id ] = $custom_menu_page_data['title'];
237
+ }
238
+ return $items;
239
+ }
240
+
241
+ /**
242
+ * customize_menu_custom_endpoints.
243
+ *
244
+ * @version 3.8.0
245
+ * @since 3.8.0
246
+ */
247
+ function customize_menu_custom_endpoints( $url, $endpoint, $value, $permalink ) {
248
+ $custom_items = array_map( 'trim', explode( PHP_EOL, get_option( 'wcj_my_account_menu_order_custom_items', '' ) ) );
249
+ foreach ( $custom_items as $custom_item ) {
250
+ $parts = array_map( 'trim', explode( '|', $custom_item, 3 ) );
251
+ if ( 3 === count( $parts ) && $parts[0] === $endpoint ) {
252
+ return $parts[2];
253
+ }
254
+ }
255
+ return $url;
256
+ }
257
+
258
+ /**
259
+ * customize_dashboard.
260
+ *
261
+ * @version 4.8.0
262
+ * @since 3.8.0
263
+ * @see woocommerce/templates/myaccount/dashboard.php
264
+ */
265
+ function customize_dashboard( $value ) {
266
+
267
+ // Custom pages
268
+ if ( 'yes' === get_option( 'wcj_my_account_custom_pages_enabled', 'no' ) ) {
269
+ if ( isset( $_GET['section'] ) || 'woocommerce_account_page_endpoint' != current_filter() ) {
270
+ if ( ! isset( $this->custom_pages ) ) {
271
+ $this->get_custom_pages();
272
+ }
273
+ $endpoint = 'woocommerce_account_page_endpoint' != current_filter() ? str_replace( array( 'woocommerce_account_', '_endpoint' ), array( '' ), current_filter() ) : false;
274
+ if ( false !== $endpoint ) {
275
+ $endpoint_tab = wp_list_filter( $this->custom_pages, array( 'endpoint' => $endpoint ) );
276
+ }
277
+ $page_id = isset( $_GET['section'] ) ? $_GET['section'] : ( false !== $endpoint ? array_keys( wp_list_pluck( $endpoint_tab, 'endpoint' ) )[0] : '' );
278
+ if ( isset( $this->custom_pages[ $page_id ] ) ) {
279
+ echo do_shortcode( $this->custom_pages[ $page_id ]['content'] );
280
+ return;
281
+ }
282
+ }
283
+ if ( 'no' === get_option( 'wcj_my_account_custom_dashboard_enabled', 'no' ) ) {
284
+ wc_get_template( 'myaccount/dashboard.php', array(
285
+ 'current_user' => get_user_by( 'id', get_current_user_id() ),
286
+ ) );
287
+ return;
288
+ }
289
+ }
290
+
291
+ // Dashboard customization
292
+ $current_user = get_user_by( 'id', get_current_user_id() );
293
+
294
+ if ( '' != ( $custom_content = get_option( 'wcj_my_account_custom_dashboard_content', '' ) ) ) {
295
+ echo do_shortcode( $custom_content );
296
+ }
297
+
298
+ if ( 'no' === get_option( 'wcj_my_account_custom_dashboard_hide_hello', 'no' ) ) {
299
+ echo '<p>';
300
+ /* translators: 1: user display name 2: logout url */
301
+ printf(
302
+ __( 'Hello %1$s (not %1$s? <a href="%2$s">Log out</a>)', 'woocommerce' ),
303
+ '<strong>' . esc_html( $current_user->display_name ) . '</strong>',
304
+ esc_url( wc_logout_url( wc_get_page_permalink( 'myaccount' ) ) )
305
+ );
306
+ echo '</p>';
307
+ }
308
+
309
+ if ( 'no' === get_option( 'wcj_my_account_custom_dashboard_hide_info', 'no' ) ) {
310
+ echo '<p>';
311
+ printf(
312
+ __( 'From your account dashboard you can view your <a href="%1$s">recent orders</a>, manage your <a href="%2$s">shipping and billing addresses</a>, and <a href="%3$s">edit your password and account details</a>.', 'woocommerce' ),
313
+ esc_url( wc_get_endpoint_url( 'orders' ) ),
314
+ esc_url( wc_get_endpoint_url( 'edit-address' ) ),
315
+ esc_url( wc_get_endpoint_url( 'edit-account' ) )
316
+ );
317
+ echo '</p>';
318
+ }
319
+
320
+ /**
321
+ * My Account dashboard.
322
+ *
323
+ * @since 2.6.0
324
+ */
325
+ do_action( 'woocommerce_account_dashboard' );
326
+
327
+ /**
328
+ * Deprecated woocommerce_before_my_account action.
329
+ *
330
+ * @deprecated 2.6.0
331
+ */
332
+ do_action( 'woocommerce_before_my_account' );
333
+
334
+ /**
335
+ * Deprecated woocommerce_after_my_account action.
336
+ *
337
+ * @deprecated 2.6.0
338
+ */
339
+ do_action( 'woocommerce_after_my_account' );
340
+
341
+ }
342
+
343
+ /**
344
+ * customize_endpoint_title.
345
+ *
346
+ * @version 3.8.0
347
+ * @since 3.8.0
348
+ * @todo (maybe) 'orders': `if ( ! empty( $wp->query_vars['orders'] ) ) { $title = sprintf( __( 'Orders (page %d)', 'woocommerce' ), intval( $wp->query_vars['orders'] ) ); }`
349
+ * @todo (maybe) 'view-order': `$title = ( $order = wc_get_order( $wp->query_vars['view-order'] ) ) ? sprintf( __( 'Order #%s', 'woocommerce' ), $order->get_order_number() ) : '';`
350
+ * @todo (maybe) 'order-pay' => __( 'Pay for order', 'woocommerce' )
351
+ * @todo (maybe) 'order-received' => __( 'Order received', 'woocommerce' )
352
+ */
353
+ function customize_endpoint_title( $title, $endpoint ) {
354
+ $menu_titles = get_option( 'wcj_my_account_menu_title', array() );
355
+ if ( ! empty( $menu_titles[ $endpoint ] ) ) {
356
+ return $menu_titles[ $endpoint ];
357
+ }
358
+ return $title;
359
+ }
360
+
361
+ /**
362
+ * customize_menu.
363
+ *
364
+ * @version 3.8.0
365
+ * @since 3.8.0
366
+ * @todo (maybe) option to disable menu
367
+ */
368
+ function customize_menu( $items ) {
369
+ $menu_titles = get_option( 'wcj_my_account_menu_title', array() );
370
+ foreach ( $items as $item_id => $item_title ) {
371
+ if ( ! empty( $menu_titles[ $item_id ] ) ) {
372
+ $items[ $item_id ] = $menu_titles[ $item_id ];
373
+ }
374
+ }
375
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_my_account_menu_order_customize_enabled', 'no' ) ) ) {
376
+ $menu_order = array_map( 'trim', explode( PHP_EOL, get_option( 'wcj_my_account_menu_order', $this->menu_order_default ) ) );
377
+ $modified_menu = array();
378
+ foreach ( $menu_order as $item_id ) {
379
+ if ( isset( $items[ $item_id ] ) ) {
380
+ $modified_menu[ $item_id ] = $items[ $item_id ];
381
+ unset( $items[ $item_id ] );
382
+ }
383
+ }
384
+ $items = array_merge( $modified_menu, $items );
385
+ }
386
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_my_account_menu_order_custom_items_enabled', 'no' ) ) ) {
387
+ $custom_items = array_map( 'trim', explode( PHP_EOL, get_option( 'wcj_my_account_menu_order_custom_items', '' ) ) );
388
+ foreach ( $custom_items as $custom_item ) {
389
+ $parts = array_map( 'trim', explode( '|', $custom_item, 3 ) );
390
+ if ( 3 === count( $parts ) ) {
391
+ $items[ $parts[0] ] = $parts[1];
392
+ }
393
+ }
394
+ }
395
+ return $items;
396
+ }
397
+
398
+ /**
399
+ * add_registration_extra_fields.
400
+ *
401
+ * @version 3.6.0
402
+ * @since 3.6.0
403
+ * @todo (maybe) more fields to choose from (i.e. not only "user role" field)
404
+ * @todo (maybe) customizable position (check for other hooks or at least customizable priority on `woocommerce_register_form`)
405
+ * @todo (maybe) move to new module (e.g. "Registration Form")
406
+ */
407
+ function add_registration_extra_fields() {
408
+ $user_roles_options_html = '';
409
+ $current_user_role_input = ! empty( $_POST['wcj_user_role'] ) ? $_POST['wcj_user_role'] :
410
+ get_option( 'wcj_my_account_registration_extra_fields_user_role_default', 'customer' );
411
+ $user_roles_options = get_option( 'wcj_my_account_registration_extra_fields_user_role_options', array( 'customer' ) );
412
+ $all_user_roles = wcj_get_user_roles_options();
413
+ foreach ( $user_roles_options as $user_role_id ) {
414
+ $user_roles_options_html .= '<option value="' . $user_role_id . '" ' . selected( $user_role_id, $current_user_role_input, false ) . '>' .
415
+ ( isset( $all_user_roles[ $user_role_id ] ) ? $all_user_roles[ $user_role_id ] : $user_role_id ) . '</option>';
416
+ }
417
+ ?><p class="woocommerce-form-row woocommerce-form-row--wide form-row form-row-wide">
418
+ <label for="reg_wcj_user_role"><?php esc_html_e( 'User role', 'woocommerce-jetpack' ); ?></label>
419
+ <select name="wcj_user_role" id="reg_wcj_user_role"><?php echo $user_roles_options_html; ?></select>
420
+ </p><?php
421
+ }
422
+
423
+ /**
424
+ * process_registration_extra_fields.
425
+ *
426
+ * @version 3.6.0
427
+ * @since 3.6.0
428
+ * @todo (maybe) optional admin confirmation for some user roles (probably will need to create additional `...-pending` user roles)
429
+ */
430
+ function process_registration_extra_fields( $customer_id, $new_customer_data, $password_generated ) {
431
+ if ( isset( $_POST['wcj_user_role'] ) && '' != $_POST['wcj_user_role'] ) {
432
+ $user_roles_options = get_option( 'wcj_my_account_registration_extra_fields_user_role_options', array( 'customer' ) );
433
+ if ( ! empty( $user_roles_options ) && in_array( $_POST['wcj_user_role'], $user_roles_options ) ) {
434
+ wp_update_user( array( 'ID' => $customer_id, 'role' => $_POST['wcj_user_role'] ) );
435
+ }
436
+ }
437
+ }
438
+
439
+ /**
440
+ * add_my_account_custom_info.
441
+ *
442
+ * @version 3.4.0
443
+ * @since 3.4.0
444
+ */
445
+ function add_my_account_custom_info() {
446
+ $current_filter = current_filter();
447
+ $current_filter_priority = wcj_current_filter_priority();
448
+ $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_my_account_custom_info_total_number', 1 ) );
449
+ for ( $i = 1; $i <= $total_number; $i++ ) {
450
+ if (
451
+ '' != get_option( 'wcj_my_account_custom_info_content_' . $i ) &&
452
+ $current_filter === get_option( 'wcj_my_account_custom_info_hook_' . $i, 'woocommerce_account_dashboard' ) &&
453
+ $current_filter_priority == get_option( 'wcj_my_account_custom_info_priority_' . $i, 10 )
454
+ ) {
455
+ echo do_shortcode( get_option( 'wcj_my_account_custom_info_content_' . $i ) );
456
+ }
457
+ }
458
+ }
459
+
460
+ /*
461
+ * maybe_add_my_account_order_actions.
462
+ *
463
+ * @version 2.9.0
464
+ * @since 2.9.0
465
+ * @see http://snippet.fm/snippets/add-order-complete-action-to-woocommerce-my-orders-customer-table/
466
+ */
467
+ function maybe_add_my_account_order_actions( $actions, $order ) {
468
+ $statuses_to_add = get_option( 'wcj_my_account_add_order_status_actions', '' );
469
+ if ( ! empty( $statuses_to_add ) ) {
470
+ $all_statuses = wcj_get_order_statuses();
471
+ foreach ( $statuses_to_add as $status_to_add ) {
472
+ if ( $status_to_add != $order->get_status() ) {
473
+ $actions[ 'wcj_mark_' . $status_to_add . '_by_customer' ] = array(
474
+ 'url' => wp_nonce_url( add_query_arg( array(
475
+ 'wcj_action' => 'wcj_woocommerce_mark_order_status',
476
+ 'status' => $status_to_add,
477
+ 'order_id' => $order->get_id() ) ), 'wcj-woocommerce-mark-order-status' ),
478
+ 'name' => $all_statuses[ $status_to_add ],
479
+ );
480
+ }
481
+ }
482
+ }
483
+ return $actions;
484
+ }
485
+
486
+ /*
487
+ * maybe_add_js_conformation.
488
+ *
489
+ * @version 2.9.0
490
+ * @since 2.9.0
491
+ */
492
+ function maybe_add_js_conformation() {
493
+ $statuses_to_add = get_option( 'wcj_my_account_add_order_status_actions', '' );
494
+ if ( ! empty( $statuses_to_add ) ) {
495
+ echo '<script>';
496
+ foreach ( $statuses_to_add as $status_to_add ) {
497
+ echo 'jQuery("a.wcj_mark_' . $status_to_add . '_by_customer").each( function() { jQuery(this).attr("onclick", "return confirm(\'' .
498
+ __( 'Are you sure?', 'woocommerce-jetpack' ) . '\')") } );';
499
+ }
500
+ echo '</script>';
501
+ }
502
+ }
503
+
504
+ /*
505
+ * process_woocommerce_mark_order_status.
506
+ *
507
+ * @version 2.9.0
508
+ * @since 2.9.0
509
+ */
510
+ function process_woocommerce_mark_order_status() {
511
+ if (
512
+ isset( $_GET['wcj_action'] ) && 'wcj_woocommerce_mark_order_status' === $_GET['wcj_action'] &&
513
+ isset( $_GET['status'] ) &&
514
+ isset( $_GET['order_id'] ) &&
515
+ isset( $_GET['_wpnonce'] )
516
+ ) {
517
+ if ( wp_verify_nonce( $_GET['_wpnonce'], 'wcj-woocommerce-mark-order-status' ) ) {
518
+ $_order = wc_get_order( $_GET['order_id'] );
519
+ if ( $_order->get_customer_id() === get_current_user_id() ) {
520
+ $_order->update_status( $_GET['status'] );
521
+ wp_safe_redirect( remove_query_arg( array( 'wcj_action', 'status', 'order_id', '_wpnonce' ) ) );
522
+ exit;
523
+ }
524
+ }
525
+ }
526
+ }
527
+
528
+ }
529
+
530
+ endif;
531
+
532
+ return new WCJ_My_Account();
includes/class-wcj-offer-price.php CHANGED
@@ -1,562 +1,562 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Module - Offer Price
4
- *
5
- * @version 4.4.0
6
- * @since 2.9.0
7
- * @author Algoritmika Ltd.
8
- */
9
-
10
- if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
-
12
- if ( ! class_exists( 'WCJ_Offer_Price' ) ) :
13
-
14
- class WCJ_Offer_Price extends WCJ_Module {
15
-
16
- /**
17
- * Constructor.
18
- *
19
- * @version 4.3.0
20
- * @since 2.9.0
21
- * @todo settings - more info about position priorities, e.g.: __( 'Standard priorities for "Inside single product summary": title - 5, rating - 10, price - 10, excerpt - 20, add to cart - 30, meta - 40, sharing - 50', 'woocommerce-jetpack' )
22
- * @todo (maybe) css - customizable fonts etc.
23
- * @todo (maybe) css - better default colors
24
- * @todo (maybe) better solution for the form hook (instead of `woocommerce_before_main_content`)
25
- * @todo (maybe) per product settings - add "use global values/use values below" for price step etc. (instead of placeholders etc.)
26
- * @todo (maybe) recheck multicurrency
27
- * @todo (maybe) more "Make an offer" button position options (on both single and archives)
28
- * @todo (maybe) variations and grouped products
29
- * @todo (maybe) add shortcode
30
- * @todo (maybe) offers history - option for disabling
31
- * @todo (maybe) offers history - global (i.e. for all products)
32
- */
33
- function __construct() {
34
-
35
- $this->id = 'offer_price';
36
- $this->short_desc = __( 'Offer Your Price', 'woocommerce-jetpack' );
37
- $this->desc = __( 'Let your customers to suggest their price for products.', 'woocommerce-jetpack' );
38
- $this->link_slug = 'woocommerce-offer-your-product-price';
39
- parent::__construct();
40
-
41
- if ( $this->is_enabled() ) {
42
- if ( 'disable' != ( $_hook = get_option( 'wcj_offer_price_button_position', 'woocommerce_single_product_summary' ) ) ) {
43
- add_action(
44
- $_hook,
45
- array( $this, 'add_offer_price_button' ),
46
- get_option( 'wcj_offer_price_button_position_priority', 31 )
47
- );
48
- }
49
- if ( 'disable' != ( $_hook = apply_filters( 'booster_option', 'disable', get_option( 'wcj_offer_price_button_position_archives', 'disable' ) ) ) ) {
50
- add_action(
51
- $_hook,
52
- array( $this, 'add_offer_price_button' ),
53
- get_option( 'wcj_offer_price_button_position_priority_archives', 10 )
54
- );
55
- }
56
- $custom_hooks = apply_filters( 'booster_option', '', get_option( 'wcj_offer_price_button_position_custom', '' ) );
57
- if ( ! empty( $custom_hooks ) ) {
58
- $custom_hooks = array_filter( array_map( 'trim', explode( '|', $custom_hooks ) ) );
59
- $custom_hook_priorities = apply_filters( 'booster_option', '', get_option( 'wcj_offer_price_button_position_priority_custom', '' ) );
60
- $custom_hook_priorities = array_map( 'trim', explode( '|', $custom_hook_priorities ) );
61
- foreach ( $custom_hooks as $i => $custom_hook ) {
62
- add_action(
63
- $custom_hook,
64
- array( $this, 'add_offer_price_button' ),
65
- ( isset( $custom_hook_priorities[ $i ] ) ? $custom_hook_priorities[ $i ] : 10 )
66
- );
67
- }
68
- }
69
- add_action( 'wp_footer', array( $this, 'add_offer_price_form' ) );
70
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
71
- add_action( 'init', array( $this, 'offer_price' ) );
72
- if ( in_array( apply_filters( 'booster_option', 'all_products', get_option( 'wcj_offer_price_enabled_type', 'all_products' ) ), array( 'per_product', 'per_product_and_per_category' ) ) ) {
73
- add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
74
- add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
75
- }
76
- // Offer history
77
- add_action( 'add_meta_boxes', array( $this, 'add_offer_price_history_meta_box' ) );
78
- add_action( 'save_post_product', array( $this, 'delete_offer_price_product_history' ), PHP_INT_MAX, 2 );
79
- // CSS
80
- add_action( 'wp_head', array( $this, 'add_styling' ), PHP_INT_MAX );
81
- }
82
- }
83
-
84
- /**
85
- * add_styling.
86
- *
87
- * @version 3.7.0
88
- * @since 3.7.0
89
- */
90
- function add_styling() {
91
- $styling_default = array(
92
- 'form_content_width' => '80%',
93
- 'form_header_back_color' => '#5cb85c',
94
- 'form_header_text_color' => '#ffffff',
95
- 'form_footer_back_color' => '#5cb85c',
96
- 'form_footer_text_color' => '#ffffff',
97
- );
98
- $styling_options = get_option( 'wcj_offer_price_styling', array() );
99
- foreach ( $styling_default as $option => $default ) {
100
- if ( ! isset( $styling_options[ $option ] ) ) {
101
- $styling_options[ $option ] = $default;
102
- }
103
- }
104
- echo "<style type=\"text/css\">
105
- .wcj-offer-price-modal-content {
106
- width: {$styling_options['form_content_width']};
107
- }
108
- .wcj-offer-modal-header {
109
- background-color: {$styling_options['form_header_back_color']};
110
- color: {$styling_options['form_header_text_color']};
111
- }
112
- .wcj-offer-modal-header h1, .wcj-offer-modal-header h2, .wcj-offer-modal-header h3, .wcj-offer-modal-header h4, .wcj-offer-modal-header h5, .wcj-offer-modal-header h6 {
113
- color: {$styling_options['form_header_text_color']};
114
- }
115
- .wcj-offer-price-modal-footer {
116
- background-color: {$styling_options['form_footer_back_color']};
117
- color: {$styling_options['form_footer_text_color']};
118
- }
119
- .wcj-offer-price-modal-footer h1, .wcj-offer-price-modal-footer h2, .wcj-offer-price-modal-footer h3, .wcj-offer-price-modal-footer h4, .wcj-offer-price-modal-footer h5, .wcj-offer-price-modal-footer h6 {
120
- color: {$styling_options['form_footer_text_color']};
121
- }
122
- </style>";
123
- }
124
-
125
- /**
126
- * delete_offer_price_product_history.
127
- *
128
- * @version 2.9.0
129
- * @since 2.9.0
130
- * @todo (maybe) add successful deletion notice
131
- */
132
- function delete_offer_price_product_history( $post_id, $post ) {
133
- if ( isset( $_POST['wcj_offer_price_delete_history'] ) ) {
134
- delete_post_meta( $post_id, '_' . 'wcj_price_offers' );
135
- add_action( 'admin_notices', array( $this, 'notice_delete_offer_price_product_history' ) );
136
- }
137
- }
138
-
139
- /**
140
- * add_offer_price_history_meta_box.
141
- *
142
- * @version 2.9.0
143
- * @since 2.9.0
144
- */
145
- function add_offer_price_history_meta_box() {
146
- add_meta_box(
147
- 'wc-booster-offer-price-history',
148
- __( 'Booster: Offer Price History', 'woocommerce-jetpack' ),
149
- array( $this, 'create_offer_price_history_meta_box' ),
150
- 'product',
151
- 'normal',
152
- 'high'
153
- );
154
- }
155
-
156
- /**
157
- * get_admin_meta_box_columns.
158
- *
159
- * @version 4.4.0
160
- * @since 4.4.0
161
- */
162
- function get_admin_meta_box_columns() {
163
- return array(
164
- 'date' => __( 'Date', 'woocommerce-jetpack' ),
165
- 'offered_price' => __( 'Price', 'woocommerce-jetpack' ),
166
- 'customer_message' => __( 'Message', 'woocommerce-jetpack' ),
167
- 'customer_name' => __( 'Name', 'woocommerce-jetpack' ),
168
- 'customer_email' => __( 'Email', 'woocommerce-jetpack' ),
169
- 'customer_id' => __( 'Customer ID', 'woocommerce-jetpack' ),
170
- 'user_ip' => __( 'User IP', 'woocommerce-jetpack' ),
171
- 'user_agent' => __( 'User Agent', 'woocommerce-jetpack' ),
172
- 'sent_to' => __( 'Sent to', 'woocommerce-jetpack' ),
173
- );
174
- }
175
-
176
- /**
177
- * create_offer_price_history_meta_box.
178
- *
179
- * @version 4.4.0
180
- * @since 2.9.0
181
- */
182
- function create_offer_price_history_meta_box() {
183
- if ( '' == ( $price_offers = get_post_meta( get_the_ID(), '_' . 'wcj_price_offers', true ) ) ) {
184
- echo '<em>' . __( 'No price offers yet.', 'woocommerce-jetpack' ) . '</em>';
185
- } else {
186
- $average_offers = array();
187
- $all_columns = $this->get_admin_meta_box_columns();
188
- $selected_columns = get_option( 'wcj_offer_price_admin_meta_box_columns',
189
- array( 'date', 'offered_price', 'customer_message', 'customer_name', 'customer_email', 'customer_id', 'user_ip', 'sent_to' ) );
190
- $table_data = array();
191
- $header = array();
192
- foreach ( $selected_columns as $selected_column ) {
193
- $header[] = $all_columns[ $selected_column ];
194
- }
195
- $table_data[] = $header;
196
- $date_ant_time_format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
197
- $price_offers = array_reverse( $price_offers );
198
- foreach ( $price_offers as $price_offer ) {
199
- $row = array();
200
- foreach ( $selected_columns as $selected_column ) {
201
- switch ( $selected_column ) {
202
- case 'date':
203
- $row[] = date_i18n( $date_ant_time_format, $price_offer['offer_timestamp'] );
204
- break;
205
- case 'offered_price':
206
- $row[] = wc_price( $price_offer['offered_price'], array( 'currency' => $price_offer['currency_code'] ) );
207
- break;
208
- case 'customer_message':
209
- $row[] = $price_offer['customer_message'];
210
- break;
211
- case 'customer_name':
212
- $row[] = $price_offer['customer_name'];
213
- break;
214
- case 'customer_email':
215
- $row[] = $price_offer['customer_email'];
216
- break;
217
- case 'customer_id':
218
- $row[] = $price_offer['customer_id'];
219
- break;
220
- case 'user_ip':
221
- $row[] = ( isset( $price_offer['user_ip'] ) ? $price_offer['user_ip'] : '' );
222
- break;
223
- case 'user_agent':
224
- $row[] = ( isset( $price_offer['user_agent'] ) ? $price_offer['user_agent'] : '' );
225
- break;
226
- case 'sent_to':
227
- $row[] = $price_offer['sent_to'] . ( 'yes' === $price_offer['copy_to_customer'] ? '<br>' . $price_offer['customer_email'] : '' );
228
- break;
229
- }
230
- }
231
- $table_data[] = $row;
232
- if ( ! isset( $average_offers[ $price_offer['currency_code'] ] ) ) {
233
- $average_offers[ $price_offer['currency_code'] ] = array( 'total_offers' => 0, 'offers_sum' => 0 );
234
- }
235
- $average_offers[ $price_offer['currency_code'] ]['total_offers']++;
236
- $average_offers[ $price_offer['currency_code'] ]['offers_sum'] += $price_offer['offered_price'];
237
- }
238
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) );
239
- foreach ( $average_offers as $average_offer_currency_code => $average_offer_data ) {
240
- echo '<p>' . sprintf( __( 'Average offer: %s (from %s offer(s))', 'woocommerce-jetpack' ),
241
- wc_price( ( $average_offer_data['offers_sum'] / $average_offer_data['total_offers'] ), array( 'currency' => $average_offer_currency_code ) ),
242
- $average_offer_data['total_offers']
243
- ) . '</p>';
244
- }
245
- echo '<p>' .
246
- '<input type="checkbox" id="wcj_offer_price_delete_history" name="wcj_offer_price_delete_history">' .
247
- '<label for="wcj_offer_price_delete_history">' . __( 'Delete history', 'woocommerce-jetpack' ) . '</label>' .
248
- wc_help_tip( __( 'Update product after checking the box.', 'woocommerce-jetpack' ) ) .
249
- '</p>';
250
- }
251
- }
252
-
253
- /**
254
- * enqueue_scripts.
255
- *
256
- * @version 2.9.0
257
- * @since 2.9.0
258
- * @see https://www.w3schools.com/howto/howto_css_modals.asp
259
- * @todo (maybe) enqueue only if really needed
260
- */
261
- function enqueue_scripts() {
262
- wp_enqueue_style( 'wcj-offer-price', wcj_plugin_url() . '/includes/css/wcj-offer-price.css', array(), WCJ()->version );
263
- wp_enqueue_script( 'wcj-offer-price-js', wcj_plugin_url() . '/includes/js/wcj-offer-price.js', array( 'jquery' ), WCJ()->version, true );
264
- }
265
-
266
- /**
267
- * is_offer_price_enabled_for_product.
268
- *
269
- * @version 4.2.0
270
- * @since 2.9.0
271
- */
272
- function is_offer_price_enabled_for_product( $product_id ) {
273
- switch ( apply_filters( 'booster_option', 'all_products', get_option( 'wcj_offer_price_enabled_type', 'all_products' ) ) ) {
274
- case 'all_products':
275
- return true;
276
- case 'empty_prices':
277
- $_product = wc_get_product( $product_id );
278
- return ( '' === $_product->get_price() );
279
- case 'per_product':
280
- return ( 'yes' === get_post_meta( $product_id, '_' . 'wcj_offer_price_enabled', true ) );
281
- case 'per_category':
282
- return wcj_is_product_term( $product_id, get_option( 'wcj_offer_price_enabled_cats', array() ), 'product_cat' );
283
- case 'per_product_and_per_category':
284
- return ( 'yes' === get_post_meta( $product_id, '_' . 'wcj_offer_price_enabled', true ) || wcj_is_product_term( $product_id, get_option( 'wcj_offer_price_enabled_cats', array() ), 'product_cat' ) );
285
- }
286
- }
287
-
288
- /**
289
- * get_wcj_data_array.
290
- *
291
- * @version 4.2.0
292
- * @since 2.9.0
293
- * @todo (maybe) rethink `str_replace( '\'', '"', ... )`
294
- */
295
- function get_wcj_data_array( $product_id ) {
296
- $is_per_product_enabled = ( in_array( apply_filters( 'booster_option', 'all_products', get_option( 'wcj_offer_price_enabled_type', 'all_products' ) ), array( 'per_product', 'per_product_and_per_category' ) ) );
297
- // Price input - price step
298
- $price_step = ( ! $is_per_product_enabled || '' === ( $price_step_per_product = get_post_meta( $product_id, '_' . 'wcj_offer_price_price_step', true ) ) ?
299
- get_option( 'wcj_offer_price_price_step', get_option( 'woocommerce_price_num_decimals' ) ) :
300
- $price_step_per_product
301
- );
302
- $price_step = sprintf( "%f", ( 1 / pow( 10, absint( $price_step ) ) ) );
303
- // Price input - min price
304
- $min_price = ( ! $is_per_product_enabled || '' === ( $min_price_per_product = get_post_meta( $product_id, '_' . 'wcj_offer_price_min_price', true ) ) ?
305
- get_option( 'wcj_offer_price_min_price', 0 ) :
306
- $min_price_per_product
307
- );
308
- // Price input - max price
309
- $max_price = ( ! $is_per_product_enabled || '' === ( $max_price_per_product = get_post_meta( $product_id, '_' . 'wcj_offer_price_max_price', true ) ) ?
310
- get_option( 'wcj_offer_price_max_price', 0 ) :
311
- $max_price_per_product
312
- );
313
- // Price input - default price
314
- $default_price = ( ! $is_per_product_enabled || '' === ( $default_price_per_product = get_post_meta( $product_id, '_' . 'wcj_offer_price_default_price', true ) ) ?
315
- get_option( 'wcj_offer_price_default_price', 0 ) :
316
- $default_price_per_product
317
- );
318
- // Price input - label
319
- $price_label = str_replace(
320
- '%currency_symbol%',
321
- get_woocommerce_currency_symbol(),
322
- get_option( 'wcj_offer_price_price_label', sprintf( __( 'Your price (%s)', 'woocommerce-jetpack' ), '%currency_symbol%' ) )
323
- );
324
- // Offer form - header
325
- $form_header = str_replace(
326
- '%product_title%',
327
- get_the_title(),
328
- get_option( 'wcj_offer_price_form_header_template', '<h3>' . sprintf( __( 'Suggest your price for %s', 'woocommerce-jetpack' ), '%product_title%' ) . '</h3>' )
329
- );
330
- return array(
331
- 'price_step' => $price_step,
332
- 'min_price' => $min_price,
333
- 'max_price' => $max_price,
334
- 'default_price' => $default_price,
335
- 'price_label' => str_replace( '\'', '"', $price_label ),
336
- 'form_header' => str_replace( '\'', '"', $form_header ),
337
- 'product_id' => $product_id,
338
- );
339
- }
340
-
341
- /**
342
- * add_offer_price_form.
343
- *
344
- * @version 2.9.0
345
- * @since 2.9.0
346
- * @todo (maybe) fix when empty header
347
- * @todo (maybe) style options for input fields (class, style)
348
- * @todo (maybe) form template
349
- * @todo (maybe) do_shortcode in form header and footer
350
- * @todo (maybe) logged user - check `nickname` and `billing_email`
351
- * @todo (maybe) better required asterix default
352
- * @todo (maybe) optional, additional and custom form fields
353
- */
354
- function add_offer_price_form() {
355
- // Prepare logged user data
356
- $customer_name = '';
357
- $customer_email = '';
358
- $customer_id = 0;
359
- if ( is_user_logged_in() ) {
360
- $current_user = wp_get_current_user();
361
- $customer_id = $current_user->ID;
362
- if ( '' != ( $meta = get_user_meta( $current_user->ID, 'nickname', true ) ) ) {
363
- $customer_name = $meta;
364
- }
365
- if ( '' != ( $meta = get_user_meta( $current_user->ID, 'billing_email', true ) ) ) {
366
- $customer_email = $meta;
367
- }
368
- }
369
- // Header
370
- $offer_form_header = '<div class="wcj-offer-modal-header">' .
371
- '<span class="wcj-offer-price-form-close">&times;</span>' . '<div id="wcj-offer-form-header"></div>' .
372
- '</div>';
373
- // Footer
374
- $offer_form_footer = ( '' != ( $footer_template = get_option( 'wcj_offer_price_form_footer_template', '' ) ) ?
375
- '<div class="wcj-offer-price-modal-footer">' . /* do_shortcode */( $footer_template ) . '</div>' : '' );
376
- // Required HTML
377
- $required_html = get_option( 'wcj_offer_price_form_required_html', ' <abbr class="required" title="required">*</abbr>' );
378
- // Content - price
379
- $offer_form_content_price = '<label for="wcj-offer-price-price">' .
380
- '<span id="wcj-offer-price-price-label"></span>' . $required_html . '</label>' . '<br>' .
381
- '<input type="number" required id="wcj-offer-price-price" name="wcj-offer-price-price">';
382
- // Content - email
383
- $offer_form_content_email = '<label for="wcj-offer-price-customer-email">' . get_option( 'wcj_offer_price_customer_email', __( 'Your email', 'woocommerce-jetpack' ) ) .
384
- $required_html . '</label>' . '<br>' .
385
- '<input type="email" required id="wcj-offer-price-customer-email" name="wcj-offer-price-customer-email" value="' . $customer_email . '">';
386
- // Content - name
387
- $offer_form_content_name = '<label for="wcj-offer-price-customer-name">' . get_option( 'wcj_offer_price_customer_name', __( 'Your name', 'woocommerce-jetpack' ) ) .
388
- '</label>' . '<br>' .
389
- '<input type="text" id="wcj-offer-price-customer-name" name="wcj-offer-price-customer-name" value="' . $customer_name . '">';
390
- // Content - message
391
- $offer_form_content_message = '<label for="wcj-offer-price-message">' . get_option( 'wcj_offer_price_customer_message', __( 'Your message', 'woocommerce-jetpack' ) ) . '</label>' . '<br>' .
392
- '<textarea id="wcj-offer-price-message" name="wcj-offer-price-message"></textarea>';
393
- // Content - button
394
- $offer_form_content_button = '<input type="submit" id="wcj-offer-price-submit" name="wcj-offer-price-submit" value="' .
395
- get_option( 'wcj_offer_price_form_button_label', __( 'Send', 'woocommerce-jetpack' ) ) . '">';
396
- // Content - copy
397
- $offer_form_content_copy = '<label for="wcj-offer-price-customer-copy">' . get_option( 'wcj_offer_price_customer_copy', __( 'Send a copy to your email', 'woocommerce-jetpack' ) ) .
398
- '</label>' . ' ' .
399
- '<input type="checkbox" id="wcj-offer-price-customer-copy" name="wcj-offer-price-customer-copy" value="yes">';
400
- // Content
401
- $offer_form_content = '<div class="wcj-offer-price-modal-body">' .
402
- '<form method="post" id="wcj-offer-price-form">' .
403
- '<p>' . $offer_form_content_price . '</p>' .
404
- '<p>' . $offer_form_content_email . '</p>' .
405
- '<p>' . $offer_form_content_name . '</p>' .
406
- '<p>' . $offer_form_content_message . '</p>' .
407
- '<p>' . $offer_form_content_button . '</p>' .
408
- '<p>' . $offer_form_content_copy . '</p>' .
409
- '<input type="hidden" id="wcj-offer-price-product-id" name="wcj-offer-price-product-id">' .
410
- '<input type="hidden" name="wcj-offer-price-customer-id" value="' . $customer_id . '">' .
411
- '</form>' .
412
- '</div>';
413
- // Final form
414
- echo '<div id="wcj-offer-price-modal" class="wcj-offer-price-modal">' .
415
- '<div class="wcj-offer-price-modal-content">' .
416
- $offer_form_header .
417
- $offer_form_content .
418
- $offer_form_footer .
419
- '</div>' .
420
- '</div>';
421
- }
422
-
423
- /**
424
- * is_offer_price_excluded_for_product.
425
- *
426
- * @version 4.4.0
427
- * @since 4.4.0
428
- * @todo [dev] add more conditions to exclude (i.e. not only "out of stock")
429
- */
430
- function is_offer_price_excluded_for_product( $product_id ) {
431
- if ( 'yes' === get_option( 'wcj_offer_price_exclude_out_of_stock', 'no' ) ) {
432
- $product = wc_get_product( $product_id );
433
- if ( ! $product->is_in_stock() ) {
434
- return true;
435
- }
436
- }
437
- return false;
438
- }
439
-
440
- /**
441
- * add_offer_price_button.
442
- *
443
- * @version 4.4.0
444
- * @since 2.9.0
445
- */
446
- function add_offer_price_button() {
447
- $product_id = get_the_ID();
448
- // Check if enabled for current product
449
- if ( ! $this->is_offer_price_enabled_for_product( $product_id ) || $this->is_offer_price_excluded_for_product( $product_id ) ) {
450
- return;
451
- }
452
- // The button
453
- if ( '' != $additional_class = get_option( 'wcj_offer_price_button_class', 'button' ) ) {
454
- $additional_class = ' ' . $additional_class;
455
- }
456
- echo '<p>' .
457
- '<button type="submit"' .
458
- ' name="wcj-offer-price-button"' .
459
- ' class="wcj-offer-price-button' . $additional_class . '"' .
460
- ' value="' . $product_id . '"' .
461
- ' style="' . get_option( 'wcj_offer_price_button_style', '' ) . '"' .
462
- ' wcj_data=\'' . json_encode( $this->get_wcj_data_array( $product_id ) ) . '\'' .
463
- '>' .
464
- get_option( 'wcj_offer_price_button_label', __( 'Make an offer', 'woocommerce-jetpack' ) ) .
465
- '</button>' .
466
- '</p>';
467
- }
468
-
469
- /**
470
- * offer_price.
471
- *
472
- * @version 4.4.0
473
- * @since 2.9.0
474
- * @todo (maybe) separate customer copy email template and subject
475
- * @todo (maybe) redirect (no notice though)
476
- * @todo (maybe) `%product_title%` etc. in notice
477
- * @todo (maybe) fix "From" header
478
- * @todo (maybe) check if mail has really been sent
479
- * @todo (maybe) sanitize $_POST
480
- */
481
- function offer_price() {
482
- if ( isset( $_POST['wcj-offer-price-submit'] ) ) {
483
- $product_id = $_POST['wcj-offer-price-product-id'];
484
- $_product = wc_get_product( $product_id );
485
- if ( ! is_a( $_product, 'WC_Product' ) ) {
486
- return;
487
- }
488
- // Email address
489
- $email_address = get_option( 'wcj_offer_price_email_address', '%admin_email%' );
490
- if ( '' == $email_address ) {
491
- $email_address = get_option( 'admin_email' );
492
- } else {
493
- $admin_email = get_option( 'admin_emai