Booster for WooCommerce - Version 3.1.0

Version Description

  • 11/09/2017 =
  • Dev - Shortcodes - visibility attribute - wrong_user_text attribute set to empty string by default now; wrong_user_text_not_logged_in attribute added (defaults to empty string).
  • Dev - Shortcodes - location and not_location attributes - wcj_get_user_location() - Code refactoring.
  • Dev - Shortcodes - General - [wcj_wholesale_price_table] - columns_style attribute added.
  • Dev - Shortcodes - General - [wcj_selector] - shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_items_table] - WooCommerce v3.x.x compatibility - unserialize() replaced with maybe_unserialize() for "WooCommerce TM Extra Product Options" plugin data.
  • Dev - Shortcodes - Orders - [wcj_order_items_table] - columns - product_categories column added.
  • Dev - Shortcodes - Orders - [wcj_order_items_table] - columns - item_quantity_refunded and item_quantity_excl_refunded columns added.
  • Dev - Shortcodes - Orders - [wcj_order_items_table] - columns - item_total_refunded column added.
  • Dev - Shortcodes - Orders - [wcj_order_items_table] - refunded_items_table attribute added.
  • Dev - Shortcodes - Orders - [wcj_order_items_table] - Returning empty string if no items found.
  • Dev - Shortcodes - Orders - [wcj_order_refunds_table] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_total_shipping_refunded] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_total_tax_refunded] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_subtotal_to_display] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_total_formatted] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_remaining_refund_amount] shortcode added.
  • Dev - Shortcodes - Products - [wcj_product_wholesale_price_table] - columns_style attribute added.
  • Dev - Widgets - Code refactoring (now as WCJ_Widget child classes).
  • Dev - Widgets - "Booster - Selector" widget added.
  • Dev - PRICES & CURRENCIES - Global Discount - "Exclude Product Categories" and "Include/Exclude Product Tags/Products" options added.
  • Dev - PRICES & CURRENCIES - Global Discount - Code refactoring, clean up and fixes.
  • Dev - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - Added "WooCommerce Product Add-ons" plugin compatibility.
  • Dev - PRICES & CURRENCIES - Multicurrency Product Base Price - "Advanced: Saved Calculated Products Prices" option added.
  • Dev - PRICES & CURRENCIES - Multicurrency Product Base Price - "Round Prices" options added.
  • Dev - PRICES & CURRENCIES - Wholesale Price - Minimum quantity for applied discount changed from 1 to 0.
  • Dev - PRODUCTS - Product Add to Cart - Variable Radio Buttons - Formatting options added.
  • Dev - PRODUCTS - Product Info - Advanced - "Extra Filters" option added.
  • Dev - PRODUCTS - Product Input Fields - Frontend View Options - "Position on Single Product Page" options added.
  • Dev - PRODUCTS - Product Input Fields - Fields Options - "Order" option added.
  • Dev - PRODUCTS - Product Input Fields - Additional check for is_string( $value ) added.
  • Dev - PRODUCTS - Product Input Fields - Values refilled after add to cart.
  • Dev - PRODUCTS - Product Input Fields - All Products - "Categories/Tags/Products to include/exclude" options added.
  • Dev - PRODUCTS - Product Input Fields - Settings restyled.
  • Dev - PRODUCTS - Product Input Fields - Code refactoring and cleanup.
  • Dev - PRODUCTS - Product Tabs - "Key" option added.
  • Dev - PRODUCTS - Product Tabs - Code refactoring, cleanup and minor fixes.
  • Dev - PRODUCTS - Product Tabs - Deprecated options not displayed (if empty).
  • Dev - PRODUCTS - Product Tabs - do_shortcode added when checking for empty content (before displaying the tab).
  • Fix - PRODUCTS - Product Visibility by Country / by User Role - Getting post__not_in from query (instead of starting with empty array).
  • Fix - PRODUCTS - Product Visibility by Country - "European Union" selection fixed.
  • Dev - PRODUCTS - Product Visibility by Country - "User Country Selection Method" option added.
  • Dev - PRODUCTS - Product Visibility by Country - Code refactoring.
  • Dev - PRODUCTS - Product Visibility by Country - Settings restyled and descriptions added.
  • Dev - PRODUCTS - Product Visibility by User Role - Descriptions added.
  • Dev - CART & CHECKOUT - Cart Customization - Change Empty Cart "Return to shop" Button Text - "Method" option added.
  • Dev - CART & CHECKOUT - Checkout Core Fields - "Override Default Address Fields" and "Override Country Locale Fields" options added.
  • Dev - CART & CHECKOUT - Checkout Core Fields - "Account Username", "Account Password-2" fields added.
  • Dev - CART & CHECKOUT - Checkout Customization - "Customize order received message" options added.
  • Dev - PAYMENT GATEWAYS - Gateways per Product or Category - "Use List Instead of Comma Separated Text for Products in Settings" support added.
  • Dev - SHIPPING & ORDERS - Left to Free Shipping - Settings restyled.
  • Dev - SHIPPING & ORDERS - Order Numbers - Code refactoring and clean up.
  • Dev - SHIPPING & ORDERS - Order Numbers - Skipping order number generation for auto-draft orders.
  • Dev - SHIPPING & ORDERS - Order Numbers - Order Tracking - Removed sanitizing order id (was added in WC v3.1.0).
  • Dev - SHIPPING & ORDERS - Order Numbers - Order Tracking - WP_Query optimized to return ids only.
  • Dev - SHIPPING & ORDERS - Order Numbers - Orders Renumerate - WP_Query optimized to return ids only.
  • Dev - PDF INVOICING & PACKING SLIPS - Checking for ZipArchive to exist before generating ZIPs.
  • Dev - PDF INVOICING & PACKING SLIPS - Default values added to get_option() calls.
  • Dev - PDF INVOICING & PACKING SLIPS - Display & Misc. - "Admin Title" option added.
  • Dev - PDF INVOICING & PACKING SLIPS - General - "Create on Order Partially Refunded" and "Create on Order Status Refunded and/or Order Partially Refunded" added.
  • Dev - PDF INVOICING & PACKING SLIPS - Email Options - "Customer - Partially Refunded Order" email added.
  • Dev - PDF INVOICING & PACKING SLIPS - Invoices Report Tool - Code refactoring, clean up, minor changes. Tool settings restyled.
  • Dev - PDF INVOICING & PACKING SLIPS - Invoices Report Tool - "Reports Filename", "CSV Separator", "CSV UTF-8 BOM", "Replace Periods with Commas in CSV Data" options added.
  • Dev - PDF INVOICING & PACKING SLIPS - Code factoring, clean up and minor fixes. Settings restyled.
  • Dev - EMAILS & MISC. - Admin Bar - "Booster: Active" admin bar added.
  • Dev - EMAILS & MISC. - Custom Emails - "Wrap in WC Email Template" option added.
  • Dev - EMAILS & MISC. - Custom Emails - Code refactoring, clean up etc. Settings page restyled.
  • Dev - EMAILS & MISC. - Custom Emails - WooCommerce v3.x.x compatibility - billing_email, order_date, post.
  • Dev - EMAILS & MISC. - Email Verification - Settings restyled.
  • Dev - EMAILS & MISC. - Email Verification - "Verified" column added to admin users list.
  • Dev - EMAILS & MISC. - Email Verification - "Verification Email Template" options added.
  • Dev - EMAILS & MISC. - Email Verification - serialize() and unserialize() replaced with json_encode() and json_decode().
  • Dev - EMAILS & MISC. - General - "Session Type in Booster" option added.
Download this release

Release Info

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

Code changes from version 3.0.1 to 3.1.0

Files changed (74) hide show
  1. includes/admin/class-wc-settings-jetpack.php +5 -2
  2. includes/class-wcj-admin-bar.php +39 -15
  3. includes/class-wcj-cart-customization.php +33 -3
  4. includes/class-wcj-checkout-core-fields.php +49 -22
  5. includes/class-wcj-checkout-customization.php +25 -2
  6. includes/class-wcj-emails-verification.php +42 -7
  7. includes/class-wcj-global-discount.php +95 -107
  8. includes/class-wcj-multicurrency.php +24 -2
  9. includes/class-wcj-order-numbers.php +55 -33
  10. includes/class-wcj-payment-gateways-per-category.php +4 -4
  11. includes/class-wcj-pdf-invoicing.php +55 -19
  12. includes/class-wcj-product-by-country.php +61 -30
  13. includes/class-wcj-product-by-user-role.php +3 -3
  14. includes/class-wcj-product-input-fields.php +20 -15
  15. includes/class-wcj-product-tabs.php +220 -162
  16. includes/class-wcj-wholesale-price.php +6 -4
  17. includes/classes/class-wcj-pdf-invoice.php +25 -24
  18. includes/constants/wcj-constants.php +51 -12
  19. includes/emails/class-wc-email-wcj-custom.php +51 -83
  20. includes/export/class-wcj-exporter-customers.php +3 -3
  21. includes/functions/wcj-admin-functions.php +4 -3
  22. includes/functions/wcj-country-functions.php +32 -2
  23. includes/functions/wcj-general-functions.php +141 -27
  24. includes/functions/wcj-invoicing-functions.php +25 -39
  25. includes/functions/wcj-order-functions.php +25 -1
  26. includes/functions/wcj-price-currency-functions.php +14 -4
  27. includes/functions/wcj-product-functions.php +49 -1
  28. includes/input-fields/{class-wcj-product-input-fields-abstract.php → class-wcj-product-input-fields-core.php} +279 -314
  29. includes/input-fields/class-wcj-product-input-fields-global.php +0 -77
  30. includes/input-fields/class-wcj-product-input-fields-per-product.php +0 -216
  31. includes/input-fields/wcj-product-input-fields-options.php +212 -0
  32. includes/js/wcj-cart-customization.js +3 -1
  33. includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php +161 -114
  34. includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php +21 -32
  35. includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-styling.php +22 -1
  36. includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-templates.php +29 -1
  37. includes/settings/wcj-settings-admin-bar.php +10 -3
  38. includes/settings/wcj-settings-cart-customization.php +13 -1
  39. includes/settings/wcj-settings-checkout-core-fields.php +33 -2
  40. includes/settings/wcj-settings-checkout-customization.php +16 -2
  41. includes/settings/wcj-settings-emails-verification.php +64 -24
  42. includes/settings/wcj-settings-general.php +12 -1
  43. includes/settings/wcj-settings-global-discount.php +62 -5
  44. includes/settings/wcj-settings-left-to-free-shipping.php +8 -4
  45. includes/settings/wcj-settings-multicurrency-base-price.php +23 -1
  46. includes/settings/wcj-settings-payment-gateways-per-category.php +33 -26
  47. includes/settings/wcj-settings-pdf-invoicing-display.php +27 -10
  48. includes/settings/wcj-settings-pdf-invoicing-emails.php +14 -13
  49. includes/settings/wcj-settings-pdf-invoicing-footer.php +5 -6
  50. includes/settings/wcj-settings-pdf-invoicing-header.php +9 -4
  51. includes/settings/wcj-settings-pdf-invoicing-numbering.php +2 -2
  52. includes/settings/wcj-settings-pdf-invoicing-page.php +2 -2
  53. includes/settings/wcj-settings-pdf-invoicing-styling.php +3 -12
  54. includes/settings/wcj-settings-pdf-invoicing-templates.php +3 -17
  55. includes/settings/wcj-settings-pdf-invoicing.php +53 -7
  56. includes/settings/wcj-settings-product-add-to-cart.php +30 -1
  57. includes/settings/wcj-settings-product-by-country.php +41 -3
  58. includes/settings/wcj-settings-product-by-user-role.php +4 -1
  59. includes/settings/wcj-settings-product-custom-info.php +47 -3
  60. includes/settings/wcj-settings-product-input-fields.php +115 -9
  61. includes/settings/wcj-settings-product-tabs.php +49 -11
  62. includes/shortcodes/class-wcj-general-shortcodes.php +54 -21
  63. includes/shortcodes/class-wcj-order-items-shortcodes.php +31 -5
  64. includes/shortcodes/class-wcj-orders-shortcodes.php +180 -55
  65. includes/shortcodes/class-wcj-products-shortcodes.php +39 -38
  66. includes/shortcodes/class-wcj-shortcodes.php +38 -41
  67. includes/templates/cart-empty.php +36 -0
  68. includes/widgets/class-wcj-widget-country-switcher.php +57 -85
  69. includes/widgets/class-wcj-widget-left-to-free-shipping.php +42 -47
  70. includes/widgets/class-wcj-widget-multicurrency.php +52 -64
  71. includes/widgets/class-wcj-widget-selector.php +86 -0
  72. includes/widgets/class-wcj-widget.php +104 -0
  73. readme.txt +75 -1
  74. woocommerce-jetpack.php +6 -4
includes/admin/class-wc-settings-jetpack.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings
4
  *
5
- * @version 3.0.0
6
  * @since 1.0.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -438,7 +438,7 @@ class WC_Settings_Jetpack extends WC_Settings_Page {
438
  /**
439
  * get_manager_settings.
440
  *
441
- * @version 2.9.1
442
  * @since 2.6.0
443
  * @return array
444
  */
@@ -456,6 +456,9 @@ class WC_Settings_Jetpack extends WC_Settings_Page {
456
  'type' => 'checkbox',
457
  'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
458
  __( 'Product Info', 'woocommerce-jetpack' ),
 
 
 
459
  ) ) ),
460
  'id' => 'wcj_list_for_products',
461
  'default' => 'yes',
2
  /**
3
  * Booster for WooCommerce - Settings
4
  *
5
+ * @version 3.1.0
6
  * @since 1.0.0
7
  * @author Algoritmika Ltd.
8
  */
438
  /**
439
  * get_manager_settings.
440
  *
441
+ * @version 3.1.0
442
  * @since 2.6.0
443
  * @return array
444
  */
456
  'type' => 'checkbox',
457
  'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
458
  __( 'Product Info', 'woocommerce-jetpack' ),
459
+ __( 'Gateways per Product or Category', 'woocommerce-jetpack' ),
460
+ __( 'Product Input Fields', 'woocommerce-jetpack' ),
461
+ __( 'Global Discount', 'woocommerce-jetpack' ),
462
  ) ) ),
463
  'id' => 'wcj_list_for_products',
464
  'default' => 'yes',
includes/class-wcj-admin-bar.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Admin Bar
4
  *
5
- * @version 3.0.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,18 +16,13 @@ class WCJ_Admin_Bar extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.9.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 "Booster Active Modules" admin bar menu
26
- * @todo (maybe) separate "Booster Modules" admin bar menu
27
- * @todo (maybe) separate "Booster Tools" admin bar menu
28
- * @todo (maybe) separate "WooCommerce Reports" admin bar menu
29
- * @todo (maybe) separate "WooCommerce Products" admin bar menu
30
- * @todo (maybe) separate "WooCommerce Settings" admin bar menu
31
  */
32
  function __construct() {
33
 
@@ -45,6 +40,9 @@ class WCJ_Admin_Bar extends WCJ_Module {
45
  }
46
  if ( 'yes' === get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) ) {
47
  add_action( 'admin_bar_menu', array( $this, 'add_booster_admin_bar' ), PHP_INT_MAX );
 
 
 
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
  }
@@ -70,11 +68,12 @@ class WCJ_Admin_Bar extends WCJ_Module {
70
  /**
71
  * add_booster_admin_bar_icon_style.
72
  *
73
- * @version 2.9.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
  }
79
 
80
  /**
@@ -117,7 +116,7 @@ class WCJ_Admin_Bar extends WCJ_Module {
117
  /**
118
  * get_nodes_booster_modules.
119
  *
120
- * @version 3.0.0
121
  * @since 2.9.0
122
  * @todo (maybe) dashes instead of underscores
123
  * @todo (maybe) dashboard > alphabetically - list all modules
@@ -126,7 +125,7 @@ class WCJ_Admin_Bar extends WCJ_Module {
126
  function get_nodes_booster_modules() {
127
  $nodes = array();
128
  $cats = include( wcj_plugin_path() . '/includes/admin/' . 'wcj-modules-cats.php' );
129
- $active_modules = array();
130
  foreach ( $cats as $id => $label_info ) {
131
  $nodes[ $id ] = array(
132
  'title' => $label_info['label'],
@@ -175,16 +174,16 @@ class WCJ_Admin_Bar extends WCJ_Module {
175
  ),
176
  );
177
  if ( WCJ()->modules[ $link_id ]->is_enabled() && 'module' === WCJ()->modules[ $link_id ]->type ) {
178
- $active_modules[ $link_id ] = $cat_nodes[ $link_id ];
179
  }
180
  }
181
  usort( $cat_nodes, array( $this, 'usort_compare_by_title' ) );
182
  $nodes[ $id ]['nodes'] = $cat_nodes;
183
  }
184
  }
185
- if ( ! empty( $active_modules ) ) {
186
- usort( $active_modules, array( $this, 'usort_compare_by_title' ) );
187
- $nodes['dashboard']['nodes']['active']['nodes'] = $active_modules;
188
  }
189
  return $nodes;
190
  }
@@ -226,6 +225,31 @@ class WCJ_Admin_Bar extends WCJ_Module {
226
  return $nodes;
227
  }
228
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
229
  /**
230
  * add_booster_admin_bar.
231
  *
2
  /**
3
  * Booster for WooCommerce - Module - Admin Bar
4
  *
5
+ * @version 3.1.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.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
 
40
  }
41
  if ( 'yes' === get_option( 'wcj_admin_bar_booster_enabled', 'yes' ) ) {
42
  add_action( 'admin_bar_menu', array( $this, 'add_booster_admin_bar' ), PHP_INT_MAX );
43
+ if ( 'yes' === get_option( 'wcj_admin_bar_booster_active_enabled', 'yes' ) ) {
44
+ add_action( 'admin_bar_menu', array( $this, 'add_booster_active_admin_bar' ), PHP_INT_MAX );
45
+ }
46
  add_action( 'wp_head', array( $this, 'add_booster_admin_bar_icon_style' ) );
47
  add_action( 'admin_head', array( $this, 'add_booster_admin_bar_icon_style' ) );
48
  }
68
  /**
69
  * add_booster_admin_bar_icon_style.
70
  *
71
+ * @version 3.1.0
72
  * @since 2.9.0
73
  */
74
  function add_booster_admin_bar_icon_style() {
75
  echo '<style type="text/css"> #wpadminbar #wp-admin-bar-booster .ab-icon:before { content: "\f185"; top: 3px; } </style>';
76
+ echo '<style type="text/css"> #wpadminbar #wp-admin-bar-booster-active .ab-icon:before { content: "\f155"; top: 3px; } </style>';
77
  }
78
 
79
  /**
116
  /**
117
  * get_nodes_booster_modules.
118
  *
119
+ * @version 3.1.0
120
  * @since 2.9.0
121
  * @todo (maybe) dashes instead of underscores
122
  * @todo (maybe) dashboard > alphabetically - list all modules
125
  function get_nodes_booster_modules() {
126
  $nodes = array();
127
  $cats = include( wcj_plugin_path() . '/includes/admin/' . 'wcj-modules-cats.php' );
128
+ $this->active_modules = array();
129
  foreach ( $cats as $id => $label_info ) {
130
  $nodes[ $id ] = array(
131
  'title' => $label_info['label'],
174
  ),
175
  );
176
  if ( WCJ()->modules[ $link_id ]->is_enabled() && 'module' === WCJ()->modules[ $link_id ]->type ) {
177
+ $this->active_modules[ $link_id ] = $cat_nodes[ $link_id ];
178
  }
179
  }
180
  usort( $cat_nodes, array( $this, 'usort_compare_by_title' ) );
181
  $nodes[ $id ]['nodes'] = $cat_nodes;
182
  }
183
  }
184
+ if ( ! empty( $this->active_modules ) ) {
185
+ usort( $this->active_modules, array( $this, 'usort_compare_by_title' ) );
186
+ $nodes['dashboard']['nodes']['active']['nodes'] = $this->active_modules;
187
  }
188
  return $nodes;
189
  }
225
  return $nodes;
226
  }
227
 
228
+ /**
229
+ * add_booster_active_admin_bar.
230
+ *
231
+ * @version 3.1.0
232
+ * @since 3.1.0
233
+ */
234
+ function add_booster_active_admin_bar( $wp_admin_bar ) {
235
+ $tools = array(
236
+ 'tools' => array(
237
+ 'title' => __( 'Tools', 'woocommerce-jetpack' ),
238
+ 'href' => admin_url( 'admin.php?page=wcj-tools' ),
239
+ 'nodes' => $this->get_nodes_booster_tools(),
240
+ ),
241
+ );
242
+ unset( $tools['tools']['nodes']['dashboard'] );
243
+ $nodes = array(
244
+ 'booster-active' => array(
245
+ 'title' => '<span class="ab-icon"></span>' . __( 'Booster: Active', 'woocommerce-jetpack' ),
246
+ 'href' => admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=dashboard&section=active' ),
247
+ 'nodes' => array_merge( $this->active_modules, $tools ),
248
+ ),
249
+ );
250
+ $this->add_woocommerce_admin_bar_nodes( $wp_admin_bar, $nodes, false );
251
+ }
252
+
253
  /**
254
  * add_booster_admin_bar.
255
  *
includes/class-wcj-cart-customization.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Cart Customization
4
  *
5
- * @version 3.0.1
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Cart_Customization extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 3.0.1
20
  * @since 2.7.0
21
  */
22
  function __construct() {
@@ -38,7 +38,12 @@ class WCJ_Cart_Customization extends WCJ_Module {
38
  }
39
  // Customize "Return to shop" button text
40
  if ( 'yes' === get_option( 'wcj_cart_customization_return_to_shop_button_enabled', 'no' ) ) {
41
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
 
 
 
 
 
42
  }
43
  // Customize "Return to shop" button link
44
  if ( 'yes' === get_option( 'wcj_cart_customization_return_to_shop_button_link_enabled', 'no' ) ) {
@@ -47,6 +52,30 @@ class WCJ_Cart_Customization extends WCJ_Module {
47
  }
48
  }
49
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
  /**
51
  * change_empty_cart_return_to_shop_link.
52
  *
@@ -63,6 +92,7 @@ class WCJ_Cart_Customization extends WCJ_Module {
63
  *
64
  * @version 2.8.0
65
  * @since 2.8.0
 
66
  */
67
  function enqueue_scripts() {
68
  wp_enqueue_script( 'wcj-cart-customization', wcj_plugin_url() . '/includes/js/wcj-cart-customization.js', array( 'jquery' ), WCJ()->version, false );
2
  /**
3
  * Booster for WooCommerce - Module - Cart Customization
4
  *
5
+ * @version 3.1.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.1.0
20
  * @since 2.7.0
21
  */
22
  function __construct() {
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' ) ) {
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 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
  *
92
  *
93
  * @version 2.8.0
94
  * @since 2.8.0
95
+ * @todo 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 );
includes/class-wcj-checkout-core-fields.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Checkout Core Fields
4
  *
5
- * @version 2.8.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,9 @@ class WCJ_Checkout_Core_Fields extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 2.8.0
 
 
19
  */
20
  function __construct() {
21
 
@@ -46,44 +48,69 @@ class WCJ_Checkout_Core_Fields extends WCJ_Module {
46
  'shipping_city',
47
  'shipping_state',
48
  'shipping_postcode',
 
49
  'account_password',
 
50
  'order_comments',
51
  );
52
 
53
  if ( $this->is_enabled() ) {
54
- add_filter( 'woocommerce_checkout_fields' , array( $this, 'custom_override_checkout_fields' ) );
55
- add_filter( 'woocommerce_default_address_fields' , array( $this, 'custom_override_default_address_fields' ) );
 
 
 
 
 
56
  }
57
  }
58
 
59
  /**
60
- * custom_override_default_address_fields.
61
  *
62
- * @version 2.8.0
63
- * @since 2.3.8
64
- * @todo check if `$section` shouldn't be used
65
  */
66
- function custom_override_default_address_fields( $fields ) {
 
 
 
 
 
67
  foreach ( $fields as $field_key => $field_values ) {
68
- foreach ( $this->woocommerce_core_checkout_fields as $field ) {
69
- $field_parts = explode( '_', $field, 2 );
70
- if ( is_array( $field_parts ) && 2 === count( $field_parts ) ) {
71
- $section = $field_parts[0]; // billing or shipping
72
- $field_name = $field_parts[1];
73
- if ( $field_key === $field_name ) {
74
- if ( '' != ( $label = get_option( 'wcj_checkout_fields_' . $field . '_' . 'label', '' ) ) ) {
75
- $fields[ $field_name ]['label'] = $label;
76
- }
77
- if ( '' != ( $placeholder = get_option( 'wcj_checkout_fields_' . $field . '_' . 'placeholder', '' ) ) ) {
78
- $fields[ $field_name ]['placeholder'] = $placeholder;
79
- }
80
- }
81
  }
82
  }
83
  }
84
  return $fields;
85
  }
86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  /**
88
  * custom_override_checkout_fields.
89
  *
2
  /**
3
  * Booster for WooCommerce - Module - Checkout Core Fields
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.1.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
 
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.1.0
72
+ * @since 3.1.0
 
73
  */
74
+ function maybe_override_fields( $fields, $override_with_section ) {
75
+ $options_to_override = array(
76
+ 'label' => '',
77
+ 'placeholder' => '',
78
+ 'priority' => 0,
79
+ );
80
  foreach ( $fields as $field_key => $field_values ) {
81
+ $field = $override_with_section . '_' . $field_key;
82
+ foreach ( $options_to_override as $option => $default_value ) {
83
+ if ( $default_value != ( $value = get_option( 'wcj_checkout_fields_' . $field . '_' . $option, $default_value ) ) ) {
84
+ $fields[ $field_key ][ $option ] = $value;
 
 
 
 
 
 
 
 
 
85
  }
86
  }
87
  }
88
  return $fields;
89
  }
90
 
91
+ /**
92
+ * custom_override_country_locale_fields.
93
+ *
94
+ * @version 3.1.0
95
+ * @since 3.1.0
96
+ */
97
+ function custom_override_country_locale_fields( $fields ) {
98
+ foreach ( $fields as $country => $country_fields ) {
99
+ $fields[ $country ] = $this->maybe_override_fields( $country_fields, $this->country_locale_override );
100
+ }
101
+ return $fields;
102
+ }
103
+
104
+ /**
105
+ * custom_override_default_address_fields.
106
+ *
107
+ * @version 3.1.0
108
+ * @since 2.3.8
109
+ */
110
+ function custom_override_default_address_fields( $fields ) {
111
+ return $this->maybe_override_fields( $fields, $this->default_address_override );
112
+ }
113
+
114
  /**
115
  * custom_override_checkout_fields.
116
  *
includes/class-wcj-checkout-customization.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Checkout Customization
4
  *
5
- * @version 2.9.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Checkout_Customization extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.9.0
20
  * @since 2.7.0
21
  * @todo "Disable Fields on Checkout for Logged Users" - billing and shipping country ('select' type)
22
  * @todo "Disable Fields on Checkout for Logged Users" - other core fields (e.g. account fields)
@@ -62,7 +62,30 @@ class WCJ_Checkout_Customization extends WCJ_Module {
62
  foreach ( $checkout_fields_types as $checkout_fields_type ) {
63
  add_filter( 'woocommerce_form_field_' . $checkout_fields_type, array( $this, 'maybe_add_description' ), PHP_INT_MAX, 4 );
64
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  }
 
66
  }
67
 
68
  /**
2
  /**
3
  * Booster for WooCommerce - Module - Checkout Customization
4
  *
5
+ * @version 3.1.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.1.0
20
  * @since 2.7.0
21
  * @todo "Disable Fields on Checkout for Logged Users" - billing and shipping country ('select' type)
22
  * @todo "Disable Fields on Checkout for Logged Users" - other core fields (e.g. account fields)
62
  foreach ( $checkout_fields_types as $checkout_fields_type ) {
63
  add_filter( 'woocommerce_form_field_' . $checkout_fields_type, array( $this, 'maybe_add_description' ), PHP_INT_MAX, 4 );
64
  }
65
+ // Custom "order received" message text
66
+ if ( 'yes' === get_option( 'wcj_checkout_customization_order_received_message_enabled', 'no' ) ) {
67
+ add_filter( 'woocommerce_thankyou_order_received_text', array( $this, 'customize_order_received_message' ), PHP_INT_MAX, 2 );
68
+ }
69
+ }
70
+ }
71
+
72
+ /**
73
+ * customize_order_received_message.
74
+ *
75
+ * @version 3.1.0
76
+ * @since 3.1.0
77
+ */
78
+ function customize_order_received_message( $message, $_order ) {
79
+ if ( null != $_order ) {
80
+ global $post;
81
+ $post = get_post( wcj_get_order_id( $_order ) );
82
+ setup_postdata( $post );
83
+ }
84
+ $message = do_shortcode( get_option( 'wcj_checkout_customization_order_received_message', __( 'Thank you. Your order has been received.', 'woocommerce' ) ) );
85
+ if ( null != $_order ) {
86
+ wp_reset_postdata();
87
  }
88
+ return $message;
89
  }
90
 
91
  /**
includes/class-wcj-emails-verification.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Email Verification
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Email_Verification extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.8.0
20
  * @since 2.8.0
21
  * @see idea from ticket #4752
22
  */
@@ -33,9 +33,40 @@ class WCJ_Email_Verification extends WCJ_Module {
33
  add_filter( 'woocommerce_registration_redirect', array( $this, 'prevent_user_login_automatically_after_register' ), PHP_INT_MAX );
34
  add_filter( 'wp_authenticate_user', array( $this, 'check_if_user_email_is_verified' ), PHP_INT_MAX );
35
  add_action( 'user_register', array( $this, 'reset_and_mail_activation_link' ), PHP_INT_MAX );
 
 
36
  }
37
  }
38
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  /**
40
  * prevent_user_login_automatically_after_register.
41
  *
@@ -79,7 +110,7 @@ class WCJ_Email_Verification extends WCJ_Module {
79
  /**
80
  * reset_and_mail_activation_link.
81
  *
82
- * @version 2.9.0
83
  * @since 2.8.0
84
  * @todo %site_name% etc. in `wcj_emails_verification_email_subject`
85
  * @todo ticket #5373 - unexpected issue with "Activation failed, please contact our administrator" message
@@ -87,7 +118,7 @@ class WCJ_Email_Verification extends WCJ_Module {
87
  function reset_and_mail_activation_link( $user_id ) {
88
  $user_info = get_userdata( $user_id );
89
  $code = md5( time() );
90
- $url = add_query_arg( 'wcj_verify_email', base64_encode( serialize( array( 'id' => $user_id, 'code' => $code ) ) ), wc_get_page_permalink( 'myaccount' ) );
91
  $email_content = do_shortcode( apply_filters( 'booster_get_option',
92
  __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ),
93
  get_option( 'wcj_emails_verification_email_content',
@@ -99,18 +130,22 @@ class WCJ_Email_Verification extends WCJ_Module {
99
  __( 'Please activate your account', 'woocommerce-jetpack' ) ) ) );
100
  update_user_meta( $user_id, 'wcj_is_activated', '0' );
101
  update_user_meta( $user_id, 'wcj_activation_code', $code );
 
 
 
 
102
  wc_mail( $user_info->user_email, $email_subject, $email_content );
103
  }
104
 
105
  /**
106
  * process_email_verification.
107
  *
108
- * @version 2.9.0
109
  * @since 2.8.0
110
  */
111
- function process_email_verification(){
112
  if ( isset( $_GET['wcj_verify_email'] ) ) {
113
- $data = unserialize( base64_decode( $_GET['wcj_verify_email'] ) );
114
  if ( get_user_meta( $data['id'], 'wcj_activation_code', true ) == $data['code'] ) {
115
  update_user_meta( $data['id'], 'wcj_is_activated', '1' );
116
  wc_add_notice( do_shortcode( get_option( 'wcj_emails_verification_success_message',
2
  /**
3
  * Booster for WooCommerce - Module - Email Verification
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.1.0
20
  * @since 2.8.0
21
  * @see idea from ticket #4752
22
  */
33
  add_filter( 'woocommerce_registration_redirect', array( $this, 'prevent_user_login_automatically_after_register' ), PHP_INT_MAX );
34
  add_filter( 'wp_authenticate_user', array( $this, 'check_if_user_email_is_verified' ), PHP_INT_MAX );
35
  add_action( 'user_register', array( $this, 'reset_and_mail_activation_link' ), PHP_INT_MAX );
36
+ add_filter( 'manage_users_columns', array( $this, 'add_verified_email_column' ) );
37
+ add_filter( 'manage_users_custom_column', array( $this, 'render_verified_email_column' ), 10, 3 );
38
  }
39
  }
40
 
41
+ /**
42
+ * add_verified_email_column.
43
+ *
44
+ * @version 3.1.0
45
+ * @since 3.1.0
46
+ * @todo (maybe) add option to enable/disable the column
47
+ */
48
+ function add_verified_email_column( $columns ) {
49
+ $columns['wcj_is_verified_email'] = __( 'Verified', 'woocommerce-jetpack' );
50
+ return $columns;
51
+ }
52
+
53
+ /**
54
+ * render_verified_email_column.
55
+ *
56
+ * @version 3.1.0
57
+ * @since 3.1.0
58
+ */
59
+ function render_verified_email_column( $output, $column_name, $user_id ) {
60
+ if ( 'wcj_is_verified_email' === $column_name ) {
61
+ $replaced_values = array(
62
+ '1' => '<span title="' . __( 'Email verified', 'woocommerce-jetpack' ) . '">&#9745;</span>',
63
+ '0' => '<span title="' . __( 'Email not verified', 'woocommerce-jetpack' ) . '">&#10006;</span>',
64
+ );
65
+ return str_replace( array_keys( $replaced_values ), array_values( $replaced_values ), get_user_meta( $user_id, 'wcj_is_activated', true ) );
66
+ }
67
+ return $output;
68
+ }
69
+
70
  /**
71
  * prevent_user_login_automatically_after_register.
72
  *
110
  /**
111
  * reset_and_mail_activation_link.
112
  *
113
+ * @version 3.1.0
114
  * @since 2.8.0
115
  * @todo %site_name% etc. in `wcj_emails_verification_email_subject`
116
  * @todo ticket #5373 - unexpected issue with "Activation failed, please contact our administrator" message
118
  function reset_and_mail_activation_link( $user_id ) {
119
  $user_info = get_userdata( $user_id );
120
  $code = md5( time() );
121
+ $url = add_query_arg( 'wcj_verify_email', base64_encode( json_encode( array( 'id' => $user_id, 'code' => $code ) ) ), wc_get_page_permalink( 'myaccount' ) );
122
  $email_content = do_shortcode( apply_filters( 'booster_get_option',
123
  __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ),
124
  get_option( 'wcj_emails_verification_email_content',
130
  __( 'Please activate your account', 'woocommerce-jetpack' ) ) ) );
131
  update_user_meta( $user_id, 'wcj_is_activated', '0' );
132
  update_user_meta( $user_id, 'wcj_activation_code', $code );
133
+ if ( 'wc' === apply_filters( 'booster_get_option', 'plain', get_option( 'wcj_emails_verification_email_template', 'plain' ) ) ) {
134
+ $email_content = wcj_wrap_in_wc_email_template( $email_content,
135
+ get_option( 'wcj_emails_verification_email_template_wc_heading', __( 'Activate your account', 'woocommerce-jetpack' ) ) );
136
+ }
137
  wc_mail( $user_info->user_email, $email_subject, $email_content );
138
  }
139
 
140
  /**
141
  * process_email_verification.
142
  *
143
+ * @version 3.1.0
144
  * @since 2.8.0
145
  */
146
+ function process_email_verification() {
147
  if ( isset( $_GET['wcj_verify_email'] ) ) {
148
+ $data = json_decode( base64_decode( $_GET['wcj_verify_email'] ), true );
149
  if ( get_user_meta( $data['id'], 'wcj_activation_code', true ) == $data['code'] ) {
150
  update_user_meta( $data['id'], 'wcj_is_activated', '1' );
151
  wc_add_notice( do_shortcode( get_option( 'wcj_emails_verification_success_message',
includes/class-wcj-global-discount.php CHANGED
@@ -2,10 +2,9 @@
2
  /**
3
  * Booster for WooCommerce - Module - Global Discount
4
  *
5
- * @version 2.8.0
6
  * @since 2.5.7
7
  * @author Algoritmika Ltd.
8
- * @todo products and cats/tags to include/exclude (cats to include - done); regular price coefficient; fee instead of discount;
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit;
@@ -17,8 +16,10 @@ class WCJ_Global_Discount extends WCJ_Module {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.8.0
21
  * @since 2.5.7
 
 
22
  */
23
  function __construct() {
24
 
@@ -30,41 +31,43 @@ class WCJ_Global_Discount extends WCJ_Module {
30
 
31
  if ( $this->is_enabled() ) {
32
  if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
33
- // Prices
34
- add_filter( WCJ_PRODUCT_GET_PRICE_FILTER, array( $this, 'add_global_discount_price' ), PHP_INT_MAX, 2 );
35
- add_filter( WCJ_PRODUCT_GET_SALE_PRICE_FILTER, array( $this, 'add_global_discount_sale_price' ), PHP_INT_MAX, 2 );
36
- // add_filter( WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER, array( $this, 'add_global_discount_regular_price' ), PHP_INT_MAX, 2 );
37
- // Variations
38
- add_filter( 'woocommerce_variation_prices_price', array( $this, 'add_global_discount_price' ), PHP_INT_MAX, 2 );
39
- add_filter( 'woocommerce_variation_prices_sale_price', array( $this, 'add_global_discount_sale_price' ), PHP_INT_MAX, 2 );
40
- // add_filter( 'woocommerce_variation_prices_regular_price', array( $this, 'add_global_discount_regular_price' ), PHP_INT_MAX, 2 );
41
- add_filter( 'woocommerce_get_variation_prices_hash', array( $this, 'get_variation_prices_hash' ), PHP_INT_MAX, 3 );
42
- // Grouped products
43
- add_filter( 'woocommerce_get_price_including_tax', array( $this, 'add_global_discount_grouped' ), PHP_INT_MAX, 3 );
44
- add_filter( 'woocommerce_get_price_excluding_tax', array( $this, 'add_global_discount_grouped' ), PHP_INT_MAX, 3 );
45
- if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
46
- add_filter( 'woocommerce_product_variation_get_price', array( $this, 'add_global_discount_price' ), PHP_INT_MAX, 2 );
47
- add_filter( 'woocommerce_product_variation_get_sale_price', array( $this, 'add_global_discount_sale_price' ), PHP_INT_MAX, 2 );
48
- // add_filter( 'woocommerce_product_variation_get_regular_price', array( $this, 'add_global_discount_regular_price' ), PHP_INT_MAX, 2 );
49
- }
50
  }
51
  }
52
  }
53
 
54
  /**
55
- * add_global_discount_grouped.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  *
57
- * @version 2.7.0
58
  * @since 2.5.7
59
  */
60
- function add_global_discount_grouped( $price, $qty, $_product ) {
61
  if ( $_product->is_type( 'grouped' ) ) {
62
  foreach ( $_product->get_children() as $child_id ) {
63
- $the_price = get_post_meta( $child_id, '_price', true );
64
  $the_product = wc_get_product( $child_id );
65
- $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
66
  if ( $the_price == $price ) {
67
- return $this->add_global_discount_price( $price, $the_product );
68
  }
69
  }
70
  }
@@ -87,46 +90,74 @@ class WCJ_Global_Discount extends WCJ_Module {
87
  /**
88
  * check_if_applicable.
89
  *
90
- * @version 2.5.7
91
  * @since 2.5.7
92
  * @return bool
93
  */
94
  function check_if_applicable( $_product, $group ) {
95
- return ( 'yes' === get_option( 'wcj_global_discount_sale_enabled_' . $group, 'yes' ) && $this->check_product_categories( $_product, $group ) );
96
  }
97
 
98
  /**
99
- * check_product_categories.
100
  *
101
- * @version 2.7.0
102
- * @since 2.5.7
103
- * @return bool
104
  */
105
- function check_product_categories( $_product, $group ) {
106
- // Check product category - include
107
- $categories_in = get_option( 'wcj_global_discount_sale_categories_incl_' . $group, '' );
108
- if ( ! empty( $categories_in ) ) {
109
- $product_categories = get_the_terms( wcj_get_product_id_or_variation_parent_id( $_product ), 'product_cat' );
110
- if ( empty( $product_categories ) ) {
111
- return false; // option set to some categories, but product has no categories
112
- }
113
- foreach( $product_categories as $product_category ) {
114
- if ( in_array( $product_category->term_id, $categories_in ) ) {
115
- return true; // category found
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  }
117
  }
118
- return false; // no categories found
 
 
 
 
 
 
 
119
  }
120
- return true; // option not set (i.e. left blank)
121
  }
122
 
123
  /**
124
- * add_global_discount_any_price.
125
  *
126
- * @version 2.7.0
127
  * @since 2.5.7
128
  */
129
- function add_global_discount_any_price( $price_type, $price, $_product ) {
 
 
 
130
  $total_number = apply_filters( 'booster_get_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
131
  for ( $i = 1; $i <= $total_number; $i++ ) {
132
  if ( ! $this->check_if_applicable( $_product, $i ) ) {
@@ -134,36 +165,11 @@ class WCJ_Global_Discount extends WCJ_Module {
134
  }
135
  $coefficient = get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
136
  if ( 0 != $coefficient ) {
137
- if ( 'sale_price' === $price_type ) {
138
- if ( 0 == $price ) {
139
- // The product is currently not on sale
140
- if ( 'only_on_sale' === get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' ) ) {
141
- continue; // no changes by current discount group
142
- } else {
143
- $price = $_product->get_regular_price();
144
- }
145
- } else {
146
- // The product is currently on sale
147
- if ( 'only_not_on_sale' === get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' ) ) {
148
- continue; // no changes by current discount group
149
- }
150
- }
151
- } else { // if ( 'price' === $price_type )
152
- remove_filter( WCJ_PRODUCT_GET_SALE_PRICE_FILTER, array( $this, 'add_global_discount_sale_price' ), PHP_INT_MAX, 2 );
153
- remove_filter( 'woocommerce_variation_prices_sale_price', array( $this, 'add_global_discount_sale_price' ), PHP_INT_MAX, 2 );
154
- if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
155
- remove_filter( 'woocommerce_product_variation_get_sale_price', array( $this, 'add_global_discount_sale_price' ), PHP_INT_MAX, 2 );
156
- }
157
- if ( 'only_on_sale' === get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' ) && 0 == $_product->get_sale_price() ) {
158
- continue; // no changes by current discount group
159
- } elseif ( 'only_not_on_sale' === get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' ) && 0 != $_product->get_sale_price() ) {
160
- continue; // no changes by current discount group
161
- }
162
- add_filter( WCJ_PRODUCT_GET_SALE_PRICE_FILTER, array( $this, 'add_global_discount_sale_price' ), PHP_INT_MAX, 2 );
163
- add_filter( 'woocommerce_variation_prices_sale_price', array( $this, 'add_global_discount_sale_price' ), PHP_INT_MAX, 2 );
164
- if ( ! WCJ_IS_WC_VERSION_BELOW_3 ) {
165
- add_filter( 'woocommerce_product_variation_get_sale_price', array( $this, 'add_global_discount_sale_price' ), PHP_INT_MAX, 2 );
166
- }
167
  }
168
  return $this->calculate_price( $price, $coefficient, $i ); // discount applied
169
  }
@@ -171,33 +177,10 @@ class WCJ_Global_Discount extends WCJ_Module {
171
  return $price; // no changes
172
  }
173
 
174
- /**
175
- * add_global_discount_sale_price.
176
- *
177
- * @version 2.5.7
178
- * @since 2.5.7
179
- */
180
- function add_global_discount_sale_price( $price, $_product ) {
181
- return $this->add_global_discount_any_price( 'sale_price', $price, $_product );
182
- }
183
-
184
- /**
185
- * add_global_discount_price.
186
- *
187
- * @version 2.5.7
188
- * @since 2.5.7
189
- */
190
- function add_global_discount_price( $price, $_product ) {
191
- if ( '' === $price ) {
192
- return $price; // no changes
193
- }
194
- return $this->add_global_discount_any_price( 'price', $price, $_product );
195
- }
196
-
197
  /**
198
  * get_variation_prices_hash.
199
  *
200
- * @version 2.5.7
201
  * @since 2.5.7
202
  */
203
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
@@ -205,11 +188,16 @@ class WCJ_Global_Discount extends WCJ_Module {
205
  $total_number = apply_filters( 'booster_get_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
206
  $wcj_global_discount_price_hash['total_number'] = $total_number;
207
  for ( $i = 1; $i <= $total_number; $i++ ) {
208
- $wcj_global_discount_price_hash[ 'enabled_' . $i ] = get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
209
- $wcj_global_discount_price_hash[ 'type_' . $i ] = get_option( 'wcj_global_discount_sale_coefficient_type_' . $i, 'percent' );
210
- $wcj_global_discount_price_hash[ 'value_' . $i ] = get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
211
- $wcj_global_discount_price_hash[ 'scope_' . $i ] = get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
212
- $wcj_global_discount_price_hash[ 'cats_in_' . $i ] = get_option( 'wcj_global_discount_sale_categories_incl_' . $i, '' );
 
 
 
 
 
213
  }
214
  $price_hash['wcj_global_discount_price_hash'] = $wcj_global_discount_price_hash;
215
  return $price_hash;
2
  /**
3
  * Booster for WooCommerce - Module - Global Discount
4
  *
5
+ * @version 3.1.0
6
  * @since 2.5.7
7
  * @author Algoritmika Ltd.
 
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.1.0
20
  * @since 2.5.7
21
+ * @todo fee instead of discount
22
+ * @todo regular price coefficient
23
  */
24
  function __construct() {
25
 
31
 
32
  if ( $this->is_enabled() ) {
33
  if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
34
+ wcj_add_change_price_hooks( $this, PHP_INT_MAX, false );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
35
  }
36
  }
37
  }
38
 
39
  /**
40
+ * change_price.
41
+ *
42
+ * @version 3.1.0
43
+ * @since 3.1.0
44
+ * @todo `WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER, 'woocommerce_variation_prices_regular_price', 'woocommerce_product_variation_get_regular_price'`
45
+ */
46
+ function change_price( $price, $_product ) {
47
+ $_current_filter = current_filter();
48
+ if ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_PRICE_FILTER, 'woocommerce_variation_prices_price', 'woocommerce_product_variation_get_price' ) ) ) {
49
+ return $this->add_global_discount( $price, $_product, 'price' );
50
+ } elseif ( in_array( $_current_filter, array( WCJ_PRODUCT_GET_SALE_PRICE_FILTER, 'woocommerce_variation_prices_sale_price', 'woocommerce_product_variation_get_sale_price' ) ) ) {
51
+ return $this->add_global_discount( $price, $_product, 'sale_price' );
52
+ } else {
53
+ return $price;
54
+ }
55
+ }
56
+
57
+ /**
58
+ * change_price_grouped.
59
  *
60
+ * @version 3.1.0
61
  * @since 2.5.7
62
  */
63
+ function change_price_grouped( $price, $qty, $_product ) {
64
  if ( $_product->is_type( 'grouped' ) ) {
65
  foreach ( $_product->get_children() as $child_id ) {
66
+ $the_price = get_post_meta( $child_id, '_price', true );
67
  $the_product = wc_get_product( $child_id );
68
+ $the_price = wcj_get_product_display_price( $the_product, $the_price, 1 );
69
  if ( $the_price == $price ) {
70
+ return $this->add_global_discount( $price, $the_product, 'price' );
71
  }
72
  }
73
  }
90
  /**
91
  * check_if_applicable.
92
  *
93
+ * @version 3.1.0
94
  * @since 2.5.7
95
  * @return bool
96
  */
97
  function check_if_applicable( $_product, $group ) {
98
+ return ( 'yes' === get_option( 'wcj_global_discount_sale_enabled_' . $group, 'yes' ) && $this->is_enabled_for_product( $_product, $group ) );
99
  }
100
 
101
  /**
102
+ * is_enabled_for_product.
103
  *
104
+ * @version 3.1.0
105
+ * @since 3.1.0
 
106
  */
107
+ function is_enabled_for_product( $_product, $group ) {
108
+ $product_id = wcj_get_product_id_or_variation_parent_id( $_product );
109
+ return wcj_is_enabled_for_product( $product_id, array(
110
+ 'include_products' => get_option( 'wcj_global_discount_sale_products_incl_' . $group, '' ),
111
+ 'exclude_products' => get_option( 'wcj_global_discount_sale_products_excl_' . $group, '' ),
112
+ 'include_categories' => get_option( 'wcj_global_discount_sale_categories_incl_' . $group, '' ),
113
+ 'exclude_categories' => get_option( 'wcj_global_discount_sale_categories_excl_' . $group, '' ),
114
+ 'include_tags' => get_option( 'wcj_global_discount_sale_tags_incl_' . $group, '' ),
115
+ 'exclude_tags' => get_option( 'wcj_global_discount_sale_tags_excl_' . $group, '' ),
116
+ ) );
117
+ }
118
+
119
+ /**
120
+ * check_if_applicable_by_product_scope.
121
+ *
122
+ * @version 3.1.0
123
+ * @since 3.1.0
124
+ */
125
+ function check_if_applicable_by_product_scope( $_product, $price, $price_type, $scope ) {
126
+ $return = true;
127
+ if ( 'sale_price' === $price_type ) {
128
+ if ( 0 == $price ) {
129
+ // The product is currently not on sale
130
+ if ( 'only_on_sale' === $scope ) {
131
+ $return = false;
132
+ }
133
+ } else {
134
+ // The product is currently on sale
135
+ if ( 'only_not_on_sale' === $scope ) {
136
+ $return = false;
137
  }
138
  }
139
+ } else { // if ( 'price' === $price_type )
140
+ wcj_remove_change_price_hooks( $this, PHP_INT_MAX, false );
141
+ if ( 'only_on_sale' === $scope && 0 == $_product->get_sale_price() ) {
142
+ $return = false;
143
+ } elseif ( 'only_not_on_sale' === $scope && 0 != $_product->get_sale_price() ) {
144
+ $return = false;
145
+ }
146
+ wcj_add_change_price_hooks( $this, PHP_INT_MAX, false );
147
  }
148
+ return $return;
149
  }
150
 
151
  /**
152
+ * add_global_discount.
153
  *
154
+ * @version 3.1.0
155
  * @since 2.5.7
156
  */
157
+ function add_global_discount( $price, $_product, $price_type ) {
158
+ if ( 'price' === $price_type && '' === $price ) {
159
+ return $price; // no changes
160
+ }
161
  $total_number = apply_filters( 'booster_get_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
162
  for ( $i = 1; $i <= $total_number; $i++ ) {
163
  if ( ! $this->check_if_applicable( $_product, $i ) ) {
165
  }
166
  $coefficient = get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
167
  if ( 0 != $coefficient ) {
168
+ if ( ! $this->check_if_applicable_by_product_scope( $_product, $price, $price_type, get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' ) ) ) {
169
+ continue; // no changes by current discount group
170
+ }
171
+ if ( 'sale_price' === $price_type && 0 == $price ) {
172
+ $price = $_product->get_regular_price();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
  }
174
  return $this->calculate_price( $price, $coefficient, $i ); // discount applied
175
  }
177
  return $price; // no changes
178
  }
179
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
180
  /**
181
  * get_variation_prices_hash.
182
  *
183
+ * @version 3.1.0
184
  * @since 2.5.7
185
  */
186
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
188
  $total_number = apply_filters( 'booster_get_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) );
189
  $wcj_global_discount_price_hash['total_number'] = $total_number;
190
  for ( $i = 1; $i <= $total_number; $i++ ) {
191
+ $wcj_global_discount_price_hash[ 'enabled_' . $i ] = get_option( 'wcj_global_discount_sale_enabled_' . $i, 'yes' );
192
+ $wcj_global_discount_price_hash[ 'type_' . $i ] = get_option( 'wcj_global_discount_sale_coefficient_type_' . $i, 'percent' );
193
+ $wcj_global_discount_price_hash[ 'value_' . $i ] = get_option( 'wcj_global_discount_sale_coefficient_' . $i, 0 );
194
+ $wcj_global_discount_price_hash[ 'scope_' . $i ] = get_option( 'wcj_global_discount_sale_product_scope_' . $i, 'all' );
195
+ $wcj_global_discount_price_hash[ 'cats_in_' . $i ] = get_option( 'wcj_global_discount_sale_categories_incl_' . $i, '' );
196
+ $wcj_global_discount_price_hash[ 'cats_ex_' . $i ] = get_option( 'wcj_global_discount_sale_categories_excl_' . $i, '' );
197
+ $wcj_global_discount_price_hash[ 'tags_in_' . $i ] = get_option( 'wcj_global_discount_sale_tags_incl_' . $i, '' );
198
+ $wcj_global_discount_price_hash[ 'tags_ex_' . $i ] = get_option( 'wcj_global_discount_sale_tags_excl_' . $i, '' );
199
+ $wcj_global_discount_price_hash[ 'products_in_' . $i ] = get_option( 'wcj_global_discount_sale_products_incl_' . $i, '' );
200
+ $wcj_global_discount_price_hash[ 'products_ex_' . $i ] = get_option( 'wcj_global_discount_sale_products_excl_' . $i, '' );
201
  }
202
  $price_hash['wcj_global_discount_price_hash'] = $wcj_global_discount_price_hash;
203
  return $price_hash;
includes/class-wcj-multicurrency.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Multicurrency (Currency Switcher)
4
  *
5
- * @version 2.8.0
6
  * @since 2.4.3
7
  * @author Algoritmika Ltd.
8
  */
@@ -45,7 +45,7 @@ class WCJ_Multicurrency extends WCJ_Module {
45
  /**
46
  * add_hooks.
47
  *
48
- * @version 2.7.0
49
  */
50
  function add_hooks() {
51
  // Session
@@ -69,7 +69,29 @@ class WCJ_Multicurrency extends WCJ_Module {
69
 
70
  // Add "Change Price" hooks
71
  wcj_add_change_price_hooks( $this, PHP_INT_MAX - 1 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  }
 
73
  }
74
 
75
  /**
2
  /**
3
  * Booster for WooCommerce - Module - Multicurrency (Currency Switcher)
4
  *
5
+ * @version 3.1.0
6
  * @since 2.4.3
7
  * @author Algoritmika Ltd.
8
  */
45
  /**
46
  * add_hooks.
47
  *
48
+ * @version 3.1.0
49
  */
50
  function add_hooks() {
51
  // Session
69
 
70
  // Add "Change Price" hooks
71
  wcj_add_change_price_hooks( $this, PHP_INT_MAX - 1 );
72
+
73
+ // "WooCommerce Product Add-ons" plugin
74
+ add_filter( 'get_product_addons', array( $this, 'change_price_addons' ) );
75
+ }
76
+ }
77
+
78
+ /**
79
+ * change_price_addons.
80
+ *
81
+ * @version 3.1.0
82
+ * @since 3.1.0
83
+ */
84
+ function change_price_addons( $addons ) {
85
+ foreach ( $addons as $addon_key => $addon ) {
86
+ if ( isset( $addon['options'] ) ) {
87
+ foreach ( $addon['options'] as $option_key => $option ) {
88
+ if ( isset( $option['price'] ) ) {
89
+ $addons[ $addon_key ]['options'][ $option_key ]['price'] = $this->change_price( $option['price'], null );
90
+ }
91
+ }
92
+ }
93
  }
94
+ return $addons;
95
  }
96
 
97
  /**
includes/class-wcj-order-numbers.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Order Numbers
4
  *
5
- * @version 2.8.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,9 @@ class WCJ_Order_Numbers extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 2.8.0
 
 
19
  */
20
  function __construct() {
21
 
@@ -29,16 +31,15 @@ class WCJ_Order_Numbers extends WCJ_Module {
29
  'renumerate_orders' => array(
30
  'title' => __( 'Orders Renumerate', 'woocommerce-jetpack' ),
31
  'desc' => __( 'Tool renumerates all orders.', 'woocommerce-jetpack' ),
32
- // 'tab_title' => __( 'Renumerate orders', 'woocommerce-jetpack' ),
33
  ),
34
  ) );
35
 
36
  if ( $this->is_enabled() ) {
37
- // add_action( 'woocommerce_new_order', array( $this, 'add_new_order_number' ), PHP_INT_MAX );
38
  add_action( 'wp_insert_post', array( $this, 'add_new_order_number' ), PHP_INT_MAX );
39
  add_filter( 'woocommerce_order_number', array( $this, 'display_order_number' ), PHP_INT_MAX, 2 );
40
  if ( 'yes' === get_option( 'wcj_order_number_order_tracking_enabled', 'yes' ) ) {
41
  add_filter( 'woocommerce_shortcode_order_tracking_order_id', array( $this, 'add_order_number_to_tracking' ), PHP_INT_MAX );
 
42
  }
43
  if ( 'yes' === get_option( 'wcj_order_number_search_by_custom_number_enabled', 'yes' ) ) {
44
  add_action( 'pre_get_posts', array( $this, 'search_by_custom_number' ) );
@@ -46,6 +47,16 @@ class WCJ_Order_Numbers extends WCJ_Module {
46
  }
47
  }
48
 
 
 
 
 
 
 
 
 
 
 
49
  /**
50
  * search_by_custom_number.
51
  *
@@ -76,32 +87,33 @@ class WCJ_Order_Numbers extends WCJ_Module {
76
  /**
77
  * add_order_number_to_tracking.
78
  *
79
- * @version 2.5.2
80
  * @since 2.5.2
81
- * @todo optimize WP_Query to return only `ids` for `fields`
82
  */
83
  function add_order_number_to_tracking( $order_number ) {
84
- $offset = 0;
85
- $block_size = 96;
86
  while( true ) {
87
  $args = array(
88
  'post_type' => 'shop_order',
89
  'post_status' => 'any',
90
  'posts_per_page' => $block_size,
91
- 'orderby' => 'date',
92
  'order' => 'DESC',
93
  'offset' => $offset,
 
94
  );
95
  $loop = new WP_Query( $args );
96
- if ( ! $loop->have_posts() ) break;
97
- while ( $loop->have_posts() ) : $loop->the_post();
98
- $_order_id = $loop->post->ID;
99
- $_order = wc_get_order( $_order_id );
 
100
  $_order_number = $this->display_order_number( $_order_id, $_order );
101
  if ( $_order_number === $order_number ) {
102
  return $_order_id;
103
  }
104
- endwhile;
105
  $offset += $block_size;
106
  }
107
  return $order_number;
@@ -135,7 +147,7 @@ class WCJ_Order_Numbers extends WCJ_Module {
135
  /**
136
  * Add Renumerate Orders tool to WooCommerce menu (the content).
137
  *
138
- * @version 2.4.4
139
  */
140
  function create_renumerate_orders_tool() {
141
  $result_message = '';
@@ -143,14 +155,22 @@ class WCJ_Order_Numbers extends WCJ_Module {
143
  $this->renumerate_orders();
144
  $result_message = '<p><div class="updated"><p><strong>' . __( 'Orders successfully renumerated!', 'woocommerce-jetpack' ) . '</strong></p></div></p>';
145
  }
146
- ?><div>
147
- <?php echo $this->get_tool_header_html( 'renumerate_orders' ); ?>
148
- <p><?php echo __( 'Press the button below to renumerate all existing orders starting from order counter settings in WooCommerce > Settings > Booster > Order Numbers.', 'woocommerce-jetpack' ); ?></p>
149
- <?php echo $result_message; ?>
150
- <form method="post" action="">
151
- <input class="button-primary" type="submit" name="renumerate_orders" value="<?php echo __( 'Renumerate orders', 'woocommerce-jetpack' ); ?>">
152
- </form>
153
- </div><?php
 
 
 
 
 
 
 
 
154
  }
155
 
156
  /**
@@ -163,10 +183,10 @@ class WCJ_Order_Numbers extends WCJ_Module {
163
  /**
164
  * Add/update order_number meta to order.
165
  *
166
- * @version 2.7.0
167
  */
168
  function add_order_number_meta( $order_id, $do_overwrite ) {
169
- if ( 'shop_order' !== get_post_type( $order_id ) ) {
170
  return;
171
  }
172
  if ( true === $do_overwrite || 0 == get_post_meta( $order_id, '_wcj_order_number', true ) ) {
@@ -202,13 +222,13 @@ class WCJ_Order_Numbers extends WCJ_Module {
202
  /**
203
  * Renumerate orders function.
204
  *
205
- * @version 2.5.0
206
  * @todo renumerate in date range only
207
- * @todo optimize WP_Query to return only `ids` for `fields`
208
  */
209
  function renumerate_orders() {
210
- $offset = 0;
211
- $block_size = 96;
212
  while( true ) {
213
  $args = array(
214
  'post_type' => 'shop_order',
@@ -217,13 +237,15 @@ class WCJ_Order_Numbers extends WCJ_Module {
217
  'orderby' => 'date',
218
  'order' => 'ASC',
219
  'offset' => $offset,
 
220
  );
221
  $loop = new WP_Query( $args );
222
- if ( ! $loop->have_posts() ) break;
223
- while ( $loop->have_posts() ) : $loop->the_post();
224
- $order_id = $loop->post->ID;
 
225
  $this->add_order_number_meta( $order_id, true );
226
- endwhile;
227
  $offset += $block_size;
228
  }
229
  }
2
  /**
3
  * Booster for WooCommerce - Module - Order Numbers
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.1.0
19
+ * @todo (maybe) rename "Orders Renumerate" to "Renumerate orders"
20
+ * @todo (maybe) use `woocommerce_new_order` hook instead of `wp_insert_post`
21
  */
22
  function __construct() {
23
 
31
  'renumerate_orders' => array(
32
  'title' => __( 'Orders Renumerate', 'woocommerce-jetpack' ),
33
  'desc' => __( 'Tool renumerates all orders.', 'woocommerce-jetpack' ),
 
34
  ),
35
  ) );
36
 
37
  if ( $this->is_enabled() ) {
 
38
  add_action( 'wp_insert_post', array( $this, 'add_new_order_number' ), PHP_INT_MAX );
39
  add_filter( 'woocommerce_order_number', array( $this, 'display_order_number' ), PHP_INT_MAX, 2 );
40
  if ( 'yes' === get_option( 'wcj_order_number_order_tracking_enabled', 'yes' ) ) {
41
  add_filter( 'woocommerce_shortcode_order_tracking_order_id', array( $this, 'add_order_number_to_tracking' ), PHP_INT_MAX );
42
+ add_action( 'init', array( $this, 'remove_order_tracking_sanitize_order_id_filter' ) );
43
  }
44
  if ( 'yes' === get_option( 'wcj_order_number_search_by_custom_number_enabled', 'yes' ) ) {
45
  add_action( 'pre_get_posts', array( $this, 'search_by_custom_number' ) );
47
  }
48
  }
49
 
50
+ /**
51
+ * remove_order_tracking_sanitize_order_id_filter.
52
+ *
53
+ * @version 3.1.0
54
+ * @since 3.1.0
55
+ */
56
+ function remove_order_tracking_sanitize_order_id_filter() {
57
+ remove_filter( 'woocommerce_shortcode_order_tracking_order_id', 'wc_sanitize_order_id' );
58
+ }
59
+
60
  /**
61
  * search_by_custom_number.
62
  *
87
  /**
88
  * add_order_number_to_tracking.
89
  *
90
+ * @version 3.1.0
91
  * @since 2.5.2
 
92
  */
93
  function add_order_number_to_tracking( $order_number ) {
94
+ $offset = 0;
95
+ $block_size = 512;
96
  while( true ) {
97
  $args = array(
98
  'post_type' => 'shop_order',
99
  'post_status' => 'any',
100
  'posts_per_page' => $block_size,
101
+ 'orderby' => 'ID',
102
  'order' => 'DESC',
103
  'offset' => $offset,
104
+ 'fields' => 'ids',
105
  );
106
  $loop = new WP_Query( $args );
107
+ if ( ! $loop->have_posts() ) {
108
+ break;
109
+ }
110
+ foreach ( $loop->posts as $_order_id ) {
111
+ $_order = wc_get_order( $_order_id );
112
  $_order_number = $this->display_order_number( $_order_id, $_order );
113
  if ( $_order_number === $order_number ) {
114
  return $_order_id;
115
  }
116
+ }
117
  $offset += $block_size;
118
  }
119
  return $order_number;
147
  /**
148
  * Add Renumerate Orders tool to WooCommerce menu (the content).
149
  *
150
+ * @version 3.1.0
151
  */
152
  function create_renumerate_orders_tool() {
153
  $result_message = '';
155
  $this->renumerate_orders();
156
  $result_message = '<p><div class="updated"><p><strong>' . __( 'Orders successfully renumerated!', 'woocommerce-jetpack' ) . '</strong></p></div></p>';
157
  }
158
+ $html = '';
159
+ $html .= '<div class="wrap">';
160
+ $html .= $this->get_tool_header_html( 'renumerate_orders' );
161
+ $html .= '<p>';
162
+ $html .= sprintf(
163
+ __( 'Press the button below to renumerate all existing orders starting from order counter settings in <a href="%s">Order Numbers</a> module.',
164
+ 'woocommerce-jetpack' ),
165
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=shipping_and_orders&section=order_numbers' )
166
+ );
167
+ $html .= '</p>';
168
+ $html .= $result_message;
169
+ $html .= '<form method="post" action="">';
170
+ $html .= '<input class="button-primary" type="submit" name="renumerate_orders" value="' . __( 'Renumerate orders', 'woocommerce-jetpack' ) . '">';
171
+ $html .= '</form>';
172
+ $html .= '</div>';
173
+ echo $html;
174
  }
175
 
176
  /**
183
  /**
184
  * Add/update order_number meta to order.
185
  *
186
+ * @version 3.1.0
187
  */
188
  function add_order_number_meta( $order_id, $do_overwrite ) {
189
+ if ( 'shop_order' !== get_post_type( $order_id ) || 'auto-draft' === get_post_status( $order_id ) ) {
190
  return;
191
  }
192
  if ( true === $do_overwrite || 0 == get_post_meta( $order_id, '_wcj_order_number', true ) ) {
222
  /**
223
  * Renumerate orders function.
224
  *
225
+ * @version 3.1.0
226
  * @todo renumerate in date range only
227
+ * @todo (maybe) `orderby` set to `ID`
228
  */
229
  function renumerate_orders() {
230
+ $offset = 0;
231
+ $block_size = 512;
232
  while( true ) {
233
  $args = array(
234
  'post_type' => 'shop_order',
237
  'orderby' => 'date',
238
  'order' => 'ASC',
239
  'offset' => $offset,
240
+ 'fields' => 'ids',
241
  );
242
  $loop = new WP_Query( $args );
243
+ if ( ! $loop->have_posts() ) {
244
+ break;
245
+ }
246
+ foreach ( $loop->posts as $order_id ) {
247
  $this->add_order_number_meta( $order_id, true );
248
+ }
249
  $offset += $block_size;
250
  }
251
  }
includes/class-wcj-payment-gateways-per-category.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Gateways per Product or Category
4
  *
5
- * @version 2.8.0
6
  * @since 2.2.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -35,7 +35,7 @@ class WCJ_Payment_Gateways_Per_Category extends WCJ_Module {
35
  /**
36
  * filter_available_payment_gateways_per_category.
37
  *
38
- * @version 2.7.0
39
  */
40
  function filter_available_payment_gateways_per_category( $available_gateways ) {
41
 
@@ -110,7 +110,7 @@ class WCJ_Payment_Gateways_Per_Category extends WCJ_Module {
110
  }
111
 
112
  // Including by products
113
- $products_in = apply_filters( 'booster_get_option', array(), get_option( 'wcj_gateways_per_products_' . $gateway_id ) );
114
  if ( ! empty( $products_in ) ) {
115
  $do_skip = true;
116
  foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
@@ -130,7 +130,7 @@ class WCJ_Payment_Gateways_Per_Category extends WCJ_Module {
130
  }
131
 
132
  // Excluding by products
133
- $products_excl = apply_filters( 'booster_get_option', array(), get_option( 'wcj_gateways_per_products_excl_' . $gateway_id ) );
134
  if ( ! empty( $products_excl ) ) {
135
  $do_skip = false;
136
  foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
2
  /**
3
  * Booster for WooCommerce - Module - Gateways per Product or Category
4
  *
5
+ * @version 3.1.0
6
  * @since 2.2.0
7
  * @author Algoritmika Ltd.
8
  */
35
  /**
36
  * filter_available_payment_gateways_per_category.
37
  *
38
+ * @version 3.1.0
39
  */
40
  function filter_available_payment_gateways_per_category( $available_gateways ) {
41
 
110
  }
111
 
112
  // Including by products
113
+ $products_in = wcj_maybe_convert_string_to_array( apply_filters( 'booster_get_option', array(), get_option( 'wcj_gateways_per_products_' . $gateway_id ) ) );
114
  if ( ! empty( $products_in ) ) {
115
  $do_skip = true;
116
  foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
130
  }
131
 
132
  // Excluding by products
133
+ $products_excl = wcj_maybe_convert_string_to_array( apply_filters( 'booster_get_option', array(), get_option( 'wcj_gateways_per_products_excl_' . $gateway_id ) ) );
134
  if ( ! empty( $products_excl ) ) {
135
  $do_skip = false;
136
  foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
includes/class-wcj-pdf-invoicing.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - PDF Invoicing
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,7 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 2.8.0
19
  */
20
  function __construct() {
21
 
@@ -60,6 +60,10 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
60
  add_action( 'kco_before_confirm_order', array( $this, 'create_document_hook' ) );
61
  add_action( 'woocommerce_checkout_order_processed', array( $this, 'create_document_hook' ) );
62
  }
 
 
 
 
63
  }
64
  }
65
  }
@@ -103,31 +107,48 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
103
  /**
104
  * bulk_actions_pdfs_notices.
105
  *
106
- * @version 2.5.7
107
  * @since 2.5.7
108
  */
109
  function bulk_actions_pdfs_notices() {
110
  global $post_type, $pagenow;
111
- if ( $pagenow == 'edit.php' && 'shop_order' == $post_type && isset( $_REQUEST['generated'] ) && (int) $_REQUEST['generated'] ) {
112
- $message = sprintf( _n( 'Document generated.', '%s documents generated.', $_REQUEST['generated'] ), number_format_i18n( $_REQUEST['generated'] ) );
113
- echo "<div class='updated'><p>{$message}</p></div>";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
114
  }
115
  }
116
 
117
  /**
118
  * bulk_actions_pdfs.
119
  *
120
- * @version 2.5.7
121
  * @since 2.5.7
122
  */
123
  function bulk_actions_pdfs() {
124
 
125
  // Get the action
126
  $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
127
- $action = $wp_list_table->current_action();
128
 
129
  // TODO: Security check
130
- // check_admin_referer('bulk-posts');
131
 
132
  // Validate the action
133
  $action_exploded = explode( '_', $action, 2 );
@@ -164,8 +185,17 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
164
  );
165
  break;
166
  case 'download':
167
- $this->get_invoices_zip( $the_type, $post_ids );
168
- exit();
 
 
 
 
 
 
 
 
 
169
  default:
170
  return;
171
  }
@@ -178,29 +208,32 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
178
  /**
179
  * get_invoices_zip.
180
  *
181
- * @version 2.5.7
182
  * @since 2.5.7
183
  */
184
  function get_invoices_zip( $invoice_type_id, $post_ids ) {
185
-
186
- $zip = new ZipArchive();
 
 
 
187
  $zip_file_name = $invoice_type_id . '.zip';
188
  $zip_file_path = sys_get_temp_dir() . '/' . $zip_file_name;
189
  if ( file_exists( $zip_file_path ) ) {
190
  unlink ( $zip_file_path );
191
  }
192
  if ( $zip->open( $zip_file_path, ZipArchive::CREATE ) !== TRUE ) {
193
- return false;
194
  }
195
  foreach( $post_ids as $post_id ) {
196
  if ( wcj_is_invoice_created( $post_id, $invoice_type_id ) ) {
197
  $the_invoice = wcj_get_pdf_invoice( $post_id, $invoice_type_id );
198
- $file_name = $the_invoice->get_pdf( 'F' );
199
  $zip->addFile( $file_name, $the_invoice->get_file_name() );
200
  }
201
  }
202
  $zip->close();
203
-
204
  header( "Content-Type: application/octet-stream" );
205
  header( "Content-Disposition: attachment; filename=" . urlencode( $zip_file_name ) );
206
  header( "Content-Type: application/octet-stream" );
@@ -214,10 +247,11 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
214
  flush(); // this is essential for large downloads
215
  }
216
  fclose( $fp );
 
217
  } else {
218
  die( __( 'Unexpected error', 'woocommerce-jetpack' ) );
219
  }
220
- return true;
221
  }
222
 
223
  /**
@@ -249,7 +283,9 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
249
  */
250
  function create_document_hook( $order_id ) {
251
  $current_filter = current_filter();
252
- if ( in_array( $current_filter, array( 'woocommerce_api_create_order', 'woocommerce_cli_create_order', 'kco_before_confirm_order', 'woocommerce_checkout_order_processed', ) ) ) {
 
 
253
  $current_filter = 'woocommerce_new_order';
254
  }
255
  $invoice_types = wcj_get_enabled_invoice_types();
2
  /**
3
  * Booster for WooCommerce - Module - PDF Invoicing
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.1.0
19
  */
20
  function __construct() {
21
 
60
  add_action( 'kco_before_confirm_order', array( $this, 'create_document_hook' ) );
61
  add_action( 'woocommerce_checkout_order_processed', array( $this, 'create_document_hook' ) );
62
  }
63
+ if ( 'wcj_pdf_invoicing_create_on_any_refund' === $the_hook ) {
64
+ add_action( 'woocommerce_order_status_refunded', array( $this, 'create_document_hook' ) );
65
+ add_action( 'woocommerce_order_partially_refunded_notification', array( $this, 'create_document_hook' ) );
66
+ }
67
  }
68
  }
69
  }
107
  /**
108
  * bulk_actions_pdfs_notices.
109
  *
110
+ * @version 3.1.0
111
  * @since 2.5.7
112
  */
113
  function bulk_actions_pdfs_notices() {
114
  global $post_type, $pagenow;
115
+ if ( $pagenow == 'edit.php' && 'shop_order' == $post_type ) {
116
+ if ( isset( $_REQUEST['generated'] ) && (int) $_REQUEST['generated'] ) {
117
+ $message = sprintf( _n( 'Document generated.', '%s documents generated.', $_REQUEST['generated'] ), number_format_i18n( $_REQUEST['generated'] ) );
118
+ echo "<div class='updated'><p>{$message}</p></div>";
119
+ }
120
+ if ( isset( $_GET['wcj_notice'] ) ) {
121
+ switch ( $_GET['wcj_notice'] ) {
122
+ case 'ziparchive_class_missing':
123
+ echo '<div class="notice notice-error"><p><strong>' .
124
+ sprintf( __( 'Booster: %s class is not accessible on your server. Please contact your hosting provider.', 'woocommerce-jetpack' ),
125
+ '<a target="_blank" href="http://php.net/manual/en/class.ziparchive.php">PHP ZipArchive</a>' ) .
126
+ '</strong></p></div>';
127
+ break;
128
+ case 'ziparchive_error':
129
+ echo '<div class="notice notice-error"><p>' .
130
+ __( 'Booster: ZipArchive error.', 'woocommerce-jetpack' ) .
131
+ '</p></div>';
132
+ break;
133
+ }
134
+ }
135
  }
136
  }
137
 
138
  /**
139
  * bulk_actions_pdfs.
140
  *
141
+ * @version 3.1.0
142
  * @since 2.5.7
143
  */
144
  function bulk_actions_pdfs() {
145
 
146
  // Get the action
147
  $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
148
+ $action = $wp_list_table->current_action();
149
 
150
  // TODO: Security check
151
+ // check_admin_referer( 'bulk-posts' );
152
 
153
  // Validate the action
154
  $action_exploded = explode( '_', $action, 2 );
185
  );
186
  break;
187
  case 'download':
188
+ if ( '' != ( $result = $this->get_invoices_zip( $the_type, $post_ids ) ) ) {
189
+ $sendback = add_query_arg(
190
+ array(
191
+ 'post_type' => 'shop_order',
192
+ 'post_status' => $_GET['post_status'],
193
+ 'wcj_notice' => $result,
194
+ ),
195
+ $sendback
196
+ );
197
+ }
198
+ break;
199
  default:
200
  return;
201
  }
208
  /**
209
  * get_invoices_zip.
210
  *
211
+ * @version 3.1.0
212
  * @since 2.5.7
213
  */
214
  function get_invoices_zip( $invoice_type_id, $post_ids ) {
215
+ if ( ! class_exists( 'ZipArchive' ) ) {
216
+ return 'ziparchive_class_missing';
217
+ }
218
+ // Creating Zip
219
+ $zip = new ZipArchive();
220
  $zip_file_name = $invoice_type_id . '.zip';
221
  $zip_file_path = sys_get_temp_dir() . '/' . $zip_file_name;
222
  if ( file_exists( $zip_file_path ) ) {
223
  unlink ( $zip_file_path );
224
  }
225
  if ( $zip->open( $zip_file_path, ZipArchive::CREATE ) !== TRUE ) {
226
+ return 'ziparchive_error';
227
  }
228
  foreach( $post_ids as $post_id ) {
229
  if ( wcj_is_invoice_created( $post_id, $invoice_type_id ) ) {
230
  $the_invoice = wcj_get_pdf_invoice( $post_id, $invoice_type_id );
231
+ $file_name = $the_invoice->get_pdf( 'F' );
232
  $zip->addFile( $file_name, $the_invoice->get_file_name() );
233
  }
234
  }
235
  $zip->close();
236
+ // Sending Zip
237
  header( "Content-Type: application/octet-stream" );
238
  header( "Content-Disposition: attachment; filename=" . urlencode( $zip_file_name ) );
239
  header( "Content-Type: application/octet-stream" );
247
  flush(); // this is essential for large downloads
248
  }
249
  fclose( $fp );
250
+ exit();
251
  } else {
252
  die( __( 'Unexpected error', 'woocommerce-jetpack' ) );
253
  }
254
+ return '';
255
  }
256
 
257
  /**
283
  */
284
  function create_document_hook( $order_id ) {
285
  $current_filter = current_filter();
286
+ if ( in_array( $current_filter,
287
+ array( 'woocommerce_api_create_order', 'woocommerce_cli_create_order', 'kco_before_confirm_order', 'woocommerce_checkout_order_processed' ) )
288
+ ) {
289
  $current_filter = 'woocommerce_new_order';
290
  }
291
  $invoice_types = wcj_get_enabled_invoice_types();
includes/class-wcj-product-by-country.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Product Visibility by Country
4
  *
5
- * @version 2.9.0
6
  * @since 2.5.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Product_By_Country extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.9.0
20
  * @since 2.5.0
21
  */
22
  function __construct() {
@@ -43,7 +43,9 @@ class WCJ_Product_By_Country extends WCJ_Module {
43
  if ( 'yes' === get_option( 'wcj_product_by_country_query', 'no' ) ) {
44
  add_action( 'pre_get_posts', array( $this, 'product_by_country_pre_get_posts' ) );
45
  }
46
-
 
 
47
  }
48
  // Admin products list
49
  if ( 'yes' === get_option( 'wcj_product_by_country_add_column_visible_countries', 'no' ) ) {
@@ -83,7 +85,7 @@ class WCJ_Product_By_Country extends WCJ_Module {
83
  /**
84
  * product_by_country_pre_get_posts.
85
  *
86
- * @version 2.9.0
87
  * @since 2.9.0
88
  */
89
  function product_by_country_pre_get_posts( $query ) {
@@ -91,21 +93,13 @@ class WCJ_Product_By_Country extends WCJ_Module {
91
  return;
92
  }
93
  remove_action( 'pre_get_posts', array( $this, 'product_by_country_pre_get_posts' ) );
94
- // Get the country by IP
95
- $location = WC_Geolocation::geolocate_ip();
96
- if ( empty( $location['country'] ) ) {
97
- // Base fallback
98
- $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
99
- }
100
- $country = ( isset( $location['country'] ) ) ? $location['country'] : '';
101
- // Calculate `post__not_in`
102
- $post__not_in = array();
103
- $args = $query->query;
104
  $args['fields'] = 'ids';
105
- $loop = new WP_Query( $args );
106
  foreach ( $loop->posts as $product_id ) {
107
- $visible_countries = get_post_meta( $product_id, '_' . 'wcj_product_by_country_visible', true );
108
- if ( is_array( $visible_countries ) && ! in_array( $country, $visible_countries ) ) {
109
  $post__not_in[] = $product_id;
110
  }
111
  }
@@ -116,32 +110,69 @@ class WCJ_Product_By_Country extends WCJ_Module {
116
  /**
117
  * product_by_country_purchasable.
118
  *
119
- * @version 2.9.0
120
  * @since 2.9.0
121
  */
122
  function product_by_country_purchasable( $purchasable, $_product ) {
123
- return $this->product_by_country( $purchasable, wcj_get_product_id_or_variation_parent_id( $_product ) );
124
  }
125
 
126
  /**
127
  * product_by_country.
128
  *
129
- * @version 2.5.0
130
  * @since 2.5.0
131
  */
132
  function product_by_country( $visible, $product_id ) {
133
- // Get the country by IP
134
- $location = WC_Geolocation::geolocate_ip();
135
- // Base fallback
136
- if ( empty( $location['country'] ) ) {
137
- $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
 
 
 
 
 
 
 
 
138
  }
139
- $country = ( isset( $location['country'] ) ) ? $location['country'] : '';
140
- $visible_countries = get_post_meta( $product_id, '_' . 'wcj_product_by_country_visible', true );
141
- if ( is_array( $visible_countries ) && ! in_array( $country, $visible_countries ) ) {
142
- return false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
143
  }
144
- return $visible;
145
  }
146
 
147
  }
2
  /**
3
  * Booster for WooCommerce - Module - Product Visibility by Country
4
  *
5
+ * @version 3.1.0
6
  * @since 2.5.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.1.0
20
  * @since 2.5.0
21
  */
22
  function __construct() {
43
  if ( 'yes' === get_option( 'wcj_product_by_country_query', 'no' ) ) {
44
  add_action( 'pre_get_posts', array( $this, 'product_by_country_pre_get_posts' ) );
45
  }
46
+ if ( 'manual' === apply_filters( 'booster_get_option', 'by_ip', get_option( 'wcj_product_by_country_selection_method', 'by_ip' ) ) ) {
47
+ add_action( 'init', array( $this, 'save_country_in_session' ), PHP_INT_MAX ) ;
48
+ }
49
  }
50
  // Admin products list
51
  if ( 'yes' === get_option( 'wcj_product_by_country_add_column_visible_countries', 'no' ) ) {
85
  /**
86
  * product_by_country_pre_get_posts.
87
  *
88
+ * @version 3.1.0
89
  * @since 2.9.0
90
  */
91
  function product_by_country_pre_get_posts( $query ) {
93
  return;
94
  }
95
  remove_action( 'pre_get_posts', array( $this, 'product_by_country_pre_get_posts' ) );
96
+ $country = $this->get_country();
97
+ $post__not_in = $query->get( 'post__not_in' );
98
+ $args = $query->query;
 
 
 
 
 
 
 
99
  $args['fields'] = 'ids';
100
+ $loop = new WP_Query( $args );
101
  foreach ( $loop->posts as $product_id ) {
102
+ if ( ! $this->is_product_visible_in_country( $product_id, $country ) ) {
 
103
  $post__not_in[] = $product_id;
104
  }
105
  }
110
  /**
111
  * product_by_country_purchasable.
112
  *
113
+ * @version 3.1.0
114
  * @since 2.9.0
115
  */
116
  function product_by_country_purchasable( $purchasable, $_product ) {
117
+ return ( ! $this->is_product_visible_in_country( wcj_get_product_id_or_variation_parent_id( $_product ), $this->get_country() ) ? false : $purchasable );
118
  }
119
 
120
  /**
121
  * product_by_country.
122
  *
123
+ * @version 3.1.0
124
  * @since 2.5.0
125
  */
126
  function product_by_country( $visible, $product_id ) {
127
+ return ( ! $this->is_product_visible_in_country( $product_id, $this->get_country() ) ? false : $visible );
128
+ }
129
+
130
+ /**
131
+ * is_product_visible_in_country.
132
+ *
133
+ * @version 3.1.0
134
+ * @since 3.1.0
135
+ */
136
+ function is_product_visible_in_country( $product_id, $country ) {
137
+ $countries = get_post_meta( $product_id, '_' . 'wcj_product_by_country_visible', true );
138
+ if ( is_array( $countries ) && in_array( 'EU', $countries ) ) {
139
+ $countries = array_merge( $countries, wcj_get_european_union_countries() );
140
  }
141
+ return ( is_array( $countries ) && ! in_array( $country, $countries ) ? false : true );
142
+ }
143
+
144
+ /**
145
+ * save_country_in_session.
146
+ *
147
+ * @version 3.1.0
148
+ * @since 3.1.0
149
+ */
150
+ function save_country_in_session() {
151
+ if ( isset( $_REQUEST['wcj_country_selector'] ) ) {
152
+ wcj_session_maybe_start();
153
+ wcj_session_set( 'wcj_selected_country', $_REQUEST['wcj_country_selector'] );
154
+ }
155
+ }
156
+
157
+ /**
158
+ * get_country.
159
+ *
160
+ * @version 3.1.0
161
+ * @since 3.1.0
162
+ */
163
+ function get_country() {
164
+ if ( 'manual' === apply_filters( 'booster_get_option', 'by_ip', get_option( 'wcj_product_by_country_selection_method', 'by_ip' ) ) ) {
165
+ if ( '' == wcj_session_get( 'wcj_selected_country' ) ) {
166
+ $country = wcj_get_country_by_ip();
167
+ wcj_session_maybe_start();
168
+ wcj_session_set( 'wcj_selected_country', $country );
169
+ return $country;
170
+ } else {
171
+ return wcj_session_get( 'wcj_selected_country' );
172
+ }
173
+ } else {
174
+ return wcj_get_country_by_ip();
175
  }
 
176
  }
177
 
178
  }
includes/class-wcj-product-by-user-role.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Product Visibility by User Role
4
  *
5
- * @version 2.8.0
6
  * @since 2.5.5
7
  * @author Algoritmika Ltd.
8
  */
@@ -49,7 +49,7 @@ class WCJ_Product_By_User_Role extends WCJ_Module {
49
  /**
50
  * product_by_user_role_pre_get_posts.
51
  *
52
- * @version 2.7.0
53
  * @since 2.6.0
54
  * @todo (maybe) add global function for this, as similar code is in "Product Visibility by Country" module
55
  * @todo check if `purchasable` and `pre_get_posts` hooks should be added to other "Product Visibility" modules
@@ -60,7 +60,7 @@ class WCJ_Product_By_User_Role extends WCJ_Module {
60
  }
61
  remove_action( 'pre_get_posts', array( $this, 'product_by_user_role_pre_get_posts' ) );
62
  $current_user_roles = wcj_get_current_user_all_roles();
63
- $post__not_in = array();
64
  $args = $query->query;
65
  $args['fields'] = 'ids';
66
  $loop = new WP_Query( $args );
2
  /**
3
  * Booster for WooCommerce - Module - Product Visibility by User Role
4
  *
5
+ * @version 3.1.0
6
  * @since 2.5.5
7
  * @author Algoritmika Ltd.
8
  */
49
  /**
50
  * product_by_user_role_pre_get_posts.
51
  *
52
+ * @version 3.1.0
53
  * @since 2.6.0
54
  * @todo (maybe) add global function for this, as similar code is in "Product Visibility by Country" module
55
  * @todo check if `purchasable` and `pre_get_posts` hooks should be added to other "Product Visibility" modules
60
  }
61
  remove_action( 'pre_get_posts', array( $this, 'product_by_user_role_pre_get_posts' ) );
62
  $current_user_roles = wcj_get_current_user_all_roles();
63
+ $post__not_in = $query->get( 'post__not_in' );
64
  $args = $query->query;
65
  $args['fields'] = 'ids';
66
  $loop = new WP_Query( $args );
includes/class-wcj-product-input-fields.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Product Input Fields
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,8 @@ class WCJ_Product_Input_Fields extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 2.8.0
 
19
  */
20
  function __construct() {
21
 
@@ -25,7 +26,7 @@ class WCJ_Product_Input_Fields extends WCJ_Module {
25
  $this->link_slug = 'woocommerce-product-input-fields';
26
  parent::__construct();
27
 
28
- include_once( 'input-fields/class-wcj-product-input-fields-abstract.php' );
29
 
30
  if ( $this->is_enabled() ) {
31
 
@@ -33,16 +34,29 @@ class WCJ_Product_Input_Fields extends WCJ_Module {
33
 
34
  add_action( 'init', array( $this, 'handle_downloads' ) );
35
 
36
- include_once( 'input-fields/class-wcj-product-input-fields-global.php' );
37
- include_once( 'input-fields/class-wcj-product-input-fields-per-product.php' );
38
 
39
- if ( 'yes' === get_option( 'wcj_product_input_fields_global_enabled' ) || 'yes' === get_option( 'wcj_product_input_fields_local_enabled' ) ) {
40
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
41
  add_action( 'init', array( $this, 'register_scripts' ) );
42
  }
43
  }
44
  }
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  /**
47
  * delete_file_uploads.
48
  *
@@ -105,15 +119,6 @@ class WCJ_Product_Input_Fields extends WCJ_Module {
105
  wp_enqueue_script( 'wcj-product-input-fields' );
106
  }
107
 
108
- /**
109
- * get_options.
110
- */
111
- function get_options() {
112
- $product_input_fields_abstract = new WCJ_Product_Input_Fields_Abstract();
113
- $product_input_fields_abstract->scope = 'global';
114
- return $product_input_fields_abstract->get_options();
115
- }
116
-
117
  }
118
 
119
  endif;
2
  /**
3
  * Booster for WooCommerce - Module - Product Input Fields
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.1.0
19
+ * @todo (maybe) option to change local and global fields order (i.e. output local fields before the global)
20
  */
21
  function __construct() {
22
 
26
  $this->link_slug = 'woocommerce-product-input-fields';
27
  parent::__construct();
28
 
29
+ require_once( 'input-fields/class-wcj-product-input-fields-core.php' );
30
 
31
  if ( $this->is_enabled() ) {
32
 
34
 
35
  add_action( 'init', array( $this, 'handle_downloads' ) );
36
 
37
+ $this->global_product_fields = new WCJ_Product_Input_Fields_Core( 'global' );
38
+ $this->local_product_fields = new WCJ_Product_Input_Fields_Core( 'local' );
39
 
40
+ if ( 'yes' === get_option( 'wcj_product_input_fields_global_enabled', 'no' ) || 'yes' === get_option( 'wcj_product_input_fields_local_enabled', 'no' ) ) {
41
  add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
42
  add_action( 'init', array( $this, 'register_scripts' ) );
43
  }
44
  }
45
  }
46
 
47
+ /**
48
+ * get_global_product_fields_options.
49
+ *
50
+ * @version 3.1.0
51
+ * @since 3.1.0
52
+ */
53
+ function get_global_product_fields_options() {
54
+ $this->scope = 'global';
55
+ $return = require( 'input-fields/wcj-product-input-fields-options.php' );
56
+ unset( $this->scope );
57
+ return $return;
58
+ }
59
+
60
  /**
61
  * delete_file_uploads.
62
  *
119
  wp_enqueue_script( 'wcj-product-input-fields' );
120
  }
121
 
 
 
 
 
 
 
 
 
 
122
  }
123
 
124
  endif;
includes/class-wcj-product-tabs.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Product Tabs
4
  *
5
- * @version 2.8.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -27,7 +27,7 @@ class WCJ_Product_Tabs extends WCJ_Module {
27
  parent::__construct();
28
 
29
  if ( $this->is_enabled() ) {
30
- add_action( 'wp_head', array( $this, 'maybe_add_js_links' ) );
31
  add_filter( 'woocommerce_product_tabs', array( $this, 'customize_product_tabs' ), 98 );
32
  if ( 'yes' === get_option( 'wcj_custom_product_tabs_local_enabled', 'yes' ) ) {
33
  add_action( 'add_meta_boxes', array( $this, 'add_custom_tabs_meta_box' ) );
@@ -37,93 +37,137 @@ class WCJ_Product_Tabs extends WCJ_Module {
37
  }
38
 
39
  /**
40
- * Customize the product tabs.
41
  *
42
- * @version 2.8.0
 
43
  */
44
- function customize_product_tabs( $tabs ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
- // DEFAULT TABS
47
  // Unset
48
- if ( get_option( 'wcj_product_info_product_tabs_description_disable' ) === 'yes' ) {
49
  unset( $tabs['description'] );
50
  }
51
- if ( get_option( 'wcj_product_info_product_tabs_reviews_disable' ) === 'yes' ) {
52
  unset( $tabs['reviews'] );
53
  }
54
- if ( get_option( 'wcj_product_info_product_tabs_additional_information_disable' ) === 'yes' ) {
55
  unset( $tabs['additional_information'] );
56
  }
57
 
58
  // Priority and Title
59
  if ( isset( $tabs['description'] ) ) {
60
- $tabs['description']['priority'] = apply_filters( 'booster_get_option', 10, get_option( 'wcj_product_info_product_tabs_description_priority' ) );
61
- if ( get_option( 'wcj_product_info_product_tabs_description_title' ) !== '' ) {
62
- $tabs['description']['title'] = get_option( 'wcj_product_info_product_tabs_description_title' );
63
  }
64
  }
65
- if ( isset( $tabs['reviews'] ) ) {
66
- $tabs['reviews']['priority'] = apply_filters( 'booster_get_option', 20, get_option( 'wcj_product_info_product_tabs_reviews_priority' ) );
67
- if ( get_option( 'wcj_product_info_product_tabs_reviews_title' ) !== '' ) {
68
- $tabs['reviews']['title'] = get_option( 'wcj_product_info_product_tabs_reviews_title' );
69
  }
70
  }
71
- if ( isset( $tabs['additional_information'] ) ) {
72
- $tabs['additional_information']['priority'] = apply_filters( 'booster_get_option', 30, get_option( 'wcj_product_info_product_tabs_additional_information_priority' ) );
73
- if ( get_option( 'wcj_product_info_product_tabs_additional_information_title' ) !== '' ) {
74
- $tabs['additional_information']['title'] = get_option( 'wcj_product_info_product_tabs_additional_information_title' );
75
  }
76
  }
77
 
78
- // CUSTOM TABS
79
- // Add New
80
- $current_post_id = get_the_ID();
81
- // Add New - Global
82
- for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_custom_product_tabs_global_total_number', 1 ) ); $i++ ) {
83
- $key = 'global_' . $i;
84
- if ( '' != get_option( 'wcj_custom_product_tabs_title_' . $key, '' ) &&
85
- ( '' != get_option( 'wcj_custom_product_tabs_content_' . $key, '' ) || '' != get_option( 'wcj_custom_product_tabs_link_' . $key, '' ) )
86
- ) {
87
- if ( ! $this->is_global_tab_visible( $i, $current_post_id ) ) {
88
- continue;
 
 
 
 
 
 
 
 
89
  }
90
- // Adding the tab
91
- $tabs[ $key ] = array(
92
- 'title' => do_shortcode( get_option( 'wcj_custom_product_tabs_title_' . $key ) ),
93
- 'priority' => get_option( 'wcj_custom_product_tabs_priority_' . $key, 40 ),
94
- 'callback' => array( $this, 'create_new_custom_product_tab_global' ),
95
- );
96
- }
97
- }
98
- // Add New - Local
99
- $option_name = 'wcj_custom_product_tabs_local_total_number';
100
- if ( ! ( $total_custom_tabs = get_post_meta( $current_post_id, '_' . $option_name, true ) ) ) {
101
- $total_custom_tabs = apply_filters( 'booster_get_option', 1, get_option( 'wcj_custom_product_tabs_local_total_number_default', 1 ) );
102
- }
103
- if ( 'yes' !== get_option( 'wcj_custom_product_tabs_local_enabled', 'yes' ) ) {
104
- $total_custom_tabs = 0;
105
  }
106
  for ( $i = 1; $i <= $total_custom_tabs; $i++ ) {
107
- if ( $this->is_local_tab_visible( $i, $current_post_id ) ) {
108
- $key = 'local_' . $i;
109
- $tab_priority = get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_priority_' . $key, true );
110
- if ( ! $tab_priority ) {
111
- $tab_priority = (50 + $i - 1);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
112
  }
113
- if ( '' != get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_title_' . $key, true ) &&
114
- (
115
- '' != get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_content_' . $key, true ) ||
116
- '' != get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_link_' . $key, true )
117
- )
118
- ) {
119
- $tabs[ $key ] = array(
120
- 'title' => do_shortcode( get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_title_' . $key, true ) ),
121
- 'priority' => $tab_priority,
122
- 'callback' => array( $this, 'create_new_custom_product_tab_local' ),
123
  );
124
  }
125
  }
126
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
 
128
  return $tabs;
129
  }
@@ -252,20 +296,110 @@ class WCJ_Product_Tabs extends WCJ_Module {
252
  return true;
253
  }
254
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
255
  /**
256
  * get_js_link_script.
257
  *
258
  * @version 2.8.0
259
  * @since 2.8.0
260
  */
261
- function get_js_link_script( $link, $key, $do_open_in_new_window ) {
262
  $link = do_shortcode( $link );
263
  $command = ( 'yes' === $do_open_in_new_window ) ?
264
  'window.open("' . $link . '","_blank");' :
265
  'window.location = "' . $link . '";';
266
  return '<script>' .
267
  'jQuery(document).ready(function() {
268
- jQuery("li.' . $key . '_tab").click(function(){
269
  ' . $command . '
270
  return false;
271
  });
@@ -276,7 +410,7 @@ class WCJ_Product_Tabs extends WCJ_Module {
276
  /**
277
  * maybe_add_js_links.
278
  *
279
- * @version 2.8.0
280
  * @since 2.8.0
281
  */
282
  function maybe_add_js_links() {
@@ -286,7 +420,7 @@ class WCJ_Product_Tabs extends WCJ_Module {
286
  if ( $this->is_global_tab_visible( $i, $current_post_id ) ) {
287
  $key = 'global_' . $i;
288
  if ( '' != get_option( 'wcj_custom_product_tabs_title_' . $key, '' ) && '' != ( $link = get_option( 'wcj_custom_product_tabs_link_' . $key, '' ) ) ) {
289
- echo $this->get_js_link_script( $link, $key, get_option( 'wcj_custom_product_tabs_link_new_tab_' . $key, true ) );
290
  }
291
  }
292
  }
@@ -302,7 +436,7 @@ class WCJ_Product_Tabs extends WCJ_Module {
302
  $key = 'local_' . $i;
303
  if ( '' != get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_title_' . $key, true ) ) {
304
  if ( '' != ( $link = get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_link_' . $key, true ) ) ) {
305
- echo $this->get_js_link_script( $link, $key, get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_link_new_tab_' . $key, true ) );
306
  }
307
  }
308
  }
@@ -311,23 +445,28 @@ class WCJ_Product_Tabs extends WCJ_Module {
311
 
312
  /**
313
  * create_new_custom_product_tab_local.
 
 
 
314
  */
315
  function create_new_custom_product_tab_local( $key, $tab ) {
316
- $current_post_id = get_the_ID();
317
- echo apply_filters( 'the_content', get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_content_' . $key, true ) );
318
  }
319
 
320
  /**
321
  * create_new_custom_product_tab_global.
 
 
 
322
  */
323
  function create_new_custom_product_tab_global( $key, $tab ) {
324
- echo apply_filters( 'the_content', get_option( 'wcj_custom_product_tabs_content_' . $key ) );
325
  }
326
 
327
  /**
328
  * save_custom_tabs_meta_box.
329
  *
330
- * @version 2.8.0
331
  * @todo rewrite as standard `WCJ_Module` function
332
  */
333
  function save_custom_tabs_meta_box( $post_id, $post ) {
@@ -336,9 +475,10 @@ class WCJ_Product_Tabs extends WCJ_Module {
336
  if ( ! isset( $_POST['woojetpack_custom_tabs_save_post'] ) )
337
  return;
338
 
339
- // Save: title, priority, content
340
  $option_names = array(
341
  'wcj_custom_product_tabs_title_local_',
 
342
  'wcj_custom_product_tabs_priority_local_',
343
  'wcj_custom_product_tabs_content_local_',
344
  'wcj_custom_product_tabs_link_local_',
@@ -377,100 +517,10 @@ class WCJ_Product_Tabs extends WCJ_Module {
377
  );
378
  }
379
 
380
- /**
381
- * is_local_tab_visible.
382
- *
383
- * @version 2.4.7
384
- * @since 2.4.7
385
- */
386
- function is_local_tab_visible( $custom_tab_index, $product_id ) {
387
-
388
- // Exclude by product id
389
- $array_to_exclude = get_option( 'wcj_custom_product_tabs_local_hide_in_products_' . $custom_tab_index );
390
- if ( '' != $array_to_exclude && ! empty( $array_to_exclude ) ) {
391
- if ( $array_to_exclude && in_array( $product_id, $array_to_exclude ) ) {
392
- return false;
393
- }
394
- }
395
-
396
- // Exclude by product category
397
- $array_to_exclude = get_option( 'wcj_custom_product_tabs_local_hide_in_cats_' . $custom_tab_index );
398
- if ( '' != $array_to_exclude && ! empty( $array_to_exclude ) ) {
399
- $product_categories_objects = get_the_terms( $product_id, 'product_cat' );
400
- if ( $product_categories_objects && ! empty( $product_categories_objects ) ) {
401
- foreach ( $product_categories_objects as $product_categories_object ) {
402
- if ( $array_to_exclude && in_array( $product_categories_object->term_id, $array_to_exclude ) ) {
403
- return false;
404
- }
405
- }
406
- }
407
- }
408
-
409
- // Exclude by product tag
410
- $array_to_exclude = get_option( 'wcj_custom_product_tabs_local_hide_in_tags_' . $custom_tab_index );
411
- if ( '' != $array_to_exclude && ! empty( $array_to_exclude ) ) {
412
- $product_tags_objects = get_the_terms( $product_id, 'product_tag' );
413
- if ( $product_tags_objects && ! empty( $product_tags_objects ) ) {
414
- foreach ( $product_tags_objects as $product_tags_object ) {
415
- if ( $array_to_exclude && in_array( $product_tags_object->term_id, $array_to_exclude ) ) {
416
- return false;
417
- }
418
- }
419
- }
420
- }
421
-
422
- // Include by product id
423
- $array_to_include = get_option( 'wcj_custom_product_tabs_local_show_in_products_' . $custom_tab_index );
424
- if ( '' != $array_to_include && ! empty( $array_to_include ) ) {
425
- // If NOT in array then hide this tab for this product
426
- if ( $array_to_include && ! in_array( $product_id, $array_to_include ) ) {
427
- return false;
428
- }
429
- }
430
-
431
- // Include by product category
432
- $array_to_include = get_option( 'wcj_custom_product_tabs_local_show_in_cats_' . $custom_tab_index );
433
- if ( '' != $array_to_include && ! empty( $array_to_include ) ) {
434
- $do_include = false;
435
- $product_categories_objects = get_the_terms( $product_id, 'product_cat' );
436
- if ( $product_categories_objects && ! empty( $product_categories_objects ) ) {
437
- foreach ( $product_categories_objects as $product_categories_object ) {
438
- if ( $array_to_include && in_array( $product_categories_object->term_id, $array_to_include ) ) {
439
- $do_include = true;
440
- break;
441
- }
442
- }
443
- }
444
- if ( ! $do_include ) {
445
- return false;
446
- }
447
- }
448
-
449
- // Include by product tag
450
- $array_to_include = get_option( 'wcj_custom_product_tabs_local_show_in_tags_' . $custom_tab_index );
451
- if ( '' != $array_to_include && ! empty( $array_to_include ) ) {
452
- $do_include = false;
453
- $product_tags_objects = get_the_terms( $product_id, 'product_tag' );
454
- if ( $product_tags_objects && ! empty( $product_tags_objects ) ) {
455
- foreach ( $product_tags_objects as $product_tags_object ) {
456
- if ( $array_to_include && in_array( $product_tags_object->term_id, $array_to_include ) ) {
457
- $do_include = true;
458
- break;
459
- }
460
- }
461
- }
462
- if ( ! $do_include ) {
463
- return false;
464
- }
465
- }
466
-
467
- return true;
468
- }
469
-
470
  /**
471
  * create_custom_tabs_meta_box.
472
  *
473
- * @version 2.8.0
474
  */
475
  function create_custom_tabs_meta_box() {
476
 
@@ -505,6 +555,11 @@ class WCJ_Product_Tabs extends WCJ_Module {
505
  'title' => __( 'Title', 'woocommerce-jetpack' ),
506
  'type' => 'text',
507
  ),
 
 
 
 
 
508
  array(
509
  'id' => 'wcj_custom_product_tabs_priority_local_',
510
  'title' => __( 'Order', 'woocommerce-jetpack' ),
@@ -547,6 +602,9 @@ class WCJ_Product_Tabs extends WCJ_Module {
547
  if ( '' === $option_value && 'wcj_custom_product_tabs_priority_local_' === $option['id'] ) {
548
  $option_value = (50 + $i - 1);
549
  }
 
 
 
550
  }
551
  switch ( $option['type'] ) {
552
  case 'select':
2
  /**
3
  * Booster for WooCommerce - Module - Product Tabs
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
27
  parent::__construct();
28
 
29
  if ( $this->is_enabled() ) {
30
+ add_action( 'wp_head', array( $this, 'maybe_add_js_links' ) );
31
  add_filter( 'woocommerce_product_tabs', array( $this, 'customize_product_tabs' ), 98 );
32
  if ( 'yes' === get_option( 'wcj_custom_product_tabs_local_enabled', 'yes' ) ) {
33
  add_action( 'add_meta_boxes', array( $this, 'add_custom_tabs_meta_box' ) );
37
  }
38
 
39
  /**
40
+ * get_tab_key.
41
  *
42
+ * @version 3.1.0
43
+ * @since 3.1.0
44
  */
45
+ function get_tab_key( $tab_option_key, $scope, $product_id = 0 ) {
46
+ $tab_key = ( 'global' === $scope ?
47
+ get_option( 'wcj_custom_product_tabs_key_' . $tab_option_key, $tab_option_key ) :
48
+ get_post_meta( $product_id, '_' . 'wcj_custom_product_tabs_key_' . $tab_option_key, true )
49
+ );
50
+ return ( '' == $tab_key ? $tab_option_key : $tab_key );
51
+ }
52
+
53
+ /**
54
+ * customize_default_tabs.
55
+ *
56
+ * @version 3.1.0
57
+ * @since 3.1.0
58
+ */
59
+ function customize_default_tabs( $tabs ) {
60
 
 
61
  // Unset
62
+ if ( 'yes' === get_option( 'wcj_product_info_product_tabs_description_disable', 'no' ) ) {
63
  unset( $tabs['description'] );
64
  }
65
+ if ( 'yes' === get_option( 'wcj_product_info_product_tabs_reviews_disable', 'no' ) ) {
66
  unset( $tabs['reviews'] );
67
  }
68
+ if ( 'yes' === get_option( 'wcj_product_info_product_tabs_additional_information_disable', 'no' ) ) {
69
  unset( $tabs['additional_information'] );
70
  }
71
 
72
  // Priority and Title
73
  if ( isset( $tabs['description'] ) ) {
74
+ $tabs['description']['priority'] = apply_filters( 'booster_get_option', 10, get_option( 'wcj_product_info_product_tabs_description_priority', 10 ) );
75
+ if ( '' != ( $title = get_option( 'wcj_product_info_product_tabs_description_title', '' ) ) ) {
76
+ $tabs['description']['title'] = $title;
77
  }
78
  }
79
+ if ( isset( $tabs['additional_information'] ) ) {
80
+ $tabs['additional_information']['priority'] = apply_filters( 'booster_get_option', 20, get_option( 'wcj_product_info_product_tabs_additional_information_priority', 20 ) );
81
+ if ( '' != ( $title = get_option( 'wcj_product_info_product_tabs_additional_information_title', '' ) ) ) {
82
+ $tabs['additional_information']['title'] = $title;
83
  }
84
  }
85
+ if ( isset( $tabs['reviews'] ) ) {
86
+ $tabs['reviews']['priority'] = apply_filters( 'booster_get_option', 30, get_option( 'wcj_product_info_product_tabs_reviews_priority', 30 ) );
87
+ if ( '' != ( $title = get_option( 'wcj_product_info_product_tabs_reviews_title', '' ) ) ) {
88
+ $tabs['reviews']['title'] = $title;
89
  }
90
  }
91
 
92
+ // The end
93
+ return $tabs;
94
+ }
95
+
96
+ /**
97
+ * add_custom_product_tabs.
98
+ *
99
+ * @version 3.1.0
100
+ * @since 3.1.0
101
+ * @todo add visibility by user roles
102
+ */
103
+ function add_custom_product_tabs( $scope, $tabs, $product_id ) {
104
+ switch ( $scope ) {
105
+ case 'global':
106
+ $total_custom_tabs = apply_filters( 'booster_get_option', 1, get_option( 'wcj_custom_product_tabs_global_total_number', 1 ) );
107
+ break;
108
+ default: // 'local'
109
+ if ( ! ( $total_custom_tabs = get_post_meta( $product_id, '_' . 'wcj_custom_product_tabs_local_total_number', true ) ) ) {
110
+ $total_custom_tabs = apply_filters( 'booster_get_option', 1, get_option( 'wcj_custom_product_tabs_local_total_number_default', 1 ) );
111
  }
112
+ break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
113
  }
114
  for ( $i = 1; $i <= $total_custom_tabs; $i++ ) {
115
+ $visibility_check_function = 'is_' . $scope . '_tab_visible';
116
+ if ( $this->$visibility_check_function( $i, $product_id ) ) {
117
+ $option_key = $scope . '_' . $i;
118
+ switch ( $scope ) {
119
+ case 'global':
120
+ $title = get_option( 'wcj_custom_product_tabs_title_' . $option_key, '' );
121
+ $content = get_option( 'wcj_custom_product_tabs_content_' . $option_key, '' );
122
+ $priority = get_option( 'wcj_custom_product_tabs_priority_' . $option_key, 40 );
123
+ $link = get_option( 'wcj_custom_product_tabs_link_' . $option_key, '' );
124
+ break;
125
+ default: // 'local'
126
+ $title = get_post_meta( $product_id, '_' . 'wcj_custom_product_tabs_title_' . $option_key, true );
127
+ $content = get_post_meta( $product_id, '_' . 'wcj_custom_product_tabs_content_' . $option_key, true );
128
+ $priority = get_post_meta( $product_id, '_' . 'wcj_custom_product_tabs_priority_' . $option_key, true );
129
+ $link = get_post_meta( $product_id, '_' . 'wcj_custom_product_tabs_link_' . $option_key, true );
130
+ if ( ! $priority ) {
131
+ $priority = ( 50 + $i - 1 );
132
+ }
133
+ break;
134
  }
135
+ if ( '' != $title && ( '' != do_shortcode( $content ) || '' != $link ) ) {
136
+ // Adding the tab
137
+ $tab_key = $this->get_tab_key( $option_key, $scope, $product_id );
138
+ $this->tab_option_keys[ $scope ][ $tab_key ] = $option_key;
139
+ $tabs[ $tab_key ] = array(
140
+ 'title' => do_shortcode( $title ),
141
+ 'priority' => $priority,
142
+ 'callback' => array( $this, 'create_new_custom_product_tab_' . $scope ),
 
 
143
  );
144
  }
145
  }
146
  }
147
+ return $tabs;
148
+ }
149
+
150
+ /**
151
+ * Customize the product tabs.
152
+ *
153
+ * @version 3.1.0
154
+ */
155
+ function customize_product_tabs( $tabs ) {
156
+
157
+ $product_id = get_the_ID();
158
+
159
+ // Default Tabs
160
+ $tabs = $this->customize_default_tabs( $tabs );
161
+
162
+ // Custom Tabs - Global
163
+ if ( 'yes' === get_option( 'wcj_custom_product_tabs_global_enabled', 'yes' ) ) {
164
+ $tabs = $this->add_custom_product_tabs( 'global', $tabs, $product_id );
165
+ }
166
+
167
+ // Custom Tabs - Local
168
+ if ( 'yes' === get_option( 'wcj_custom_product_tabs_local_enabled', 'yes' ) ) {
169
+ $tabs = $this->add_custom_product_tabs( 'local', $tabs, $product_id );
170
+ }
171
 
172
  return $tabs;
173
  }
296
  return true;
297
  }
298
 
299
+ /**
300
+ * is_local_tab_visible.
301
+ *
302
+ * @version 2.4.7
303
+ * @since 2.4.7
304
+ */
305
+ function is_local_tab_visible( $custom_tab_index, $product_id ) {
306
+
307
+ // Exclude by product id
308
+ $array_to_exclude = get_option( 'wcj_custom_product_tabs_local_hide_in_products_' . $custom_tab_index );
309
+ if ( '' != $array_to_exclude && ! empty( $array_to_exclude ) ) {
310
+ if ( $array_to_exclude && in_array( $product_id, $array_to_exclude ) ) {
311
+ return false;
312
+ }
313
+ }
314
+
315
+ // Exclude by product category
316
+ $array_to_exclude = get_option( 'wcj_custom_product_tabs_local_hide_in_cats_' . $custom_tab_index );
317
+ if ( '' != $array_to_exclude && ! empty( $array_to_exclude ) ) {
318
+ $product_categories_objects = get_the_terms( $product_id, 'product_cat' );
319
+ if ( $product_categories_objects && ! empty( $product_categories_objects ) ) {
320
+ foreach ( $product_categories_objects as $product_categories_object ) {
321
+ if ( $array_to_exclude && in_array( $product_categories_object->term_id, $array_to_exclude ) ) {
322
+ return false;
323
+ }
324
+ }
325
+ }
326
+ }
327
+
328
+ // Exclude by product tag
329
+ $array_to_exclude = get_option( 'wcj_custom_product_tabs_local_hide_in_tags_' . $custom_tab_index );
330
+ if ( '' != $array_to_exclude && ! empty( $array_to_exclude ) ) {
331
+ $product_tags_objects = get_the_terms( $product_id, 'product_tag' );
332
+ if ( $product_tags_objects && ! empty( $product_tags_objects ) ) {
333
+ foreach ( $product_tags_objects as $product_tags_object ) {
334
+ if ( $array_to_exclude && in_array( $product_tags_object->term_id, $array_to_exclude ) ) {
335
+ return false;
336
+ }
337
+ }
338
+ }
339
+ }
340
+
341
+ // Include by product id
342
+ $array_to_include = get_option( 'wcj_custom_product_tabs_local_show_in_products_' . $custom_tab_index );
343
+ if ( '' != $array_to_include && ! empty( $array_to_include ) ) {
344
+ // If NOT in array then hide this tab for this product
345
+ if ( $array_to_include && ! in_array( $product_id, $array_to_include ) ) {
346
+ return false;
347
+ }
348
+ }
349
+
350
+ // Include by product category
351
+ $array_to_include = get_option( 'wcj_custom_product_tabs_local_show_in_cats_' . $custom_tab_index );
352
+ if ( '' != $array_to_include && ! empty( $array_to_include ) ) {
353
+ $do_include = false;
354
+ $product_categories_objects = get_the_terms( $product_id, 'product_cat' );
355
+ if ( $product_categories_objects && ! empty( $product_categories_objects ) ) {
356
+ foreach ( $product_categories_objects as $product_categories_object ) {
357
+ if ( $array_to_include && in_array( $product_categories_object->term_id, $array_to_include ) ) {
358
+ $do_include = true;
359
+ break;
360
+ }
361
+ }
362
+ }
363
+ if ( ! $do_include ) {
364
+ return false;
365
+ }
366
+ }
367
+
368
+ // Include by product tag
369
+ $array_to_include = get_option( 'wcj_custom_product_tabs_local_show_in_tags_' . $custom_tab_index );
370
+ if ( '' != $array_to_include && ! empty( $array_to_include ) ) {
371
+ $do_include = false;
372
+ $product_tags_objects = get_the_terms( $product_id, 'product_tag' );
373
+ if ( $product_tags_objects && ! empty( $product_tags_objects ) ) {
374
+ foreach ( $product_tags_objects as $product_tags_object ) {
375
+ if ( $array_to_include && in_array( $product_tags_object->term_id, $array_to_include ) ) {
376
+ $do_include = true;
377
+ break;
378
+ }
379
+ }
380
+ }
381
+ if ( ! $do_include ) {
382
+ return false;
383
+ }
384
+ }
385
+
386
+ return true;
387
+ }
388
+
389
  /**
390
  * get_js_link_script.
391
  *
392
  * @version 2.8.0
393
  * @since 2.8.0
394
  */
395
+ function get_js_link_script( $link, $tab_key, $do_open_in_new_window ) {
396
  $link = do_shortcode( $link );
397
  $command = ( 'yes' === $do_open_in_new_window ) ?
398
  'window.open("' . $link . '","_blank");' :
399
  'window.location = "' . $link . '";';
400
  return '<script>' .
401
  'jQuery(document).ready(function() {
402
+ jQuery("li.' . $tab_key . '_tab").click(function(){
403
  ' . $command . '
404
  return false;
405
  });
410
  /**
411
  * maybe_add_js_links.
412
  *
413
+ * @version 3.1.0
414
  * @since 2.8.0
415
  */
416
  function maybe_add_js_links() {
420
  if ( $this->is_global_tab_visible( $i, $current_post_id ) ) {
421
  $key = 'global_' . $i;
422
  if ( '' != get_option( 'wcj_custom_product_tabs_title_' . $key, '' ) && '' != ( $link = get_option( 'wcj_custom_product_tabs_link_' . $key, '' ) ) ) {
423
+ echo $this->get_js_link_script( $link, $this->get_tab_key( $key, 'global' ), get_option( 'wcj_custom_product_tabs_link_new_tab_' . $key, true ) );
424
  }
425
  }
426
  }
436
  $key = 'local_' . $i;
437
  if ( '' != get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_title_' . $key, true ) ) {
438
  if ( '' != ( $link = get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_link_' . $key, true ) ) ) {
439
+ echo $this->get_js_link_script( $link, $this->get_tab_key( $key, 'local', $current_post_id ), get_post_meta( $current_post_id, '_' . 'wcj_custom_product_tabs_link_new_tab_' . $key, true ) );
440
  }
441
  }
442
  }
445
 
446
  /**
447
  * create_new_custom_product_tab_local.
448
+ *
449
+ * @version 3.1.0
450
+ * @todo (maybe) replace `the_content` with `do_shortcode`
451
  */
452
  function create_new_custom_product_tab_local( $key, $tab ) {
453
+ echo apply_filters( 'the_content', get_post_meta( get_the_ID(), '_' . 'wcj_custom_product_tabs_content_' . $this->tab_option_keys['local'][ $key ], true ) );
 
454
  }
455
 
456
  /**
457
  * create_new_custom_product_tab_global.
458
+ *
459
+ * @version 3.1.0
460
+ * @todo (maybe) replace `the_content` with `do_shortcode`
461
  */
462
  function create_new_custom_product_tab_global( $key, $tab ) {
463
+ echo apply_filters( 'the_content', get_option( 'wcj_custom_product_tabs_content_' . $this->tab_option_keys['global'][ $key ] ) );
464
  }
465
 
466
  /**
467
  * save_custom_tabs_meta_box.
468
  *
469
+ * @version 3.1.0
470
  * @todo rewrite as standard `WCJ_Module` function
471
  */
472
  function save_custom_tabs_meta_box( $post_id, $post ) {
475
  if ( ! isset( $_POST['woojetpack_custom_tabs_save_post'] ) )
476
  return;
477
 
478
+ // Save: title, priority, content etc.
479
  $option_names = array(
480
  'wcj_custom_product_tabs_title_local_',
481
+ 'wcj_custom_product_tabs_key_local_',
482
  'wcj_custom_product_tabs_priority_local_',
483
  'wcj_custom_product_tabs_content_local_',
484
  'wcj_custom_product_tabs_link_local_',
517
  );
518
  }
519
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
520
  /**
521
  * create_custom_tabs_meta_box.
522
  *
523
+ * @version 3.1.0
524
  */
525
  function create_custom_tabs_meta_box() {
526
 
555
  'title' => __( 'Title', 'woocommerce-jetpack' ),
556
  'type' => 'text',
557
  ),
558
+ array(
559
+ 'id' => 'wcj_custom_product_tabs_key_local_',
560
+ 'title' => __( 'Key', 'woocommerce-jetpack' ),
561
+ 'type' => 'text',
562
+ ),
563
  array(
564
  'id' => 'wcj_custom_product_tabs_priority_local_',
565
  'title' => __( 'Order', 'woocommerce-jetpack' ),
602
  if ( '' === $option_value && 'wcj_custom_product_tabs_priority_local_' === $option['id'] ) {
603
  $option_value = (50 + $i - 1);
604
  }
605
+ if ( '' === $option_value && 'wcj_custom_product_tabs_key_local_' === $option['id'] ) {
606
+ $option_value = 'local_' . $i;
607
+ }
608
  }
609
  switch ( $option['type'] ) {
610
  case 'select':
includes/class-wcj-wholesale-price.php CHANGED
@@ -2,10 +2,11 @@
2
  /**
3
  * Booster for WooCommerce - Module - Wholesale Price
4
  *
5
- * @version 2.8.0
6
  * @since 2.2.0
7
  * @author Algoritmika Ltd.
8
  * @todo per variation
 
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit;
@@ -167,7 +168,7 @@ class WCJ_Wholesale_Price extends WCJ_Module {
167
  /**
168
  * calculate_totals.
169
  *
170
- * @version 2.7.0
171
  * @since 2.5.0
172
  */
173
  function calculate_totals( $cart ) {
@@ -210,7 +211,7 @@ class WCJ_Wholesale_Price extends WCJ_Module {
210
  $the_quantity = ( 'yes' === get_option( 'wcj_wholesale_price_use_total_cart_quantity', 'no' ) )
211
  ? $cart->cart_contents_count
212
  : $item['quantity'];
213
- if ( $the_quantity > 1 ) {
214
  $wholesale_price = $this->get_wholesale_price( $price, $the_quantity, wcj_get_product_id_or_variation_parent_id( $_product ) );
215
  if ( $wholesale_price != $price ) {
216
  // Setting wholesale price
@@ -231,7 +232,8 @@ class WCJ_Wholesale_Price extends WCJ_Module {
231
  * @version 2.7.0
232
  */
233
  function wholesale_price( $price, $_product ) {
234
- return ( wcj_is_product_wholesale_enabled( wcj_get_product_id_or_variation_parent_id( $_product ) ) && isset( $_product->wcj_wholesale_price ) ) ? $_product->wcj_wholesale_price : $price;
 
235
  }
236
 
237
  }
2
  /**
3
  * Booster for WooCommerce - Module - Wholesale Price
4
  *
5
+ * @version 3.1.0
6
  * @since 2.2.0
7
  * @author Algoritmika Ltd.
8
  * @todo per variation
9
+ * @todo sort discounts table by quantity (asc) before using
10
  */
11
 
12
  if ( ! defined( 'ABSPATH' ) ) exit;
168
  /**
169
  * calculate_totals.
170
  *
171
+ * @version 3.1.0
172
  * @since 2.5.0
173
  */
174
  function calculate_totals( $cart ) {
211
  $the_quantity = ( 'yes' === get_option( 'wcj_wholesale_price_use_total_cart_quantity', 'no' ) )
212
  ? $cart->cart_contents_count
213
  : $item['quantity'];
214
+ if ( $the_quantity > 0 ) {
215
  $wholesale_price = $this->get_wholesale_price( $price, $the_quantity, wcj_get_product_id_or_variation_parent_id( $_product ) );
216
  if ( $wholesale_price != $price ) {
217
  // Setting wholesale price
232
  * @version 2.7.0
233
  */
234
  function wholesale_price( $price, $_product ) {
235
+ return ( wcj_is_product_wholesale_enabled( wcj_get_product_id_or_variation_parent_id( $_product ) ) && isset( $_product->wcj_wholesale_price ) ) ?
236
+ $_product->wcj_wholesale_price : $price;
237
  }
238
 
239
  }
includes/classes/class-wcj-pdf-invoice.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce PDF Invoice
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -22,7 +22,7 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
22
  /**
23
  * prepare_pdf.
24
  *
25
- * @version 2.9.0
26
  */
27
  function prepare_pdf() {
28
 
@@ -60,29 +60,29 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
60
  $pdf->SetKeywords( 'invoice, PDF' );
61
 
62
  // Header - set default header data
63
- if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type . '_header_enabled' ) ) {
64
  $the_logo = '';
65
  $the_logo_width_mm = 0;
66
- if ( '' != get_option( 'wcj_invoicing_' . $invoice_type . '_header_image' ) ) {
67
- $the_logo = parse_url( get_option( 'wcj_invoicing_' . $invoice_type . '_header_image' ), PHP_URL_PATH );
68
- $the_logo_width_mm = get_option( 'wcj_invoicing_' . $invoice_type . '_header_image_width_mm' );
69
  }
70
  $pdf->SetHeaderData(
71
  $the_logo,
72
  $the_logo_width_mm,
73
- do_shortcode( get_option( 'wcj_invoicing_' . $invoice_type . '_header_title_text' ) ),
74
- do_shortcode( get_option( 'wcj_invoicing_' . $invoice_type . '_header_text' ) ),
75
- wcj_hex2rgb( get_option( 'wcj_invoicing_' . $invoice_type . '_header_text_color' ) ),
76
- wcj_hex2rgb( get_option( 'wcj_invoicing_' . $invoice_type . '_header_line_color' ) ) );
77
  } else {
78
  $pdf->SetPrintHeader( false );
79
  }
80
 
81
  // Footer
82
- if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type . '_footer_enabled' ) ) {
83
  $pdf->setFooterData(
84
- wcj_hex2rgb( get_option( 'wcj_invoicing_' . $invoice_type . '_footer_text_color' ) ),
85
- wcj_hex2rgb( get_option( 'wcj_invoicing_' . $invoice_type . '_footer_line_color' ) )
86
  );
87
  } else {
88
  $pdf->SetPrintFooter( false );
@@ -99,15 +99,15 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
99
 
100
  // Set margins
101
  $pdf->SetMargins(
102
- get_option( 'wcj_invoicing_' . $invoice_type . '_margin_left' ),
103
- get_option( 'wcj_invoicing_' . $invoice_type . '_margin_top' ),
104
- get_option( 'wcj_invoicing_' . $invoice_type . '_margin_right' )
105
  );
106
- $pdf->SetHeaderMargin( get_option( 'wcj_invoicing_' . $invoice_type . '_margin_header' ) );
107
- $pdf->SetFooterMargin( get_option( 'wcj_invoicing_' . $invoice_type . '_margin_footer' ) );
108
 
109
  // Set auto page breaks
110
- $pdf->SetAutoPageBreak( TRUE, get_option( 'wcj_invoicing_' . $invoice_type . '_margin_bottom' ) );
111
 
112
  // Set image scale factor
113
  $pdf->setImageScale( PDF_IMAGE_SCALE_RATIO );
@@ -131,7 +131,7 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
131
  $pdf->AddPage();
132
 
133
  // Set text shadow effect
134
- if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type . '_general_font_shadowed', 'yes' ) ) {
135
  $pdf->setTextShadow( array( 'enabled' => true, 'depth_w' => 0.2, 'depth_h' => 0.2, 'color' => array( 196, 196, 196 ), 'opacity' => 1, 'blend_mode' => 'Normal' ) );
136
  }
137
 
@@ -141,7 +141,7 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
141
  /**
142
  * get_pdf.
143
  *
144
- * @version 2.8.0
145
  * @todo pass other params (billing_country, payment_method) as global (same as user_id) instead of $_GET
146
  */
147
  function get_pdf( $dest ) {
@@ -159,10 +159,11 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
159
  if ( ! isset( $wcj_pdf_invoice_data['user_id'] ) ) {
160
  $wcj_pdf_invoice_data['user_id'] = ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_order->customer_user : $the_order->get_customer_id() );
161
  }
162
- $html = do_shortcode( get_option( 'wcj_invoicing_' . $this->invoice_type . '_template' ) );
 
163
  $html = force_balance_tags( $html );
164
- //$html = apply_filters( 'the_content', get_option( 'wcj_invoicing_' . $this->invoice_type . '_template' ) );
165
- $styling = '<style>' . get_option( 'wcj_invoicing_' . $this->invoice_type . '_css' ) . '</style>';
166
 
167
  $pdf = $this->prepare_pdf();
168
  // Print text using writeHTMLCell()
2
  /**
3
  * Booster for WooCommerce PDF Invoice
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
22
  /**
23
  * prepare_pdf.
24
  *
25
+ * @version 3.1.0
26
  */
27
  function prepare_pdf() {
28
 
60
  $pdf->SetKeywords( 'invoice, PDF' );
61
 
62
  // Header - set default header data
63
+ if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type . '_header_enabled', 'yes' ) ) {
64
  $the_logo = '';
65
  $the_logo_width_mm = 0;
66
+ if ( '' != get_option( 'wcj_invoicing_' . $invoice_type . '_header_image', '' ) ) {
67
+ $the_logo = parse_url( get_option( 'wcj_invoicing_' . $invoice_type . '_header_image', '' ), PHP_URL_PATH );
68
+ $the_logo_width_mm = get_option( 'wcj_invoicing_' . $invoice_type . '_header_image_width_mm', 50 );
69
  }
70
  $pdf->SetHeaderData(
71
  $the_logo,
72
  $the_logo_width_mm,
73
+ do_shortcode( get_option( 'wcj_invoicing_' . $invoice_type . '_header_title_text', $invoice_title ) ),
74
+ do_shortcode( get_option( 'wcj_invoicing_' . $invoice_type . '_header_text', __( 'Company Name', 'woocommerce-jetpack' ) ) ),
75
+ wcj_hex2rgb( get_option( 'wcj_invoicing_' . $invoice_type . '_header_text_color', '#cccccc' ) ),
76
+ wcj_hex2rgb( get_option( 'wcj_invoicing_' . $invoice_type . '_header_line_color', '#cccccc' ) ) );
77
  } else {
78
  $pdf->SetPrintHeader( false );
79
  }
80
 
81
  // Footer
82
+ if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type . '_footer_enabled', 'yes' ) ) {
83
  $pdf->setFooterData(
84
+ wcj_hex2rgb( get_option( 'wcj_invoicing_' . $invoice_type . '_footer_text_color', '#cccccc' ) ),
85
+ wcj_hex2rgb( get_option( 'wcj_invoicing_' . $invoice_type . '_footer_line_color', '#cccccc' ) )
86
  );
87
  } else {
88
  $pdf->SetPrintFooter( false );
99
 
100
  // Set margins
101
  $pdf->SetMargins(
102
+ get_option( 'wcj_invoicing_' . $invoice_type . '_margin_left', 15 ),
103
+ get_option( 'wcj_invoicing_' . $invoice_type . '_margin_top', 27 ),
104
+ get_option( 'wcj_invoicing_' . $invoice_type . '_margin_right', 15 )
105
  );
106
+ $pdf->SetHeaderMargin( get_option( 'wcj_invoicing_' . $invoice_type . '_margin_header', 10 ) );
107
+ $pdf->SetFooterMargin( get_option( 'wcj_invoicing_' . $invoice_type . '_margin_footer', 10 ) );
108
 
109
  // Set auto page breaks
110
+ $pdf->SetAutoPageBreak( TRUE, get_option( 'wcj_invoicing_' . $invoice_type . '_margin_bottom', 0 ) );
111
 
112
  // Set image scale factor
113
  $pdf->setImageScale( PDF_IMAGE_SCALE_RATIO );
131
  $pdf->AddPage();
132
 
133
  // Set text shadow effect
134
+ if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type . '_general_font_shadowed', 'no' ) ) {
135
  $pdf->setTextShadow( array( 'enabled' => true, 'depth_w' => 0.2, 'depth_h' => 0.2, 'color' => array( 196, 196, 196 ), 'opacity' => 1, 'blend_mode' => 'Normal' ) );
136
  }
137
 
141
  /**
142
  * get_pdf.
143
  *
144
+ * @version 3.1.0
145
  * @todo pass other params (billing_country, payment_method) as global (same as user_id) instead of $_GET
146
  */
147
  function get_pdf( $dest ) {
159
  if ( ! isset( $wcj_pdf_invoice_data['user_id'] ) ) {
160
  $wcj_pdf_invoice_data['user_id'] = ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_order->customer_user : $the_order->get_customer_id() );
161
  }
162
+ $html = do_shortcode( get_option( 'wcj_invoicing_' . $this->invoice_type . '_template',
163
+ WCJ()->modules['pdf_invoicing_templates']->get_default_template( $this->invoice_type ) ) );
164
  $html = force_balance_tags( $html );
165
+ $styling = '<style>' . get_option( 'wcj_invoicing_' . $this->invoice_type . '_css',
166
+ WCJ()->modules['pdf_invoicing_styling']->get_default_css_template( $this->invoice_type ) ) . '</style>';
167
 
168
  $pdf = $this->prepare_pdf();
169
  // Print text using writeHTMLCell()
includes/constants/wcj-constants.php CHANGED
@@ -2,36 +2,75 @@
2
  /**
3
  * Booster for WooCommerce Constants
4
  *
5
- * @version 2.7.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
- // WooCommerce version
13
-
14
  if ( ! defined( 'WCJ_WC_VERSION' ) ) {
 
 
 
 
 
 
 
15
  define( 'WCJ_WC_VERSION', get_option( 'woocommerce_version', null ) );
16
  }
17
 
18
  if ( ! defined( 'WCJ_IS_WC_VERSION_BELOW_3' ) ) {
 
 
 
 
 
 
 
19
  define( 'WCJ_IS_WC_VERSION_BELOW_3', version_compare( WCJ_WC_VERSION, '3.0.0', '<' ) );
20
  }
21
 
22
- // Price filters
23
-
24
  if ( ! defined( 'WCJ_PRODUCT_GET_PRICE_FILTER' ) ) {
25
- $filter = ( WCJ_IS_WC_VERSION_BELOW_3 ) ? 'woocommerce_get_price' : 'woocommerce_product_get_price';
26
- define( 'WCJ_PRODUCT_GET_PRICE_FILTER', $filter );
 
 
 
 
 
 
27
  }
28
 
29
  if ( ! defined( 'WCJ_PRODUCT_GET_SALE_PRICE_FILTER' ) ) {
30
- $filter = ( WCJ_IS_WC_VERSION_BELOW_3 ) ? 'woocommerce_get_sale_price' : 'woocommerce_product_get_sale_price';
31
- define( 'WCJ_PRODUCT_GET_SALE_PRICE_FILTER', $filter );
 
 
 
 
 
 
32
  }
33
 
34
  if ( ! defined( 'WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER' ) ) {
35
- $filter = ( WCJ_IS_WC_VERSION_BELOW_3 ) ? 'woocommerce_get_regular_price' : 'woocommerce_product_get_regular_price';
36
- define( 'WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER', $filter );
37
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2
  /**
3
  * Booster for WooCommerce Constants
4
  *
5
+ * @version 3.1.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
 
 
12
  if ( ! defined( 'WCJ_WC_VERSION' ) ) {
13
+ /**
14
+ * WooCommerce version.
15
+ *
16
+ * @version 2.7.0
17
+ * @since 2.7.0
18
+ * @author Algoritmika Ltd.
19
+ */
20
  define( 'WCJ_WC_VERSION', get_option( 'woocommerce_version', null ) );
21
  }
22
 
23
  if ( ! defined( 'WCJ_IS_WC_VERSION_BELOW_3' ) ) {
24
+ /**
25
+ * WooCommerce version - is below version 3.
26
+ *
27
+ * @version 2.7.0
28
+ * @since 2.7.0
29
+ * @author Algoritmika Ltd.
30
+ */
31
  define( 'WCJ_IS_WC_VERSION_BELOW_3', version_compare( WCJ_WC_VERSION, '3.0.0', '<' ) );
32
  }
33
 
 
 
34
  if ( ! defined( 'WCJ_PRODUCT_GET_PRICE_FILTER' ) ) {
35
+ /**
36
+ * Price filters - price.
37
+ *
38
+ * @version 2.7.0
39
+ * @since 2.7.0
40
+ * @author Algoritmika Ltd.
41
+ */
42
+ define( 'WCJ_PRODUCT_GET_PRICE_FILTER', ( WCJ_IS_WC_VERSION_BELOW_3 ? 'woocommerce_get_price' : 'woocommerce_product_get_price' ) );
43
  }
44
 
45
  if ( ! defined( 'WCJ_PRODUCT_GET_SALE_PRICE_FILTER' ) ) {
46
+ /**
47
+ * Price filters - sale price.
48
+ *
49
+ * @version 2.7.0
50
+ * @since 2.7.0
51
+ * @author Algoritmika Ltd.
52
+ */
53
+ define( 'WCJ_PRODUCT_GET_SALE_PRICE_FILTER', ( WCJ_IS_WC_VERSION_BELOW_3 ? 'woocommerce_get_sale_price' : 'woocommerce_product_get_sale_price' ) );
54
  }
55
 
56
  if ( ! defined( 'WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER' ) ) {
57
+ /**
58
+ * Price filters - regular price.
59
+ *
60
+ * @version 2.7.0
61
+ * @since 2.7.0
62
+ * @author Algoritmika Ltd.
63
+ */
64
+ define( 'WCJ_PRODUCT_GET_REGULAR_PRICE_FILTER', ( WCJ_IS_WC_VERSION_BELOW_3 ? 'woocommerce_get_regular_price' : 'woocommerce_product_get_regular_price' ) );
65
+ }
66
+
67
+ if ( ! defined( 'WCJ_SESSION_TYPE' ) ) {
68
+ /**
69
+ * Session type.
70
+ *
71
+ * @version 3.1.0
72
+ * @since 3.1.0
73
+ * @author Algoritmika Ltd.
74
+ */
75
+ define( 'WCJ_SESSION_TYPE', ( 'yes' === get_option( 'wcj_general_enabled', 'no' ) ? get_option( 'wcj_general_advanced_session_type', 'standard' ) : 'standard' ) );
76
+ }
includes/emails/class-wc-email-wcj-custom.php CHANGED
@@ -1,21 +1,21 @@
1
  <?php
2
-
3
- if ( ! defined( 'ABSPATH' ) ) {
4
- exit; // Exit if accessed directly
5
- }
6
-
7
- if ( ! class_exists( 'WC_Email_WCJ_Custom' ) ) :
8
-
9
  /**
10
- * Custom Email
11
  *
12
  * An email sent to recipient list when selected triggers are called.
13
  *
14
- * @version 2.5.6
15
  * @since 2.3.9
16
  * @author Algoritmika Ltd.
17
  * @extends WC_Email
18
  */
 
 
 
 
 
 
 
19
  class WC_Email_WCJ_Custom extends WC_Email {
20
 
21
  /**
@@ -33,9 +33,6 @@ class WC_Email_WCJ_Custom extends WC_Email {
33
  $this->heading = __( 'Custom Heading', 'woocommerce' );
34
  $this->subject = __( '[{site_title}] Custom Subject - Order ({order_number}) - {order_date}', 'woocommerce-jetpack' );
35
 
36
- /* $this->template_html = 'emails/admin-new-order.php';
37
- $this->template_plain = 'emails/plain/admin-new-order.php'; */
38
-
39
  // Triggers for this email
40
  $trigger_hooks = $this->get_option( 'trigger' );
41
  if ( ! empty( $trigger_hooks ) && is_array( $trigger_hooks ) ) {
@@ -73,14 +70,6 @@ class WC_Email_WCJ_Custom extends WC_Email {
73
  */
74
  function validate_custom_textarea_field( $key, $value ) {
75
  $value = is_null( $value ) ? '' : $value;
76
- /* return wp_kses( trim( stripslashes( $value ) ),
77
- array_merge(
78
- array(
79
- 'iframe' => array( 'src' => true, 'style' => true, 'id' => true, 'class' => true )
80
- ),
81
- wp_kses_allowed_html( 'post' )
82
- )
83
- ); */
84
  return stripslashes( $value );
85
  }
86
 
@@ -113,33 +102,31 @@ class WC_Email_WCJ_Custom extends WC_Email {
113
  }
114
 
115
  /**
116
- * Trigger.
117
  *
118
- * @version 2.5.6
119
- * @todo WC3 compatibility
120
  */
121
  function trigger( $order_id ) {
122
 
123
- if ( ! $this->is_enabled() /* || ! $this->get_recipient() */ ) {
124
  return;
125
  }
126
 
127
  if ( $order_id ) {
128
 
129
- $this->object = wc_get_order( $order_id );
130
 
131
  if ( $this->customer_email ) {
132
- $this->recipient = $this->object->billing_email;
133
  }
134
 
135
  $this->find['order-date'] = '{order_date}';
136
  $this->find['order-number'] = '{order_number}';
137
 
138
- $this->replace['order-date'] = date_i18n( wc_date_format(), strtotime( $this->object->order_date ) );
139
- $this->replace['order-number'] = $this->object->get_order_number();
140
 
141
  global $post;
142
- $order = wc_get_order( $order_id );
143
  if ( 'woocommerce_checkout_order_processed_notification' === current_filter() ) {
144
  // Check status
145
  $is_status_found = false;
@@ -157,7 +144,7 @@ class WC_Email_WCJ_Custom extends WC_Email {
157
  return;
158
  }
159
  }
160
- $post = $order->post;
161
  setup_postdata( $post );
162
  }
163
 
@@ -178,62 +165,37 @@ class WC_Email_WCJ_Custom extends WC_Email {
178
  }
179
 
180
  /**
181
- * get_content_html function.
182
  *
183
- * @version 2.4.8
184
  * @access public
185
  * @return string
 
186
  */
187
  function get_content_html() {
188
- /* ob_start();
189
- wc_get_template( $this->template_html, array(
190
- 'order' => $this->object,
191
- 'email_heading' => $this->get_heading(),
192
- 'sent_to_admin' => true,
193
- 'plain_text' => false
194
- ), '', wcj_plugin_path() . '/templates' );
195
- return ob_get_clean(); */
196
- return do_shortcode( $this->get_option( 'content_html_template' ) );
197
  }
198
 
199
  /**
200
- * get_content_plain function.
201
  *
202
  * @version 2.4.8
203
  * @access public
204
  * @return string
205
  */
206
  function get_content_plain() {
207
- /* ob_start();
208
- wc_get_template( $this->template_plain, array(
209
- 'order' => $this->object,
210
- 'email_heading' => $this->get_heading(),
211
- 'sent_to_admin' => true,
212
- 'plain_text' => true
213
- ), '', wcj_plugin_path() . '/templates' );
214
- return ob_get_clean(); */
215
  return do_shortcode( $this->get_option( 'content_plain_template' ) );
216
  }
217
 
218
  /**
219
- * get_order_statuses.
220
- *
221
- * @version 2.4.0
222
- * @since 2.4.0
223
- */
224
- function get_order_statuses() {
225
- $result = array();
226
- $statuses = function_exists( 'wc_get_order_statuses' ) ? wc_get_order_statuses() : array();
227
- foreach( $statuses as $status => $status_name ) {
228
- $result[ substr( $status, 3 ) ] = $statuses[ $status ];
229
- }
230
- return $result;
231
- }
232
-
233
- /**
234
- * Initialise settings form fields
235
  *
236
- * @version 2.5.6
 
237
  */
238
  function init_form_fields() {
239
 
@@ -245,9 +207,9 @@ class WC_Email_WCJ_Custom extends WC_Email {
245
  $default_plain_template = ob_get_clean();
246
 
247
  $status_change_triggers = array();
248
- $new_order_triggers = array();
249
- $status_triggers = array();
250
- $order_statuses = $this->get_order_statuses();
251
  foreach ( $order_statuses as $slug => $name ) {
252
  $new_order_triggers[ 'woocommerce_new_order_notification_' . $slug ] = sprintf( __( 'New order (%s)', 'woocommerce-jetpack' ), $name );
253
  $status_triggers[ 'woocommerce_order_status_' . $slug . '_notification' ] = sprintf( __( 'Order status updated to %s', 'woocommerce-jetpack' ), $name );
@@ -290,14 +252,15 @@ class WC_Email_WCJ_Custom extends WC_Email {
290
  $status_change_triggers
291
  ),
292
  'css' => 'height:300px;',
293
- // 'class' => 'chosen_select',
294
  ),
295
  'recipient' => array(
296
  'title' => __( 'Recipient(s)', 'woocommerce' ),
297
  'type' => 'text',
298
- 'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to <code>%s</code>.', 'woocommerce' ), esc_attr( get_option('admin_email') ) ) . ' ' . __( 'Or enter <code>%customer%</code> to send to customer billing email.', 'woocommerce-jetpack' ),
 
299
  'placeholder' => '',
300
  'default' => '',
 
301
  ),
302
  'subject' => array(
303
  'title' => __( 'Subject', 'woocommerce' ),
@@ -305,13 +268,7 @@ class WC_Email_WCJ_Custom extends WC_Email {
305
  'description' => sprintf( __( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', 'woocommerce' ), $this->subject ),
306
  'placeholder' => '',
307
  'default' => '',
308
- ),
309
- 'heading' => array(
310
- 'title' => __( 'Email Heading', 'woocommerce' ),
311
- 'type' => 'text',
312
- 'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.', 'woocommerce' ), $this->heading ),
313
- 'placeholder' => '',
314
- 'default' => '',
315
  ),
316
  'email_type' => array(
317
  'title' => __( 'Email type', 'woocommerce' ),
@@ -321,6 +278,19 @@ class WC_Email_WCJ_Custom extends WC_Email {
321
  'class' => 'email_type wc-enhanced-select',
322
  'options' => $this->get_email_type_options(),
323
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
324
  'content_html_template' => array(
325
  'title' => __( 'HTML template', 'woocommerce' ),
326
  'type' => 'custom_textarea',
@@ -328,7 +298,7 @@ class WC_Email_WCJ_Custom extends WC_Email {
328
  'description' => '',
329
  'placeholder' => '',
330
  'default' => $default_html_template,
331
- 'css' => 'width:66%;min-width:300px;height:500px;',
332
  ),
333
  'content_plain_template' => array(
334
  'title' => __( 'Plain text template', 'woocommerce' ),
@@ -337,12 +307,10 @@ class WC_Email_WCJ_Custom extends WC_Email {
337
  'description' => '',
338
  'placeholder' => '',
339
  'default' => $default_plain_template,
340
- 'css' => 'width:66%;min-width:300px;height:500px;',
341
  ),
342
  );
343
  }
344
  }
345
 
346
  endif;
347
-
348
- //return new WC_Email_WCJ_Custom();
1
  <?php
 
 
 
 
 
 
 
2
  /**
3
+ * Booster for WooCommerce - Custom Email
4
  *
5
  * An email sent to recipient list when selected triggers are called.
6
  *
7
+ * @version 3.1.0
8
  * @since 2.3.9
9
  * @author Algoritmika Ltd.
10
  * @extends WC_Email
11
  */
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) {
14
+ exit; // Exit if accessed directly
15
+ }
16
+
17
+ if ( ! class_exists( 'WC_Email_WCJ_Custom' ) ) :
18
+
19
  class WC_Email_WCJ_Custom extends WC_Email {
20
 
21
  /**
33
  $this->heading = __( 'Custom Heading', 'woocommerce' );
34
  $this->subject = __( '[{site_title}] Custom Subject - Order ({order_number}) - {order_date}', 'woocommerce-jetpack' );
35
 
 
 
 
36
  // Triggers for this email
37
  $trigger_hooks = $this->get_option( 'trigger' );
38
  if ( ! empty( $trigger_hooks ) && is_array( $trigger_hooks ) ) {
70
  */
71
  function validate_custom_textarea_field( $key, $value ) {
72
  $value = is_null( $value ) ? '' : $value;
 
 
 
 
 
 
 
 
73
  return stripslashes( $value );
74
  }
75
 
102
  }
103
 
104
  /**
105
+ * trigger.
106
  *
107
+ * @version 3.1.0
 
108
  */
109
  function trigger( $order_id ) {
110
 
111
+ if ( ! $this->is_enabled() ) {
112
  return;
113
  }
114
 
115
  if ( $order_id ) {
116
 
117
+ $order = wc_get_order( $order_id );
118
 
119
  if ( $this->customer_email ) {
120
+ $this->recipient = wcj_get_order_billing_email( $order );
121
  }
122
 
123
  $this->find['order-date'] = '{order_date}';
124
  $this->find['order-number'] = '{order_number}';
125
 
126
+ $this->replace['order-date'] = date_i18n( wc_date_format(), strtotime( wcj_get_order_date( $order ) ) );
127
+ $this->replace['order-number'] = $order->get_order_number();
128
 
129
  global $post;
 
130
  if ( 'woocommerce_checkout_order_processed_notification' === current_filter() ) {
131
  // Check status
132
  $is_status_found = false;
144
  return;
145
  }
146
  }
147
+ $post = ( WCJ_IS_WC_VERSION_BELOW_3 ? $order->post : get_post( $order_id ) );
148
  setup_postdata( $post );
149
  }
150
 
165
  }
166
 
167
  /**
168
+ * get_content_html.
169
  *
170
+ * @version 3.1.0
171
  * @access public
172
  * @return string
173
+ * @todo (maybe) use `wc_get_template` for custom templates (same for `get_content_plain()`)
174
  */
175
  function get_content_html() {
176
+ $content = $this->get_option( 'content_html_template' );
177
+ if ( 'yes' === $this->get_option( 'wrap_in_wc_template' ) ) {
178
+ $content = wcj_wrap_in_wc_email_template( $content, $this->get_heading() );
179
+ }
180
+ return do_shortcode( $content );
 
 
 
 
181
  }
182
 
183
  /**
184
+ * get_content_plain.
185
  *
186
  * @version 2.4.8
187
  * @access public
188
  * @return string
189
  */
190
  function get_content_plain() {
 
 
 
 
 
 
 
 
191
  return do_shortcode( $this->get_option( 'content_plain_template' ) );
192
  }
193
 
194
  /**
195
+ * Initialise settings form fields.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  *
197
+ * @version 3.1.0
198
+ * @todo (maybe) `chosen_select` class in `trigger`
199
  */
200
  function init_form_fields() {
201
 
207
  $default_plain_template = ob_get_clean();
208
 
209
  $status_change_triggers = array();
210
+ $new_order_triggers = array();
211
+ $status_triggers = array();
212
+ $order_statuses = wcj_get_order_statuses_v2();
213
  foreach ( $order_statuses as $slug => $name ) {
214
  $new_order_triggers[ 'woocommerce_new_order_notification_' . $slug ] = sprintf( __( 'New order (%s)', 'woocommerce-jetpack' ), $name );
215
  $status_triggers[ 'woocommerce_order_status_' . $slug . '_notification' ] = sprintf( __( 'Order status updated to %s', 'woocommerce-jetpack' ), $name );
252
  $status_change_triggers
253
  ),
254
  'css' => 'height:300px;',
 
255
  ),
256
  'recipient' => array(
257
  'title' => __( 'Recipient(s)', 'woocommerce' ),
258
  'type' => 'text',
259
+ 'description' => sprintf( __( 'Enter recipients (comma separated) for this email. Defaults to <code>%s</code>.', 'woocommerce' ), esc_attr( get_option( 'admin_email' ) ) ) . ' ' .
260
+ __( 'Or enter <code>%customer%</code> to send to customer billing email.', 'woocommerce-jetpack' ),
261
  'placeholder' => '',
262
  'default' => '',
263
+ 'css' => 'width:99%;min-width:300px;',
264
  ),
265
  'subject' => array(
266
  'title' => __( 'Subject', 'woocommerce' ),
268
  'description' => sprintf( __( 'This controls the email subject line. Leave blank to use the default subject: <code>%s</code>.', 'woocommerce' ), $this->subject ),
269
  'placeholder' => '',
270
  'default' => '',
271
+ 'css' => 'width:99%;min-width:300px;',
 
 
 
 
 
 
272
  ),
273
  'email_type' => array(
274
  'title' => __( 'Email type', 'woocommerce' ),
278
  'class' => 'email_type wc-enhanced-select',
279
  'options' => $this->get_email_type_options(),
280
  ),
281
+ 'wrap_in_wc_template' => array(
282
+ 'title' => __( 'Wrap in WC Email Template', 'woocommerce' ),
283
+ 'type' => 'checkbox',
284
+ 'default' => 'no',
285
+ ),
286
+ 'heading' => array(
287
+ 'type' => 'text',
288
+ 'desc_tip' =>__( 'WC Email Heading. Used only if "Wrap in WC Email Template" is enabled and only for HTML templates.', 'woocommerce-jetpack' ),
289
+ 'description' => sprintf( __( 'This controls the main heading contained within the email notification. Leave blank to use the default heading: <code>%s</code>.', 'woocommerce' ), $this->heading ),
290
+ 'placeholder' => '',
291
+ 'default' => '',
292
+ 'css' => 'width:99%;min-width:300px;',
293
+ ),
294
  'content_html_template' => array(
295
  'title' => __( 'HTML template', 'woocommerce' ),
296
  'type' => 'custom_textarea',
298
  'description' => '',
299
  'placeholder' => '',
300
  'default' => $default_html_template,
301
+ 'css' => 'width:99%;min-width:300px;height:500px;',
302
  ),
303
  'content_plain_template' => array(
304
  'title' => __( 'Plain text template', 'woocommerce' ),
307
  'description' => '',
308
  'placeholder' => '',
309
  'default' => $default_plain_template,
310
+ 'css' => 'width:99%;min-width:300px;height:500px;',
311
  ),
312
  );
313
  }
314
  }
315
 
316
  endif;
 
 
includes/export/class-wcj-exporter-customers.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce Exporter Customers
4
  *
5
- * @version 3.0.0
6
  * @since 2.5.9
7
  * @author Algoritmika Ltd.
8
  */
@@ -89,7 +89,7 @@ class WCJ_Exporter_Customers {
89
  /**
90
  * export_customers_from_orders.
91
  *
92
- * @version 3.0.0
93
  * @since 2.4.8
94
  * @todo (maybe) add more order fields (shipping)
95
  */
@@ -127,7 +127,7 @@ class WCJ_Exporter_Customers {
127
  }
128
  foreach ( $loop_orders->posts as $order_id ) {
129
  $order = wc_get_order( $order_id );
130
- $_billing_email = ( WCJ_IS_WC_VERSION_BELOW_3 ? $order->billing_email : $order->get_billing_email() );
131
  if ( isset( $_billing_email ) && '' != $_billing_email && ! in_array( $_billing_email, $orders ) ) {
132
  $emails_to_skip = array(); // `emails_to_skip` is not really used...
133
  if ( ! in_array( $_billing_email, $emails_to_skip ) ) {
2
  /**
3
  * Booster for WooCommerce Exporter Customers
4
  *
5
+ * @version 3.1.0
6
  * @since 2.5.9
7
  * @author Algoritmika Ltd.
8
  */
89
  /**
90
  * export_customers_from_orders.
91
  *
92
+ * @version 3.1.0
93
  * @since 2.4.8
94
  * @todo (maybe) add more order fields (shipping)
95
  */
127
  }
128
  foreach ( $loop_orders->posts as $order_id ) {
129
  $order = wc_get_order( $order_id );
130
+ $_billing_email = wcj_get_order_billing_email( $order );
131
  if ( isset( $_billing_email ) && '' != $_billing_email && ! in_array( $_billing_email, $orders ) ) {
132
  $emails_to_skip = array(); // `emails_to_skip` is not really used...
133
  if ( ! in_array( $_billing_email, $emails_to_skip ) ) {
includes/functions/wcj-admin-functions.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Admin
4
  *
5
- * @version 2.9.1
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -13,10 +13,11 @@ if ( ! function_exists( 'wcj_get_settings_as_multiselect_or_text' ) ) {
13
  /**
14
  * wcj_get_settings_as_multiselect_or_text.
15
  *
16
- * @version 2.9.1
17
  * @since 2.9.1
18
  */
19
  function wcj_get_settings_as_multiselect_or_text( $values, $multiselect_options, $is_multiselect ) {
 
20
  return ( $is_multiselect ?
21
  array_merge( $values, array(
22
  'type' => 'multiselect',
@@ -25,7 +26,7 @@ if ( ! function_exists( 'wcj_get_settings_as_multiselect_or_text' ) ) {
25
  ) ) :
26
  array_merge( $values, array(
27
  'type' => 'text',
28
- 'desc' => __( 'Enter comma separated list of IDs.', 'woocommerce-jetpack' ),
29
  ) )
30
  );
31
  }
2
  /**
3
  * Booster for WooCommerce - Functions - Admin
4
  *
5
+ * @version 3.1.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
13
  /**
14
  * wcj_get_settings_as_multiselect_or_text.
15
  *
16
+ * @version 3.1.0
17
  * @since 2.9.1
18
  */
19
  function wcj_get_settings_as_multiselect_or_text( $values, $multiselect_options, $is_multiselect ) {
20
+ $prev_desc = ( isset( $values['desc'] ) ? $values['desc'] . ' ' : '' );
21
  return ( $is_multiselect ?
22
  array_merge( $values, array(
23
  'type' => 'multiselect',
26
  ) ) :
27
  array_merge( $values, array(
28
  'type' => 'text',
29
+ 'desc' => $prev_desc . __( 'Enter comma separated list of IDs.', 'woocommerce-jetpack' ),
30
  ) )
31
  );
32
  }
includes/functions/wcj-country-functions.php CHANGED
@@ -2,10 +2,28 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Country
4
  *
5
- * @version 2.9.1
6
  * @author Algoritmika Ltd.
7
  */
8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  if ( ! function_exists( 'wcj_get_country_flag_by_code' ) ) {
10
  /**
11
  * wcj_get_country_flag_by_code.
@@ -40,7 +58,7 @@ if ( ! function_exists( 'wcj_get_european_union_countries_with_vat' ) ) {
40
  * wcj_get_european_union_countries_with_vat.
41
  *
42
  * @version 2.4.0
43
- * @return array
44
  */
45
  function wcj_get_european_union_countries_with_vat() {
46
  return array(
@@ -79,6 +97,18 @@ if ( ! function_exists( 'wcj_get_european_union_countries_with_vat' ) ) {
79
  }
80
  }
81
 
 
 
 
 
 
 
 
 
 
 
 
 
82
  if ( ! function_exists( 'wcj_get_country_name_by_code' ) ) {
83
  /**
84
  * Get country name by country code.
2
  /**
3
  * Booster for WooCommerce - Functions - Country
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
9
+ if ( ! function_exists( 'wcj_get_country_by_ip' ) ) {
10
+ /**
11
+ * wcj_get_country_by_ip.
12
+ *
13
+ * @version 3.1.0
14
+ * @since 3.1.0
15
+ */
16
+ function wcj_get_country_by_ip() {
17
+ // Get the country by IP
18
+ $location = ( class_exists( 'WC_Geolocation' ) ? WC_Geolocation::geolocate_ip() : array( 'country' => '' ) );
19
+ // Base fallback
20
+ if ( empty( $location['country'] ) ) {
21
+ $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
22
+ }
23
+ return ( isset( $location['country'] ) ) ? $location['country'] : '';
24
+ }
25
+ }
26
+
27
  if ( ! function_exists( 'wcj_get_country_flag_by_code' ) ) {
28
  /**
29
  * wcj_get_country_flag_by_code.
58
  * wcj_get_european_union_countries_with_vat.
59
  *
60
  * @version 2.4.0
61
+ * @return array
62
  */
63
  function wcj_get_european_union_countries_with_vat() {
64
  return array(
97
  }
98
  }
99
 
100
+ if ( ! function_exists( 'wcj_get_european_union_countries' ) ) {
101
+ /**
102
+ * wcj_get_european_union_countries.
103
+ *
104
+ * @version 3.1.0
105
+ * @since 3.1.0
106
+ */
107
+ function wcj_get_european_union_countries() {
108
+ return array_keys( wcj_get_european_union_countries_with_vat() );
109
+ }
110
+ }
111
+
112
  if ( ! function_exists( 'wcj_get_country_name_by_code' ) ) {
113
  /**
114
  * Get country name by country code.
includes/functions/wcj-general-functions.php CHANGED
@@ -2,12 +2,104 @@
2
  /**
3
  * Booster for WooCommerce - Functions
4
  *
5
- * @version 3.0.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
9
  if ( ! defined( 'ABSPATH' ) ) exit;
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  if ( ! function_exists( 'wcj_maybe_add_date_query' ) ) {
12
  /**
13
  * wcj_maybe_add_date_query.
@@ -100,57 +192,79 @@ if ( ! function_exists( 'wcj_add_files_upload_form_to_checkout_frontend' ) ) {
100
  }
101
  }
102
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  if ( ! function_exists( 'wcj_variation_radio_button' ) ) {
104
  /**
105
  * wcj_variation_radio_button.
106
  *
107
- * @version 2.5.0
108
  * @since 2.4.8
 
109
  */
110
  function wcj_variation_radio_button( $_product, $variation ) {
111
- $attributes_html = '';
112
  $variation_attributes_display_values = array();
113
- $is_checked = true;
114
  foreach ( $variation['attributes'] as $attribute_full_name => $attribute_value ) {
115
-
116
  $attributes_html .= ' ' . $attribute_full_name . '="' . $attribute_value . '"';
117
-
118
  $attribute_name = $attribute_full_name;
119
- $prefix = 'attribute_';
120
  if ( substr( $attribute_full_name, 0, strlen( $prefix ) ) === $prefix ) {
121
  $attribute_name = substr( $attribute_full_name, strlen( $prefix ) );
122
  }
123
-
124
- $checked = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ? wc_clean( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) : $_product->get_variation_default_attribute( $attribute_name );
125
- if ( $checked != $attribute_value ) $is_checked = false;
126
-
 
 
 
127
  $terms = get_terms( $attribute_name );
128
  foreach ( $terms as $term ) {
129
  if ( is_object( $term ) && isset( $term->slug ) && $term->slug === $attribute_value && isset( $term->name ) ) {
130
  $attribute_value = $term->name;
131
  }
132
  }
133
-
134
  $variation_attributes_display_values[] = $attribute_value;
135
-
136
  }
137
- $variation_title = implode( ', ', $variation_attributes_display_values ) . ' (' . wc_price( $variation['display_price'] ) . ')';
 
 
 
 
 
138
  $variation_id = $variation['variation_id'];
139
- $is_checked = checked( $is_checked, true, false );
140
-
141
- echo '<td style="width:10%;">';
142
- echo '<input id="wcj_variation_' . $variation_id . '" name="wcj_variations" type="radio"' . $attributes_html . ' variation_id="' . $variation_id . '"' . $is_checked . '>';
143
- echo '</td>';
144
- echo '<td>';
145
- echo '<label for="wcj_variation_' . $variation_id . '">';
146
- echo $variation_title;
 
 
147
  if ( '' != ( $variation_description = get_post_meta( $variation_id, '_variation_description', true ) ) ) {
148
- echo '<br>';
149
- // echo '<small>' . $variation['variation_description'] . '</small>';
150
- echo '<small>' . $variation_description . '</small>';
151
  }
152
- echo '</label>';
153
- echo '</td>';
 
154
  }
155
  }
156
 
2
  /**
3
  * Booster for WooCommerce - Functions
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
9
  if ( ! defined( 'ABSPATH' ) ) exit;
10
 
11
+ if ( ! function_exists( 'wcj_session_maybe_start' ) ) {
12
+ /**
13
+ * wcj_session_maybe_start.
14
+ *
15
+ * @version 3.1.0
16
+ * @since 3.1.0
17
+ */
18
+ function wcj_session_maybe_start() {
19
+ switch ( WCJ_SESSION_TYPE ) {
20
+ case 'wc':
21
+ if ( ! WC()->session->has_session() ) {
22
+ WC()->session->set_customer_session_cookie( true );
23
+ }
24
+ break;
25
+ default: // 'standard'
26
+ if ( ! session_id() ) {
27
+ session_start();
28
+ }
29
+ break;
30
+ }
31
+ }
32
+ }
33
+
34
+ if ( ! function_exists( 'wcj_session_set' ) ) {
35
+ /**
36
+ * wcj_session_set.
37
+ *
38
+ * @version 3.1.0
39
+ * @since 3.1.0
40
+ */
41
+ function wcj_session_set( $key, $value ) {
42
+ switch ( WCJ_SESSION_TYPE ) {
43
+ case 'wc':
44
+ WC()->session->set( $key, $value );
45
+ break;
46
+ default: // 'standard'
47
+ $_SESSION[ $key ] = $value;
48
+ break;
49
+ }
50
+ }
51
+ }
52
+
53
+ if ( ! function_exists( 'wcj_session_get' ) ) {
54
+ /**
55
+ * wcj_session_get.
56
+ *
57
+ * @version 3.1.0
58
+ * @since 3.1.0
59
+ */
60
+ function wcj_session_get( $key, $default = null ) {
61
+ switch ( WCJ_SESSION_TYPE ) {
62
+ case 'wc':
63
+ return WC()->session->get( $key, $default );
64
+ default: // 'standard'
65
+ return ( isset( $_SESSION[ $key ] ) ? $_SESSION[ $key ] : $default );
66
+ }
67
+ }
68
+ }
69
+
70
+ if ( ! function_exists( 'wcj_wrap_in_wc_email_template' ) ) {
71
+ /**
72
+ * wcj_wrap_in_wc_email_template.
73
+ *
74
+ * @version 3.1.0
75
+ * @since 3.1.0
76
+ */
77
+ function wcj_wrap_in_wc_email_template( $content, $email_heading = '' ) {
78
+ return wcj_get_wc_email_part( 'header', $email_heading ) . $content . wcj_get_wc_email_part( 'footer' );
79
+ }
80
+ }
81
+
82
+ if ( ! function_exists( 'wcj_get_wc_email_part' ) ) {
83
+ /**
84
+ * wcj_get_wc_email_part.
85
+ *
86
+ * @version 3.1.0
87
+ * @since 3.1.0
88
+ */
89
+ function wcj_get_wc_email_part( $part, $email_heading = '' ) {
90
+ ob_start();
91
+ switch ( $part ) {
92
+ case 'header':
93
+ wc_get_template( 'emails/email-header.php', array( 'email_heading' => $email_heading ) );
94
+ break;
95
+ case 'footer':
96
+ wc_get_template( 'emails/email-footer.php' );
97
+ break;
98
+ }
99
+ return ob_get_clean();
100
+ }
101
+ }
102
+
103
  if ( ! function_exists( 'wcj_maybe_add_date_query' ) ) {
104
  /**
105
  * wcj_maybe_add_date_query.
192
  }
193
  }
194
 
195
+ if ( ! function_exists( 'wcj_replace_values_in_template' ) ) {
196
+ /**
197
+ * wcj_replace_values_in_template.
198
+ *
199
+ * @version 3.1.0
200
+ * @since 3.1.0
201
+ */
202
+ function wcj_replace_values_in_template( $values_to_replace, $template ) {
203
+ return str_replace( array_keys( $values_to_replace ), array_values( $values_to_replace ), $template );
204
+ }
205
+ }
206
+
207
  if ( ! function_exists( 'wcj_variation_radio_button' ) ) {
208
  /**
209
  * wcj_variation_radio_button.
210
  *
211
+ * @version 3.1.0
212
  * @since 2.4.8
213
+ * @todo (maybe) check - maybe we can use `$variation['variation_description']` instead of `get_post_meta( $variation_id, '_variation_description', true )`
214
  */
215
  function wcj_variation_radio_button( $_product, $variation ) {
216
+ $attributes_html = '';
217
  $variation_attributes_display_values = array();
218
+ $is_checked = true;
219
  foreach ( $variation['attributes'] as $attribute_full_name => $attribute_value ) {
 
220
  $attributes_html .= ' ' . $attribute_full_name . '="' . $attribute_value . '"';
221
+ // Attribute name
222
  $attribute_name = $attribute_full_name;
223
+ $prefix = 'attribute_';
224
  if ( substr( $attribute_full_name, 0, strlen( $prefix ) ) === $prefix ) {
225
  $attribute_name = substr( $attribute_full_name, strlen( $prefix ) );
226
  }
227
+ // Checked
228
+ $checked = isset( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) ?
229
+ wc_clean( $_REQUEST[ 'attribute_' . sanitize_title( $attribute_name ) ] ) : $_product->get_variation_default_attribute( $attribute_name );
230
+ if ( $checked != $attribute_value ) {
231
+ $is_checked = false;
232
+ }
233
+ // Attribute value
234
  $terms = get_terms( $attribute_name );
235
  foreach ( $terms as $term ) {
236
  if ( is_object( $term ) && isset( $term->slug ) && $term->slug === $attribute_value && isset( $term->name ) ) {
237
  $attribute_value = $term->name;
238
  }
239
  }
240
+ // Display values
241
  $variation_attributes_display_values[] = $attribute_value;
 
242
  }
243
+ // Variation label
244
+ $variation_label = wcj_replace_values_in_template( array(
245
+ '%variation_title%' => implode( ', ', $variation_attributes_display_values ),
246
+ '%variation_price%' => wc_price( $variation['display_price'] ),
247
+ ), get_option( 'wcj_add_to_cart_variable_as_radio_variation_label_template', '%variation_title% (%variation_price%)' ) );
248
+ // Variation ID and "is checked"
249
  $variation_id = $variation['variation_id'];
250
+ $is_checked = checked( $is_checked, true, false );
251
+ // Final HTML
252
+ $html = '';
253
+ $html .= '<td class="wcj_variable_as_radio_input_td" style="' . get_option( 'wcj_add_to_cart_variable_as_radio_input_td_style', 'width:10%;' ) . '">';
254
+ $html .= '<input id="wcj_variation_' . $variation_id . '" name="wcj_variations" type="radio"' . $attributes_html . ' variation_id="' .
255
+ $variation_id . '"' . $is_checked . '>';
256
+ $html .= '</td>';
257
+ $html .= '<td class="wcj_variable_as_radio_label_td">';
258
+ $html .= '<label for="wcj_variation_' . $variation_id . '">';
259
+ $html .= $variation_label;
260
  if ( '' != ( $variation_description = get_post_meta( $variation_id, '_variation_description', true ) ) ) {
261
+ $html .= wcj_replace_values_in_template( array(
262
+ '%variation_description%' => $variation_description,
263
+ ), get_option( 'wcj_add_to_cart_variable_as_radio_variation_desc_template', '<br><small>%variation_description%</small>' ) );
264
  }
265
+ $html .= '</label>';
266
+ $html .= '</td>';
267
+ echo $html;
268
  }
269
  }
270
 
includes/functions/wcj-invoicing-functions.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Invoicing
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -200,61 +200,47 @@ if ( ! function_exists( 'wcj_get_invoice_types' ) ) {
200
  /*
201
  * wcj_get_invoice_types.
202
  *
203
- * @version 2.7.0
204
  */
205
  function wcj_get_invoice_types() {
206
  $invoice_types = array(
207
  array(
208
- 'id' => 'invoice',
209
- 'title' => __( 'Invoice', 'woocommerce-jetpack' ),
210
- 'desc' => __( 'Invoices', 'woocommerce-jetpack' ),
211
- 'defaults' => array( 'init' => 'disabled', ),
212
- // 'icon' => '\e028',
213
  ),
214
-
215
  array(
216
- 'id' => 'proforma_invoice',
217
- 'title' => __( 'Proforma Invoice', 'woocommerce-jetpack' ),
218
- 'desc' => __( 'Proforma Invoices', 'woocommerce-jetpack' ),
219
- 'defaults' => array( 'init' => 'disabled', ),
220
- // 'icon' => '\e030',
221
  ),
222
-
223
  array(
224
- 'id' => 'packing_slip',
225
- 'title' => __( 'Packing Slip', 'woocommerce-jetpack' ),
226
- 'desc' => __( 'Packing Slips', 'woocommerce-jetpack' ),
227
- 'defaults' => array( 'init' => 'disabled', ),
228
- // 'icon' => '\e019',
229
  ),
230
-
231
  array(
232
- 'id' => 'credit_note',
233
- 'title' => __( 'Credit Note', 'woocommerce-jetpack' ),
234
- 'desc' => __( 'Credit Notes', 'woocommerce-jetpack' ),
235
- 'defaults' => array( 'init' => 'disabled', ),
236
- // 'icon' => '\e019',
237
  ),
238
-
239
- /* array(
240
- 'id' => 'custom_doc',
241
- 'title' => __( 'Custom Document', 'woocommerce-jetpack' ),
242
- 'desc' => __( 'Custom Documents', 'woocommerce-jetpack' ),
243
- 'defaults' => array( 'init' => 'disabled', ),
244
- // 'icon' => '\e019',
245
- ), */
246
  );
247
-
248
  $total_custom_docs = get_option( 'wcj_invoicing_custom_doc_total_number', 1 );
249
  for ( $i = 1; $i <= $total_custom_docs; $i++ ) {
250
  $invoice_types[] = array(
251
- 'id' => ( 1 == $i ? 'custom_doc' : 'custom_doc' . '_' . $i ),
252
- 'title' => __( 'Custom Document', 'woocommerce-jetpack' ) . ' #' . $i,
253
- 'desc' => __( 'Custom Documents', 'woocommerce-jetpack' ) . ' #' . $i,
254
- 'defaults' => array( 'init' => 'disabled', ),
 
 
 
255
  );
256
  }
257
-
258
  return $invoice_types;
259
  }
260
  }
2
  /**
3
  * Booster for WooCommerce - Functions - Invoicing
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
200
  /*
201
  * wcj_get_invoice_types.
202
  *
203
+ * @version 3.1.0
204
  */
205
  function wcj_get_invoice_types() {
206
  $invoice_types = array(
207
  array(
208
+ 'id' => 'invoice',
209
+ 'title' => get_option( 'wcj_invoicing_' . 'invoice' . '_admin_title', __( 'Invoice', 'woocommerce-jetpack' ) ),
210
+ 'defaults' => array( 'init' => 'disabled' ),
211
+ 'color' => 'green',
 
212
  ),
 
213
  array(
214
+ 'id' => 'proforma_invoice',
215
+ 'title' => get_option( 'wcj_invoicing_' . 'proforma_invoice' . '_admin_title', __( 'Proforma Invoice', 'woocommerce-jetpack' ) ),
216
+ 'defaults' => array( 'init' => 'disabled' ),
217
+ 'color' => 'orange',
 
218
  ),
 
219
  array(
220
+ 'id' => 'packing_slip',
221
+ 'title' => get_option( 'wcj_invoicing_' . 'packing_slip' . '_admin_title', __( 'Packing Slip', 'woocommerce-jetpack' ) ),
222
+ 'defaults' => array( 'init' => 'disabled' ),
223
+ 'color' => 'blue',
 
224
  ),
 
225
  array(
226
+ 'id' => 'credit_note',
227
+ 'title' => get_option( 'wcj_invoicing_' . 'credit_note' . '_admin_title', __( 'Credit Note', 'woocommerce-jetpack' ) ),
228
+ 'defaults' => array( 'init' => 'disabled' ),
229
+ 'color' => 'red',
 
230
  ),
 
 
 
 
 
 
 
 
231
  );
 
232
  $total_custom_docs = get_option( 'wcj_invoicing_custom_doc_total_number', 1 );
233
  for ( $i = 1; $i <= $total_custom_docs; $i++ ) {
234
  $invoice_types[] = array(
235
+ 'id' => ( 1 == $i ? 'custom_doc' : 'custom_doc' . '_' . $i ),
236
+ 'title' => get_option( 'wcj_invoicing_' . ( 1 == $i ? 'custom_doc' : 'custom_doc' . '_' . $i ) . '_admin_title',
237
+ __( 'Custom Document', 'woocommerce-jetpack' ) . ' #' . $i ),
238
+ 'defaults' => array( 'init' => 'disabled' ),
239
+ 'color' => 'gray',
240
+ 'is_custom_doc' => true,
241
+ 'custom_doc_nr' => $i,
242
  );
243
  }
 
244
  return $invoice_types;
245
  }
246
  }
includes/functions/wcj-order-functions.php CHANGED
@@ -2,13 +2,37 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Order
4
  *
5
- * @version 2.9.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  if ( ! function_exists( 'wcj_get_order_id' ) ) {
13
  /**
14
  * wcj_get_order_id.
2
  /**
3
  * Booster for WooCommerce - Functions - Order
4
  *
5
+ * @version 3.1.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
+ if ( ! function_exists( 'wcj_get_order_billing_email' ) ) {
13
+ /**
14
+ * wcj_get_order_billing_email.
15
+ *
16
+ * @version 3.1.0
17
+ * @since 3.1.0
18
+ */
19
+ function wcj_get_order_billing_email( $_order ) {
20
+ return ( WCJ_IS_WC_VERSION_BELOW_3 ? $_order->billing_email : $_order->get_billing_email() );
21
+ }
22
+ }
23
+
24
+ if ( ! function_exists( 'wcj_get_order_date' ) ) {
25
+ /**
26
+ * wcj_get_order_date.
27
+ *
28
+ * @version 3.1.0
29
+ * @since 3.1.0
30
+ */
31
+ function wcj_get_order_date( $_order ) {
32
+ return ( WCJ_IS_WC_VERSION_BELOW_3 ? $_order->order_date : $_order->get_date_created() );
33
+ }
34
+ }
35
+
36
  if ( ! function_exists( 'wcj_get_order_id' ) ) {
37
  /**
38
  * wcj_get_order_id.
includes/functions/wcj-price-currency-functions.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Price and Currency
4
  *
5
- * @version 2.9.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -98,17 +98,28 @@ if ( ! function_exists( 'wcj_price_by_product_base_currency' ) ) {
98
  /**
99
  * wcj_price_by_product_base_currency.
100
  *
101
- * @version 2.7.0
102
  * @since 2.5.6
103
  */
104
  function wcj_price_by_product_base_currency( $price, $product_id ) {
105
  if ( '' == $price ) {
106
  return $price;
107
  }
 
 
 
 
108
  $multicurrency_base_price_currency = get_post_meta( $product_id, '_' . 'wcj_multicurrency_base_price_currency', true );
109
  if ( '' != $multicurrency_base_price_currency ) {
110
  if ( 1 != ( $currency_exchange_rate = wcj_get_currency_exchange_rate_product_base_currency( $multicurrency_base_price_currency ) ) ) {
111
- return $price / $currency_exchange_rate;
 
 
 
 
 
 
 
112
  }
113
  }
114
  return $price;
@@ -473,4 +484,3 @@ if ( ! function_exists( 'wcj_price' ) ) {
473
  return ( 'yes' === $hide_currency ) ? wc_price( $price, array( 'currency' => 'DISABLED' ) ) : wc_price( $price, array( 'currency' => $currency ) );
474
  }
475
  }
476
-
2
  /**
3
  * Booster for WooCommerce - Functions - Price and Currency
4
  *
5
+ * @version 3.1.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
98
  /**
99
  * wcj_price_by_product_base_currency.
100
  *
101
+ * @version 3.1.0
102
  * @since 2.5.6
103
  */
104
  function wcj_price_by_product_base_currency( $price, $product_id ) {
105
  if ( '' == $price ) {
106
  return $price;
107
  }
108
+ $do_save = ( 'yes' === get_option( 'wcj_multicurrency_base_price_save_prices', 'no' ) );
109
+ if ( $do_save && isset( WCJ()->modules['multicurrency_base_price']->calculated_products_prices[ $product_id ] ) ) {
110
+ return WCJ()->modules['multicurrency_base_price']->calculated_products_prices[ $product_id ];
111
+ }
112
  $multicurrency_base_price_currency = get_post_meta( $product_id, '_' . 'wcj_multicurrency_base_price_currency', true );
113
  if ( '' != $multicurrency_base_price_currency ) {
114
  if ( 1 != ( $currency_exchange_rate = wcj_get_currency_exchange_rate_product_base_currency( $multicurrency_base_price_currency ) ) ) {
115
+ $_price = $price / $currency_exchange_rate;
116
+ if ( 'yes' === get_option( 'wcj_multicurrency_base_price_round_enabled', 'no' ) ) {
117
+ $_price = round( $_price, get_option( 'wcj_multicurrency_base_price_round_precision', get_option( 'woocommerce_price_num_decimals' ) ) );
118
+ }
119
+ if ( $do_save ) {
120
+ WCJ()->modules['multicurrency_base_price']->calculated_products_prices[ $product_id ] = $_price;
121
+ }
122
+ return $_price;
123
  }
124
  }
125
  return $price;
484
  return ( 'yes' === $hide_currency ) ? wc_price( $price, array( 'currency' => 'DISABLED' ) ) : wc_price( $price, array( 'currency' => $currency ) );
485
  }
486
  }
 
includes/functions/wcj-product-functions.php CHANGED
@@ -2,13 +2,61 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Product
4
  *
5
- * @version 3.0.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  if ( ! function_exists( 'wcj_get_product' ) ) {
13
  /*
14
  * wcj_get_product.
2
  /**
3
  * Booster for WooCommerce - Functions - Product
4
  *
5
+ * @version 3.1.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
+ if ( ! function_exists( 'wcj_is_enabled_for_product' ) ) {
13
+ /*
14
+ * wcj_is_enabled_for_product.
15
+ *
16
+ * @version 3.1.0
17
+ * @since 3.1.0
18
+ */
19
+ function wcj_is_enabled_for_product( $product_id, $args ) {
20
+ if ( isset( $args['include_products'] ) && ! empty( $args['include_products'] ) ) {
21
+ if ( ! is_array( $args['include_products'] ) ) {
22
+ $args['include_products'] = array_map( 'trim', explode( ',', $args['include_products'] ) );
23
+ }
24
+ if ( ! in_array( $product_id, $args['include_products'] ) ) {
25
+ return false;
26
+ }
27
+ }
28
+ if ( isset( $args['exclude_products'] ) && ! empty( $args['exclude_products'] ) ) {
29
+ if ( ! is_array( $args['exclude_products'] ) ) {
30
+ $args['exclude_products'] = array_map( 'trim', explode( ',', $args['exclude_products'] ) );
31
+ }
32
+ if ( in_array( $product_id, $args['exclude_products'] ) ) {
33
+ return false;
34
+ }
35
+ }
36
+ if ( isset( $args['include_categories'] ) && ! empty( $args['include_categories'] ) ) {
37
+ if ( ! wcj_is_product_term( $product_id, $args['include_categories'], 'product_cat' ) ) {
38
+ return false;
39
+ }
40
+ }
41
+ if ( isset( $args['exclude_categories'] ) && ! empty( $args['exclude_categories'] ) ) {
42
+ if ( wcj_is_product_term( $product_id, $args['exclude_categories'], 'product_cat' ) ) {
43
+ return false;
44
+ }
45
+ }
46
+ if ( isset( $args['include_tags'] ) && ! empty( $args['include_tags'] ) ) {
47
+ if ( ! wcj_is_product_term( $product_id, $args['include_tags'], 'product_tag' ) ) {
48
+ return false;
49
+ }
50
+ }
51
+ if ( isset( $args['exclude_tags'] ) && ! empty( $args['exclude_tags'] ) ) {
52
+ if ( wcj_is_product_term( $product_id, $args['exclude_tags'], 'product_tag' ) ) {
53
+ return false;
54
+ }
55
+ }
56
+ return true;
57
+ }
58
+ }
59
+
60
  if ( ! function_exists( 'wcj_get_product' ) ) {
61
  /*
62
  * wcj_get_product.
includes/input-fields/{class-wcj-product-input-fields-abstract.php → class-wcj-product-input-fields-core.php} RENAMED
@@ -1,16 +1,16 @@
1
  <?php
2
  /**
3
- * Booster for WooCommerce - Product Input Fields - Abstract
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
9
  if ( ! defined( 'ABSPATH' ) ) exit;
10
 
11
- if ( ! class_exists( 'WCJ_Product_Input_Fields_Abstract' ) ) :
12
 
13
- class WCJ_Product_Input_Fields_Abstract {
14
 
15
  /** @var string scope. */
16
  public $scope = '';
@@ -18,236 +18,231 @@ class WCJ_Product_Input_Fields_Abstract {
18
  /**
19
  * Constructor.
20
  *
21
- * @version 2.8.0
 
22
  */
23
- function __construct() {
24
- return true;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
25
  }
26
 
27
  /**
28
  * get_options.
29
  *
30
- * @version 2.8.0
31
  */
32
  function get_options() {
33
- $options = array(
34
-
35
- array(
36
- 'id' => 'wcj_product_input_fields_enabled_' . $this->scope . '_',
37
- 'title' => __( 'Enabled', 'woocommerce-jetpack' ),
38
- 'type' => 'checkbox',
39
- 'default' => 'no',
40
- ),
41
-
42
- array(
43
- 'id' => 'wcj_product_input_fields_type_' . $this->scope . '_',
44
- 'title' => __( 'Type', 'woocommerce-jetpack' ),
45
- 'type' => 'select',
46
- 'default' => 'text',
47
- 'options' => array(
48
- 'text' => __( 'Text', 'woocommerce-jetpack' ),
49
- 'textarea' => __( 'Textarea', 'woocommerce-jetpack' ),
50
- 'number' => __( 'Number', 'woocommerce-jetpack' ),
51
- 'checkbox' => __( 'Checkbox', 'woocommerce-jetpack' ),
52
- 'file' => __( 'File', 'woocommerce-jetpack' ),
53
- 'datepicker' => __( 'Datepicker', 'woocommerce-jetpack' ),
54
- 'weekpicker' => __( 'Weekpicker', 'woocommerce-jetpack' ),
55
- 'timepicker' => __( 'Timepicker', 'woocommerce-jetpack' ),
56
- 'select' => __( 'Select', 'woocommerce-jetpack' ),
57
- 'radio' => __( 'Radio', 'woocommerce-jetpack' ),
58
- 'password' => __( 'Password', 'woocommerce-jetpack' ),
59
- 'country' => __( 'Country', 'woocommerce-jetpack' ),
60
- // 'state' => __( 'State', 'woocommerce-jetpack' ),
61
- 'email' => __( 'Email', 'woocommerce-jetpack' ),
62
- 'tel' => __( 'Phone', 'woocommerce-jetpack' ),
63
- ),
64
- ),
65
-
66
- array(
67
- 'id' => 'wcj_product_input_fields_title_' . $this->scope . '_',
68
- 'title' => __( 'Title', 'woocommerce-jetpack' ),
69
- 'type' => 'textarea',
70
- 'default' => '',
71
- ),
72
-
73
- array(
74
- 'id' => 'wcj_product_input_fields_placeholder_' . $this->scope . '_',
75
- 'title' => __( 'Placeholder', 'woocommerce-jetpack' ),
76
- 'type' => 'textarea',
77
- 'default' => '',
78
- ),
79
-
80
- array(
81
- 'id' => 'wcj_product_input_fields_required_' . $this->scope . '_',
82
- 'title' => __( 'Required', 'woocommerce-jetpack' ),
83
- 'type' => 'checkbox',
84
- 'default' => 'no',
85
- ),
86
-
87
- array(
88
- 'id' => 'wcj_product_input_fields_required_message_' . $this->scope . '_',
89
- 'title' => __( 'Message on required', 'woocommerce-jetpack' ),
90
- 'type' => 'textarea',
91
- 'default' => '',
92
- ),
93
-
94
- /* array(
95
- 'id' => 'wcj_product_input_fields_type_checkbox_' . $this->scope . '_',
96
- 'title' => __( 'If checkbox is selected, set possible pairs here.', 'woocommerce-jetpack' ),
97
- 'type' => 'select',
98
- 'default' => 'yes_no',
99
- 'options' => array(
100
- 'yes_no' => __( 'Yes / No', 'woocommerce-jetpack' ),
101
- 'on_off' => __( 'On / Off', 'woocommerce-jetpack' ),
102
- ),
103
- ), */
104
-
105
- array(
106
- 'id' => 'wcj_product_input_fields_type_checkbox_yes_' . $this->scope . '_',
107
- 'title' => __( 'If checkbox is selected, set value for ON here', 'woocommerce-jetpack' ),
108
- 'short_title' => __( 'Checkbox: ON', 'woocommerce-jetpack' ),
109
- 'type' => 'text',
110
- 'default' => __( 'Yes', 'woocommerce-jetpack' ),
111
- ),
112
-
113
- array(
114
- 'id' => 'wcj_product_input_fields_type_checkbox_no_' . $this->scope . '_',
115
- 'title' => __( 'If checkbox is selected, set value for OFF here', 'woocommerce-jetpack' ),
116
- 'short_title' => __( 'Checkbox: OFF', 'woocommerce-jetpack' ),
117
- 'type' => 'text',
118
- 'default' => __( 'No', 'woocommerce-jetpack' ),
119
- ),
120
-
121
- array(
122
- 'id' => 'wcj_product_input_fields_type_checkbox_default_' . $this->scope . '_',
123
- 'title' => __( 'If checkbox is selected, set default value here', 'woocommerce-jetpack' ),
124
- 'short_title' => __( 'Checkbox: Default', 'woocommerce-jetpack' ),
125
- 'type' => 'select',
126
- 'default' => 'no',
127
- 'options' => array(
128
- 'no' => __( 'Not Checked', 'woocommerce-jetpack' ),
129
- 'yes' => __( 'Checked', 'woocommerce-jetpack' ),
130
- ),
131
- ),
132
-
133
- array(
134
- 'id' => 'wcj_product_input_fields_type_file_accept_' . $this->scope . '_',
135
- 'title' => __( 'If file is selected, set accepted file types here. E.g.: ".jpg,.jpeg,.png". Leave blank to accept all files', 'woocommerce-jetpack' )
136
- . '. ' . __( 'Visit <a href="https://www.w3schools.com/tags/att_input_accept.asp" target="_blank">documentation on input accept attribute</a> for valid option formats', 'woocommerce-jetpack' ),
137
- 'short_title' => __( 'File: Accepted types', 'woocommerce-jetpack' ),
138
- 'type' => 'text',
139
- 'default' => __( '.jpg,.jpeg,.png', 'woocommerce-jetpack' ),
140
- ),
141
-
142
- array(
143
- 'id' => 'wcj_product_input_fields_type_file_max_size_' . $this->scope . '_',
144
- 'title' => __( 'If file is selected, set max file size here. Set to zero to accept all files', 'woocommerce-jetpack' ),
145
- 'short_title' => __( 'File: Max size', 'woocommerce-jetpack' ),
146
- 'type' => 'number',
147
- 'default' => 0,
148
- ),
149
-
150
- array(
151
- 'id' => 'wcj_product_input_fields_type_datepicker_format_' . $this->scope . '_',
152
- 'title' => __( 'If datepicker/weekpicker is selected, set date format here. Visit <a href="https://codex.wordpress.org/Formatting_Date_and_Time" target="_blank">documentation on date and time formatting</a> for valid date formats', 'woocommerce-jetpack' ),
153
- 'desc_tip' => __( 'Leave blank to use your current WordPress format', 'woocommerce-jetpack' ) . ': ' . get_option( 'date_format' ),
154
- 'short_title' => __( 'Datepicker/Weekpicker: Date format', 'woocommerce-jetpack' ),
155
- 'type' => 'text',
156
- 'default' => '',
157
- ),
158
-
159
- array(
160
- 'id' => 'wcj_product_input_fields_type_datepicker_mindate_' . $this->scope . '_',
161
- 'title' => __( 'If datepicker/weekpicker is selected, set min date (in days) here', 'woocommerce-jetpack' ),
162
- 'short_title' => __( 'Datepicker/Weekpicker: Min date', 'woocommerce-jetpack' ),
163
- 'type' => 'number',
164
- 'default' => -365,
165
- ),
166
-
167
- array(
168
- 'id' => 'wcj_product_input_fields_type_datepicker_maxdate_' . $this->scope . '_',
169
- 'title' => __( 'If datepicker/weekpicker is selected, set max date (in days) here', 'woocommerce-jetpack' ),
170
- 'short_title' => __( 'Datepicker/Weekpicker: Max date', 'woocommerce-jetpack' ),
171
- 'type' => 'number',
172
- 'default' => 365,
173
- ),
174
-
175
- array(
176
- 'id' => 'wcj_product_input_fields_type_datepicker_changeyear_' . $this->scope . '_',
177
- 'title' => __( 'If datepicker/weekpicker is selected, set if you want to add year selector', 'woocommerce-jetpack' ),
178
- 'short_title' => __( 'Datepicker/Weekpicker: Change year', 'woocommerce-jetpack' ),
179
- 'type' => 'checkbox',
180
- 'default' => 'no',
181
- ),
182
-
183
- array(
184
- 'id' => 'wcj_product_input_fields_type_datepicker_yearrange_' . $this->scope . '_',
185
- 'title' => __( 'If datepicker/weekpicker is selected, and year selector is enabled, set year range here', 'woocommerce-jetpack' ),
186
- 'short_title' => __( 'Datepicker/Weekpicker: Year range', 'woocommerce-jetpack' ),
187
- // 'desc_tip' => __( 'The range of years displayed in the year drop-down: either relative to today\'s year ("-nn:+nn"), relative to the currently selected year ("c-nn:c+nn"), absolute ("nnnn:nnnn"), or combinations of these formats ("nnnn:-nn"). Note that this option only affects what appears in the drop-down, to restrict which dates may be selected use the minDate and/or maxDate options.', 'woocommerce-jetpack' ),
188
- 'type' => 'text',
189
- 'default' => 'c-10:c+10',
190
- ),
191
-
192
- array(
193
- 'id' => 'wcj_product_input_fields_type_datepicker_firstday_' . $this->scope . '_',
194
- 'title' => __( 'If datepicker/weekpicker is selected, set first week day here', 'woocommerce-jetpack' ),
195
- 'short_title' => __( 'Datepicker/Weekpicker: First week day', 'woocommerce-jetpack' ),
196
- 'type' => 'select',
197
- 'default' => 0,
198
- 'options' => array(
199
- __( 'Sunday', 'woocommerce-jetpack' ),
200
- __( 'Monday', 'woocommerce-jetpack' ),
201
- __( 'Tuesday', 'woocommerce-jetpack' ),
202
- __( 'Wednesday', 'woocommerce-jetpack' ),
203
- __( 'Thursday', 'woocommerce-jetpack' ),
204
- __( 'Friday', 'woocommerce-jetpack' ),
205
- __( 'Saturday', 'woocommerce-jetpack' ),
206
- ),
207
- ),
208
-
209
- array(
210
- 'id' => 'wcj_product_input_fields_type_timepicker_format_' . $this->scope . '_',
211
- 'title' => __( 'If timepicker is selected, set time format here. Visit <a href="http://timepicker.co/options/" target="_blank">timepicker options page</a> for valid time formats', 'woocommerce-jetpack' ),
212
- 'short_title' => __( 'Timepicker: Time format', 'woocommerce-jetpack' ),
213
- 'type' => 'text',
214
- 'default' => 'hh:mm p',
215
- ),
216
-
217
- array(
218
- 'id' => 'wcj_product_input_fields_type_timepicker_mintime_' . $this->scope . '_',
219
- 'title' => __( 'If timepicker is selected, set min time here. Visit <a href="http://timepicker.co/options/" target="_blank">timepicker options page</a> for valid option formats', 'woocommerce-jetpack' ),
220
- 'short_title' => __( 'Timepicker: Min Time', 'woocommerce-jetpack' ),
221
- 'type' => 'text',
222
- 'default' => '',
223
- ),
224
-
225
- array(
226
- 'id' => 'wcj_product_input_fields_type_timepicker_maxtime_' . $this->scope . '_',
227
- 'title' => __( 'If timepicker is selected, set max time here. Visit <a href="http://timepicker.co/options/" target="_blank">timepicker options page</a> for valid option formats', 'woocommerce-jetpack' ),
228
- 'short_title' => __( 'Timepicker: Max Time', 'woocommerce-jetpack' ),
229
- 'type' => 'text',
230
- 'default' => '',
231
- ),
232
-
233
- array(
234
- 'id' => 'wcj_product_input_fields_type_timepicker_interval_' . $this->scope . '_',
235
- 'title' => __( 'If timepicker is selected, set interval (in minutes) here', 'woocommerce-jetpack' ),
236
- 'short_title' => __( 'Timepicker: Interval', 'woocommerce-jetpack' ),
237
- 'type' => 'number',
238
- 'default' => 15,
239
- ),
240
-
241
- array(
242
- 'id' => 'wcj_product_input_fields_type_select_options_' . $this->scope . '_',
243
- 'title' => __( 'If select/radio is selected, set options here. One option per line', 'woocommerce-jetpack' ),
244
- 'short_title' => __( 'Select/Radio: Options', 'woocommerce-jetpack' ),
245
- 'type' => 'textarea',
246
- 'default' => '',
247
- ),
248
 
249
- );
250
- return $options;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
251
  }
252
 
253
  /**
@@ -307,7 +302,7 @@ class WCJ_Product_Input_Fields_Abstract {
307
  /**
308
  * output_custom_input_fields_in_admin_order.
309
  *
310
- * @version 2.7.0
311
  */
312
  function output_custom_input_fields_in_admin_order( $item_id, $item, $_product ) {
313
  if ( null === $_product ) {
@@ -326,18 +321,12 @@ class WCJ_Product_Input_Fields_Abstract {
326
 
327
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $_product_id, '' );
328
  if ( 'file' === $type ) {
329
- /* $file_name = $the_value;
330
- $upload_dir = wp_upload_dir();
331
- $upload_url = $upload_dir['baseurl'];
332
- $the_value = $upload_url . '/woocommerce_uploads/' . $file_name;
333
- //$the_value = $upload_url . '/' . $the_value;
334
- //$the_value = '<img style="width:50px;" src="' . $the_value . '">'; */
335
  $the_value = maybe_unserialize( $the_value );
336
  if ( isset( $the_value['name'] ) ) {
337
  $the_value = '<a href="' . add_query_arg( 'wcj_download_file', $item_id . '.' . pathinfo( $the_value['name'], PATHINFO_EXTENSION ) ) . '">' . $the_value['name'] . '</a>';
338
  }
339
  } else {
340
- if ( 'no' === get_option( 'wcj_product_input_fields_make_nicer_name_enabled' ) ) {
341
  continue;
342
  }
343
  }
@@ -351,22 +340,23 @@ class WCJ_Product_Input_Fields_Abstract {
351
 
352
  /**
353
  * get_value.
 
 
354
  */
355
  function get_value( $option_name, $product_id, $default ) {
356
- return false;
357
  }
358
 
359
  /**
360
  * validate_product_input_fields_on_add_to_cart.
361
  *
362
- * @version 2.7.0
363
  */
364
  function validate_product_input_fields_on_add_to_cart( $passed, $product_id ) {
365
  $total_number = apply_filters( 'booster_get_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $product_id, 1 ) );
366
  for ( $i = 1; $i <= $total_number; $i++ ) {
367
 
368
- $is_enabled = $this->get_value( 'wcj_product_input_fields_enabled_' . $this->scope . '_' . $i, $product_id, 'no' );
369
- if ( ! ( 'on' === $is_enabled || 'yes' === $is_enabled ) ) {
370
  continue;
371
  }
372
 
@@ -402,7 +392,6 @@ class WCJ_Product_Input_Fields_Abstract {
402
  if ( ! in_array( $file_type, $file_accept ) ) {
403
  $passed = false;
404
  wc_add_notice( __( 'Wrong file type!', 'woocommerce-jetpack' ), 'error' );
405
- // wc_add_notice( $this->get_value( 'wcj_product_input_fields_wrong_file_type_msg_' . $this->scope . '_' . $i, $product_id, '' ), 'error' );
406
  }
407
  }
408
  }
@@ -422,7 +411,10 @@ class WCJ_Product_Input_Fields_Abstract {
422
  /**
423
  * add_product_input_fields_to_frontend.
424
  *
425
- * @version 2.8.0
 
 
 
426
  */
427
  function add_product_input_fields_to_frontend() {
428
  global $product;
@@ -430,12 +422,11 @@ class WCJ_Product_Input_Fields_Abstract {
430
  return;
431
  }
432
  $_product_id = wcj_get_product_id_or_variation_parent_id( $product );
433
- $final_html = '';
434
  $total_number = apply_filters( 'booster_get_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $_product_id, 1 ) );
435
  for ( $i = 1; $i <= $total_number; $i++ ) {
436
 
437
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $_product_id, 'text' );
438
- $is_enabled = $this->get_value( 'wcj_product_input_fields_enabled_' . $this->scope . '_' . $i, $_product_id, 'no' );
439
  $is_required = $this->get_value( 'wcj_product_input_fields_required_' . $this->scope . '_' . $i, $_product_id, 'no' );
440
  $title = $this->get_value( 'wcj_product_input_fields_title_' . $this->scope . '_' . $i, $_product_id, '' );
441
  $placeholder = $this->get_value( 'wcj_product_input_fields_placeholder_' . $this->scope . '_' . $i, $_product_id, '' );
@@ -475,7 +466,16 @@ class WCJ_Product_Input_Fields_Abstract {
475
  $title .= get_option( 'wcj_product_input_fields_frontend_view_required_html', '&nbsp;<abbr class="required" title="required">*</abbr>' );
476
  }
477
 
478
- if ( 'on' === $is_enabled || 'yes' === $is_enabled ) {
 
 
 
 
 
 
 
 
 
479
  $html = '';
480
  switch ( $type ) {
481
 
@@ -485,42 +485,47 @@ class WCJ_Product_Input_Fields_Abstract {
485
  case 'password':
486
  case 'email':
487
  case 'tel':
488
-
489
- $html = '<input class="wcj_product_input_fields" id="' . $field_name . '" type="' . $type . '" name="' . $field_name . '" placeholder="' . $placeholder . '"' . $custom_attributes . '>';
490
  break;
491
 
492
  case 'checkbox':
493
-
494
  $checked = checked(
495
- $this->get_value( 'wcj_product_input_fields_type_checkbox_default_' . $this->scope . '_' . $i, $_product_id, 'no' ),
496
- 'yes',
497
  false
498
  );
499
- $html = '<input class="wcj_product_input_fields" id="' . $field_name . '" type="' . $type . '" name="' . $field_name . '"' . $custom_attributes . $checked . '>';
 
500
  break;
501
 
502
  case 'datepicker':
503
-
504
- $html = '<input class="wcj_product_input_fields" id="' . $field_name . '" ' . $datepicker_year . 'firstday="' . $datepicker_firstday . '" dateformat="' . $datepicker_format . '" mindate="' . $datepicker_mindate . '" maxdate="' . $datepicker_maxdate . '" type="' . $type . '" display="date" name="' . $field_name . '" placeholder="' . $placeholder . '"' . $custom_attributes . '>';
 
 
505
  break;
506
 
507
  case 'weekpicker':
508
-
509
- $html = '<input class="wcj_product_input_fields" id="' . $field_name . '" ' . $datepicker_year . 'firstday="' . $datepicker_firstday . '" dateformat="' . $datepicker_format . '" mindate="' . $datepicker_mindate . '" maxdate="' . $datepicker_maxdate . '" type="' . $type . '" display="week" name="' . $field_name . '" placeholder="' . $placeholder . '"' . $custom_attributes . '>';
 
 
510
  break;
511
 
512
  case 'timepicker':
513
-
514
- $html = '<input class="wcj_product_input_fields" id="' . $field_name . '"' . $timepicker_mintime . $timepicker_maxtime . ' interval="' . $timepicker_interval . '" timeformat="' . $timepicker_format . '" type="' . $type . '" display="time" name="' . $field_name . '" placeholder="' . $placeholder . '"' . $custom_attributes . '>';
 
 
515
  break;
516
 
517
  case 'textarea':
518
-
519
- $html = '<textarea class="wcj_product_input_fields" id="' . $field_name . '" name="' . $field_name . '" placeholder="' . $placeholder . '">' . '</textarea>';
520
  break;
521
 
522
  case 'select':
523
-
524
  $select_options_raw = $this->get_value( 'wcj_product_input_fields_type_select_options_' . $this->scope . '_' . $i, $_product_id, '' );
525
  $select_options = wcj_get_select_options( $select_options_raw, false );
526
  if ( '' != $placeholder ) {
@@ -529,7 +534,7 @@ class WCJ_Product_Input_Fields_Abstract {
529
  $select_options_html = '';
530
  if ( ! empty( $select_options ) ) {
531
  reset( $select_options );
532
- $value = key( $select_options );
533
  foreach ( $select_options as $select_option_key => $select_option_title ) {
534
  $select_options_html .= '<option value="' . $select_option_key . '" ' . selected( $value, $select_option_key, false ) . '>';
535
  $select_options_html .= $select_option_title;
@@ -540,14 +545,12 @@ class WCJ_Product_Input_Fields_Abstract {
540
  break;
541
 
542
  case 'radio':
543
-
544
  $select_options_raw = $this->get_value( 'wcj_product_input_fields_type_select_options_' . $this->scope . '_' . $i, $_product_id, '' );
545
  $select_options = wcj_get_select_options( $select_options_raw, false );
546
  $select_options_html = '';
547
- //$label_id = current( array_keys( $args['options'] ) );
548
  if ( ! empty( $select_options ) ) {
549
  reset( $select_options );
550
- $value = key( $select_options );
551
  foreach ( $select_options as $option_key => $option_text ) {
552
  $select_options_html .= '<input type="radio" class="input-radio wcj_product_input_fields" value="' . esc_attr( $option_key ) .
553
  '" name="' . $field_name . '" id="' . $field_name . '_' . esc_attr( $option_key ) . '"' . checked( $value, $option_key, false ) . ' />';
@@ -559,10 +562,9 @@ class WCJ_Product_Input_Fields_Abstract {
559
  break;
560
 
561
  case 'country':
562
-
563
  $countries = WC()->countries->get_allowed_countries();
564
  if ( sizeof( $countries ) > 1 ) {
565
- $value = key( $countries );
566
  $field = '<select name="' . $field_name . '" id="' . $field_name . '" class="country_to_state country_select wcj_product_input_fields">' .
567
  '<option value="">'.__( 'Select a country&hellip;', 'woocommerce' ) .'</option>';
568
  foreach ( $countries as $ckey => $cvalue ) {
@@ -573,41 +575,13 @@ class WCJ_Product_Input_Fields_Abstract {
573
  }
574
  break;
575
 
576
- /* case 'state' : // from woocommerce_form_field()
577
-
578
- // Get Country
579
- $country_key = $key == 'billing_state'? 'billing_country' : 'shipping_country';
580
- $current_cc = WC()->checkout->get_value( $country_key );
581
- $states = WC()->countries->get_states( $current_cc );
582
-
583
- if ( is_array( $states ) && empty( $states ) ) {
584
-
585
- $field_container = '<p class="form-row %1$s" id="%2$s" style="display: none">%3$s</p>';
586
-
587
- $field .= '<input type="hidden" class="hidden" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" value="" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '" />';
588
-
589
- } elseif ( is_array( $states ) ) {
590
-
591
- $field .= '<select name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" class="state_select ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" ' . implode( ' ', $custom_attributes ) . ' placeholder="' . esc_attr( $args['placeholder'] ) . '">
592
- <option value="">'.__( 'Select a state&hellip;', 'woocommerce' ) .'</option>';
593
-
594
- foreach ( $states as $ckey => $cvalue ) {
595
- $field .= '<option value="' . esc_attr( $ckey ) . '" '.selected( $value, $ckey, false ) .'>'.__( $cvalue, 'woocommerce' ) .'</option>';
596
- }
597
-
598
- $field .= '</select>';
599
-
600
- } else {
601
-
602
- $field .= '<input type="text" class="input-text ' . esc_attr( implode( ' ', $args['input_class'] ) ) .'" value="' . esc_attr( $value ) . '" placeholder="' . esc_attr( $args['placeholder'] ) . '" name="' . esc_attr( $key ) . '" id="' . esc_attr( $args['id'] ) . '" ' . implode( ' ', $custom_attributes ) . ' />';
603
-
604
- }
605
-
606
- break; */
607
  }
608
  $html = str_replace( array( '%field_title%', '%field_id%', '%field_html%' ), array( $title, $field_name, $html ),
609
  get_option( 'wcj_product_input_fields_field_template', '<p><label for="%field_id%">%field_title%</label> %field_html%</p>' ) );
610
- $final_html .= apply_filters( 'wcj_product_input_field_frontend_html', $html, array(
 
 
 
611
  'title' => $title,
612
  'type' => $type,
613
  'field_name' => $field_name,
@@ -619,21 +593,21 @@ class WCJ_Product_Input_Fields_Abstract {
619
  ) );
620
  }
621
  }
622
- if ( '' != $final_html ) {
623
- echo get_option( 'wcj_product_input_fields_start_template', '' ) . $final_html . get_option( 'wcj_product_input_fields_end_template', '' );
 
624
  }
625
  }
626
 
627
  /**
628
  * add_product_input_fields_to_cart_item_data - from $_POST to $cart_item_data
629
  *
630
- * @version 2.7.0
631
  */
632
  function add_product_input_fields_to_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
633
  $total_number = apply_filters( 'booster_get_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $product_id, 1 ) );
634
  for ( $i = 1; $i <= $total_number; $i++ ) {
635
- $is_enabled = $this->get_value( 'wcj_product_input_fields_enabled_' . $this->scope . '_' . $i, $product_id, 'no' );
636
- if ( ! ( 'on' === $is_enabled || 'yes' === $is_enabled ) ) {
637
  continue;
638
  }
639
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $product_id, '' );
@@ -669,7 +643,7 @@ class WCJ_Product_Input_Fields_Abstract {
669
  /**
670
  * Adds product input values to order details (and emails).
671
  *
672
- * @version 2.9.0
673
  */
674
  function add_product_input_fields_to_order_item_name( $name, $item, $is_cart = false ) {
675
  $total_number = apply_filters( 'booster_get_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $item['product_id'], 1 ) );
@@ -683,8 +657,7 @@ class WCJ_Product_Input_Fields_Abstract {
683
  $item_template = get_option( 'wcj_product_input_fields_frontend_view_order_table_format', '&nbsp;| %title% %value%' );
684
  }
685
  for ( $i = 1; $i <= $total_number; $i++ ) {
686
- $is_enabled = $this->get_value( 'wcj_product_input_fields_enabled_' . $this->scope . '_' . $i, $item['product_id'], 'no' );
687
- if ( ! ( 'on' === $is_enabled || 'yes' === $is_enabled ) ) {
688
  continue;
689
  }
690
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $item['product_id'], '' );
@@ -710,7 +683,7 @@ class WCJ_Product_Input_Fields_Abstract {
710
  $value = maybe_unserialize( $value );
711
  $value = ( isset( $value['name'] ) ) ? $value['name'] : '';
712
  }
713
- if ( '' != $value ) {
714
  $name .= str_replace( array( '%title%', '%value%' ), array( $title, $value ), $item_template );
715
  }
716
  }
@@ -733,7 +706,7 @@ class WCJ_Product_Input_Fields_Abstract {
733
  /**
734
  * add_product_input_fields_to_cart_item_display_data.
735
  *
736
- * @version 2.9.0
737
  * @since 2.9.0
738
  */
739
  function add_product_input_fields_to_cart_item_display_data( $item_data, $item ) {
@@ -742,8 +715,7 @@ class WCJ_Product_Input_Fields_Abstract {
742
  return $item_data;
743
  }
744
  for ( $i = 1; $i <= $total_number; $i++ ) {
745
- $is_enabled = $this->get_value( 'wcj_product_input_fields_enabled_' . $this->scope . '_' . $i, $item['product_id'], 'no' );
746
- if ( ! ( 'on' === $is_enabled || 'yes' === $is_enabled ) ) {
747
  continue;
748
  }
749
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $item['product_id'], '' );
@@ -797,19 +769,12 @@ class WCJ_Product_Input_Fields_Abstract {
797
  if ( ! file_exists( $upload_dir ) ) {
798
  mkdir( $upload_dir, 0755, true );
799
  }
800
- //$upload_dir = ( wp_mkdir_p( $upload_dir['path'] ) ) ? $upload_dir['path'] : $upload_dir['basedir'];
801
  $upload_dir_and_name = $upload_dir . '/' . $name;
802
- //move_uploaded_file( $tmp_name, $upload_dir_and_name );
803
  $file_data = file_get_contents( $tmp_name );
804
  file_put_contents( $upload_dir_and_name, $file_data );
805
  unlink( $tmp_name );
806
- //unset( $input_field_value['tmp_name'] );
807
  $input_field_value['tmp_name'] = addslashes( $upload_dir_and_name );
808
  $input_field_value['wcj_type'] = 'file';
809
- //$orig_file_name = $input_field_value['name'];
810
- //wc_add_order_item_meta( $item_id, '_wcj_product_input_fields_' . $this->scope . '_' . $i . '_orig_file_name', $orig_file_name );
811
- //$input_field_value = '<a href="' . add_query_arg( 'wcj_download_file', $name ) . '">' . $orig_file_name . '</a>';
812
- //$input_field_value = $orig_file_name;
813
  }
814
 
815
  wc_add_order_item_meta( $item_id, '_wcj_product_input_fields_' . $this->scope . '_' . $i, $input_field_value );
1
  <?php
2
  /**
3
+ * Booster for WooCommerce - Product Input Fields - Core
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
9
  if ( ! defined( 'ABSPATH' ) ) exit;
10
 
11
+ if ( ! class_exists( 'WCJ_Product_Input_Fields_Core' ) ) :
12
 
13
+ class WCJ_Product_Input_Fields_Core {
14
 
15
  /** @var string scope. */
16
  public $scope = '';
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 3.1.0
22
+ * @todo save all info in product meta
23
  */
24
+ function __construct( $scope ) {
25
+ $this->scope = $scope;
26
+ if ( 'yes' === get_option( 'wcj_product_input_fields_' . $this->scope . '_enabled', 'no' ) ) {
27
+
28
+ // Show fields at frontend
29
+ add_action( get_option( 'wcj_product_input_fields_position', 'woocommerce_before_add_to_cart_button' ),
30
+ array( $this, 'add_product_input_fields_to_frontend' ), get_option( 'wcj_product_input_fields_position_priority', 100 ) );
31
+
32
+ // Process from $_POST to cart item data
33
+ add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_product_input_fields_on_add_to_cart' ), 100, 2 );
34
+ add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_product_input_fields_to_cart_item_data' ), 100, 3 );
35
+ // from session
36
+ add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'get_cart_item_product_input_fields_from_session' ), 100, 3 );
37
+
38
+ // Show details at cart, order details, emails
39
+ if ( 'data' === get_option( 'wcj_product_input_fields_display_options', 'name' ) ) {
40
+ add_filter( 'woocommerce_get_item_data', array( $this, 'add_product_input_fields_to_cart_item_display_data' ), PHP_INT_MAX, 2 );
41
+ } else {
42
+ add_filter( 'woocommerce_cart_item_name', array( $this, 'add_product_input_fields_to_cart_item_name' ), 100, 3 );
43
+ }
44
+ add_filter( 'woocommerce_order_item_name', array( $this, 'add_product_input_fields_to_order_item_name' ), 100, 2 );
45
+
46
+ // Add item meta from cart to order
47
+ add_action( 'woocommerce_add_order_item_meta', array( $this, 'add_product_input_fields_to_order_item_meta' ), 100, 3 );
48
+
49
+ // Make nicer name for product input fields in order at backend (shop manager)
50
+ add_action( 'woocommerce_after_order_itemmeta', array( $this, 'output_custom_input_fields_in_admin_order' ), 100, 3 );
51
+ if ( 'yes' === get_option( 'wcj_product_input_fields_make_nicer_name_enabled', 'yes' ) ) {
52
+ add_filter( 'woocommerce_hidden_order_itemmeta', array( $this, 'hide_custom_input_fields_default_output_in_admin_order' ), 100 );
53
+ }
54
+
55
+ // Add to emails
56
+ add_filter( 'woocommerce_email_attachments', array( $this, 'add_files_to_email_attachments' ), PHP_INT_MAX, 3 );
57
+
58
+ if ( 'local' === $this->scope ) {
59
+ // Product Edit
60
+ add_action( 'add_meta_boxes', array( $this, 'add_local_product_input_fields_meta_box_to_product_edit' ) );
61
+ add_action( 'save_post_product', array( $this, 'save_local_product_input_fields_on_product_edit' ), 999, 2 );
62
+ }
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Save product input fields on Product Edit.
68
+ *
69
+ * @version 2.2.9
70
+ */
71
+ function save_local_product_input_fields_on_product_edit( $post_id, $post ) {
72
+
73
+ // Check that we are saving with input fields displayed.
74
+ if ( ! isset( $_POST['woojetpack_product_input_fields_save_post'] ) )
75
+ return;
76
+
77
+ // Save enabled, required, title etc.
78
+ $default_total_input_fields = apply_filters( 'booster_get_option', 1, get_option( 'wcj_product_input_fields_local_total_number_default', 1 ) );
79
+ $total_input_fields_before_saving = get_post_meta( $post_id, '_' . 'wcj_product_input_fields_local_total_number', true );
80
+ $total_input_fields_before_saving = ( '' != $total_input_fields_before_saving ) ? $total_input_fields_before_saving : $default_total_input_fields;
81
+ $options = $this->get_options();
82
+ for ( $i = 1; $i <= $total_input_fields_before_saving; $i++ ) {
83
+ foreach ( $options as $option ) {
84
+ if ( isset( $_POST[ $option['id'] . $i ] ) ) {
85
+ update_post_meta( $post_id, '_' . $option['id'] . $i, $_POST[ $option['id'] . $i ] );
86
+ } elseif ( 'checkbox' === $option['type'] ) {
87
+ update_post_meta( $post_id, '_' . $option['id'] . $i, 'off' );
88
+ }
89
+ }
90
+ }
91
+
92
+ // Save total product input fields number
93
+ $option_name = 'wcj_product_input_fields_local_total_number';
94
+ $total_input_fields = isset( $_POST[ $option_name ] ) ? $_POST[ $option_name ] : $default_total_input_fields;
95
+ update_post_meta( $post_id, '_' . $option_name, $_POST[ $option_name ] );
96
+ }
97
+
98
+ /**
99
+ * add_local_product_input_fields_meta_box_to_product_edit.
100
+ *
101
+ * @version 2.4.8
102
+ */
103
+ function add_local_product_input_fields_meta_box_to_product_edit() {
104
+ add_meta_box(
105
+ 'wc-jetpack-product-input-fields',
106
+ __( 'Booster: Product Input Fields', 'woocommerce-jetpack' ),
107
+ array( $this, 'create_local_product_input_fields_meta_box' ),
108
+ 'product',
109
+ 'normal',
110
+ 'high'
111
+ );
112
+ }
113
+
114
+ /**
115
+ * create_local_product_input_fields_meta_box.
116
+ *
117
+ * @version 3.1.0
118
+ * @todo output options via standard "meta-box" mechanism
119
+ */
120
+ function create_local_product_input_fields_meta_box() {
121
+
122
+ $meta_box_id = 'product_input_fields';
123
+ $meta_box_desc = __( 'Product Input Fields', 'woocommerce-jetpack' );
124
+
125
+ $options = $this->get_options();
126
+
127
+ // Get total number
128
+ $current_post_id = get_the_ID();
129
+ $option_name = 'wcj_' . $meta_box_id . '_local_total_number';
130
+ // If none total number set - check for the default
131
+ if ( ! ( $total_number = apply_filters( 'booster_get_option', 1, get_post_meta( $current_post_id, '_' . $option_name, true ) ) ) )
132
+ $total_number = apply_filters( 'booster_get_option', 1, get_option( 'wcj_' . $meta_box_id . '_local_total_number_default', 1 ) );
133
+
134
+ // Start html
135
+ $html = '';
136
+
137
+ // Total number
138
+ $is_disabled = apply_filters( 'booster_get_message', '', 'readonly_string' );
139
+ $is_disabled_message = apply_filters( 'booster_get_message', '', 'desc' );
140
+ $html .= '<table>';
141
+ $html .= '<tr>';
142
+ $html .= '<th>';
143
+ $html .= __( 'Total number of ', 'woocommerce-jetpack' ) . $meta_box_desc;
144
+ $html .= '</th>';
145
+ $html .= '<td>';
146
+ $html .= '<input type="number" id="' . $option_name . '" name="' . $option_name . '" value="' . $total_number . '" ' . $is_disabled . '>';
147
+ $html .= '</td>';
148
+ $html .= '<td>';
149
+ $html .= __( 'Click "Update" product after you change this number.', 'woocommerce-jetpack' ) . '<br>' . $is_disabled_message;
150
+ $html .= '</td>';
151
+ $html .= '</td>';
152
+ $html .= '</tr>';
153
+ $html .= '</table>';
154
+
155
+ // The options
156
+ for ( $i = 1; $i <= $total_number; $i++ ) {
157
+ $data = array();
158
+ $html .= '<hr>';
159
+ $html .= '<h3>' . __( 'Product Input Field', 'woocommerce-jetpack' ) . ' #' . $i . '</h3>';
160
+ foreach ( $options as $option ) {
161
+ $option_id = $option['id'] . $i;
162
+ $option_value = get_post_meta( $current_post_id, '_' . $option_id, true );
163
+
164
+ if ( ! metadata_exists( 'post', $current_post_id, '_' . $option_id ) ) {
165
+ $option_value = $option['default'];
166
+ }
167
+
168
+ if ( 'checkbox' === $option['type'] )
169
+ $is_checked = checked( $option_value, 'on', false );
170
+
171
+ $select_options_html = '';
172
+ if ( 'select' === $option['type'] ) {
173
+ foreach( $option['options'] as $select_option_id => $select_option_label ) {
174
+ $select_options_html .= '<option value="' . $select_option_id . '"' . selected( $option_value, $select_option_id, false ) . '>' .
175
+ $select_option_label . '</option>';
176
+ }
177
+ }
178
+
179
+ switch ( $option['type'] ) {
180
+ case 'number':
181
+ case 'text':
182
+ $the_field = '<input class="widefat" type="' . $option['type'] . '" id="' . $option_id . '" name="' . $option_id . '" value="' . $option_value . '">';
183
+ break;
184
+ case 'textarea':
185
+ $the_field = '<textarea style="' . ( isset( $option['css'] ) ? $option['css'] : '' ) .
186
+ '" class="widefat" style="" id="' . $option_id . '" name="' . $option_id . '">' . $option_value . '</textarea>';
187
+ break;
188
+ case 'checkbox':
189
+ $the_field = '<input class="checkbox" type="checkbox" name="' . $option_id . '" id="' . $option_id . '" ' . $is_checked . ' />' . ' ' . $option['title'];
190
+ break;
191
+ case 'select':
192
+ $the_field = '<select class="widefat" id="' . $option_id . '" name="' . $option_id . '">' . $select_options_html . '</select>';
193
+ break;
194
+ }
195
+
196
+ $maybe_tooltip = ( isset( $option['short_title'] ) && $option['short_title'] != $option['title'] ? wc_help_tip( $option['title'], true ) : '' );
197
+
198
+ $data[] = array(
199
+ ( isset( $option['short_title'] ) ? $option['short_title'] : $option['title'] ) . $maybe_tooltip,
200
+ $the_field,
201
+ );
202
+ }
203
+ $html .= wcj_get_table_html( $data, array( 'table_heading_type' => 'vertical', 'table_class' => 'widefat striped', 'columns_styles' => array( 'width:33%;' ) ) );
204
+ }
205
+ $html .= '<input type="hidden" name="woojetpack_' . $meta_box_id . '_save_post" value="woojetpack_' . $meta_box_id . '_save_post">';
206
+
207
+ // Output
208
+ echo $html;
209
  }
210
 
211
  /**
212
  * get_options.
213
  *
214
+ * @version 3.1.0
215
  */
216
  function get_options() {
217
+ return require( 'wcj-product-input-fields-options.php' );
218
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
219
 
220
+ /**
221
+ * is_enabled_for_product_global.
222
+ *
223
+ * @version 3.1.0
224
+ * @since 3.1.0
225
+ */
226
+ function is_enabled_for_product_global( $field_nr, $product_id ) {
227
+ return wcj_is_enabled_for_product( $product_id, array(
228
+ 'include_products' => get_option( 'wcj_product_input_fields_in_products_' . 'global' . '_' . $field_nr, '' ),
229
+ 'exclude_products' => get_option( 'wcj_product_input_fields_ex_products_' . 'global' . '_' . $field_nr, '' ),
230
+ 'include_categories' => get_option( 'wcj_product_input_fields_in_cats_' . 'global' . '_' . $field_nr, '' ),
231
+ 'exclude_categories' => get_option( 'wcj_product_input_fields_ex_cats_' . 'global' . '_' . $field_nr, '' ),
232
+ 'include_tags' => get_option( 'wcj_product_input_fields_in_tags_' . 'global' . '_' . $field_nr, '' ),
233
+ 'exclude_tags' => get_option( 'wcj_product_input_fields_ex_tags_' . 'global' . '_' . $field_nr, '' ),
234
+ ) );
235
+ }
236
+
237
+ /**
238
+ * is_enabled.
239
+ *
240
+ * @version 3.1.0
241
+ * @since 3.1.0
242
+ */
243
+ function is_enabled( $field_nr, $product_id ) {
244
+ $is_enabled = $this->get_value( 'wcj_product_input_fields_enabled_' . $this->scope . '_' . $field_nr, $product_id, 'no' );
245
+ return ( ( 'on' === $is_enabled || 'yes' === $is_enabled ) && ( 'local' === $this->scope || $this->is_enabled_for_product_global( $field_nr, $product_id ) ) );
246
  }
247
 
248
  /**
302
  /**
303
  * output_custom_input_fields_in_admin_order.
304
  *
305
+ * @version 3.1.0
306
  */
307
  function output_custom_input_fields_in_admin_order( $item_id, $item, $_product ) {
308
  if ( null === $_product ) {
321
 
322
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $_product_id, '' );
323
  if ( 'file' === $type ) {
 
 
 
 
 
 
324
  $the_value = maybe_unserialize( $the_value );
325
  if ( isset( $the_value['name'] ) ) {
326
  $the_value = '<a href="' . add_query_arg( 'wcj_download_file', $item_id . '.' . pathinfo( $the_value['name'], PATHINFO_EXTENSION ) ) . '">' . $the_value['name'] . '</a>';
327
  }
328
  } else {
329
+ if ( 'no' === get_option( 'wcj_product_input_fields_make_nicer_name_enabled', 'yes' ) ) {
330
  continue;
331
  }
332
  }
340
 
341
  /**
342
  * get_value.
343
+ *
344
+ * @version 3.1.0
345
  */
346
  function get_value( $option_name, $product_id, $default ) {
347
+ return ( 'global' === $this->scope ? get_option( $option_name, $default ) : get_post_meta( $product_id, '_' . $option_name, true ) );
348
  }
349
 
350
  /**
351
  * validate_product_input_fields_on_add_to_cart.
352
  *
353
+ * @version 3.1.0
354
  */
355
  function validate_product_input_fields_on_add_to_cart( $passed, $product_id ) {
356
  $total_number = apply_filters( 'booster_get_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $product_id, 1 ) );
357
  for ( $i = 1; $i <= $total_number; $i++ ) {
358
 
359
+ if ( ! $this->is_enabled( $i, $product_id ) ) {
 
360
  continue;
361
  }
362
 
392
  if ( ! in_array( $file_type, $file_accept ) ) {
393
  $passed = false;
394
  wc_add_notice( __( 'Wrong file type!', 'woocommerce-jetpack' ), 'error' );
 
395
  }
396
  }
397
  }
411
  /**
412
  * add_product_input_fields_to_frontend.
413
  *
414
+ * @version 3.1.0
415
+ * @todo `$set_value` - add "default" option for all other types except checkbox
416
+ * @todo `$set_value` - 'file' type
417
+ * @todo add `required` attributes
418
  */
419
  function add_product_input_fields_to_frontend() {
420
  global $product;
422
  return;
423
  }
424
  $_product_id = wcj_get_product_id_or_variation_parent_id( $product );
425
+ $fields = array();
426
  $total_number = apply_filters( 'booster_get_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $_product_id, 1 ) );
427
  for ( $i = 1; $i <= $total_number; $i++ ) {
428
 
429
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $_product_id, 'text' );
 
430
  $is_required = $this->get_value( 'wcj_product_input_fields_required_' . $this->scope . '_' . $i, $_product_id, 'no' );
431
  $title = $this->get_value( 'wcj_product_input_fields_title_' . $this->scope . '_' . $i, $_product_id, '' );
432
  $placeholder = $this->get_value( 'wcj_product_input_fields_placeholder_' . $this->scope . '_' . $i, $_product_id, '' );
466
  $title .= get_option( 'wcj_product_input_fields_frontend_view_required_html', '&nbsp;<abbr class="required" title="required">*</abbr>' );
467
  }
468
 
469
+ if ( $this->is_enabled( $i, $_product_id ) ) {
470
+
471
+ $set_value = ( isset( $_POST[ $field_name ] ) ?
472
+ $_POST[ $field_name ] :
473
+ ( 'checkbox' == $type ?
474
+ ( 'yes' === $this->get_value( 'wcj_product_input_fields_type_checkbox_default_' . $this->scope . '_' . $i, $_product_id, 'no' ) ? 'on' : 'off' ) :
475
+ ''
476
+ )
477
+ );
478
+
479
  $html = '';
480
  switch ( $type ) {
481
 
485
  case 'password':
486
  case 'email':
487
  case 'tel':
488
+ $html = '<input value="' . $set_value . '" class="wcj_product_input_fields" id="' . $field_name . '" type="' . $type . '" name="' .
489
+ $field_name . '" placeholder="' . $placeholder . '"' . $custom_attributes . '>';
490
  break;
491
 
492
  case 'checkbox':
 
493
  $checked = checked(
494
+ $set_value,
495
+ 'on',
496
  false
497
  );
498
+ $html = '<input class="wcj_product_input_fields" id="' . $field_name . '" type="' . $type . '" name="' . $field_name . '"' .
499
+ $custom_attributes . $checked . '>';
500
  break;
501
 
502
  case 'datepicker':
503
+ $html = '<input value="' . $set_value . '" class="wcj_product_input_fields" id="' . $field_name . '" ' . $datepicker_year . 'firstday="' .
504
+ $datepicker_firstday . '" dateformat="' . $datepicker_format . '" mindate="' .
505
+ $datepicker_mindate . '" maxdate="' . $datepicker_maxdate . '" type="' .
506
+ $type . '" display="date" name="' . $field_name . '" placeholder="' . $placeholder . '"' . $custom_attributes . '>';
507
  break;
508
 
509
  case 'weekpicker':
510
+ $html = '<input value="' . $set_value . '" class="wcj_product_input_fields" id="' . $field_name . '" ' . $datepicker_year . 'firstday="' .
511
+ $datepicker_firstday . '" dateformat="' . $datepicker_format . '" mindate="' .
512
+ $datepicker_mindate . '" maxdate="' . $datepicker_maxdate . '" type="' .
513
+ $type . '" display="week" name="' . $field_name . '" placeholder="' . $placeholder . '"' . $custom_attributes . '>';
514
  break;
515
 
516
  case 'timepicker':
517
+ $html = '<input value="' . $set_value . '" class="wcj_product_input_fields" id="' . $field_name . '"' .
518
+ $timepicker_mintime . $timepicker_maxtime . ' interval="' . $timepicker_interval . '" timeformat="' .
519
+ $timepicker_format . '" type="' . $type . '" display="time" name="' . $field_name . '" placeholder="' .
520
+ $placeholder . '"' . $custom_attributes . '>';
521
  break;
522
 
523
  case 'textarea':
524
+ $html = '<textarea class="wcj_product_input_fields" id="' . $field_name . '" name="' . $field_name . '" placeholder="' . $placeholder . '">' .
525
+ $set_value . '</textarea>';
526
  break;
527
 
528
  case 'select':
 
529
  $select_options_raw = $this->get_value( 'wcj_product_input_fields_type_select_options_' . $this->scope . '_' . $i, $_product_id, '' );
530
  $select_options = wcj_get_select_options( $select_options_raw, false );
531
  if ( '' != $placeholder ) {
534
  $select_options_html = '';
535
  if ( ! empty( $select_options ) ) {
536
  reset( $select_options );
537
+ $value = ( '' != $set_value ? $set_value : key( $select_options ) );
538
  foreach ( $select_options as $select_option_key => $select_option_title ) {
539
  $select_options_html .= '<option value="' . $select_option_key . '" ' . selected( $value, $select_option_key, false ) . '>';
540
  $select_options_html .= $select_option_title;
545
  break;
546
 
547
  case 'radio':
 
548
  $select_options_raw = $this->get_value( 'wcj_product_input_fields_type_select_options_' . $this->scope . '_' . $i, $_product_id, '' );
549
  $select_options = wcj_get_select_options( $select_options_raw, false );
550
  $select_options_html = '';
 
551
  if ( ! empty( $select_options ) ) {
552
  reset( $select_options );
553
+ $value = ( '' != $set_value ? $set_value : key( $select_options ) );
554
  foreach ( $select_options as $option_key => $option_text ) {
555
  $select_options_html .= '<input type="radio" class="input-radio wcj_product_input_fields" value="' . esc_attr( $option_key ) .
556
  '" name="' . $field_name . '" id="' . $field_name . '_' . esc_attr( $option_key ) . '"' . checked( $value, $option_key, false ) . ' />';
562
  break;
563
 
564
  case 'country':
 
565
  $countries = WC()->countries->get_allowed_countries();
566
  if ( sizeof( $countries ) > 1 ) {
567
+ $value = ( '' != $set_value ? $set_value : key( $countries ) );
568
  $field = '<select name="' . $field_name . '" id="' . $field_name . '" class="country_to_state country_select wcj_product_input_fields">' .
569
  '<option value="">'.__( 'Select a country&hellip;', 'woocommerce' ) .'</option>';
570
  foreach ( $countries as $ckey => $cvalue ) {
575
  }
576
  break;
577
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
578
  }
579
  $html = str_replace( array( '%field_title%', '%field_id%', '%field_html%' ), array( $title, $field_name, $html ),
580
  get_option( 'wcj_product_input_fields_field_template', '<p><label for="%field_id%">%field_title%</label> %field_html%</p>' ) );
581
+ if ( 0 == ( $field_order = $this->get_value( 'wcj_product_input_fields_order_' . $this->scope . '_' . $i, $_product_id, 0 ) ) ) {
582
+ $field_order = $i;
583
+ }
584
+ $fields[ $field_order ] = apply_filters( 'wcj_product_input_field_frontend_html', $html, array(
585
  'title' => $title,
586
  'type' => $type,
587
  'field_name' => $field_name,
593
  ) );
594
  }
595
  }
596
+ ksort( $fields );
597
+ if ( ! empty ( $fields ) ) {
598
+ echo get_option( 'wcj_product_input_fields_start_template', '' ) . implode( $fields ) . get_option( 'wcj_product_input_fields_end_template', '' );
599
  }
600
  }
601
 
602
  /**
603
  * add_product_input_fields_to_cart_item_data - from $_POST to $cart_item_data
604
  *
605
+ * @version 3.1.0
606
  */
607
  function add_product_input_fields_to_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
608
  $total_number = apply_filters( 'booster_get_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $product_id, 1 ) );
609
  for ( $i = 1; $i <= $total_number; $i++ ) {
610
+ if ( ! $this->is_enabled( $i, $product_id ) ) {
 
611
  continue;
612
  }
613
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $product_id, '' );
643
  /**
644
  * Adds product input values to order details (and emails).
645
  *
646
+ * @version 3.1.0
647
  */
648
  function add_product_input_fields_to_order_item_name( $name, $item, $is_cart = false ) {
649
  $total_number = apply_filters( 'booster_get_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $item['product_id'], 1 ) );
657
  $item_template = get_option( 'wcj_product_input_fields_frontend_view_order_table_format', '&nbsp;| %title% %value%' );
658
  }
659
  for ( $i = 1; $i <= $total_number; $i++ ) {
660
+ if ( ! $this->is_enabled( $i, $item['product_id'] ) ) {
 
661
  continue;
662
  }
663
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $item['product_id'], '' );
683
  $value = maybe_unserialize( $value );
684
  $value = ( isset( $value['name'] ) ) ? $value['name'] : '';
685
  }
686
+ if ( '' != $value && is_string( $value ) ) {
687
  $name .= str_replace( array( '%title%', '%value%' ), array( $title, $value ), $item_template );
688
  }
689
  }
706
  /**
707
  * add_product_input_fields_to_cart_item_display_data.
708
  *
709
+ * @version 3.1.0
710
  * @since 2.9.0
711
  */
712
  function add_product_input_fields_to_cart_item_display_data( $item_data, $item ) {
715
  return $item_data;
716
  }
717
  for ( $i = 1; $i <= $total_number; $i++ ) {
718
+ if ( ! $this->is_enabled( $i, $item['product_id'] ) ) {
 
719
  continue;
720
  }
721
  $type = $this->get_value( 'wcj_product_input_fields_type_' . $this->scope . '_' . $i, $item['product_id'], '' );
769
  if ( ! file_exists( $upload_dir ) ) {
770
  mkdir( $upload_dir, 0755, true );
771
  }
 
772
  $upload_dir_and_name = $upload_dir . '/' . $name;
 
773
  $file_data = file_get_contents( $tmp_name );
774
  file_put_contents( $upload_dir_and_name, $file_data );
775
  unlink( $tmp_name );
 
776
  $input_field_value['tmp_name'] = addslashes( $upload_dir_and_name );
777
  $input_field_value['wcj_type'] = 'file';
 
 
 
 
778
  }
779
 
780
  wc_add_order_item_meta( $item_id, '_wcj_product_input_fields_' . $this->scope . '_' . $i, $input_field_value );
includes/input-fields/class-wcj-product-input-fields-global.php DELETED
@@ -1,77 +0,0 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Product Input Fields - Global
4
- *
5
- * @version 2.9.0
6
- * @author Algoritmika Ltd.
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) exit;
10
-
11
- if ( ! class_exists( 'WCJ_Product_Input_Fields_Global' ) ) :
12
-
13
- class WCJ_Product_Input_Fields_Global extends WCJ_Product_Input_Fields_Abstract {
14
-
15
- /**
16
- * Constructor.
17
- *
18
- * @version 2.9.0
19
- */
20
- function __construct() {
21
-
22
- $this->scope = 'global';
23
-
24
- if ( 'yes' === get_option( 'wcj_product_input_fields_global_enabled' ) ) {
25
-
26
- // Show fields at frontend
27
- add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'add_product_input_fields_to_frontend' ), 100 );
28
-
29
- // Process from $_POST to cart item data
30
- add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_product_input_fields_on_add_to_cart' ), 100, 2 );
31
- add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_product_input_fields_to_cart_item_data' ), 100, 3 );
32
- // from session
33
- add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'get_cart_item_product_input_fields_from_session' ), 100, 3 );
34
-
35
- // Show details at cart, order details, emails
36
- if ( 'data' === get_option( 'wcj_product_input_fields_display_options', 'name' ) ) {
37
- add_filter( 'woocommerce_get_item_data', array( $this, 'add_product_input_fields_to_cart_item_display_data' ), PHP_INT_MAX, 2 );
38
- } else {
39
- add_filter( 'woocommerce_cart_item_name', array( $this, 'add_product_input_fields_to_cart_item_name' ), 100, 3 );
40
- }
41
- add_filter( 'woocommerce_order_item_name', array( $this, 'add_product_input_fields_to_order_item_name' ), 100, 2 );
42
-
43
- // Add item meta from cart to order
44
- add_action( 'woocommerce_add_order_item_meta', array( $this, 'add_product_input_fields_to_order_item_meta' ), 100, 3 );
45
-
46
- // Make nicer name for product input fields in order at backend (shop manager)
47
- //add_action( 'woocommerce_before_order_itemmeta', array( $this, 'start_making_nicer_name_for_product_input_fields' ), 100, 3 );
48
- //add_action( 'woocommerce_before_order_itemmeta', 'ob_start' );
49
- //add_action( 'woocommerce_after_order_itemmeta', array( $this, 'finish_making_nicer_name_for_product_input_fields' ), 100, 3 );
50
- add_action( 'woocommerce_after_order_itemmeta', array( $this, 'output_custom_input_fields_in_admin_order' ), 100, 3 );
51
- if ( 'yes' === get_option( 'wcj_product_input_fields_make_nicer_name_enabled' ) ) {
52
- add_filter( 'woocommerce_hidden_order_itemmeta', array( $this, 'hide_custom_input_fields_default_output_in_admin_order' ), 100 );
53
- }
54
- //add_filter( 'woocommerce_attribute_label', array( $this, 'change_woocommerce_attribute_label' ), PHP_INT_MAX, 2 );
55
-
56
- // Add to emails
57
- add_filter( 'woocommerce_email_attachments', array( $this, 'add_files_to_email_attachments' ), PHP_INT_MAX, 3 );
58
-
59
- //add_action( 'init', array( $this, 'init' ), 100 );
60
- //add_action( 'woocommerce_ajax_added_to_cart', array( $this, 'ajax_add_to_cart' ), 100 );
61
- //add_action( 'woocommerce_loop_add_to_cart_link', array( $this, 'replace_loop_add_to_cart_button' ), 100, 2 );
62
- //add_action( 'woocommerce_after_shop_loop_item', array( $this, 'add_product_input_fields_to_frontend' ), 100 );
63
- }
64
- }
65
-
66
- /**
67
- * get_value.
68
- */
69
- function get_value( $option_name, $product_id, $default ) {
70
- return get_option( $option_name, $default );
71
- }
72
-
73
- }
74
-
75
- endif;
76
-
77
- return new WCJ_Product_Input_Fields_Global();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/input-fields/class-wcj-product-input-fields-per-product.php DELETED
@@ -1,216 +0,0 @@
1
- <?php
2
- /**
3
- * Booster for WooCommerce - Product Input Fields - per Product
4
- *
5
- * @version 2.9.0
6
- * @author Algoritmika Ltd.
7
- */
8
-
9
- if ( ! defined( 'ABSPATH' ) ) exit;
10
-
11
- if ( ! class_exists( 'WCJ_Product_Input_Fields_Per_Product' ) ) :
12
-
13
- class WCJ_Product_Input_Fields_Per_Product extends WCJ_Product_Input_Fields_Abstract {
14
-
15
- /**
16
- * Constructor.
17
- *
18
- * @version 2.9.0
19
- */
20
- function __construct() {
21
-
22
- $this->scope = 'local';
23
-
24
- if ( 'yes' === get_option( 'wcj_product_input_fields_local_enabled' ) ) {
25
-
26
- // Product Edit
27
- add_action( 'add_meta_boxes', array( $this, 'add_local_product_input_fields_meta_box_to_product_edit' ) );
28
- add_action( 'save_post_product', array( $this, 'save_local_product_input_fields_on_product_edit' ), 999, 2 );
29
-
30
- // Show fields at frontend
31
- add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'add_product_input_fields_to_frontend' ), 100 );
32
-
33
- // Process from $_POST to cart item data
34
- add_filter( 'woocommerce_add_to_cart_validation', array( $this, 'validate_product_input_fields_on_add_to_cart' ), 100, 2 );
35
- add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_product_input_fields_to_cart_item_data' ), 100, 3 );
36
- // from session
37
- add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'get_cart_item_product_input_fields_from_session' ), 100, 3 );
38
-
39
- // Show details at cart, order details, emails
40
- if ( 'data' === get_option( 'wcj_product_input_fields_display_options', 'name' ) ) {
41
- add_filter( 'woocommerce_get_item_data', array( $this, 'add_product_input_fields_to_cart_item_display_data' ), PHP_INT_MAX, 2 );
42
- } else {
43
- add_filter( 'woocommerce_cart_item_name', array( $this, 'add_product_input_fields_to_cart_item_name' ), 100, 3 );
44
- }
45
- add_filter( 'woocommerce_order_item_name', array( $this, 'add_product_input_fields_to_order_item_name' ), 100, 2 );
46
-
47
- // Add item meta from cart to order
48
- add_action( 'woocommerce_add_order_item_meta', array( $this, 'add_product_input_fields_to_order_item_meta' ), 100, 3 );
49
-
50
- // Make nicer name for product input fields in order at backend (shop manager)
51
- // add_action( 'woocommerce_before_order_itemmeta', array( $this, 'start_making_nicer_name_for_product_input_fields' ), 100, 3 );
52
- // add_action( 'woocommerce_before_order_itemmeta', 'ob_start' );
53
- // add_action( 'woocommerce_after_order_itemmeta', array( $this, 'finish_making_nicer_name_for_product_input_fields' ), 100, 3 );
54
- add_action( 'woocommerce_after_order_itemmeta', array( $this, 'output_custom_input_fields_in_admin_order' ), 100, 3 );
55
- if ( 'yes' === get_option( 'wcj_product_input_fields_make_nicer_name_enabled' ) ) {
56
- add_filter( 'woocommerce_hidden_order_itemmeta', array( $this, 'hide_custom_input_fields_default_output_in_admin_order' ), 100 );
57
- }
58
- // add_filter( 'woocommerce_attribute_label', array( $this, 'change_woocommerce_attribute_label' ), PHP_INT_MAX, 2 );
59
-
60
- // Add to emails
61
- add_filter( 'woocommerce_email_attachments', array( $this, 'add_files_to_email_attachments' ), PHP_INT_MAX, 3 );
62
- }
63
- }
64
-
65
- /**
66
- * get_value.
67
- */
68
- function get_value( $option_name, $product_id, $default ) {
69
- return get_post_meta( $product_id, '_' . $option_name, true );
70
- }
71
-
72
- /**
73
- * Save product input fields on Product Edit.
74
- *
75
- * @version 2.2.9
76
- */
77
- function save_local_product_input_fields_on_product_edit( $post_id, $post ) {
78
-
79
- // Check that we are saving with input fields displayed.
80
- if ( ! isset( $_POST['woojetpack_product_input_fields_save_post'] ) )
81
- return;
82
-
83
- // Save enabled, required, title etc.
84
- $default_total_input_fields = apply_filters( 'booster_get_option', 1, get_option( 'wcj_product_input_fields_local_total_number_default', 1 ) );
85
- $total_input_fields_before_saving = get_post_meta( $post_id, '_' . 'wcj_product_input_fields_local_total_number', true );
86
- $total_input_fields_before_saving = ( '' != $total_input_fields_before_saving ) ? $total_input_fields_before_saving : $default_total_input_fields;
87
- $options = $this->get_options();
88
- for ( $i = 1; $i <= $total_input_fields_before_saving; $i++ ) {
89
- foreach ( $options as $option ) {
90
- if ( isset( $_POST[ $option['id'] . $i ] ) )
91
- update_post_meta( $post_id, '_' . $option['id'] . $i, $_POST[ $option['id'] . $i ] );
92
- // elseif ( 'wcj_product_input_fields_title_local_' != $option['id'] && 'wcj_product_input_fields_placeholder_local_' != $option['id'] )
93
- elseif ( 'checkbox' === $option['type'] )
94
- update_post_meta( $post_id, '_' . $option['id'] . $i, 'off' );
95
- }
96
- }
97
-
98
- // Save total product input fields number
99
- $option_name = 'wcj_product_input_fields_local_total_number';
100
- $total_input_fields = isset( $_POST[ $option_name ] ) ? $_POST[ $option_name ] : $default_total_input_fields;
101
- update_post_meta( $post_id, '_' . $option_name, $_POST[ $option_name ] );
102
- }
103
-
104
- /**
105
- * add_local_product_input_fields_meta_box_to_product_edit.
106
- *
107
- * @version 2.4.8
108
- */
109
- function add_local_product_input_fields_meta_box_to_product_edit() {
110
- add_meta_box(
111
- 'wc-jetpack-product-input-fields',
112
- __( 'Booster: Product Input Fields', 'woocommerce-jetpack' ),
113
- array( $this, 'create_local_product_input_fields_meta_box' ),
114
- 'product',
115
- 'normal',
116
- 'high'
117
- );
118
- }
119
-
120
- /**
121
- * create_local_product_input_fields_meta_box.
122
- *
123
- * @version 2.2.9
124
- */
125
- function create_local_product_input_fields_meta_box() {
126
-
127
- $meta_box_id = 'product_input_fields';
128
- $meta_box_desc = __( 'Product Input Fields', 'woocommerce-jetpack' );
129
-
130
- $options = $this->get_options();
131
-
132
- // Get total number
133
- $current_post_id = get_the_ID();
134
- $option_name = 'wcj_' . $meta_box_id . '_local_total_number';
135
- // If none total number set - check for the default
136
- if ( ! ( $total_number = apply_filters( 'booster_get_option', 1, get_post_meta( $current_post_id, '_' . $option_name, true ) ) ) )
137
- $total_number = apply_filters( 'booster_get_option', 1, get_option( 'wcj_' . $meta_box_id . '_local_total_number_default', 1 ) );
138
-
139
- // Start html
140
- $html = '';
141
-
142
- // Total number
143
- $is_disabled = apply_filters( 'booster_get_message', '', 'readonly_string' );
144
- $is_disabled_message = apply_filters( 'booster_get_message', '', 'desc' );
145
- $html .= '<table>';
146
- $html .= '<tr>';
147
- $html .= '<th>';
148
- $html .= __( 'Total number of ', 'woocommerce-jetpack' ) . $meta_box_desc;
149
- $html .= '</th>';
150
- $html .= '<td>';
151
- $html .= '<input type="number" id="' . $option_name . '" name="' . $option_name . '" value="' . $total_number . '" ' . $is_disabled . '>';
152
- $html .= '</td>';
153
- $html .= '<td>';
154
- $html .= __( 'Click "Update" product after you change this number.', 'woocommerce-jetpack' ) . '<br>' . $is_disabled_message;
155
- $html .= '</td>';
156
- $html .= '</td>';
157
- $html .= '</tr>';
158
- $html .= '</table>';
159
-
160
- // The options
161
- // $html .= '<h4>' . $meta_box_desc . '</h4>';
162
- for ( $i = 1; $i <= $total_number; $i++ ) {
163
- $data = array();
164
- $html .= '<hr>';
165
- $html .= '<h4>' . __( 'Product Input Field', 'woocommerce-jetpack' ) . ' #' . $i . '</h4>';
166
- foreach ( $options as $option ) {
167
- $option_id = $option['id'] . $i;
168
- $option_value = get_post_meta( $current_post_id, '_' . $option_id, true );
169
-
170
- if ( ! metadata_exists( 'post', $current_post_id, '_' . $option_id ) ) {
171
- $option_value = $option['default'];
172
- }
173
-
174
- if ( 'checkbox' === $option['type'] )
175
- $is_checked = checked( $option_value, 'on', false );
176
-
177
- $select_options_html = '';
178
- if ( 'select' === $option['type'] ) {
179
- foreach( $option['options'] as $select_option_id => $select_option_label ) {
180
- $select_options_html .= '<option value="' . $select_option_id . '"' . selected( $option_value, $select_option_id, false ) . '>' . $select_option_label . '</option>';
181
- }
182
- }
183
-
184
- switch ( $option['type'] ) {
185
- case 'number':
186
- case 'text':
187
- $the_field = '<input type="' . $option['type'] . '" id="' . $option_id . '" name="' . $option_id . '" value="' . $option_value . '">';
188
- break;
189
- case 'textarea':
190
- $the_field = '<textarea style="width:100%;" id="' . $option_id . '" name="' . $option_id . '">' . $option_value . '</textarea>';
191
- break;
192
- case 'checkbox':
193
- $the_field = '<input class="checkbox" type="checkbox" name="' . $option_id . '" id="' . $option_id . '" ' . $is_checked . ' />';
194
- break;
195
- case 'select':
196
- $the_field = '<select id="' . $option_id . '" name="' . $option_id . '">' . $select_options_html . '</select>';
197
- break;
198
- }
199
- $data[] = array(
200
- ( isset( $option['short_title'] ) ) ? $option['short_title'] : $option['title'],
201
- $the_field,
202
- );
203
- }
204
- $html .= wcj_get_table_html( $data, array( 'table_heading_type' => 'vertical', 'columns_styles' => array( 'text-align:right;', ), ) );
205
- }
206
- $html .= '<input type="hidden" name="woojetpack_' . $meta_box_id . '_save_post" value="woojetpack_' . $meta_box_id . '_save_post">';
207
-
208
- // Output
209
- echo $html;
210
- }
211
-
212
- }
213
-
214
- endif;
215
-
216
- return new WCJ_Product_Input_Fields_Per_Product();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/input-fields/wcj-product-input-fields-options.php ADDED
@@ -0,0 +1,212 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Product Input Fields - Options
4
+ *
5
+ * @version 3.1.0
6
+ * @since 3.1.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit;
11
+
12
+ return array(
13
+ array(
14
+ 'id' => 'wcj_product_input_fields_enabled_' . $this->scope . '_',
15
+ 'title' => __( 'Enabled', 'woocommerce-jetpack' ),
16
+ 'type' => 'checkbox',
17
+ 'default' => 'no',
18
+ ),
19
+ array(
20
+ 'id' => 'wcj_product_input_fields_order_' . $this->scope . '_',
21
+ 'short_title' => __( 'Order', 'woocommerce-jetpack' ),
22
+ 'title' => __( 'Set to zero for default order.', 'woocommerce-jetpack' ),
23
+ 'type' => 'number',
24
+ 'default' => 0,
25
+ ),
26
+ array(
27
+ 'id' => 'wcj_product_input_fields_type_' . $this->scope . '_',
28
+ 'title' => __( 'Type', 'woocommerce-jetpack' ),
29
+ 'type' => 'select',
30
+ 'default' => 'text',
31
+ 'options' => array(
32
+ 'text' => __( 'Text', 'woocommerce-jetpack' ),
33
+ 'textarea' => __( 'Textarea', 'woocommerce-jetpack' ),
34
+ 'number' => __( 'Number', 'woocommerce-jetpack' ),
35
+ 'checkbox' => __( 'Checkbox', 'woocommerce-jetpack' ),
36
+ 'file' => __( 'File', 'woocommerce-jetpack' ),
37
+ 'datepicker' => __( 'Datepicker', 'woocommerce-jetpack' ),
38
+ 'weekpicker' => __( 'Weekpicker', 'woocommerce-jetpack' ),
39
+ 'timepicker' => __( 'Timepicker', 'woocommerce-jetpack' ),
40
+ 'select' => __( 'Select', 'woocommerce-jetpack' ),
41
+ 'radio' => __( 'Radio', 'woocommerce-jetpack' ),
42
+ 'password' => __( 'Password', 'woocommerce-jetpack' ),
43
+ 'country' => __( 'Country', 'woocommerce-jetpack' ),
44
+ // 'state' => __( 'State', 'woocommerce-jetpack' ),
45
+ 'email' => __( 'Email', 'woocommerce-jetpack' ),
46
+ 'tel' => __( 'Phone', 'woocommerce-jetpack' ),
47
+ ),
48
+ ),
49
+ array(
50
+ 'id' => 'wcj_product_input_fields_title_' . $this->scope . '_',
51
+ 'title' => __( 'Title', 'woocommerce-jetpack' ),
52
+ 'type' => 'textarea',
53
+ 'default' => '',
54
+ ),
55
+ array(
56
+ 'id' => 'wcj_product_input_fields_placeholder_' . $this->scope . '_',
57
+ 'title' => __( 'Placeholder', 'woocommerce-jetpack' ),
58
+ 'type' => 'textarea',
59
+ 'default' => '',
60
+ ),
61
+ array(
62
+ 'id' => 'wcj_product_input_fields_required_' . $this->scope . '_',
63
+ 'title' => __( 'Required', 'woocommerce-jetpack' ),
64
+ 'type' => 'checkbox',
65
+ 'default' => 'no',
66
+ ),
67
+ array(
68
+ 'id' => 'wcj_product_input_fields_required_message_' . $this->scope . '_',
69
+ 'title' => __( 'Message on required', 'woocommerce-jetpack' ),
70
+ 'type' => 'textarea',
71
+ 'default' => '',
72
+ ),
73
+ /* array(
74
+ 'id' => 'wcj_product_input_fields_type_checkbox_' . $this->scope . '_',
75
+ 'title' => __( 'If checkbox is selected, set possible pairs here.', 'woocommerce-jetpack' ),
76
+ 'type' => 'select',
77
+ 'default' => 'yes_no',
78
+ 'options' => array(
79
+ 'yes_no' => __( 'Yes / No', 'woocommerce-jetpack' ),
80
+ 'on_off' => __( 'On / Off', 'woocommerce-jetpack' ),
81
+ ),
82
+ ), */
83
+ array(
84
+ 'id' => 'wcj_product_input_fields_type_checkbox_yes_' . $this->scope . '_',
85
+ 'title' => __( 'If checkbox is selected, set value for ON here', 'woocommerce-jetpack' ),
86
+ 'short_title' => __( 'Checkbox: ON', 'woocommerce-jetpack' ),
87
+ 'type' => 'text',
88
+ 'default' => __( 'Yes', 'woocommerce-jetpack' ),
89
+ ),
90
+ array(
91
+ 'id' => 'wcj_product_input_fields_type_checkbox_no_' . $this->scope . '_',
92
+ 'title' => __( 'If checkbox is selected, set value for OFF here', 'woocommerce-jetpack' ),
93
+ 'short_title' => __( 'Checkbox: OFF', 'woocommerce-jetpack' ),
94
+ 'type' => 'text',
95
+ 'default' => __( 'No', 'woocommerce-jetpack' ),
96
+ ),
97
+ array(
98
+ 'id' => 'wcj_product_input_fields_type_checkbox_default_' . $this->scope . '_',
99
+ 'title' => __( 'If checkbox is selected, set default value here', 'woocommerce-jetpack' ),
100
+ 'short_title' => __( 'Checkbox: Default', 'woocommerce-jetpack' ),
101
+ 'type' => 'select',
102
+ 'default' => 'no',
103
+ 'options' => array(
104
+ 'no' => __( 'Not Checked', 'woocommerce-jetpack' ),
105
+ 'yes' => __( 'Checked', 'woocommerce-jetpack' ),
106
+ ),
107
+ ),
108
+ array(
109
+ 'id' => 'wcj_product_input_fields_type_file_accept_' . $this->scope . '_',
110
+ 'title' => __( 'If file is selected, set accepted file types here. E.g.: ".jpg,.jpeg,.png". Leave blank to accept all files', 'woocommerce-jetpack' )
111
+ . '. ' . __( 'Visit <a href="https://www.w3schools.com/tags/att_input_accept.asp" target="_blank">documentation on input accept attribute</a> for valid option formats', 'woocommerce-jetpack' ),
112
+ 'short_title' => __( 'File: Accepted types', 'woocommerce-jetpack' ),
113
+ 'type' => 'text',
114
+ 'default' => __( '.jpg,.jpeg,.png', 'woocommerce-jetpack' ),
115
+ ),
116
+ array(
117
+ 'id' => 'wcj_product_input_fields_type_file_max_size_' . $this->scope . '_',
118
+ 'title' => __( 'If file is selected, set max file size here. Set to zero to accept all files', 'woocommerce-jetpack' ),
119
+ 'short_title' => __( 'File: Max size', 'woocommerce-jetpack' ),
120
+ 'type' => 'number',
121
+ 'default' => 0,
122
+ ),
123
+ array(
124
+ 'id' => 'wcj_product_input_fields_type_datepicker_format_' . $this->scope . '_',
125
+ 'title' => __( 'If datepicker/weekpicker is selected, set date format here. Visit <a href="https://codex.wordpress.org/Formatting_Date_and_Time" target="_blank">documentation on date and time formatting</a> for valid date formats', 'woocommerce-jetpack' ),
126
+ 'desc_tip' => __( 'Leave blank to use your current WordPress format', 'woocommerce-jetpack' ) . ': ' . get_option( 'date_format' ),
127
+ 'short_title' => __( 'Datepicker/Weekpicker: Date format', 'woocommerce-jetpack' ),
128
+ 'type' => 'text',
129
+ 'default' => '',
130
+ ),
131
+ array(
132
+ 'id' => 'wcj_product_input_fields_type_datepicker_mindate_' . $this->scope . '_',
133
+ 'title' => __( 'If datepicker/weekpicker is selected, set min date (in days) here', 'woocommerce-jetpack' ),
134
+ 'short_title' => __( 'Datepicker/Weekpicker: Min date', 'woocommerce-jetpack' ),
135
+ 'type' => 'number',
136
+ 'default' => -365,
137
+ ),
138
+ array(
139
+ 'id' => 'wcj_product_input_fields_type_datepicker_maxdate_' . $this->scope . '_',
140
+ 'title' => __( 'If datepicker/weekpicker is selected, set max date (in days) here', 'woocommerce-jetpack' ),
141
+ 'short_title' => __( 'Datepicker/Weekpicker: Max date', 'woocommerce-jetpack' ),
142
+ 'type' => 'number',
143
+ 'default' => 365,
144
+ ),
145
+ array(
146
+ 'id' => 'wcj_product_input_fields_type_datepicker_changeyear_' . $this->scope . '_',
147
+ 'title' => __( 'If datepicker/weekpicker is selected, set if you want to add year selector', 'woocommerce-jetpack' ),
148
+ 'short_title' => __( 'Datepicker/Weekpicker: Change year', 'woocommerce-jetpack' ),
149
+ 'type' => 'checkbox',
150
+ 'default' => 'no',
151
+ ),
152
+ array(
153
+ 'id' => 'wcj_product_input_fields_type_datepicker_yearrange_' . $this->scope . '_',
154
+ 'title' => __( 'If datepicker/weekpicker is selected, and year selector is enabled, set year range here', 'woocommerce-jetpack' ),
155
+ 'short_title' => __( 'Datepicker/Weekpicker: Year range', 'woocommerce-jetpack' ),
156
+ // 'desc_tip' => __( 'The range of years displayed in the year drop-down: either relative to today\'s year ("-nn:+nn"), relative to the currently selected year ("c-nn:c+nn"), absolute ("nnnn:nnnn"), or combinations of these formats ("nnnn:-nn"). Note that this option only affects what appears in the drop-down, to restrict which dates may be selected use the minDate and/or maxDate options.', 'woocommerce-jetpack' ),
157
+ 'type' => 'text',
158
+ 'default' => 'c-10:c+10',
159
+ ),
160
+ array(
161
+ 'id' => 'wcj_product_input_fields_type_datepicker_firstday_' . $this->scope . '_',
162
+ 'title' => __( 'If datepicker/weekpicker is selected, set first week day here', 'woocommerce-jetpack' ),
163
+ 'short_title' => __( 'Datepicker/Weekpicker: First week day', 'woocommerce-jetpack' ),
164
+ 'type' => 'select',
165
+ 'default' => 0,
166
+ 'options' => array(
167
+ __( 'Sunday', 'woocommerce-jetpack' ),
168
+ __( 'Monday', 'woocommerce-jetpack' ),
169
+ __( 'Tuesday', 'woocommerce-jetpack' ),
170
+ __( 'Wednesday', 'woocommerce-jetpack' ),
171
+ __( 'Thursday', 'woocommerce-jetpack' ),
172
+ __( 'Friday', 'woocommerce-jetpack' ),
173
+ __( 'Saturday', 'woocommerce-jetpack' ),
174
+ ),
175
+ ),
176
+ array(
177
+ 'id' => 'wcj_product_input_fields_type_timepicker_format_' . $this->scope . '_',
178
+ 'title' => __( 'If timepicker is selected, set time format here. Visit <a href="http://timepicker.co/options/" target="_blank">timepicker options page</a> for valid time formats', 'woocommerce-jetpack' ),
179
+ 'short_title' => __( 'Timepicker: Time format', 'woocommerce-jetpack' ),
180
+ 'type' => 'text',
181
+ 'default' => 'hh:mm p',
182
+ ),
183
+ array(
184
+ 'id' => 'wcj_product_input_fields_type_timepicker_mintime_' . $this->scope . '_',
185
+ 'title' => __( 'If timepicker is selected, set min time here. Visit <a href="http://timepicker.co/options/" target="_blank">timepicker options page</a> for valid option formats', 'woocommerce-jetpack' ),
186
+ 'short_title' => __( 'Timepicker: Min Time', 'woocommerce-jetpack' ),
187
+ 'type' => 'text',
188
+ 'default' => '',
189
+ ),
190
+ array(
191
+ 'id' => 'wcj_product_input_fields_type_timepicker_maxtime_' . $this->scope . '_',
192
+ 'title' => __( 'If timepicker is selected, set max time here. Visit <a href="http://timepicker.co/options/" target="_blank">timepicker options page</a> for valid option formats', 'woocommerce-jetpack' ),
193
+ 'short_title' => __( 'Timepicker: Max Time', 'woocommerce-jetpack' ),
194
+ 'type' => 'text',
195
+ 'default' => '',
196
+ ),
197
+ array(
198
+ 'id' => 'wcj_product_input_fields_type_timepicker_interval_' . $this->scope . '_',
199
+ 'title' => __( 'If timepicker is selected, set interval (in minutes) here', 'woocommerce-jetpack' ),
200
+ 'short_title' => __( 'Timepicker: Interval', 'woocommerce-jetpack' ),
201
+ 'type' => 'number',
202
+ 'default' => 15,
203
+ ),
204
+ array(
205
+ 'id' => 'wcj_product_input_fields_type_select_options_' . $this->scope . '_',
206
+ 'title' => __( 'If select/radio is selected, set options here. One option per line', 'woocommerce-jetpack' ),
207
+ 'short_title' => __( 'Select/Radio: Options', 'woocommerce-jetpack' ),
208
+ 'type' => 'textarea',
209
+ 'default' => '',
210
+ 'css' => 'height:200px;',
211
+ ),
212
+ );
includes/js/wcj-cart-customization.js CHANGED
@@ -3,9 +3,11 @@
3
  *
4
  * version 2.8.0
5
  * since 2.8.0
 
6
  */
 
7
  jQuery(document).ready( function() {
8
  jQuery( "p.return-to-shop a.button.wc-backward" ).each( function() {
9
  jQuery(this).text( wcj_cart_customization.return_to_shop_button_text );
10
  } );
11
- } );
3
  *
4
  * version 2.8.0
5
  * since 2.8.0
6
+ * todo (maybe) fix when cart is emptied (i.e. after products removed)
7
  */
8
+
9
  jQuery(document).ready( function() {
10
  jQuery( "p.return-to-shop a.button.wc-backward" ).each( function() {
11
  jQuery(this).text( wcj_cart_customization.return_to_shop_button_text );
12
  } );
13
+ } );
includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Report Tool
4
  *
5
- * @version 2.7.0
6
  * @since 2.2.1
7
  * @author Algoritmika Ltd.
8
  */
@@ -24,21 +24,47 @@ class WCJ_PDF_Invoicing_Report_Tool {
24
  add_action( 'init', array( $this, 'export_csv' ) );
25
  }
26
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
  /**
28
  * generate_report_zip.
29
  *
30
- * @version 2.5.0
31
  * @since 2.3.10
32
  */
33
  function generate_report_zip() {
34
  if ( isset( $_POST['get_invoices_report_zip'] ) ) {
35
  if ( wcj_is_module_enabled( 'general' ) && 'yes' === get_option( 'wcj_general_advanced_disable_save_sys_temp_dir', 'no' ) ) {
36
- $this->notice = '<div class="error"><p><strong>' . __( 'This option is disabled in WooCommerce > Settings > Booster > Emails & Misc. > General > Advanced Options > Disable Saving PDFs in PHP directory for temporary files', 'woocommerce-jetpack' ) . '</strong></p></div>';
 
 
 
37
  } else {
38
- if ( ! empty( $_POST['report_year'] ) && ! empty( $_POST['report_month'] ) && ! empty( $_POST['invoice_type'] ) ) {
 
 
 
39
  if ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) {
40
- if ( false === $this->get_invoices_report_zip( $_POST['report_year'], $_POST['report_month'], $_POST['invoice_type'] ) ) {
 
41
  $this->notice = '<div class="error"><p><strong>' . __( 'Sorry, but something went wrong...', 'woocommerce-jetpack' ) . '</strong></p></div>';
 
 
42
  }
43
  }
44
  } else {
@@ -51,13 +77,13 @@ class WCJ_PDF_Invoicing_Report_Tool {
51
  /**
52
  * Add Invoices Report tool to WooCommerce menu (the content).
53
  *
54
- * @version 2.5.7
55
  */
56
  function create_invoices_report_tool() {
57
  $result_message = '';
58
  $result_message .= $this->notice;
59
- $the_year = ( ! empty( $_POST['report_year'] ) ) ? $_POST['report_year'] : '';
60
- $the_month = ( ! empty( $_POST['report_month'] ) ) ? $_POST['report_month'] : '';
61
  $the_invoice_type = ( ! empty( $_POST['invoice_type'] ) ) ? $_POST['invoice_type'] : 'invoice';
62
  if ( isset( $_POST['get_invoices_report'] ) ) {
63
  if ( ! empty( $the_year ) && ! empty( $the_month ) && ! empty( $the_invoice_type ) ) {
@@ -66,66 +92,73 @@ class WCJ_PDF_Invoicing_Report_Tool {
66
  $result_message = '<div class="error"><p><strong>' . __( 'Please fill year and month values.', 'woocommerce-jetpack' ) . '</strong></p></div>';
67
  }
68
  }
69
- ?><div>
70
- <?php echo WCJ()->modules['pdf_invoicing']->get_tool_header_html( 'invoices_report' ); ?>
71
- <?php echo $result_message; ?>
72
- <p><form method="post" action=""><?php
73
-
74
- // Type
75
- $invoice_type_select_html = '<select name="invoice_type">';
76
- $invoice_types = wcj_get_enabled_invoice_types();
77
- foreach ( $invoice_types as $invoice_type ) {
78
- $invoice_type_select_html .= '<option value="' . $invoice_type['id'] . '" ' . selected( $invoice_type['id'], $the_invoice_type, false ) . '>' . $invoice_type['title'] . '</option>';
79
- }
80
- $invoice_type_select_html .= '</select>';
81
-
82
- $data = array(
83
- // Year
84
- array(
85
- __( 'Year', 'woocommerce-jetpack' ),
86
- '<input class="input-text" type="number" min="2000" max="2100" step="1" name="report_year" value="' . $the_year . '">',
87
- ),
88
- // Month
89
- array(
90
- __( 'Month', 'woocommerce-jetpack' ),
91
- '<input class="input-text" type="number" min="1" max="12" step="1" name="report_month" value="' . $the_month . '">',
92
- ),
93
- // Type
94
- array(
95
- __( 'Document Type', 'woocommerce-jetpack' ),
96
- $invoice_type_select_html,
97
- ),
98
- // Get Report Button
99
- array(
100
- '',
101
- '<input class="button-primary" type="submit" name="get_invoices_report" value="' . __( 'Display monthly documents table', 'woocommerce-jetpack' ) . '">',
102
- ),
103
- // Get Report Zip Button
104
- array(
105
- '',
106
- '<input class="button-primary" type="submit" name="get_invoices_report_zip" value="' . __( 'Download all monthly documents PDFs in single ZIP file', 'woocommerce-jetpack' ) . '">',
107
- ),
108
- // Get Report CSV Button
109
- array(
110
- '',
111
- '<input class="button-primary" type="submit" name="get_invoices_report_csv" value="' . __( 'Download monthly documents CSV', 'woocommerce-jetpack' ) . '">',
112
- ),
113
- );
114
- // Print all
115
- echo wcj_get_table_html( $data, array( 'table_heading_type' => 'vertical', ) );
116
- ?></form></p>
117
- </div><?php
 
 
 
118
  }
119
 
120
  /**
121
  * get_invoices_report_zip.
122
  *
123
- * @version 2.5.7
124
  * @since 2.3.10
125
  */
126
  function get_invoices_report_zip( $year, $month, $invoice_type_id ) {
127
- $zip = new ZipArchive();
128
- $zip_file_name = $year . '_' . $month . '-' . $invoice_type_id . '.zip';
 
 
 
 
129
  $zip_file_path = sys_get_temp_dir() . '/' . $zip_file_name;
130
  if ( file_exists( $zip_file_path ) ) {
131
  unlink ( $zip_file_path );
@@ -137,8 +170,10 @@ class WCJ_PDF_Invoicing_Report_Tool {
137
  $first_minute = mktime( 0, 0, 0, $month, 1, $year );
138
  $last_minute = mktime( 23, 59, 59, $month, date( 't', $first_minute ), $year );
139
 
140
- $offset = 0;
141
- $block_size = 96;
 
 
142
  while( true ) {
143
  $args = array(
144
  'post_type' => 'shop_order',
@@ -147,8 +182,6 @@ class WCJ_PDF_Invoicing_Report_Tool {
147
  'orderby' => 'meta_value_num',
148
  'meta_key' => '_wcj_invoicing_' . $invoice_type_id . '_date',
149
  'order' => 'ASC',
150
- // 'year' => $year,
151
- // 'monthnum' => $month,
152
  'meta_query' => array(
153
  array(
154
  'key' => '_wcj_invoicing_' . $invoice_type_id . '_date',
@@ -158,27 +191,30 @@ class WCJ_PDF_Invoicing_Report_Tool {
158
  ),
159
  ),
160
  'offset' => $offset,
 
161
  );
162
  $loop = new WP_Query( $args );
163
- if ( ! $loop->have_posts() ) break;
164
- while ( $loop->have_posts() ) : $loop->the_post();
165
- $order_id = $loop->post->ID;
 
166
  if ( wcj_is_invoice_created( $order_id, $invoice_type_id ) ) {
167
  $the_invoice = wcj_get_pdf_invoice( $order_id, $invoice_type_id );
168
- $file_name = $the_invoice->get_pdf( 'F' );
169
  $zip->addFile( $file_name, $the_invoice->get_file_name() );
 
170
  }
171
- endwhile;
172
  $offset += $block_size;
173
  }
174
 
175
- /* $output .= "numfiles: " . $zip->numFiles . "\n";
176
- $output .= "status: " . $zip->getStatusString() . "\n"; */
177
  $zip->close();
178
 
179
- // header( "Content-Type: application/octet-stream" );
 
 
 
180
  header( "Content-Disposition: attachment; filename=" . urlencode( $zip_file_name ) );
181
- // header( "Content-Type: application/octet-stream" );
182
  header( "Content-Type: application/download" );
183
  header( "Content-Description: File Transfer" );
184
  header( "Content-Length: " . filesize( $zip_file_path ) );
@@ -189,35 +225,53 @@ class WCJ_PDF_Invoicing_Report_Tool {
189
  flush(); // this is essential for large downloads
190
  }
191
  fclose( $fp );
 
192
  } else {
193
  die( __( 'Unexpected error', 'woocommerce-jetpack' ) );
194
  }
195
  return true;
196
  }
197
 
 
 
 
 
 
 
 
 
 
 
198
  /**
199
  * export_csv.
200
  *
201
- * @version 2.5.7
202
  * @since 2.5.7
203
  */
204
  function export_csv() {
205
- $the_year = ( ! empty( $_POST['report_year'] ) ) ? $_POST['report_year'] : date( 'Y' );
206
- $the_month = ( ! empty( $_POST['report_month'] ) ) ? $_POST['report_month'] : date( 'm' );
207
- $the_invoice_type = ( ! empty( $_POST['invoice_type'] ) ) ? $_POST['invoice_type'] : 'invoice';
208
  if ( isset( $_POST['get_invoices_report_csv'] ) ) {
209
- $data = $this->get_invoices_report_data( $the_year, $the_month, $the_invoice_type );
210
- $csv = '';
 
 
 
 
 
 
211
  foreach ( $data as $row ) {
212
- $row = str_replace( '.', ',', $row );
213
- // $csv .= implode( get_option( 'wcj_export_csv_separator', ',' ), $row ) . PHP_EOL;
214
- $csv .= implode( ';', $row ) . PHP_EOL;
 
215
  }
216
- // if ( 'yes' === get_option( 'wcj_export_csv_add_utf_8_bom', 'yes' ) ) {
217
  $csv = "\xEF\xBB\xBF" . $csv; // UTF-8 BOM
218
- // }
219
- $filename = 'report_' . $the_year . '_' . $the_month . '_' . $the_invoice_type;
220
- header( "Content-Disposition: attachment; filename=" . $filename . ".csv" );
221
  header( "Content-Type: Content-Type: text/html; charset=utf-8" );
222
  header( "Content-Description: File Transfer" );
223
  header( "Content-Length: " . strlen( $csv ) );
@@ -229,46 +283,46 @@ class WCJ_PDF_Invoicing_Report_Tool {
229
  /**
230
  * Invoices Report function.
231
  *
232
- * @version 2.5.7
233
  */
234
  function get_invoices_report( $year, $month, $invoice_type_id ) {
235
- $output = '';
236
  $data = $this->get_invoices_report_data( $year, $month, $invoice_type_id );
237
- $output .= wcj_get_table_html( $data, array( 'table_class' => 'widefat', ) );
238
- return $output;
 
239
  }
240
 
241
  /**
242
  * Invoices Report Data function.
243
  *
244
- * @version 2.7.0
245
  * @since 2.5.7
246
  */
247
  function get_invoices_report_data( $year, $month, $invoice_type_id ) {
248
- $data = array();
249
- $data[] = array(
250
- __( 'Document Nr.', 'woocommerce-jetpack' ),
251
  __( 'Document Date', 'woocommerce-jetpack' ),
252
  __( 'Order ID', 'woocommerce-jetpack' ),
253
  __( 'Customer Country', 'woocommerce-jetpack' ),
254
  __( 'Customer VAT ID', 'woocommerce-jetpack' ),
255
  __( 'Tax %', 'woocommerce-jetpack' ),
256
- __( 'Order Total Tax Excl.', 'woocommerce-jetpack' ),
257
  __( 'Order Taxes', 'woocommerce-jetpack' ),
258
  __( 'Order Total', 'woocommerce-jetpack' ),
259
  __( 'Order Currency', 'woocommerce-jetpack' ),
260
  __( 'Refunds', 'woocommerce-jetpack' ),
261
  );
262
 
263
- $total_sum = 0;
264
  $total_sum_excl_tax = 0;
265
- $total_tax = 0;
266
 
267
  $first_minute = mktime( 0, 0, 0, $month, 1, $year );
268
  $last_minute = mktime( 23, 59, 59, $month, date( 't', $first_minute ), $year );
269
 
270
- $offset = 0;
271
- $block_size = 256;
 
272
  while( true ) {
273
  $args = array(
274
  'post_type' => 'shop_order',
@@ -277,8 +331,6 @@ class WCJ_PDF_Invoicing_Report_Tool {
277
  'orderby' => 'meta_value_num',
278
  'meta_key' => '_wcj_invoicing_' . $invoice_type_id . '_date',
279
  'order' => 'ASC',
280
- // 'year' => $year,
281
- // 'monthnum' => $month,
282
  'meta_query' => array(
283
  array(
284
  'key' => '_wcj_invoicing_' . $invoice_type_id . '_date',
@@ -300,27 +352,23 @@ class WCJ_PDF_Invoicing_Report_Tool {
300
 
301
  $the_order = wc_get_order( $order_id );
302
 
303
- $user_meta = get_user_meta( $the_order->get_user_id() );
304
  $billing_country = isset( $user_meta['billing_country'][0] ) ? $user_meta['billing_country'][0] : '';
305
  $shipping_country = isset( $user_meta['shipping_country'][0] ) ? $user_meta['shipping_country'][0] : '';
306
  $customer_country = ( '' == $billing_country ) ? $shipping_country : $billing_country;
307
- $customer_vat_id = get_post_meta( $order_id, '_billing_eu_vat_number', true );
308
 
309
  $order_total = $the_order->get_total();
310
 
311
- $order_tax = apply_filters( 'wcj_order_total_tax', $the_order->get_total_tax(), $the_order );
312
- // $order_tax_percent = ( isset( $taxes_by_countries_eu[ $customer_country ] ) ) ? $taxes_by_countries_eu[ $customer_country ] : 0;
313
- // $order_tax_percent /= 100;
314
- // $order_tax = $order_total * $order_tax_percent;
315
- $order_total_exlc_tax = $order_total - $order_tax;
316
  $order_total_tax_not_rounded = $the_order->get_cart_tax() + $the_order->get_shipping_tax();
317
- $order_tax_percent = ( 0 == $order_total ) ? 0 : $order_total_tax_not_rounded / $order_total_exlc_tax;
318
 
319
- $total_sum += $order_total;
320
  $total_sum_excl_tax += $order_total_exlc_tax;
321
- $total_tax += $order_tax;
322
 
323
- // $order_tax_html = ( 0 == $order_tax ) ? '' : sprintf( '$ %.2f', $order_tax );
324
  $order_tax_html = sprintf( '%.2f', $order_tax );
325
 
326
  $data[] = array(
@@ -335,14 +383,13 @@ class WCJ_PDF_Invoicing_Report_Tool {
335
  sprintf( '%.2f', $order_total ),
336
  wcj_get_order_currency( $the_order ),
337
  $the_order->get_total_refunded(),
338
- //'<pre>' . print_r( get_post_meta( $order_id ), true ) . '</pre>',
339
  );
340
  }
341
  }
342
  $offset += $block_size;
343
  }
344
 
345
- return $data;
346
  }
347
 
348
  }
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Report Tool
4
  *
5
+ * @version 3.1.0
6
  * @since 2.2.1
7
  * @author Algoritmika Ltd.
8
  */
24
  add_action( 'init', array( $this, 'export_csv' ) );
25
  }
26
 
27
+ /**
28
+ * get_report_file_name.
29
+ *
30
+ * @version 3.1.0
31
+ * @since 3.1.0
32
+ */
33
+ function get_report_file_name( $year, $month, $invoice_type, $extension ) {
34
+ $replaced_values = array(
35
+ '%year%' => $year,
36
+ '%month%' => sprintf( '%02d', $month ),
37
+ '%invoice_type%' => $invoice_type,
38
+ '%site%' => sanitize_title( str_replace( array( 'http://', 'https://' ), '', site_url() ) ),
39
+ );
40
+ return str_replace( array_keys( $replaced_values ), array_values( $replaced_values ),
41
+ get_option( 'wcj_pdf_invoicing_report_tool_filename', '%site%-%invoice_type%-%year%_%month%' ) ) . '.' . $extension;
42
+ }
43
+
44
  /**
45
  * generate_report_zip.
46
  *
47
+ * @version 3.1.0
48
  * @since 2.3.10
49
  */
50
  function generate_report_zip() {
51
  if ( isset( $_POST['get_invoices_report_zip'] ) ) {
52
  if ( wcj_is_module_enabled( 'general' ) && 'yes' === get_option( 'wcj_general_advanced_disable_save_sys_temp_dir', 'no' ) ) {
53
+ $this->notice = '<div class="error"><p><strong>' . sprintf(
54
+ __( 'This option is disabled with "Disable Saving PDFs in PHP directory for temporary files" checkbox in <a href="%s" target="_blank">WooCommerce > Settings > Booster > Emails & Misc. > General > Advanced Options</a>.', 'woocommerce-jetpack' ),
55
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=general' ) ) .
56
+ '</strong></p></div>';
57
  } else {
58
+ $_year = ( ! empty( $_POST['report_year'] ) ) ? $_POST['report_year'] : date( 'Y' );
59
+ $_month = ( ! empty( $_POST['report_month'] ) ) ? $_POST['report_month'] : date( 'n' );
60
+ $_invoice_type = ( ! empty( $_POST['invoice_type'] ) ) ? $_POST['invoice_type'] : 'invoice';
61
+ if ( ! empty( $_year ) && ! empty( $_month ) && ! empty( $_invoice_type ) ) {
62
  if ( wcj_is_user_role( 'administrator' ) || is_shop_manager() ) {
63
+ $result = $this->get_invoices_report_zip( $_year, $_month, $_invoice_type );
64
+ if ( false === $result ) {
65
  $this->notice = '<div class="error"><p><strong>' . __( 'Sorry, but something went wrong...', 'woocommerce-jetpack' ) . '</strong></p></div>';
66
+ } elseif ( true !== $result ) {
67
+ $this->notice = '<div class="error"><p><strong>' . $result . '</strong></p></div>';
68
  }
69
  }
70
  } else {
77
  /**
78
  * Add Invoices Report tool to WooCommerce menu (the content).
79
  *
80
+ * @version 3.1.0
81
  */
82
  function create_invoices_report_tool() {
83
  $result_message = '';
84
  $result_message .= $this->notice;
85
+ $the_year = ( ! empty( $_POST['report_year'] ) ) ? $_POST['report_year'] : date( 'Y' );
86
+ $the_month = ( ! empty( $_POST['report_month'] ) ) ? $_POST['report_month'] : date( 'n' );
87
  $the_invoice_type = ( ! empty( $_POST['invoice_type'] ) ) ? $_POST['invoice_type'] : 'invoice';
88
  if ( isset( $_POST['get_invoices_report'] ) ) {
89
  if ( ! empty( $the_year ) && ! empty( $the_month ) && ! empty( $the_invoice_type ) ) {
92
  $result_message = '<div class="error"><p><strong>' . __( 'Please fill year and month values.', 'woocommerce-jetpack' ) . '</strong></p></div>';
93
  }
94
  }
95
+ $html = '';
96
+ $html .= '<div class="wrap">';
97
+ $html .= WCJ()->modules['pdf_invoicing']->get_tool_header_html( 'invoices_report' );
98
+ $html .= $result_message;
99
+ $html .= '<p><form method="post" action="">';
100
+ // Type
101
+ $invoice_type_select_html = '<select name="invoice_type" class="widefat">';
102
+ $invoice_types = wcj_get_enabled_invoice_types();
103
+ foreach ( $invoice_types as $invoice_type ) {
104
+ $invoice_type_select_html .= '<option value="' . $invoice_type['id'] . '" ' . selected( $invoice_type['id'], $the_invoice_type, false ) . '>' .
105
+ $invoice_type['title'] . '</option>';
106
+ }
107
+ $invoice_type_select_html .= '</select>';
108
+ $data = array(
109
+ // Year
110
+ array(
111
+ __( 'Year', 'woocommerce-jetpack' ),
112
+ '<input class="input-text widefat" type="number" min="2000" max="2100" step="1" name="report_year" value="' . $the_year . '">',
113
+ ),
114
+ // Month
115
+ array(
116
+ __( 'Month', 'woocommerce-jetpack' ),
117
+ '<input class="input-text widefat" type="number" min="1" max="12" step="1" name="report_month" value="' . $the_month . '">',
118
+ ),
119
+ // Type
120
+ array(
121
+ __( 'Document Type', 'woocommerce-jetpack' ),
122
+ $invoice_type_select_html,
123
+ ),
124
+ // Get Report Button
125
+ array(
126
+ '',
127
+ '<input class="button-primary" type="submit" name="get_invoices_report" value="' .
128
+ __( 'Display monthly documents table', 'woocommerce-jetpack' ) . '">',
129
+ ),
130
+ // Get Report Zip Button
131
+ array(
132
+ '',
133
+ '<input class="button-primary" type="submit" name="get_invoices_report_zip" value="' .
134
+ __( 'Download all monthly documents PDFs in single ZIP file', 'woocommerce-jetpack' ) . '">',
135
+ ),
136
+ // Get Report CSV Button
137
+ array(
138
+ '',
139
+ '<input class="button-primary" type="submit" name="get_invoices_report_csv" value="' .
140
+ __( 'Download monthly documents CSV', 'woocommerce-jetpack' ) . '">',
141
+ ),
142
+ );
143
+ $html .= wcj_get_table_html( $data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'vertical' ) );
144
+ $html .= '</form></p>';
145
+ $html .= '</div>';
146
+ echo $html;
147
  }
148
 
149
  /**
150
  * get_invoices_report_zip.
151
  *
152
+ * @version 3.1.0
153
  * @since 2.3.10
154
  */
155
  function get_invoices_report_zip( $year, $month, $invoice_type_id ) {
156
+ if ( ! class_exists( 'ZipArchive' ) ) {
157
+ return sprintf( __( 'Booster: %s class is not accessible on your server. Please contact your hosting provider.', 'woocommerce-jetpack' ),
158
+ '<a target="_blank" href="http://php.net/manual/en/class.ziparchive.php">PHP ZipArchive</a>' );
159
+ }
160
+ $zip = new ZipArchive();
161
+ $zip_file_name = $this->get_report_file_name( $year, $month, $invoice_type_id, 'zip' );
162
  $zip_file_path = sys_get_temp_dir() . '/' . $zip_file_name;
163
  if ( file_exists( $zip_file_path ) ) {
164
  unlink ( $zip_file_path );
170
  $first_minute = mktime( 0, 0, 0, $month, 1, $year );
171
  $last_minute = mktime( 23, 59, 59, $month, date( 't', $first_minute ), $year );
172
 
173
+ $archive_is_empty = true;
174
+
175
+ $offset = 0;
176
+ $block_size = 512;
177
  while( true ) {
178
  $args = array(
179
  'post_type' => 'shop_order',
182
  'orderby' => 'meta_value_num',
183
  'meta_key' => '_wcj_invoicing_' . $invoice_type_id . '_date',
184
  'order' => 'ASC',
 
 
185
  'meta_query' => array(
186
  array(
187
  'key' => '_wcj_invoicing_' . $invoice_type_id . '_date',
191
  ),
192
  ),
193
  'offset' => $offset,
194
+ 'fields' => 'ids',
195
  );
196
  $loop = new WP_Query( $args );
197
+ if ( ! $loop->have_posts() ) {
198
+ break;
199
+ }
200
+ foreach ( $loop->posts as $order_id ) {
201
  if ( wcj_is_invoice_created( $order_id, $invoice_type_id ) ) {
202
  $the_invoice = wcj_get_pdf_invoice( $order_id, $invoice_type_id );
203
+ $file_name = $the_invoice->get_pdf( 'F' );
204
  $zip->addFile( $file_name, $the_invoice->get_file_name() );
205
+ $archive_is_empty = false;
206
  }
207
+ }
208
  $offset += $block_size;
209
  }
210
 
 
 
211
  $zip->close();
212
 
213
+ if ( $archive_is_empty ) {
214
+ return $this->get_no_documents_found_message( $year, $month, $invoice_type_id );
215
+ }
216
+
217
  header( "Content-Disposition: attachment; filename=" . urlencode( $zip_file_name ) );
 
218
  header( "Content-Type: application/download" );
219
  header( "Content-Description: File Transfer" );
220
  header( "Content-Length: " . filesize( $zip_file_path ) );
225
  flush(); // this is essential for large downloads
226
  }
227
  fclose( $fp );
228
+ exit();
229
  } else {
230
  die( __( 'Unexpected error', 'woocommerce-jetpack' ) );
231
  }
232
  return true;
233
  }
234
 
235
+ /**
236
+ * get_no_documents_found_message.
237
+ *
238
+ * @version 3.1.0
239
+ * @since 3.1.0
240
+ */
241
+ function get_no_documents_found_message( $year, $month, $invoice_type_id ) {
242
+ return sprintf( __( 'No documents (%s) found for %d-%02d.', 'woocommerce-jetpack' ), $invoice_type_id, $year, $month );
243
+ }
244
+
245
  /**
246
  * export_csv.
247
  *
248
+ * @version 3.1.0
249
  * @since 2.5.7
250
  */
251
  function export_csv() {
252
+ $_year = ( ! empty( $_POST['report_year'] ) ) ? $_POST['report_year'] : date( 'Y' );
253
+ $_month = ( ! empty( $_POST['report_month'] ) ) ? $_POST['report_month'] : date( 'm' );
254
+ $_invoice_type = ( ! empty( $_POST['invoice_type'] ) ) ? $_POST['invoice_type'] : 'invoice';
255
  if ( isset( $_POST['get_invoices_report_csv'] ) ) {
256
+ $data = $this->get_invoices_report_data( $_year, $_month, $_invoice_type );
257
+ if ( empty( $data ) ) {
258
+ $this->notice = '<div class="error"><p><strong>' . $this->get_no_documents_found_message( $_year, $_month, $_invoice_type ) . '</strong></p></div>';
259
+ return false;
260
+ }
261
+ $csv = '';
262
+ $sep = get_option( 'wcj_pdf_invoicing_report_tool_csv_separator', ';' );
263
+ $replace_periods_with_commas = ( 'yes' === get_option( 'wcj_pdf_invoicing_report_tool_csv_replace_periods_w_commas', 'yes' ) );
264
  foreach ( $data as $row ) {
265
+ if ( $replace_periods_with_commas ) {
266
+ $row = str_replace( '.', ',', $row );
267
+ }
268
+ $csv .= implode( $sep, $row ) . PHP_EOL;
269
  }
270
+ if ( 'yes' === get_option( 'wcj_pdf_invoicing_report_tool_csv_add_utf_8_bom', 'yes' ) ) {
271
  $csv = "\xEF\xBB\xBF" . $csv; // UTF-8 BOM
272
+ }
273
+ $filename = $this->get_report_file_name( $_year, $_month, $_invoice_type, 'csv' );
274
+ header( "Content-Disposition: attachment; filename=" . $filename );
275
  header( "Content-Type: Content-Type: text/html; charset=utf-8" );
276
  header( "Content-Description: File Transfer" );
277
  header( "Content-Length: " . strlen( $csv ) );
283
  /**
284
  * Invoices Report function.
285
  *
286
+ * @version 3.1.0
287
  */
288
  function get_invoices_report( $year, $month, $invoice_type_id ) {
 
289
  $data = $this->get_invoices_report_data( $year, $month, $invoice_type_id );
290
+ return ( ! empty( $data ) ?
291
+ wcj_get_table_html( $data, array( 'table_class' => 'widefat' ) ) :
292
+ '<div class="error"><p><strong>' . $this->get_no_documents_found_message( $year, $month, $invoice_type_id ) . '</strong></p></div>' );
293
  }
294
 
295
  /**
296
  * Invoices Report Data function.
297
  *
298
+ * @version 3.1.0
299
  * @since 2.5.7
300
  */
301
  function get_invoices_report_data( $year, $month, $invoice_type_id ) {
302
+ $headers = array(
303
+ __( 'Document Number', 'woocommerce-jetpack' ),
 
304
  __( 'Document Date', 'woocommerce-jetpack' ),
305
  __( 'Order ID', 'woocommerce-jetpack' ),
306
  __( 'Customer Country', 'woocommerce-jetpack' ),
307
  __( 'Customer VAT ID', 'woocommerce-jetpack' ),
308
  __( 'Tax %', 'woocommerce-jetpack' ),
309
+ __( 'Order Total Tax Excluding', 'woocommerce-jetpack' ),
310
  __( 'Order Taxes', 'woocommerce-jetpack' ),
311
  __( 'Order Total', 'woocommerce-jetpack' ),
312
  __( 'Order Currency', 'woocommerce-jetpack' ),
313
  __( 'Refunds', 'woocommerce-jetpack' ),
314
  );
315
 
316
+ $total_sum = 0;
317
  $total_sum_excl_tax = 0;
318
+ $total_tax = 0;
319
 
320
  $first_minute = mktime( 0, 0, 0, $month, 1, $year );
321
  $last_minute = mktime( 23, 59, 59, $month, date( 't', $first_minute ), $year );
322
 
323
+ $data = array();
324
+ $offset = 0;
325
+ $block_size = 512;
326
  while( true ) {
327
  $args = array(
328
  'post_type' => 'shop_order',
331
  'orderby' => 'meta_value_num',
332
  'meta_key' => '_wcj_invoicing_' . $invoice_type_id . '_date',
333
  'order' => 'ASC',
 
 
334
  'meta_query' => array(
335
  array(
336
  'key' => '_wcj_invoicing_' . $invoice_type_id . '_date',
352
 
353
  $the_order = wc_get_order( $order_id );
354
 
355
+ $user_meta = get_user_meta( $the_order->get_user_id() );
356
  $billing_country = isset( $user_meta['billing_country'][0] ) ? $user_meta['billing_country'][0] : '';
357
  $shipping_country = isset( $user_meta['shipping_country'][0] ) ? $user_meta['shipping_country'][0] : '';
358
  $customer_country = ( '' == $billing_country ) ? $shipping_country : $billing_country;
359
+ $customer_vat_id = get_post_meta( $order_id, '_billing_eu_vat_number', true );
360
 
361
  $order_total = $the_order->get_total();
362
 
363
+ $order_tax = apply_filters( 'wcj_order_total_tax', $the_order->get_total_tax(), $the_order );
364
+ $order_total_exlc_tax = $order_total - $order_tax;
 
 
 
365
  $order_total_tax_not_rounded = $the_order->get_cart_tax() + $the_order->get_shipping_tax();
366
+ $order_tax_percent = ( 0 == $order_total ) ? 0 : $order_total_tax_not_rounded / $order_total_exlc_tax;
367
 
368
+ $total_sum += $order_total;
369
  $total_sum_excl_tax += $order_total_exlc_tax;
370
+ $total_tax += $order_tax;
371
 
 
372
  $order_tax_html = sprintf( '%.2f', $order_tax );
373
 
374
  $data[] = array(
383
  sprintf( '%.2f', $order_total ),
384
  wcj_get_order_currency( $the_order ),
385
  $the_order->get_total_refunded(),
 
386
  );
387
  }
388
  }
389
  $offset += $block_size;
390
  }
391
 
392
+ return ( ! empty( $data ) ? array_merge( array( $headers ), $data ) : array() );
393
  }
394
 
395
  }
includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Display
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -92,36 +92,19 @@ class WCJ_PDF_Invoicing_Display extends WCJ_Module {
92
  /**
93
  * add_pdf_invoices_admin_actions_buttons_css.
94
  *
95
- * @version 2.5.2
96
  * @since 2.4.7
97
  */
98
  function add_pdf_invoices_admin_actions_buttons_css() {
99
  echo '<style>' . PHP_EOL;
100
  $invoice_types = wcj_get_enabled_invoice_types();
101
  foreach ( $invoice_types as $invoice_type ) {
102
- switch ( $invoice_type['id'] ) {
103
- case 'invoice':
104
- $color = 'green';
105
- break;
106
- case 'proforma_invoice':
107
- $color = 'orange';
108
- break;
109
- case 'packing_slip':
110
- $color = 'blue';
111
- break;
112
- case 'credit_note':
113
- $color = 'red';
114
- break;
115
- default: // 'custom_doc'
116
- $color = 'gray';
117
- break;
118
- }
119
- echo '.view.' . $invoice_type['id'] . '{ color: ' . $color . ' !important; }' . PHP_EOL;
120
- echo '.view.' . $invoice_type['id'] . '_' . 'create' . '{ color: ' . $color . ' !important; }' . PHP_EOL;
121
- echo '.view.' . $invoice_type['id'] . '_' . 'delete' . '{ color: ' . $color . ' !important; }' . PHP_EOL;
122
- echo '.view.' . $invoice_type['id'] . '::after { content: "\f159" !important; }' . PHP_EOL;
123
- echo '.view.' . $invoice_type['id'] . '_' . 'create' . '::after { content: "\f132" !important; }' . PHP_EOL;
124
- echo '.view.' . $invoice_type['id'] . '_' . 'delete' . '::after { content: "\f460" !important; }' . PHP_EOL;
125
  }
126
  echo '</style>' . PHP_EOL;
127
  }
@@ -175,13 +158,13 @@ class WCJ_PDF_Invoicing_Display extends WCJ_Module {
175
  /**
176
  * add_order_column.
177
  *
178
- * @version 2.3.10
179
  */
180
  function add_order_column( $columns ) {
181
  $invoice_types = wcj_get_enabled_invoice_types();
182
  foreach ( $invoice_types as $invoice_type ) {
183
  if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_page_column', 'yes' ) ) {
184
- $columns[ $invoice_type['id'] ] = get_option( 'wcj_invoicing_' . $invoice_type['id'] . '_admin_page_column_text' );
185
  }
186
  }
187
  return $columns;
@@ -274,14 +257,14 @@ class WCJ_PDF_Invoicing_Display extends WCJ_Module {
274
  /**
275
  * add_invoices_meta_box.
276
  *
277
- * @version 2.8.0
278
  * @since 2.8.0
279
  */
280
  function add_invoices_meta_box() {
281
  if ( 'yes' === get_option( 'wcj_invoicing_add_order_meta_box', 'yes' ) ) {
282
  add_meta_box(
283
  'wc-booster-pdf-invoicing',
284
- __( 'Booster: PDF Invoices', 'woocommerce-jetpack' ),
285
  array( $this, 'create_invoices_meta_box' ),
286
  'shop_order',
287
  'side',
@@ -293,7 +276,7 @@ class WCJ_PDF_Invoicing_Display extends WCJ_Module {
293
  /**
294
  * create_invoices_meta_box.
295
  *
296
- * @version 2.8.0
297
  * @since 2.8.0
298
  */
299
  function create_invoices_meta_box() {
@@ -312,7 +295,7 @@ class WCJ_PDF_Invoicing_Display extends WCJ_Module {
312
  $the_url = add_query_arg( $query_args, remove_query_arg( array ( 'create_invoice_for_order_id', 'delete_invoice_for_order_id' ) ) );
313
  $the_name = __( 'View', 'woocommerce-jetpack' );
314
  $the_invoice = wcj_get_invoice( $order_id, $invoice_type['id'] );
315
- $the_number = ' #' . $the_invoice->get_invoice_number();
316
  $view_link = '<a href="' . $the_url . '">' . $the_name . '</a>';
317
  // "Delete" link
318
  $query_args = array( 'delete_invoice_for_order_id' => $order_id, 'invoice_type_id' => $invoice_type['id'] );
@@ -326,7 +309,13 @@ class WCJ_PDF_Invoicing_Display extends WCJ_Module {
326
  $the_name = __( 'Create', 'woocommerce-jetpack' );
327
  $actions = array( '<a class="wcj_need_confirmation" href="' . $the_url . '">' . $the_name . '</a>' );
328
  }
329
- $table_data[] = array( $invoice_type['title'] . $the_number );
 
 
 
 
 
 
330
  $table_data[] = $actions;
331
  echo '<p>' . wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) ) . '</p>';
332
  }
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Display
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
92
  /**
93
  * add_pdf_invoices_admin_actions_buttons_css.
94
  *
95
+ * @version 3.1.0
96
  * @since 2.4.7
97
  */
98
  function add_pdf_invoices_admin_actions_buttons_css() {
99
  echo '<style>' . PHP_EOL;
100
  $invoice_types = wcj_get_enabled_invoice_types();
101
  foreach ( $invoice_types as $invoice_type ) {
102
+ echo '.view.' . $invoice_type['id'] . '{ color: ' . $invoice_type['color'] . ' !important; }' . PHP_EOL;
103
+ echo '.view.' . $invoice_type['id'] . '_' . 'create' . '{ color: ' . $invoice_type['color'] . ' !important; }' . PHP_EOL;
104
+ echo '.view.' . $invoice_type['id'] . '_' . 'delete' . '{ color: ' . $invoice_type['color'] . ' !important; }' . PHP_EOL;
105
+ echo '.view.' . $invoice_type['id'] . '::after { content: "\f498" !important; }' . PHP_EOL;
106
+ echo '.view.' . $invoice_type['id'] . '_' . 'create' . '::after { content: "\f119" !important; }' . PHP_EOL;
107
+ echo '.view.' . $invoice_type['id'] . '_' . 'delete' . '::after { content: "\f153" !important; }' . PHP_EOL;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  }
109
  echo '</style>' . PHP_EOL;
110
  }
158
  /**
159
  * add_order_column.
160
  *
161
+ * @version 3.1.0
162
  */
163
  function add_order_column( $columns ) {
164
  $invoice_types = wcj_get_enabled_invoice_types();
165
  foreach ( $invoice_types as $invoice_type ) {
166
  if ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_page_column', 'yes' ) ) {
167
+ $columns[ $invoice_type['id'] ] = get_option( 'wcj_invoicing_' . $invoice_type['id'] . '_admin_page_column_text', $invoice_type['title'] );
168
  }
169
  }
170
  return $columns;
257
  /**
258
  * add_invoices_meta_box.
259
  *
260
+ * @version 3.1.0
261
  * @since 2.8.0
262
  */
263
  function add_invoices_meta_box() {
264
  if ( 'yes' === get_option( 'wcj_invoicing_add_order_meta_box', 'yes' ) ) {
265
  add_meta_box(
266
  'wc-booster-pdf-invoicing',
267
+ '<span class="dashicons dashicons-media-default" style="color:#23282d;"></span>' . ' ' . __( 'Booster: PDF Invoices', 'woocommerce-jetpack' ),
268
  array( $this, 'create_invoices_meta_box' ),
269
  'shop_order',
270
  'side',
276
  /**
277
  * create_invoices_meta_box.
278
  *
279
+ * @version 3.1.0
280
  * @since 2.8.0
281
  */
282
  function create_invoices_meta_box() {
295
  $the_url = add_query_arg( $query_args, remove_query_arg( array ( 'create_invoice_for_order_id', 'delete_invoice_for_order_id' ) ) );
296
  $the_name = __( 'View', 'woocommerce-jetpack' );
297
  $the_invoice = wcj_get_invoice( $order_id, $invoice_type['id'] );
298
+ $the_number = ' [#' . $the_invoice->get_invoice_number() . ']';
299
  $view_link = '<a href="' . $the_url . '">' . $the_name . '</a>';
300
  // "Delete" link
301
  $query_args = array( 'delete_invoice_for_order_id' => $order_id, 'invoice_type_id' => $invoice_type['id'] );
309
  $the_name = __( 'Create', 'woocommerce-jetpack' );
310
  $actions = array( '<a class="wcj_need_confirmation" href="' . $the_url . '">' . $the_name . '</a>' );
311
  }
312
+ $maybe_toolptip = '';
313
+ $_hook = get_option( 'wcj_invoicing_' . $invoice_type['id'] . '_create_on', 'woocommerce_new_order' );
314
+ if ( in_array( $_hook, array( 'woocommerce_order_partially_refunded_notification', 'wcj_pdf_invoicing_create_on_any_refund' ) ) ) {
315
+ $maybe_toolptip = wc_help_tip( __( 'In case of partial refund, you need to reload the page to see created document in this meta box.', 'woocommerce-jetpack' ), true );
316
+ }
317
+ $table_data[] = array( '<span class="dashicons dashicons-media-default" style="color:' . $invoice_type['color'] . ';"></span>' . ' ' .
318
+ $invoice_type['title'] . $the_number . $maybe_toolptip );
319
  $table_data[] = $actions;
320
  echo '<p>' . wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) ) . '</p>';
321
  }
includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-styling.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Styling
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -29,6 +29,27 @@ class WCJ_PDF_Invoicing_Styling extends WCJ_Module {
29
  add_action( 'wcj_download_tcpdf_fonts_hook', array( $this, 'download_fonts' ) );
30
  }
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  /**
33
  * On an early action hook, check if the hook is scheduled - if not, schedule it.
34
  *
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Styling
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
29
  add_action( 'wcj_download_tcpdf_fonts_hook', array( $this, 'download_fonts' ) );
30
  }
31
 
32
+ /**
33
+ * get_default_css_template.
34
+ *
35
+ * @version 3.1.0
36
+ * @version 3.1.0
37
+ */
38
+ function get_default_css_template( $invoice_type_id ) {
39
+ if ( ! isset( $this->default_css_template[ $invoice_type_id ] ) ) {
40
+ $default_template_filename = ( false === strpos( $invoice_type_id, 'custom_doc_' ) ? $invoice_type_id : 'custom_doc' );
41
+ $default_template_filename = wcj_plugin_path() . '/includes/settings/pdf-invoicing/wcj-' . $default_template_filename . '.css';
42
+ if ( file_exists( $default_template_filename ) ) {
43
+ ob_start();
44
+ include( $default_template_filename );
45
+ $this->default_css_template[ $invoice_type_id ] = ob_get_clean();
46
+ } else {
47
+ $this->default_css_template[ $invoice_type_id ] = '';
48
+ }
49
+ }
50
+ return $this->default_css_template[ $invoice_type_id ];
51
+ }
52
+
53
  /**
54
  * On an early action hook, check if the hook is scheduled - if not, schedule it.
55
  *
includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-templates.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Templates
4
  *
5
- * @version 2.8.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -25,6 +25,34 @@ class WCJ_PDF_Invoicing_Templates extends WCJ_Module {
25
  parent::__construct( 'submodule' );
26
  }
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  }
29
 
30
  endif;
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Templates
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
25
  parent::__construct( 'submodule' );
26
  }
27
 
28
+ /**
29
+ * get_default_template.
30
+ *
31
+ * @version 3.1.0
32
+ * @since 3.1.0
33
+ */
34
+ function get_default_template( $invoice_type_id ) {
35
+ if ( ! isset( $this->default_template[ $invoice_type_id ] ) ) {
36
+ $default_template_filename = ( false === strpos( $invoice_type_id, 'custom_doc_' ) ? $invoice_type_id : 'custom_doc' );
37
+ $default_template_filename = wcj_plugin_path() . '/includes/settings/pdf-invoicing/wcj-content-template-' . $default_template_filename . '.php';
38
+ if ( file_exists( $default_template_filename ) ) {
39
+ ob_start();
40
+ include( $default_template_filename );
41
+ $this->default_template[ $invoice_type_id ] = ob_get_clean();
42
+ if ( false !== strpos( $invoice_type_id, 'custom_doc' ) ) {
43
+ $custom_doc_nr = ( 'custom_doc' === $invoice_type_id ) ? '1' : str_replace( 'custom_doc_', '', $invoice_type_id );
44
+ $this->default_template[ $invoice_type_id ] = str_replace( '[wcj_custom_doc_number]', '[wcj_custom_doc_number doc_nr="' . $custom_doc_nr . '"]',
45
+ $this->default_template[ $invoice_type_id ] );
46
+ $this->default_template[ $invoice_type_id ] = str_replace( '[wcj_custom_doc_date]', '[wcj_custom_doc_date doc_nr="' . $custom_doc_nr . '"]',
47
+ $this->default_template[ $invoice_type_id ] );
48
+ }
49
+ } else {
50
+ $this->default_template[ $invoice_type_id ] = '';
51
+ }
52
+ }
53
+ return $this->default_template[ $invoice_type_id ];
54
+ }
55
+
56
  }
57
 
58
  endif;
includes/settings/wcj-settings-admin-bar.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Admin Bar
4
  *
5
- * @version 2.9.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,19 +16,26 @@ return array(
16
  'id' => 'wcj_admin_bar_options',
17
  ),
18
  array(
19
- 'title' => __( 'WooCommerce Admin Bar', 'woocommerce-jetpack' ),
20
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
21
  'id' => 'wcj_admin_bar_wc_enabled',
22
  'default' => 'yes',
23
  'type' => 'checkbox',
24
  ),
25
  array(
26
- 'title' => __( 'Booster Admin Bar', 'woocommerce-jetpack' ),
27
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
28
  'id' => 'wcj_admin_bar_booster_enabled',
29
  'default' => 'yes',
30
  'type' => 'checkbox',
31
  ),
 
 
 
 
 
 
 
32
  array(
33
  'type' => 'sectionend',
34
  'id' => 'wcj_admin_bar_options',
2
  /**
3
  * Booster for WooCommerce - Settings - Admin Bar
4
  *
5
+ * @version 3.1.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
16
  'id' => 'wcj_admin_bar_options',
17
  ),
18
  array(
19
+ 'title' => __( '"WooCommerce" Admin Bar', 'woocommerce-jetpack' ),
20
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
21
  'id' => 'wcj_admin_bar_wc_enabled',
22
  'default' => 'yes',
23
  'type' => 'checkbox',
24
  ),
25
  array(
26
+ 'title' => __( '"Booster" Admin Bar', 'woocommerce-jetpack' ),
27
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
28
  'id' => 'wcj_admin_bar_booster_enabled',
29
  'default' => 'yes',
30
  'type' => 'checkbox',
31
  ),
32
+ array(
33
+ 'title' => __( '"Booster: Active" Admin Bar', 'woocommerce-jetpack' ),
34
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
35
+ 'id' => 'wcj_admin_bar_booster_active_enabled',
36
+ 'default' => 'yes',
37
+ 'type' => 'checkbox',
38
+ ),
39
  array(
40
  'type' => 'sectionend',
41
  'id' => 'wcj_admin_bar_options',
includes/settings/wcj-settings-cart-customization.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Cart Customization
4
  *
5
- * @version 3.0.1
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -37,6 +37,17 @@ return array(
37
  'type' => 'checkbox',
38
  ),
39
  array(
 
 
 
 
 
 
 
 
 
 
 
40
  'id' => 'wcj_cart_customization_return_to_shop_button_text',
41
  'default' => __( 'Return to shop', 'woocommerce' ),
42
  'type' => 'text',
@@ -49,6 +60,7 @@ return array(
49
  'type' => 'checkbox',
50
  ),
51
  array(
 
52
  'id' => 'wcj_cart_customization_return_to_shop_button_link',
53
  'default' => '',
54
  'type' => 'text',
2
  /**
3
  * Booster for WooCommerce - Settings - Cart Customization
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
37
  'type' => 'checkbox',
38
  ),
39
  array(
40
+ 'desc' => __( 'Method', 'woocommerce-jetpack' ),
41
+ 'id' => 'wcj_cart_customization_return_to_shop_button_text_method',
42
+ 'default' => 'js',
43
+ 'type' => 'select',
44
+ 'options' => array(
45
+ 'js' => __( 'Use JavaScript', 'woocommerce-jetpack' ),
46
+ 'template' => __( 'Replace empty cart template', 'woocommerce-jetpack' ),
47
+ ),
48
+ ),
49
+ array(
50
+ 'desc' => __( 'Text', 'woocommerce-jetpack' ),
51
  'id' => 'wcj_cart_customization_return_to_shop_button_text',
52
  'default' => __( 'Return to shop', 'woocommerce' ),
53
  'type' => 'text',
60
  'type' => 'checkbox',
61
  ),
62
  array(
63
+ 'desc' => __( 'Link', 'woocommerce-jetpack' ),
64
  'id' => 'wcj_cart_customization_return_to_shop_button_link',
65
  'default' => '',
66
  'type' => 'text',
includes/settings/wcj-settings-checkout-core-fields.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Checkout Core Fields
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -11,7 +11,38 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
  $settings = array(
13
  array(
14
- 'title' => __( 'Checkout Core Fields Options', 'woocommerce-jetpack' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  'type' => 'title',
16
  'id' => 'wcj_checkout_core_fields_options',
17
  ),
2
  /**
3
  * Booster for WooCommerce - Settings - Checkout Core Fields
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
11
 
12
  $settings = array(
13
  array(
14
+ 'title' => __( 'General Options', 'woocommerce-jetpack' ),
15
+ 'type' => 'title',
16
+ 'id' => 'wcj_checkout_core_fields_general_options',
17
+ ),
18
+ array(
19
+ 'title' => __( 'Override Default Address Fields', 'woocommerce-jetpack' ),
20
+ 'type' => 'select',
21
+ 'id' => 'wcj_checkout_core_fields_override_default_address_fields',
22
+ 'default' => 'billing',
23
+ 'options' => array(
24
+ 'billing' => __( 'Override with billing fields', 'woocommerce-jetpack' ),
25
+ 'shipping' => __( 'Override with shipping fields', 'woocommerce-jetpack' ),
26
+ 'disable' => __( 'Do not override', 'woocommerce-jetpack' ),
27
+ ),
28
+ ),
29
+ array(
30
+ 'title' => __( 'Override Country Locale Fields', 'woocommerce-jetpack' ),
31
+ 'type' => 'select',
32
+ 'id' => 'wcj_checkout_core_fields_override_country_locale_fields',
33
+ 'default' => 'billing',
34
+ 'options' => array(
35
+ 'billing' => __( 'Override with billing fields', 'woocommerce-jetpack' ),
36
+ 'shipping' => __( 'Override with shipping fields', 'woocommerce-jetpack' ),
37
+ 'disable' => __( 'Do not override', 'woocommerce-jetpack' ),
38
+ ),
39
+ ),
40
+ array(
41
+ 'type' => 'sectionend',
42
+ 'id' => 'wcj_checkout_core_fields_general_options',
43
+ ),
44
+ array(
45
+ 'title' => __( 'Fields Options', 'woocommerce-jetpack' ),
46
  'type' => 'title',
47
  'id' => 'wcj_checkout_core_fields_options',
48
  ),
includes/settings/wcj-settings-checkout-customization.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Checkout Customization
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -71,7 +71,21 @@ return array(
71
  'id' => 'wcj_checkout_customization_disable_fields_for_logged_message',
72
  'default' => '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>',
73
  'type' => 'custom_textarea',
74
- 'css' => 'width:66%;min-width:300px;',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  ),
76
  array(
77
  'type' => 'sectionend',
2
  /**
3
  * Booster for WooCommerce - Settings - Checkout Customization
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
71
  'id' => 'wcj_checkout_customization_disable_fields_for_logged_message',
72
  'default' => '<em>' . __( 'This field can not be changed', 'woocommerce-jetpack' ) . '</em>',
73
  'type' => 'custom_textarea',
74
+ 'css' => 'width:99%;',
75
+ ),
76
+ array(
77
+ 'title' => __( 'Customize "order received" message', 'woocommerce-jetpack' ),
78
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
79
+ 'id' => 'wcj_checkout_customization_order_received_message_enabled',
80
+ 'default' => 'no',
81
+ 'type' => 'checkbox',
82
+ ),
83
+ array(
84
+ 'desc_tip' => __( 'You can use HTML and/or shortcodes here.', 'woocommerce-jetpack' ),
85
+ 'id' => 'wcj_checkout_customization_order_received_message',
86
+ 'default' => __( 'Thank you. Your order has been received.', 'woocommerce' ),
87
+ 'type' => 'custom_textarea',
88
+ 'css' => 'width:99%;',
89
  ),
90
  array(
91
  'type' => 'sectionend',
includes/settings/wcj-settings-emails-verification.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Email Verification
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -11,9 +11,9 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
  return array(
13
  array(
14
- 'title' => __( 'Options', 'woocommerce-jetpack' ),
15
  'type' => 'title',
16
- 'id' => 'wcj_emails_verification_options',
17
  ),
18
  array(
19
  'title' => __( 'Skip Email Verification for User Roles', 'woocommerce-jetpack' ),
@@ -39,33 +39,23 @@ return array(
39
  'default' => 'yes',
40
  ),
41
  array(
42
- 'title' => __( 'Verification Email Subject', 'woocommerce-jetpack' ),
43
- 'type' => 'custom_textarea',
44
- 'id' => 'wcj_emails_verification_email_subject',
45
- 'default' => __( 'Please activate your account', 'woocommerce-jetpack' ),
46
- 'css' => 'width:66%;min-width:300px;',
47
- 'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
48
- 'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
49
  ),
50
  array(
51
- 'title' => __( 'Verification Email Content', 'woocommerce-jetpack' ),
52
- 'desc_tip' => sprintf( __( 'Replaced value: %s', 'woocommerce-jetpack' ), '%verification_url%' ),
53
- 'type' => 'custom_textarea',
54
- 'id' => 'wcj_emails_verification_email_content',
55
- 'default' => __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ),
56
- 'css' => 'width:66%;min-width:300px;height:150px;',
57
- 'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
58
- 'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
59
  ),
60
  array(
61
- 'title' => __( 'Verification Message - Success', 'woocommerce-jetpack' ),
62
  'type' => 'custom_textarea',
63
  'id' => 'wcj_emails_verification_success_message',
64
  'default' => __( '<strong>Success:</strong> Your account has been activated!', 'woocommerce-jetpack' ),
65
  'css' => 'width:66%;min-width:300px;',
66
  ),
67
  array(
68
- 'title' => __( 'Verification Message - Error', 'woocommerce-jetpack' ),
69
  'desc_tip' => sprintf( __( 'Replaced value: %s', 'woocommerce-jetpack' ), '%resend_verification_url%' ),
70
  'type' => 'custom_textarea',
71
  'id' => 'wcj_emails_verification_error_message',
@@ -73,7 +63,7 @@ return array(
73
  'css' => 'width:66%;min-width:300px;',
74
  ),
75
  array(
76
- 'title' => __( 'Verification Message - Failed', 'woocommerce-jetpack' ),
77
  'desc_tip' => sprintf( __( 'Replaced value: %s', 'woocommerce-jetpack' ), '%resend_verification_url%' ),
78
  'type' => 'custom_textarea',
79
  'id' => 'wcj_emails_verification_failed_message',
@@ -81,14 +71,14 @@ return array(
81
  'css' => 'width:66%;min-width:300px;',
82
  ),
83
  array(
84
- 'title' => __( 'Verification Message - Activate', 'woocommerce-jetpack' ),
85
  'type' => 'custom_textarea',
86
  'id' => 'wcj_emails_verification_activation_message',
87
  'default' => __( 'Thank you for your registration. Your account has to be activated before you can login. Please check your email.', 'woocommerce-jetpack' ),
88
  'css' => 'width:66%;min-width:300px;',
89
  ),
90
  array(
91
- 'title' => __( 'Verification Message - Resend', 'woocommerce-jetpack' ),
92
  'type' => 'custom_textarea',
93
  'id' => 'wcj_emails_verification_email_resend_message',
94
  'default' => __( '<strong>Success:</strong> Your activation email has been resend. Please check your email.', 'woocommerce-jetpack' ),
@@ -96,6 +86,56 @@ return array(
96
  ),
97
  array(
98
  'type' => 'sectionend',
99
- 'id' => 'wcj_emails_verification_options',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
  ),
101
  );
2
  /**
3
  * Booster for WooCommerce - Settings - Email Verification
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
11
 
12
  return array(
13
  array(
14
+ 'title' => __( 'General Options', 'woocommerce-jetpack' ),
15
  'type' => 'title',
16
+ 'id' => 'wcj_emails_verification_general_options',
17
  ),
18
  array(
19
  'title' => __( 'Skip Email Verification for User Roles', 'woocommerce-jetpack' ),
39
  'default' => 'yes',
40
  ),
41
  array(
42
+ 'type' => 'sectionend',
43
+ 'id' => 'wcj_emails_verification_general_options',
 
 
 
 
 
44
  ),
45
  array(
46
+ 'title' => __( 'Messages', 'woocommerce-jetpack' ),
47
+ 'type' => 'title',
48
+ 'id' => 'wcj_emails_verification_messages_options',
 
 
 
 
 
49
  ),
50
  array(
51
+ 'title' => __( 'Message - Success', 'woocommerce-jetpack' ),
52
  'type' => 'custom_textarea',
53
  'id' => 'wcj_emails_verification_success_message',
54
  'default' => __( '<strong>Success:</strong> Your account has been activated!', 'woocommerce-jetpack' ),
55
  'css' => 'width:66%;min-width:300px;',
56
  ),
57
  array(
58
+ 'title' => __( 'Message - Error', 'woocommerce-jetpack' ),
59
  'desc_tip' => sprintf( __( 'Replaced value: %s', 'woocommerce-jetpack' ), '%resend_verification_url%' ),
60
  'type' => 'custom_textarea',
61
  'id' => 'wcj_emails_verification_error_message',
63
  'css' => 'width:66%;min-width:300px;',
64
  ),
65
  array(
66
+ 'title' => __( 'Message - Failed', 'woocommerce-jetpack' ),
67
  'desc_tip' => sprintf( __( 'Replaced value: %s', 'woocommerce-jetpack' ), '%resend_verification_url%' ),
68
  'type' => 'custom_textarea',
69
  'id' => 'wcj_emails_verification_failed_message',
71
  'css' => 'width:66%;min-width:300px;',
72
  ),
73
  array(
74
+ 'title' => __( 'Message - Activate', 'woocommerce-jetpack' ),
75
  'type' => 'custom_textarea',
76
  'id' => 'wcj_emails_verification_activation_message',
77
  'default' => __( 'Thank you for your registration. Your account has to be activated before you can login. Please check your email.', 'woocommerce-jetpack' ),
78
  'css' => 'width:66%;min-width:300px;',
79
  ),
80
  array(
81
+ 'title' => __( 'Message - Resend', 'woocommerce-jetpack' ),
82
  'type' => 'custom_textarea',
83
  'id' => 'wcj_emails_verification_email_resend_message',
84
  'default' => __( '<strong>Success:</strong> Your activation email has been resend. Please check your email.', 'woocommerce-jetpack' ),
86
  ),
87
  array(
88
  'type' => 'sectionend',
89
+ 'id' => 'wcj_emails_verification_messages_options',
90
+ ),
91
+ array(
92
+ 'title' => __( 'Email Options', 'woocommerce-jetpack' ),
93
+ 'type' => 'title',
94
+ 'id' => 'wcj_emails_verification_email_options',
95
+ ),
96
+ array(
97
+ 'title' => __( 'Email Subject', 'woocommerce-jetpack' ),
98
+ 'type' => 'custom_textarea',
99
+ 'id' => 'wcj_emails_verification_email_subject',
100
+ 'default' => __( 'Please activate your account', 'woocommerce-jetpack' ),
101
+ 'css' => 'width:66%;min-width:300px;',
102
+ 'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
103
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
104
+ ),
105
+ array(
106
+ 'title' => __( 'Email Content', 'woocommerce-jetpack' ),
107
+ 'desc_tip' => sprintf( __( 'Replaced value: %s', 'woocommerce-jetpack' ), '%verification_url%' ),
108
+ 'type' => 'custom_textarea',
109
+ 'id' => 'wcj_emails_verification_email_content',
110
+ 'default' => __( 'Please click the following link to verify your email:<br><br><a href="%verification_url%">%verification_url%</a>', 'woocommerce-jetpack' ),
111
+ 'css' => 'width:66%;min-width:300px;height:150px;',
112
+ 'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
113
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
114
+ ),
115
+ array(
116
+ 'title' => __( 'Email Template', 'woocommerce-jetpack' ),
117
+ 'desc_tip' => __( 'Possible values: Plain, WooCommerce.', 'woocommerce-jetpack' ),
118
+ 'id' => 'wcj_emails_verification_email_template',
119
+ 'type' => 'select',
120
+ 'default' => 'plain',
121
+ 'options' => array(
122
+ 'plain' => __( 'Plain', 'woocommerce-jetpack' ),
123
+ 'wc' => __( 'WooCommerce', 'woocommerce-jetpack' ),
124
+ ),
125
+ 'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
126
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
127
+ ),
128
+ array(
129
+ 'desc_tip' => __( 'If WooCommerce template is selected, set email heading here.', 'woocommerce-jetpack' ),
130
+ 'id' => 'wcj_emails_verification_email_template_wc_heading',
131
+ 'type' => 'custom_textarea',
132
+ 'default' => __( 'Activate your account', 'woocommerce-jetpack' ),
133
+ 'css' => 'width:66%;min-width:300px;',
134
+ 'desc' => apply_filters( 'booster_get_message', '', 'desc' ),
135
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
136
+ ),
137
+ array(
138
+ 'type' => 'sectionend',
139
+ 'id' => 'wcj_emails_verification_email_options',
140
  ),
141
  );
includes/settings/wcj-settings-general.php CHANGED
@@ -2,10 +2,11 @@
2
  /**
3
  * Booster for WooCommerce - Settings - General
4
  *
5
- * @version 2.9.1
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo add link to Booster's shortcodes list
 
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
@@ -83,6 +84,16 @@ $settings = array(
83
  'default' => 'no',
84
  'type' => 'checkbox',
85
  ),
 
 
 
 
 
 
 
 
 
 
86
  array(
87
  'title' => __( 'Disable Loading Datepicker/Weekpicker CSS', 'woocommerce-jetpack' ),
88
  'desc' => __( 'Disable', 'woocommerce-jetpack' ),
2
  /**
3
  * Booster for WooCommerce - Settings - General
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo add link to Booster's shortcodes list
9
+ * @todo clean up
10
  */
11
 
12
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
84
  'default' => 'no',
85
  'type' => 'checkbox',
86
  ),
87
+ array(
88
+ 'title' => __( 'Session Type in Booster', 'woocommerce-jetpack' ),
89
+ 'id' => 'wcj_general_advanced_session_type',
90
+ 'default' => 'standard',
91
+ 'type' => 'select',
92
+ 'options' => array(
93
+ 'standard' => __( 'Standard PHP sessions', 'woocommerce-jetpack' ),
94
+ 'wc' => __( 'WC sessions', 'woocommerce-jetpack' ),
95
+ ),
96
+ ),
97
  array(
98
  'title' => __( 'Disable Loading Datepicker/Weekpicker CSS', 'woocommerce-jetpack' ),
99
  'desc' => __( 'Disable', 'woocommerce-jetpack' ),
includes/settings/wcj-settings-global-discount.php CHANGED
@@ -2,14 +2,18 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Global Discount
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
- $product_cats_options = wcj_get_terms( 'product_cat' );
 
 
 
 
13
  $settings = array(
14
  array(
15
  'title' => __( 'Options', 'woocommerce-jetpack' ),
@@ -32,6 +36,10 @@ $settings = array(
32
  ),
33
  );
34
  for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) ); $i++ ) {
 
 
 
 
35
  $settings = array_merge( $settings, array(
36
  array(
37
  'title' => __( 'Discount Group', 'woocommerce-jetpack' ) . ' #' . $i,
@@ -61,7 +69,7 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_glo
61
  'id' => 'wcj_global_discount_sale_coefficient_' . $i,
62
  'default' => 0,
63
  'type' => 'number',
64
- 'custom_attributes' => array( /* 'min' => 0, */ 'max' => 0, 'step' => 0.0001 ), // todo
65
  ),
66
  array(
67
  'title' => __( 'Product Scope', 'woocommerce-jetpack' ),
@@ -76,12 +84,61 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_glo
76
  ),
77
  array(
78
  'title' => __( 'Include Product Categories', 'woocommerce-jetpack' ),
79
- 'desc_tip' => __( 'Set this field to apply discount to selected categories only. Leave blank to apply to all categories.', 'woocommerce-jetpack' ),
80
  'id' => 'wcj_global_discount_sale_categories_incl_' . $i,
81
  'default' => '',
82
  'class' => 'chosen_select',
83
  'type' => 'multiselect',
84
- 'options' => $product_cats_options,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
  ),
86
  array(
87
  'type' => 'sectionend',
2
  /**
3
  * Booster for WooCommerce - Settings - Global Discount
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
+ $is_multiselect_products = ( 'yes' === get_option( 'wcj_list_for_products', 'yes' ) );
13
+ $products = ( $is_multiselect_products ? wcj_get_products() : false );
14
+ $product_cats = wcj_get_terms( 'product_cat' );
15
+ $product_tags = wcj_get_terms( 'product_tag' );
16
+
17
  $settings = array(
18
  array(
19
  'title' => __( 'Options', 'woocommerce-jetpack' ),
36
  ),
37
  );
38
  for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_global_discount_groups_total_number', 1 ) ); $i++ ) {
39
+ wcj_maybe_convert_and_update_option_value( array(
40
+ array( 'id' => 'wcj_global_discount_sale_products_incl_' . $i, 'default' => '' ),
41
+ array( 'id' => 'wcj_global_discount_sale_products_excl_' . $i, 'default' => '' ),
42
+ ), $is_multiselect_products );
43
  $settings = array_merge( $settings, array(
44
  array(
45
  'title' => __( 'Discount Group', 'woocommerce-jetpack' ) . ' #' . $i,
69
  'id' => 'wcj_global_discount_sale_coefficient_' . $i,
70
  'default' => 0,
71
  'type' => 'number',
72
+ 'custom_attributes' => array( 'max' => 0, 'step' => 0.0001 ),
73
  ),
74
  array(
75
  'title' => __( 'Product Scope', 'woocommerce-jetpack' ),
84
  ),
85
  array(
86
  'title' => __( 'Include Product Categories', 'woocommerce-jetpack' ),
87
+ 'desc_tip' => __( 'Set this field to apply discount to selected product categories only. Leave blank to apply to all products.', 'woocommerce-jetpack' ),
88
  'id' => 'wcj_global_discount_sale_categories_incl_' . $i,
89
  'default' => '',
90
  'class' => 'chosen_select',
91
  'type' => 'multiselect',
92
+ 'options' => $product_cats,
93
+ ),
94
+ array(
95
+ 'title' => __( 'Exclude Product Categories', 'woocommerce-jetpack' ),
96
+ 'desc_tip' => __( 'Set this field to NOT apply discount to selected product categories. Leave blank to apply to all products.', 'woocommerce-jetpack' ),
97
+ 'id' => 'wcj_global_discount_sale_categories_excl_' . $i,
98
+ 'default' => '',
99
+ 'class' => 'chosen_select',
100
+ 'type' => 'multiselect',
101
+ 'options' => $product_cats,
102
+ ),
103
+ array(
104
+ 'title' => __( 'Include Product Tags', 'woocommerce-jetpack' ),
105
+ 'desc_tip' => __( 'Set this field to apply discount to selected product tags only. Leave blank to apply to all products.', 'woocommerce-jetpack' ),
106
+ 'id' => 'wcj_global_discount_sale_tags_incl_' . $i,
107
+ 'default' => '',
108
+ 'class' => 'chosen_select',
109
+ 'type' => 'multiselect',
110
+ 'options' => $product_tags,
111
+ ),
112
+ array(
113
+ 'title' => __( 'Exclude Product Tags', 'woocommerce-jetpack' ),
114
+ 'desc_tip' => __( 'Set this field to NOT apply discount to selected product tags. Leave blank to apply to all products.', 'woocommerce-jetpack' ),
115
+ 'id' => 'wcj_global_discount_sale_tags_excl_' . $i,
116
+ 'default' => '',
117
+ 'class' => 'chosen_select',
118
+ 'type' => 'multiselect',
119
+ 'options' => $product_tags,
120
+ ),
121
+ wcj_get_settings_as_multiselect_or_text(
122
+ array(
123
+ 'title' => __( 'Include Products', 'woocommerce-jetpack' ),
124
+ 'desc_tip' => __( 'Set this field to apply discount to selected products only. Leave blank to apply to all products.', 'woocommerce-jetpack' ),
125
+ 'id' => 'wcj_global_discount_sale_products_incl_' . $i,
126
+ 'default' => '',
127
+ 'class' => 'widefat',
128
+ ),
129
+ $products,
130
+ $is_multiselect_products
131
+ ),
132
+ wcj_get_settings_as_multiselect_or_text(
133
+ array(
134
+ 'title' => __( 'Exclude Products', 'woocommerce-jetpack' ),
135
+ 'desc_tip' => __( 'Set this field to NOT apply discount to selected products. Leave blank to apply to all products.', 'woocommerce-jetpack' ),
136
+ 'id' => 'wcj_global_discount_sale_products_excl_' . $i,
137
+ 'default' => '',
138
+ 'class' => 'widefat',
139
+ ),
140
+ $products,
141
+ $is_multiselect_products
142
  ),
143
  array(
144
  'type' => 'sectionend',
includes/settings/wcj-settings-left-to-free-shipping.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Left to Free Shipping
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -13,9 +13,13 @@ return array(
13
  array(
14
  'title' => __( 'Left to Free Shipping Info Options', 'woocommerce-jetpack' ),
15
  'type' => 'title',
16
- 'desc' => __( 'This section lets you enable info on cart, mini cart and checkout pages.', 'woocommerce-jetpack' )
17
- . '<br>' . __( 'You can also use <em>Booster - Left to Free Shipping</em> widget, <em>[wcj_get_left_to_free_shipping content=""]</em> shortcode or <em>wcj_get_left_to_free_shipping( $content );</em> function.', 'woocommerce-jetpack' )
18
- . '<br>' . __( 'In content you can use: <em>%left_to_free%</em> and <em>%free_shipping_min_amount%</em> shortcodes.', 'woocommerce-jetpack' ),
 
 
 
 
19
  'id' => 'wcj_shipping_left_to_free_info_options',
20
  ),
21
  array(
2
  /**
3
  * Booster for WooCommerce - Settings - Left to Free Shipping
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
13
  array(
14
  'title' => __( 'Left to Free Shipping Info Options', 'woocommerce-jetpack' ),
15
  'type' => 'title',
16
+ 'desc' => __( 'This section lets you enable info on cart, mini cart and checkout pages.', 'woocommerce-jetpack' ) . '<br>' . '<br>' .
17
+ sprintf( __( 'You can also use <em>Booster - Left to Free Shipping</em> widget, %s shortcode or %s function.', 'woocommerce-jetpack' ),
18
+ '<code>[wcj_get_left_to_free_shipping content=""]</code>',
19
+ '<code>wcj_get_left_to_free_shipping( $content );</code>' ) . '<br>' . '<br>' .
20
+ sprintf( __( 'In content replaced values are: %s and %s.', 'woocommerce-jetpack' ),
21
+ '<code>%left_to_free%</code>',
22
+ '<code>%free_shipping_min_amount%</code>' ),
23
  'id' => 'wcj_shipping_left_to_free_info_options',
24
  ),
25
  array(
includes/settings/wcj-settings-multicurrency-base-price.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Multicurrency Product Base Price
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -35,6 +35,28 @@ $settings = array(
35
  apply_filters( 'booster_get_message', '', 'desc' ),
36
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
37
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  array(
39
  'type' => 'sectionend',
40
  'id' => 'wcj_multicurrency_base_price_options',
2
  /**
3
  * Booster for WooCommerce - Settings - Multicurrency Product Base Price
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
35
  apply_filters( 'booster_get_message', '', 'desc' ),
36
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
37
  ),
38
+ array(
39
+ 'title' => __( 'Round Prices', 'woocommerce-jetpack' ),
40
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
41
+ 'id' => 'wcj_multicurrency_base_price_round_enabled',
42
+ 'default' => 'no',
43
+ 'type' => 'checkbox',
44
+ ),
45
+ array(
46
+ 'desc' => __( 'rounding precision', 'woocommerce-jetpack' ),
47
+ 'id' => 'wcj_multicurrency_base_price_round_precision',
48
+ 'default' => get_option( 'woocommerce_price_num_decimals' ),
49
+ 'type' => 'number',
50
+ 'custom_attributes' => array( 'min' => 0 ),
51
+ ),
52
+ array(
53
+ 'title' => __( 'Advanced: Saved Calculated Products Prices', 'woocommerce-jetpack' ),
54
+ 'desc_tip' => __( 'This may help if you are experiencing compatibility issues with other plugins.', 'woocommerce-jetpack' ),
55
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
56
+ 'id' => 'wcj_multicurrency_base_price_save_prices',
57
+ 'default' => 'no',
58
+ 'type' => 'checkbox',
59
+ ),
60
  array(
61
  'type' => 'sectionend',
62
  'id' => 'wcj_multicurrency_base_price_options',
includes/settings/wcj-settings-payment-gateways-per-category.php CHANGED
@@ -2,16 +2,17 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Gateways per Product or Category
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
- $product_cats = wcj_get_terms( 'product_cat' );
13
- $products = wcj_get_products();
14
- $available_gateways = WC()->payment_gateways->payment_gateways();
 
15
  $settings = array(
16
  array(
17
  'title' => __( 'Options', 'woocommerce-jetpack' ),
@@ -20,6 +21,10 @@ $settings = array(
20
  ),
21
  );
22
  foreach ( $available_gateways as $gateway_id => $gateway ) {
 
 
 
 
23
  $settings = array_merge( $settings, array(
24
  array(
25
  'title' => $gateway->title,
@@ -43,29 +48,31 @@ foreach ( $available_gateways as $gateway_id => $gateway ) {
43
  'css' => 'width: 450px;',
44
  'options' => $product_cats,
45
  ),
46
- array(
47
- 'title' => '',
48
- 'desc' => __( 'Products - Include', 'woocommerce-jetpack' ) . '. ' . apply_filters( 'booster_get_message', '', 'desc' ),
49
- 'desc_tip' => __( 'Show gateway only if there is selected products in cart. Leave blank to disable the option.', 'woocommerce-jetpack' ),
50
- 'id' => 'wcj_gateways_per_products_' . $gateway_id,
51
- 'default' => '',
52
- 'type' => 'multiselect',
53
- 'class' => 'chosen_select',
54
- 'css' => 'width: 450px;',
55
- 'options' => $products,
56
- 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
 
57
  ),
58
- array(
59
- 'title' => '',
60
- 'desc' => __( 'Products - Exclude', 'woocommerce-jetpack' ) . '. ' . apply_filters( 'booster_get_message', '', 'desc' ),
61
- 'desc_tip' => __( 'Hide gateway if there is selected products in cart. Leave blank to disable the option.', 'woocommerce-jetpack' ),
62
- 'id' => 'wcj_gateways_per_products_excl_' . $gateway_id,
63
- 'default' => '',
64
- 'type' => 'multiselect',
65
- 'class' => 'chosen_select',
66
- 'css' => 'width: 450px;',
67
- 'options' => $products,
68
- 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
 
69
  ),
70
  ) );
71
  }
2
  /**
3
  * Booster for WooCommerce - Settings - Gateways per Product or Category
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
+ $product_cats = wcj_get_terms( 'product_cat' );
13
+ $is_multiselect_products = ( 'yes' === get_option( 'wcj_list_for_products', 'yes' ) );
14
+ $products = ( $is_multiselect_products ? wcj_get_products() : false );
15
+ $available_gateways = WC()->payment_gateways->payment_gateways();
16
  $settings = array(
17
  array(
18
  'title' => __( 'Options', 'woocommerce-jetpack' ),
21
  ),
22
  );
23
  foreach ( $available_gateways as $gateway_id => $gateway ) {
24
+ wcj_maybe_convert_and_update_option_value( array(
25
+ array( 'id' => 'wcj_gateways_per_products_' . $gateway_id, 'default' => '' ),
26
+ array( 'id' => 'wcj_gateways_per_products_excl_' . $gateway_id, 'default' => '' ),
27
+ ), $is_multiselect_products );
28
  $settings = array_merge( $settings, array(
29
  array(
30
  'title' => $gateway->title,
48
  'css' => 'width: 450px;',
49
  'options' => $product_cats,
50
  ),
51
+ wcj_get_settings_as_multiselect_or_text(
52
+ array(
53
+ 'title' => '',
54
+ 'desc' => __( 'Products - Include', 'woocommerce-jetpack' ) . '. ' . apply_filters( 'booster_get_message', '', 'desc' ),
55
+ 'desc_tip' => __( 'Show gateway only if there is selected products in cart. Leave blank to disable the option.', 'woocommerce-jetpack' ),
56
+ 'id' => 'wcj_gateways_per_products_' . $gateway_id,
57
+ 'default' => '',
58
+ 'css' => 'width: 450px;',
59
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
60
+ ),
61
+ $products,
62
+ $is_multiselect_products
63
  ),
64
+ wcj_get_settings_as_multiselect_or_text(
65
+ array(
66
+ 'title' => '',
67
+ 'desc' => __( 'Products - Exclude', 'woocommerce-jetpack' ) . '. ' . apply_filters( 'booster_get_message', '', 'desc' ),
68
+ 'desc_tip' => __( 'Hide gateway if there is selected products in cart. Leave blank to disable the option.', 'woocommerce-jetpack' ),
69
+ 'id' => 'wcj_gateways_per_products_excl_' . $gateway_id,
70
+ 'default' => '',
71
+ 'css' => 'width: 450px;',
72
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
73
+ ),
74
+ $products,
75
+ $is_multiselect_products
76
  ),
77
  ) );
78
  }
includes/settings/wcj-settings-pdf-invoicing-display.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Display
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) add "Save all settings" buttons to each document type
@@ -13,12 +13,21 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
  $settings = array();
14
  $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ) ? wcj_get_enabled_invoice_types() : wcj_get_invoice_types();
15
  foreach ( $invoice_types as $invoice_type ) {
 
 
16
  $settings = array_merge( $settings, array(
17
  array(
18
- 'title' => strtoupper( $invoice_type['desc'] ),
19
  'type' => 'title',
20
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_display_options',
21
  ),
 
 
 
 
 
 
 
22
  array(
23
  'title' => __( 'Admin\'s "Orders" Page', 'woocommerce-jetpack' ),
24
  'desc' => __( 'Add Column', 'woocommerce-jetpack' ),
@@ -32,6 +41,7 @@ foreach ( $invoice_types as $invoice_type ) {
32
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_page_column_text',
33
  'default' => $invoice_type['title'],
34
  'type' => 'text',
 
35
  ),
36
  /* array(
37
  'title' => '',
@@ -50,34 +60,39 @@ foreach ( $invoice_types as $invoice_type ) {
50
  'type' => 'text',
51
  ), */
52
  array(
53
- 'desc' => __( 'Add View Button', 'woocommerce-jetpack' ),
54
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_view_btn',
55
  'default' => 'no',
56
  'type' => 'checkbox',
 
57
  ),
58
  array(
59
- 'desc' => __( 'Add Create Button', 'woocommerce-jetpack' ),
60
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_create_btn',
61
  'default' => 'yes',
62
  'type' => 'checkbox',
 
63
  ),
64
  array(
65
- 'desc' => __( 'Add Delete Button', 'woocommerce-jetpack' ),
66
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_delete_btn',
67
  'default' => 'yes',
68
  'type' => 'checkbox',
 
69
  ),
70
  array(
71
- 'desc' => __( 'Create Button Requires Confirmation', 'woocommerce-jetpack' ),
72
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_create_btn_confirm',
73
  'default' => 'yes',
74
  'type' => 'checkbox',
 
75
  ),
76
  array(
77
- 'desc' => __( 'Delete Button Requires Confirmation', 'woocommerce-jetpack' ),
78
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_delete_btn_confirm',
79
  'default' => 'yes',
80
  'type' => 'checkbox',
 
81
  ),
82
  array(
83
  'title' => __( 'Customer\'s "My Account" Page', 'woocommerce-jetpack' ),
@@ -87,11 +102,11 @@ foreach ( $invoice_types as $invoice_type ) {
87
  'type' => 'checkbox',
88
  ),
89
  array(
90
- 'title' => '',
91
  'desc' => __( 'Link Text', 'woocommerce-jetpack' ),
92
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_link_text',
93
  'default' => $invoice_type['title'],
94
  'type' => 'text',
 
95
  ),
96
  array(
97
  'title' => __( 'Enable "Save as"', 'woocommerce-jetpack' ),
@@ -103,10 +118,12 @@ foreach ( $invoice_types as $invoice_type ) {
103
  ),
104
  array(
105
  'title' => __( 'PDF File Name', 'woocommerce-jetpack' ),
106
- 'desc' => __( 'Enter file name for PDF documents. You can use shortcodes here, e.g. [wcj_' . $invoice_type['id'] . '_number]', 'woocommerce-jetpack' ),
 
107
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_file_name',
108
- 'default' => '[wcj_' . $invoice_type['id'] . '_number]',
109
  'type' => 'text',
 
110
  ),
111
  array(
112
  'title' => __( 'Allowed User Roles', 'woocommerce-jetpack' ),
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Display
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) add "Save all settings" buttons to each document type
13
  $settings = array();
14
  $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ) ? wcj_get_enabled_invoice_types() : wcj_get_invoice_types();
15
  foreach ( $invoice_types as $invoice_type ) {
16
+ $document_number_shortode = ( isset( $invoice_type['is_custom_doc'] ) && true === $invoice_type['is_custom_doc'] ?
17
+ '[wcj_custom_doc_number doc_nr="' . $invoice_type['custom_doc_nr'] . '"]' : '[wcj_' . $invoice_type['id'] . '_number]' );
18
  $settings = array_merge( $settings, array(
19
  array(
20
+ 'title' => $invoice_type['title'],
21
  'type' => 'title',
22
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_display_options',
23
  ),
24
+ array(
25
+ 'title' => __( 'Admin Title', 'woocommerce-jetpack' ),
26
+ 'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_title',
27
+ 'default' => $invoice_type['title'],
28
+ 'type' => 'text',
29
+ 'class' => 'widefat',
30
+ ),
31
  array(
32
  'title' => __( 'Admin\'s "Orders" Page', 'woocommerce-jetpack' ),
33
  'desc' => __( 'Add Column', 'woocommerce-jetpack' ),
41
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_page_column_text',
42
  'default' => $invoice_type['title'],
43
  'type' => 'text',
44
+ 'class' => 'widefat',
45
  ),
46
  /* array(
47
  'title' => '',
60
  'type' => 'text',
61
  ), */
62
  array(
63
+ 'desc' => __( 'Add "View" button', 'woocommerce-jetpack' ),
64
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_view_btn',
65
  'default' => 'no',
66
  'type' => 'checkbox',
67
+ 'checkboxgroup' => 'start',
68
  ),
69
  array(
70
+ 'desc' => __( 'Add "Create" button', 'woocommerce-jetpack' ),
71
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_create_btn',
72
  'default' => 'yes',
73
  'type' => 'checkbox',
74
+ 'checkboxgroup' => '',
75
  ),
76
  array(
77
+ 'desc' => __( 'Add "Delete" button', 'woocommerce-jetpack' ),
78
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_delete_btn',
79
  'default' => 'yes',
80
  'type' => 'checkbox',
81
+ 'checkboxgroup' => '',
82
  ),
83
  array(
84
+ 'desc' => __( '"Create" button requires confirmation', 'woocommerce-jetpack' ),
85
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_create_btn_confirm',
86
  'default' => 'yes',
87
  'type' => 'checkbox',
88
+ 'checkboxgroup' => '',
89
  ),
90
  array(
91
+ 'desc' => __( '"Delete" button requires confirmation', 'woocommerce-jetpack' ),
92
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_admin_orders_delete_btn_confirm',
93
  'default' => 'yes',
94
  'type' => 'checkbox',
95
+ 'checkboxgroup' => 'end',
96
  ),
97
  array(
98
  'title' => __( 'Customer\'s "My Account" Page', 'woocommerce-jetpack' ),
102
  'type' => 'checkbox',
103
  ),
104
  array(
 
105
  'desc' => __( 'Link Text', 'woocommerce-jetpack' ),
106
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_link_text',
107
  'default' => $invoice_type['title'],
108
  'type' => 'text',
109
+ 'class' => 'widefat',
110
  ),
111
  array(
112
  'title' => __( 'Enable "Save as"', 'woocommerce-jetpack' ),
118
  ),
119
  array(
120
  'title' => __( 'PDF File Name', 'woocommerce-jetpack' ),
121
+ 'desc' => sprintf( __( 'Enter file name for PDF documents. You can use shortcodes here, e.g. %s.', 'woocommerce-jetpack' ),
122
+ '<code>' . $document_number_shortode . '</code>' ),
123
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_file_name',
124
+ 'default' => $document_number_shortode,
125
  'type' => 'text',
126
+ 'class' => 'widefat',
127
  ),
128
  array(
129
  'title' => __( 'Allowed User Roles', 'woocommerce-jetpack' ),
includes/settings/wcj-settings-pdf-invoicing-emails.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Email Options
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -14,17 +14,18 @@ foreach ( $available_gateways as $key => $gateway ) {
14
  $available_gateways_options_array[ $key ] = $gateway->title;
15
  }
16
  $available_emails = array(
17
- 'new_order' => __( 'Admin - New Order', 'woocommerce-jetpack' ),
18
- 'cancelled_order' => __( 'Admin - Cancelled Order', 'woocommerce-jetpack' ),
19
- 'failed_order' => __( 'Admin - Failed Order', 'woocommerce-jetpack' ),
20
- 'customer_processing_order' => __( 'Customer - Processing Order', 'woocommerce-jetpack' ),
21
- 'customer_on_hold_order' => __( 'Customer - On-Hold Order', 'woocommerce-jetpack' ),
22
- 'customer_completed_order' => __( 'Customer - Completed Order', 'woocommerce-jetpack' ),
23
- 'customer_invoice' => __( 'Customer - Invoice', 'woocommerce-jetpack' ),
24
- 'customer_refunded_order' => __( 'Customer - Refunded Order', 'woocommerce-jetpack' ),
25
- 'customer_note' => __( 'Customer - Note', 'woocommerce-jetpack' ),
26
- 'customer_new_account' => __( 'Customer - New Account', 'woocommerce-jetpack' ),
27
- 'customer_reset_password' => __( 'Customer - Reset Password', 'woocommerce-jetpack' ),
 
28
  );
29
  if ( wcj_is_module_enabled( 'emails' ) ) {
30
  for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
@@ -36,7 +37,7 @@ $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_setti
36
  foreach ( $invoice_types as $invoice_type ) {
37
  $settings = array_merge( $settings, array(
38
  array(
39
- 'title' => strtoupper( $invoice_type['desc'] ),
40
  'type' => 'title',
41
  'desc' => '',
42
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_emails_options',
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Email Options
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
14
  $available_gateways_options_array[ $key ] = $gateway->title;
15
  }
16
  $available_emails = array(
17
+ 'new_order' => __( 'Admin - New Order', 'woocommerce-jetpack' ),
18
+ 'cancelled_order' => __( 'Admin - Cancelled Order', 'woocommerce-jetpack' ),
19
+ 'failed_order' => __( 'Admin - Failed Order', 'woocommerce-jetpack' ),
20
+ 'customer_processing_order' => __( 'Customer - Processing Order', 'woocommerce-jetpack' ),
21
+ 'customer_on_hold_order' => __( 'Customer - On-Hold Order', 'woocommerce-jetpack' ),
22
+ 'customer_completed_order' => __( 'Customer - Completed Order', 'woocommerce-jetpack' ),
23
+ 'customer_invoice' => __( 'Customer - Invoice', 'woocommerce-jetpack' ),
24
+ 'customer_refunded_order' => __( 'Customer - Refunded Order', 'woocommerce-jetpack' ),
25
+ 'customer_partially_refunded_order' => __( 'Customer - Partially Refunded Order', 'woocommerce-jetpack' ),
26
+ 'customer_note' => __( 'Customer - Note', 'woocommerce-jetpack' ),
27
+ 'customer_new_account' => __( 'Customer - New Account', 'woocommerce-jetpack' ),
28
+ 'customer_reset_password' => __( 'Customer - Reset Password', 'woocommerce-jetpack' ),
29
  );
30
  if ( wcj_is_module_enabled( 'emails' ) ) {
31
  for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_emails_custom_emails_total_number', 1 ) ); $i++ ) {
37
  foreach ( $invoice_types as $invoice_type ) {
38
  $settings = array_merge( $settings, array(
39
  array(
40
+ 'title' => $invoice_type['title'],
41
  'type' => 'title',
42
  'desc' => '',
43
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_emails_options',
includes/settings/wcj-settings-pdf-invoicing-footer.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Footer
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -14,12 +14,13 @@ $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_setti
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
17
- 'title' => strtoupper( $invoice_type['desc'] ),
18
  'type' => 'title',
19
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_footer_options',
20
  ),
21
  array(
22
  'title' => __( 'Enable Footer', 'woocommerce-jetpack' ),
 
23
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_footer_enabled',
24
  'default' => 'yes',
25
  'type' => 'checkbox',
@@ -30,10 +31,8 @@ foreach ( $invoice_types as $invoice_type ) {
30
  'default' => __( 'Page %page_number% / %total_pages%', 'woocommerce-jetpack' ),
31
  'type' => 'textarea',
32
  'css' => 'width:66%;min-width:300px;height:165px;',
33
- 'desc' => sprintf(
34
- __( 'You can use HTML here, as well as any WordPress shortcodes. There are two more predefined values you can use: %s.', 'woocommerce-jetpack' ),
35
- '<code>%page_number%</code>, <code>%total_pages%</code>'
36
- ),
37
  ),
38
  array(
39
  'title' => __( 'Footer Text Color', 'woocommerce-jetpack' ),
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Footer
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
17
+ 'title' => $invoice_type['title'],
18
  'type' => 'title',
19
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_footer_options',
20
  ),
21
  array(
22
  'title' => __( 'Enable Footer', 'woocommerce-jetpack' ),
23
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
24
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_footer_enabled',
25
  'default' => 'yes',
26
  'type' => 'checkbox',
31
  'default' => __( 'Page %page_number% / %total_pages%', 'woocommerce-jetpack' ),
32
  'type' => 'textarea',
33
  'css' => 'width:66%;min-width:300px;height:165px;',
34
+ 'desc' => __( 'You can use HTML here, as well as any WordPress shortcodes.', 'woocommerce-jetpack' ) . ' ' .
35
+ wcj_message_replaced_values( array( '%page_number%', '%total_pages%' ) ),
 
 
36
  ),
37
  array(
38
  'title' => __( 'Footer Text Color', 'woocommerce-jetpack' ),
includes/settings/wcj-settings-pdf-invoicing-header.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Header
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -14,12 +14,13 @@ $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_setti
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
17
- 'title' => strtoupper( $invoice_type['desc'] ),
18
  'type' => 'title',
19
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_options',
20
  ),
21
  array(
22
  'title' => __( 'Enable Header', 'woocommerce-jetpack' ),
 
23
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_enabled',
24
  'default' => 'yes',
25
  'type' => 'checkbox',
@@ -29,9 +30,11 @@ foreach ( $invoice_types as $invoice_type ) {
29
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_image',
30
  'default' => '',
31
  'type' => 'text',
32
- 'css' => 'width:33%;min-width:300px;',
33
- 'desc' => __( 'Enter a URL to an image you want to show in the invoice\'s header. Upload your image using the <a href="/wp-admin/media-new.php">media uploader</a>.', 'woocommerce-jetpack' ),
 
34
  'desc_tip' => __( 'Leave blank to disable', 'woocommerce-jetpack' ),
 
35
  ),
36
  array(
37
  'title' => __( 'Header Image Width in mm', 'woocommerce-jetpack' ),
@@ -44,12 +47,14 @@ foreach ( $invoice_types as $invoice_type ) {
44
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_title_text',
45
  'default' => $invoice_type['title'],
46
  'type' => 'text',
 
47
  ),
48
  array(
49
  'title' => __( 'Header Text', 'woocommerce-jetpack' ),
50
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_text',
51
  'default' => __( 'Company Name', 'woocommerce-jetpack' ),
52
  'type' => 'text',
 
53
  ),
54
  array(
55
  'title' => __( 'Header Text Color', 'woocommerce-jetpack' ),
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Header
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
17
+ 'title' => $invoice_type['title'],
18
  'type' => 'title',
19
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_options',
20
  ),
21
  array(
22
  'title' => __( 'Enable Header', 'woocommerce-jetpack' ),
23
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
24
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_enabled',
25
  'default' => 'yes',
26
  'type' => 'checkbox',
30
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_image',
31
  'default' => '',
32
  'type' => 'text',
33
+ 'desc' => sprintf(
34
+ __( 'Enter a URL to an image you want to show in the invoice\'s header. Upload your image using the <a href="%s">media uploader</a>.', 'woocommerce-jetpack' ),
35
+ admin_url( 'media-new.php' ) ),
36
  'desc_tip' => __( 'Leave blank to disable', 'woocommerce-jetpack' ),
37
+ 'class' => 'widefat',
38
  ),
39
  array(
40
  'title' => __( 'Header Image Width in mm', 'woocommerce-jetpack' ),
47
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_title_text',
48
  'default' => $invoice_type['title'],
49
  'type' => 'text',
50
+ 'class' => 'widefat',
51
  ),
52
  array(
53
  'title' => __( 'Header Text', 'woocommerce-jetpack' ),
54
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_header_text',
55
  'default' => __( 'Company Name', 'woocommerce-jetpack' ),
56
  'type' => 'text',
57
+ 'class' => 'widefat',
58
  ),
59
  array(
60
  'title' => __( 'Header Text Color', 'woocommerce-jetpack' ),
includes/settings/wcj-settings-pdf-invoicing-numbering.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Numbering
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -14,7 +14,7 @@ $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_setti
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
17
- 'title' => strtoupper( $invoice_type['desc'] ),
18
  'type' => 'title',
19
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_numbering_options',
20
  ),
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Numbering
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
17
+ 'title' => $invoice_type['title'],
18
  'type' => 'title',
19
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_numbering_options',
20
  ),
includes/settings/wcj-settings-pdf-invoicing-page.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Page Settings
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -14,7 +14,7 @@ $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_setti
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
17
- 'title' => strtoupper( $invoice_type['desc'] ),
18
  'type' => 'title',
19
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_page_options',
20
  ),
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Page Settings
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
14
  foreach ( $invoice_types as $invoice_type ) {
15
  $settings = array_merge( $settings, array(
16
  array(
17
+ 'title' => $invoice_type['title'],
18
  'type' => 'title',
19
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_page_options',
20
  ),
includes/settings/wcj-settings-pdf-invoicing-styling.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Styling
4
  *
5
- * @version 3.0.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -13,15 +13,6 @@ $is_full_fonts = wcj_check_and_maybe_download_tcpdf_fonts();
13
  $settings = array();
14
  $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ) ? wcj_get_enabled_invoice_types() : wcj_get_invoice_types();
15
  foreach ( $invoice_types as $invoice_type ) {
16
- $default_template_filename = ( false === strpos( $invoice_type['id'], 'custom_doc_' ) ? $invoice_type['id'] : 'custom_doc' );
17
- $default_template_filename = wcj_plugin_path() . '/includes/settings/pdf-invoicing/wcj-' . $default_template_filename . '.css';
18
- if ( file_exists( $default_template_filename ) ) {
19
- ob_start();
20
- include( $default_template_filename );
21
- $default_template = ob_get_clean();
22
- } else {
23
- $default_template = '';
24
- }
25
  // Font family
26
  $font_family_option = ( $is_full_fonts ?
27
  array(
@@ -57,14 +48,14 @@ foreach ( $invoice_types as $invoice_type ) {
57
  );
58
  $settings = array_merge( $settings, array(
59
  array(
60
- 'title' => strtoupper( $invoice_type['desc'] ),
61
  'type' => 'title',
62
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_styling_options',
63
  ),
64
  array(
65
  'title' => __( 'CSS', 'woocommerce-jetpack' ),
66
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_css',
67
- 'default' => $default_template,
68
  'type' => 'textarea',
69
  'css' => 'width:66%;min-width:300px;height:200px;',
70
  ),
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Styling
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
13
  $settings = array();
14
  $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ) ? wcj_get_enabled_invoice_types() : wcj_get_invoice_types();
15
  foreach ( $invoice_types as $invoice_type ) {
 
 
 
 
 
 
 
 
 
16
  // Font family
17
  $font_family_option = ( $is_full_fonts ?
18
  array(
48
  );
49
  $settings = array_merge( $settings, array(
50
  array(
51
+ 'title' => $invoice_type['title'],
52
  'type' => 'title',
53
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_styling_options',
54
  ),
55
  array(
56
  'title' => __( 'CSS', 'woocommerce-jetpack' ),
57
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_css',
58
+ 'default' => $this->get_default_css_template( $invoice_type['id'] ),
59
  'type' => 'textarea',
60
  'css' => 'width:66%;min-width:300px;height:200px;',
61
  ),
includes/settings/wcj-settings-pdf-invoicing-templates.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Templates
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -12,30 +12,16 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
12
  $settings = array();
13
  $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ) ? wcj_get_enabled_invoice_types() : wcj_get_invoice_types();
14
  foreach ( $invoice_types as $invoice_type ) {
15
- $default_template_filename = ( false === strpos( $invoice_type['id'], 'custom_doc_' ) ? $invoice_type['id'] : 'custom_doc' );
16
- $default_template_filename = wcj_plugin_path() . '/includes/settings/pdf-invoicing/wcj-content-template-' . $default_template_filename . '.php';
17
- if ( file_exists( $default_template_filename ) ) {
18
- ob_start();
19
- include( $default_template_filename );
20
- $default_template = ob_get_clean();
21
- } else {
22
- $default_template = '';
23
- }
24
- if ( false !== strpos( $invoice_type['id'], 'custom_doc' ) ) {
25
- $custom_doc_nr = ( 'custom_doc' === $invoice_type['id'] ) ? '1' : str_replace( 'custom_doc_', '', $invoice_type['id'] );
26
- $default_template = str_replace( '[wcj_custom_doc_number]', '[wcj_custom_doc_number doc_nr="' . $custom_doc_nr . '"]', $default_template );
27
- $default_template = str_replace( '[wcj_custom_doc_date]', '[wcj_custom_doc_date doc_nr="' . $custom_doc_nr . '"]', $default_template );
28
- }
29
  $settings = array_merge( $settings, array(
30
  array(
31
- 'title' => strtoupper( $invoice_type['desc'] ),
32
  'type' => 'title',
33
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_templates_options',
34
  ),
35
  array(
36
  'title' => __( 'HTML Template', 'woocommerce-jetpack' ),
37
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_template',
38
- 'default' => $default_template,
39
  'type' => 'textarea',
40
  'css' => 'width:66%;min-width:300px;height:500px;',
41
  ),
2
  /**
3
  * Booster for WooCommerce - Settings - Templates
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
12
  $settings = array();
13
  $invoice_types = ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ) ? wcj_get_enabled_invoice_types() : wcj_get_invoice_types();
14
  foreach ( $invoice_types as $invoice_type ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  $settings = array_merge( $settings, array(
16
  array(
17
+ 'title' => $invoice_type['title'],
18
  'type' => 'title',
19
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_templates_options',
20
  ),
21
  array(
22
  'title' => __( 'HTML Template', 'woocommerce-jetpack' ),
23
  'id' => 'wcj_invoicing_' . $invoice_type['id'] . '_template',
24
+ 'default' => $this->get_default_template( $invoice_type['id'] ),
25
  'type' => 'textarea',
26
  'css' => 'width:66%;min-width:300px;height:500px;',
27
  ),
includes/settings/wcj-settings-pdf-invoicing.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - General
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -17,14 +17,23 @@ $settings = array(
17
  ),
18
  );
19
  // Hooks Array
20
- $create_on_array = array();
21
- $create_on_array['disabled'] = __( 'Disabled', 'woocommerce-jetpack' );
22
- $create_on_array['woocommerce_new_order'] = __( 'Create on New Order', 'woocommerce-jetpack' );
23
- $order_statuses = wcj_get_order_statuses( true );
24
  foreach ( $order_statuses as $status => $desc ) {
25
- $create_on_array[ 'woocommerce_order_status_' . $status ] = __( 'Create on Order Status', 'woocommerce-jetpack' ) . ' ' . $desc;
26
  }
27
- $create_on_array['manual'] = __( 'Manual Only', 'woocommerce-jetpack' );
 
 
 
 
 
 
 
 
 
 
 
28
  // Settings
29
  $invoice_types = wcj_get_invoice_types();
30
  foreach ( $invoice_types as $k => $invoice_type ) {
@@ -72,5 +81,42 @@ $settings = array_merge( $settings, array(
72
  'type' => 'sectionend',
73
  'id' => 'wcj_pdf_invoicing_options',
74
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  ) );
76
  return $settings;
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - General
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
17
  ),
18
  );
19
  // Hooks Array
20
+ $status_change_hooks = array();
21
+ $order_statuses = wcj_get_order_statuses( true );
 
 
22
  foreach ( $order_statuses as $status => $desc ) {
23
+ $status_change_hooks[ 'woocommerce_order_status_' . $status ] = sprintf( __( 'Create on Order Status %s', 'woocommerce-jetpack' ), $desc );
24
  }
25
+ $create_on_array = array_merge(
26
+ array(
27
+ 'disabled' => __( 'Disabled', 'woocommerce-jetpack' ),
28
+ 'woocommerce_new_order' => __( 'Create on New Order', 'woocommerce-jetpack' ),
29
+ ),
30
+ $status_change_hooks,
31
+ array(
32
+ 'wcj_pdf_invoicing_create_on_any_refund' => __( 'Create on Order Status Refunded and/or Order Partially Refunded', 'woocommerce-jetpack' ),
33
+ 'woocommerce_order_partially_refunded_notification' => __( 'Create on Order Partially Refunded', 'woocommerce-jetpack' ),
34
+ 'manual' => __( 'Manual Only', 'woocommerce-jetpack' ),
35
+ )
36
+ );
37
  // Settings
38
  $invoice_types = wcj_get_invoice_types();
39
  foreach ( $invoice_types as $k => $invoice_type ) {
81
  'type' => 'sectionend',
82
  'id' => 'wcj_pdf_invoicing_options',
83
  ),
84
+ array(
85
+ 'title' => __( 'Report Tool Options', 'woocommerce-jetpack' ),
86
+ 'type' => 'title',
87
+ 'id' => 'wcj_pdf_invoicing_report_tool_options',
88
+ ),
89
+ array(
90
+ 'title' => __( 'Reports Filename', 'woocommerce-jetpack' ),
91
+ 'desc' => wcj_message_replaced_values( array( '%site%', '%invoice_type%', '%year%', '%month%' ) ),
92
+ 'id' => 'wcj_pdf_invoicing_report_tool_filename',
93
+ 'default' => '%site%-%invoice_type%-%year%_%month%',
94
+ 'type' => 'text',
95
+ 'class' => 'widefat',
96
+ ),
97
+ array(
98
+ 'title' => __( 'CSV Separator', 'woocommerce-jetpack' ),
99
+ 'id' => 'wcj_pdf_invoicing_report_tool_csv_separator',
100
+ 'default' => ';',
101
+ 'type' => 'text',
102
+ ),
103
+ array(
104
+ 'title' => __( 'CSV UTF-8 BOM', 'woocommerce-jetpack' ),
105
+ 'desc' => __( 'Add', 'woocommerce-jetpack' ),
106
+ 'id' => 'wcj_pdf_invoicing_report_tool_csv_add_utf_8_bom',
107
+ 'default' => 'yes',
108
+ 'type' => 'checkbox',
109
+ ),
110
+ array(
111
+ 'title' => __( 'Replace Periods with Commas in CSV Data', 'woocommerce-jetpack' ),
112
+ 'desc' => __( 'Replace', 'woocommerce-jetpack' ),
113
+ 'id' => 'wcj_pdf_invoicing_report_tool_csv_replace_periods_w_commas',
114
+ 'default' => 'yes',
115
+ 'type' => 'checkbox',
116
+ ),
117
+ array(
118
+ 'type' => 'sectionend',
119
+ 'id' => 'wcj_pdf_invoicing_report_tool_options',
120
+ ),
121
  ) );
122
  return $settings;
includes/settings/wcj-settings-product-add-to-cart.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Product Add To Cart
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -84,6 +84,35 @@ return array(
84
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
85
  'desc_tip' => apply_filters( 'booster_get_message', '', 'desc' ),
86
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  array(
88
  'type' => 'sectionend',
89
  'id' => 'wcj_add_to_cart_variable_options',
2
  /**
3
  * Booster for WooCommerce - Settings - Product Add To Cart
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
84
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
85
  'desc_tip' => apply_filters( 'booster_get_message', '', 'desc' ),
86
  ),
87
+ array(
88
+ 'title' => __( 'Variation Label Template', 'woocommerce-jetpack' ),
89
+ 'desc' => wcj_message_replaced_values( array( '%variation_title%', '%variation_price%' ) ),
90
+ 'id' => 'wcj_add_to_cart_variable_as_radio_variation_label_template',
91
+ 'default' => '%variation_title% (%variation_price%)',
92
+ 'type' => 'custom_textarea',
93
+ 'css' => 'width:99%;',
94
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
95
+ 'desc_tip' => apply_filters( 'booster_get_message', '', 'desc_no_link' ),
96
+ ),
97
+ array(
98
+ 'title' => __( 'Variation Description Template', 'woocommerce-jetpack' ),
99
+ 'desc' => wcj_message_replaced_values( array( '%variation_description%' ) ),
100
+ 'id' => 'wcj_add_to_cart_variable_as_radio_variation_desc_template',
101
+ 'default' => '<br><small>%variation_description%</small>',
102
+ 'type' => 'custom_textarea',
103
+ 'css' => 'width:99%;',
104
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
105
+ 'desc_tip' => apply_filters( 'booster_get_message', '', 'desc_no_link' ),
106
+ ),
107
+ array(
108
+ 'title' => __( 'Variation Radio Input td Style', 'woocommerce-jetpack' ),
109
+ 'id' => 'wcj_add_to_cart_variable_as_radio_input_td_style',
110
+ 'default' => 'width:10%;',
111
+ 'type' => 'text',
112
+ 'css' => 'width:99%;',
113
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
114
+ 'desc_tip' => apply_filters( 'booster_get_message', '', 'desc_no_link' ),
115
+ ),
116
  array(
117
  'type' => 'sectionend',
118
  'id' => 'wcj_add_to_cart_variable_options',
includes/settings/wcj-settings-product-by-country.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Product Visibility by Country
4
  *
5
- * @version 2.9.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -11,12 +11,13 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
  return array(
13
  array(
14
- 'title' => __( 'Options', 'woocommerce-jetpack' ),
15
  'type' => 'title',
16
  'id' => 'wcj_product_by_country_options',
17
  ),
18
  array(
19
  'title' => __( 'Hide Visibility', 'woocommerce-jetpack' ),
 
20
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
21
  'id' => 'wcj_product_by_country_visibility',
22
  'default' => 'yes',
@@ -24,6 +25,7 @@ return array(
24
  ),
25
  array(
26
  'title' => __( 'Make Non-purchasable', 'woocommerce-jetpack' ),
 
27
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
28
  'id' => 'wcj_product_by_country_purchasable',
29
  'default' => 'no',
@@ -31,13 +33,49 @@ return array(
31
  ),
32
  array(
33
  'title' => __( 'Modify Query', 'woocommerce-jetpack' ),
 
34
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
35
  'id' => 'wcj_product_by_country_query',
36
  'default' => 'no',
37
  'type' => 'checkbox',
38
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
39
  array(
40
  'title' => __( 'Admin Products List Column', 'woocommerce-jetpack' ),
 
41
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
42
  'id' => 'wcj_product_by_country_add_column_visible_countries',
43
  'default' => 'no',
@@ -45,6 +83,6 @@ return array(
45
  ),
46
  array(
47
  'type' => 'sectionend',
48
- 'id' => 'wcj_product_by_country_options',
49
  ),
50
  );
2
  /**
3
  * Booster for WooCommerce - Settings - Product Visibility by Country
4
  *
5
+ * @version 3.1.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
11
 
12
  return array(
13
  array(
14
+ 'title' => __( 'Visibility Options', 'woocommerce-jetpack' ),
15
  'type' => 'title',
16
  'id' => 'wcj_product_by_country_options',
17
  ),
18
  array(
19
  'title' => __( 'Hide Visibility', 'woocommerce-jetpack' ),
20
+ 'desc_tip' => __( 'This will hide selected products in shop and search results. However product still will be accessible via direct link.', 'woocommerce-jetpack' ),
21
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
22
  'id' => 'wcj_product_by_country_visibility',
23
  'default' => 'yes',
25
  ),
26
  array(
27
  'title' => __( 'Make Non-purchasable', 'woocommerce-jetpack' ),
28
+ 'desc_tip' => __( 'This will make selected products non-purchasable (i.e. product can\'t be added to the cart).', 'woocommerce-jetpack' ),
29
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
30
  'id' => 'wcj_product_by_country_purchasable',
31
  'default' => 'no',
33
  ),
34
  array(
35
  'title' => __( 'Modify Query', 'woocommerce-jetpack' ),
36
+ 'desc_tip' => __( 'This will hide selected products completely (including direct link).', 'woocommerce-jetpack' ),
37
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
38
  'id' => 'wcj_product_by_country_query',
39
  'default' => 'no',
40
  'type' => 'checkbox',
41
  ),
42
+ array(
43
+ 'type' => 'sectionend',
44
+ 'id' => 'wcj_product_by_country_options',
45
+ ),
46
+ array(
47
+ 'title' => __( 'User Country Selection Options', 'woocommerce-jetpack' ),
48
+ 'type' => 'title',
49
+ 'id' => 'wcj_product_by_country_selection_options',
50
+ ),
51
+ array(
52
+ 'title' => __( 'User Country Selection Method', 'woocommerce-jetpack' ),
53
+ 'desc_tip' => __( 'Possible values: "Automatically by IP" or "Manually".', 'woocommerce-jetpack' ),
54
+ 'desc' => sprintf(
55
+ __( 'If "Manually" option is selected, you can add country selection drop box to frontend with "%s" widget or %s shortcode.', 'woocommerce-jetpack' ),
56
+ __( 'Booster - Selector', 'woocommerce-jetpack' ),
57
+ '<code>' . '[wcj_selector selector_type="country"]' . '</code>' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
58
+ 'id' => 'wcj_product_by_country_selection_method',
59
+ 'default' => 'by_ip',
60
+ 'type' => 'select',
61
+ 'options' => array(
62
+ 'by_ip' => __( 'Automatically by IP', 'woocommerce-jetpack' ),
63
+ 'manual' => __( 'Manually', 'woocommerce-jetpack' ),
64
+ ),
65
+ 'custom_attributes' => apply_filters( 'booster_get_message', '', 'disabled' ),
66
+ ),
67
+ array(
68
+ 'type' => 'sectionend',
69
+ 'id' => 'wcj_product_by_country_selection_options',
70
+ ),
71
+ array(
72
+ 'title' => __( 'Admin Options', 'woocommerce-jetpack' ),
73
+ 'type' => 'title',
74
+ 'id' => 'wcj_product_by_country_admin_options',
75
+ ),
76
  array(
77
  'title' => __( 'Admin Products List Column', 'woocommerce-jetpack' ),
78
+ 'desc_tip' => __( 'This will add "Countries" column to the admin products list.', 'woocommerce-jetpack' ),
79
  'desc' => __( 'Add', 'woocommerce-jetpack' ),
80
  'id' => 'wcj_product_by_country_add_column_visible_countries',
81
  'default' => 'no',
83
  ),
84
  array(
85
  'type' => 'sectionend',
86
+ 'id' => 'wcj_product_by_country_admin_options',
87
  ),
88
  );
includes/settings/wcj-settings-product-by-user-role.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Product Visibility by User Role
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -17,6 +17,7 @@ return array(
17
  ),
18
  array(
19
  'title' => __( 'Hide Visibility', 'woocommerce-jetpack' ),
 
20
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
21
  'id' => 'wcj_product_by_user_role_visibility',
22
  'default' => 'yes',
@@ -24,6 +25,7 @@ return array(
24
  ),
25
  array(
26
  'title' => __( 'Make Non-purchasable', 'woocommerce-jetpack' ),
 
27
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
28
  'id' => 'wcj_product_by_user_role_purchasable',
29
  'default' => 'no',
@@ -31,6 +33,7 @@ return array(
31
  ),
32
  array(
33
  'title' => __( 'Modify Query', 'woocommerce-jetpack' ),
 
34
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
35
  'id' => 'wcj_product_by_user_role_query',
36
  'default' => 'no',
2
  /**
3
  * Booster for WooCommerce - Settings - Product Visibility by User Role
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
17
  ),
18
  array(
19
  'title' => __( 'Hide Visibility', 'woocommerce-jetpack' ),
20
+ 'desc_tip' => __( 'This will hide selected products in shop and search results. However product still will be accessible via direct link.', 'woocommerce-jetpack' ),
21
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
22
  'id' => 'wcj_product_by_user_role_visibility',
23
  'default' => 'yes',
25
  ),
26
  array(
27
  'title' => __( 'Make Non-purchasable', 'woocommerce-jetpack' ),
28
+ 'desc_tip' => __( 'This will make selected products non-purchasable (i.e. product can\'t be added to the cart).', 'woocommerce-jetpack' ),
29
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
30
  'id' => 'wcj_product_by_user_role_purchasable',
31
  'default' => 'no',
33
  ),
34
  array(
35
  'title' => __( 'Modify Query', 'woocommerce-jetpack' ),
36
+ 'desc_tip' => __( 'This will hide selected products completely (including direct link).', 'woocommerce-jetpack' ),
37
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
38
  'id' => 'wcj_product_by_user_role_query',
39
  'default' => 'no',
includes/settings/wcj-settings-product-custom-info.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Product Info
4
  *
5
- * @version 2.9.1
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -17,6 +17,29 @@ $settings = array();
17
  $single_or_archive_array = array( 'single', 'archive' );
18
 
19
  foreach ( $single_or_archive_array as $single_or_archive ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  $single_or_archive_desc = ( 'single' === $single_or_archive ) ? __( 'Single', 'woocommerce-jetpack' ) : __( 'Archive', 'woocommerce-jetpack' );
21
  $settings = array_merge( $settings, array(
22
  array(
@@ -63,7 +86,7 @@ foreach ( $single_or_archive_array as $single_or_archive ) {
63
  'id' => 'wcj_product_custom_info_hook_' . $single_or_archive . '_' . $i,
64
  'default' => ( 'single' === $single_or_archive ) ? 'woocommerce_after_single_product_summary' : 'woocommerce_after_shop_loop_item_title',
65
  'type' => 'select',
66
- 'options' => ( 'single' === $single_or_archive ) ?
67
  array(
68
  'woocommerce_before_single_product' => __( 'Before single product', 'woocommerce-jetpack' ),
69
  'woocommerce_before_single_product_summary' => __( 'Before single product summary', 'woocommerce-jetpack' ),
@@ -81,7 +104,8 @@ foreach ( $single_or_archive_array as $single_or_archive ) {
81
  'woocommerce_shop_loop_item_title' => __( 'Inside product title', 'woocommerce-jetpack' ),
82
  'woocommerce_after_shop_loop_item_title' => __( 'After product title', 'woocommerce-jetpack' ),
83
  'woocommerce_after_shop_loop_item' => __( 'After product', 'woocommerce-jetpack' ),
84
- ),
 
85
  'css' => 'width:250px;',
86
  ),
87
  array(
@@ -159,5 +183,25 @@ foreach ( $single_or_archive_array as $single_or_archive ) {
159
  ),
160
  ) );
161
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
162
  }
163
  return $settings;
2
  /**
3
  * Booster for WooCommerce - Settings - Product Info
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
17
  $single_or_archive_array = array( 'single', 'archive' );
18
 
19
  foreach ( $single_or_archive_array as $single_or_archive ) {
20
+
21
+ if ( '' == ( $extra_filters = get_option( 'wcj_product_custom_info_extra_filters_' . $single_or_archive, '' ) ) ) {
22
+ $extra_filters = array();
23
+ } else {
24
+ $extra_filters = explode( PHP_EOL, $extra_filters );
25
+ $extra_filters_result = array();
26
+ if ( ! empty( $extra_filters ) ) {
27
+ foreach ( $extra_filters as $extra_filter ) {
28
+ if ( '' != ( $extra_filter = trim( $extra_filter ) ) ) {
29
+ $extra_filter = explode( '|', $extra_filter, 2 );
30
+ if ( 2 == count( $extra_filter ) ) {
31
+ $extra_filter_id = trim( $extra_filter[0] );
32
+ $extra_filter_title = trim( $extra_filter[1] );
33
+ if ( '' != $extra_filter_id && '' != $extra_filter_title ) {
34
+ $extra_filters_result[ $extra_filter_id ] = $extra_filter_title;
35
+ }
36
+ }
37
+ }
38
+ }
39
+ }
40
+ $extra_filters = $extra_filters_result;
41
+ }
42
+
43
  $single_or_archive_desc = ( 'single' === $single_or_archive ) ? __( 'Single', 'woocommerce-jetpack' ) : __( 'Archive', 'woocommerce-jetpack' );
44
  $settings = array_merge( $settings, array(
45
  array(
86
  'id' => 'wcj_product_custom_info_hook_' . $single_or_archive . '_' . $i,
87
  'default' => ( 'single' === $single_or_archive ) ? 'woocommerce_after_single_product_summary' : 'woocommerce_after_shop_loop_item_title',
88
  'type' => 'select',
89
+ 'options' => array_merge( ( 'single' === $single_or_archive ?
90
  array(
91
  'woocommerce_before_single_product' => __( 'Before single product', 'woocommerce-jetpack' ),
92
  'woocommerce_before_single_product_summary' => __( 'Before single product summary', 'woocommerce-jetpack' ),
104
  'woocommerce_shop_loop_item_title' => __( 'Inside product title', 'woocommerce-jetpack' ),
105
  'woocommerce_after_shop_loop_item_title' => __( 'After product title', 'woocommerce-jetpack' ),
106
  'woocommerce_after_shop_loop_item' => __( 'After product', 'woocommerce-jetpack' ),
107
+ ) ),
108
+ $extra_filters ),
109
  'css' => 'width:250px;',
110
  ),
111
  array(
183
  ),
184
  ) );
185
  }
186
+ $settings = array_merge( $settings, array(
187
+ array(
188
+ 'title' => __( 'Advanced Options', 'woocommerce-jetpack' ) . ' - ' . $single_or_archive_desc,
189
+ 'type' => 'title',
190
+ 'id' => 'wcj_product_custom_info_advanced_options_' . $single_or_archive,
191
+ ),
192
+ array(
193
+ 'title' => __( 'Extra Filters', 'woocommerce-jetpack' ),
194
+ 'desc_tip' => __( 'Leave blank to disable.', 'woocommerce-jetpack' ),
195
+ 'desc' => __( 'You can add custom filters here (one per line, in filter|title format). E.g.: <code>rehub_woo_after_compact_grid_title|Rehub: After title</code>.', 'woocommerce-jetpack' ),
196
+ 'id' => 'wcj_product_custom_info_extra_filters_' . $single_or_archive,
197
+ 'default' => '',
198
+ 'type' => 'custom_textarea',
199
+ 'css' => 'width:450px;height:100px',
200
+ ),
201
+ array(
202
+ 'type' => 'sectionend',
203
+ 'id' => 'wcj_product_custom_info_advanced_options_' . $single_or_archive,
204
+ ),
205
+ ) );
206
  }
207
  return $settings;
includes/settings/wcj-settings-product-input-fields.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Product Input Fields
4
  *
5
- * @version 2.9.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -67,34 +67,140 @@ $settings = array(
67
  array( 'step' => '1', 'min' => '1' )
68
  ),
69
  ),
 
 
 
 
70
  );
71
- $options = $this->get_options();
 
 
 
 
72
  for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_product_input_fields_global_total_number', 1 ) ); $i++ ) {
 
 
 
 
 
 
 
73
  foreach( $options as $option ) {
74
  $settings = array_merge( $settings, array(
75
  array(
76
- 'title' => ( 'wcj_product_input_fields_enabled_global_' === $option['id'] ) ? __( 'Product Input Field', 'woocommerce-jetpack' ) . ' #' . $i : '',
77
- 'desc' => $option['title'],
78
  'desc_tip' => ( isset( $option['desc_tip'] ) ) ? $option['desc_tip'] : '',
79
  'id' => $option['id'] . $i,
80
  'default' => $option['default'],
81
  'type' => $option['type'],
82
  'options' => isset( $option['options'] ) ? $option['options'] : '',
83
- 'css' => 'width:30%;min-width:300px;',
 
84
  ),
85
  ) );
86
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
87
  }
88
  $settings = array_merge( $settings, array(
89
- array(
90
- 'type' => 'sectionend',
91
- 'id' => 'wcj_product_input_fields_global_options',
92
- ),
93
  array(
94
  'title' => __( 'Frontend View Options', 'woocommerce-jetpack' ),
95
  'type' => 'title',
96
  'id' => 'wcj_product_input_fields_frontend_view_options',
97
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
98
  array(
99
  'title' => __( 'HTML Template - Start', 'woocommerce-jetpack' ),
100
  'id' => 'wcj_product_input_fields_start_template',
2
  /**
3
  * Booster for WooCommerce - Settings - Product Input Fields
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
67
  array( 'step' => '1', 'min' => '1' )
68
  ),
69
  ),
70
+ array(
71
+ 'type' => 'sectionend',
72
+ 'id' => 'wcj_product_input_fields_global_options',
73
+ ),
74
  );
75
+ $is_multiselect_products = ( 'yes' === get_option( 'wcj_list_for_products', 'yes' ) );
76
+ $products = ( $is_multiselect_products ? wcj_get_products() : false );
77
+ $product_cats = wcj_get_terms( 'product_cat' );
78
+ $product_tags = wcj_get_terms( 'product_tag' );
79
+ $options = $this->get_global_product_fields_options();
80
  for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_product_input_fields_global_total_number', 1 ) ); $i++ ) {
81
+ $settings = array_merge( $settings, array(
82
+ array(
83
+ 'title' => __( 'Product Input Field', 'woocommerce-jetpack' ) . ' #' . $i,
84
+ 'type' => 'title',
85
+ 'id' => 'wcj_product_input_fields_global_options_' . $i,
86
+ ),
87
+ ) );
88
  foreach( $options as $option ) {
89
  $settings = array_merge( $settings, array(
90
  array(
91
+ 'title' => ( isset( $option['short_title'] ) ? $option['short_title'] : $option['title'] ),
92
+ 'desc' => ( ( 'checkbox' === $option['type'] ) || isset( $option['short_title'] ) && $option['short_title'] != $option['title'] ? $option['title'] : '' ),
93
  'desc_tip' => ( isset( $option['desc_tip'] ) ) ? $option['desc_tip'] : '',
94
  'id' => $option['id'] . $i,
95
  'default' => $option['default'],
96
  'type' => $option['type'],
97
  'options' => isset( $option['options'] ) ? $option['options'] : '',
98
+ 'css' => ( 'wcj_product_input_fields_type_select_options_global_' === $option['id'] ?
99
+ 'width:30%;min-width:300px;height:200px;' : 'width:30%;min-width:300px;' ),
100
  ),
101
  ) );
102
  }
103
+ wcj_maybe_convert_and_update_option_value( array(
104
+ array( 'id' => 'wcj_product_input_fields_in_products_' . 'global' . '_' . $i, 'default' => '' ),
105
+ array( 'id' => 'wcj_product_input_fields_ex_products_' . 'global' . '_' . $i, 'default' => '' ),
106
+ ), $is_multiselect_products );
107
+ $settings = array_merge( $settings, array(
108
+ array(
109
+ 'title' => __( 'Product Categories - Include', 'woocommerce-jetpack' ),
110
+ 'desc' => __( 'Product categories to include.', 'woocommerce-jetpack' ),
111
+ 'desc_tip' => __( 'Leave blank to include all products.', 'woocommerce-jetpack' ),
112
+ 'id' => 'wcj_product_input_fields_in_cats_' . 'global' . '_' . $i,
113
+ 'default' => '',
114
+ 'type' => 'multiselect',
115
+ 'class' => 'chosen_select',
116
+ 'css' => 'width: 450px;',
117
+ 'options' => $product_cats,
118
+ ),
119
+ array(
120
+ 'title' => __( 'Product Categories - Exclude', 'woocommerce-jetpack' ),
121
+ 'desc' => __( 'Product categories to exclude.', 'woocommerce-jetpack' ),
122
+ 'desc_tip' => __( 'Leave blank to include all products.', 'woocommerce-jetpack' ),
123
+ 'id' => 'wcj_product_input_fields_ex_cats_' . 'global' . '_' . $i,
124
+ 'default' => '',
125
+ 'type' => 'multiselect',
126
+ 'class' => 'chosen_select',
127
+ 'css' => 'width: 450px;',
128
+ 'options' => $product_cats,
129
+ ),
130
+ array(
131
+ 'title' => __( 'Product Tags - Include', 'woocommerce-jetpack' ),
132
+ 'desc' => __( 'Product tags to include.', 'woocommerce-jetpack' ),
133
+ 'desc_tip' => __( 'Leave blank to include all products.', 'woocommerce-jetpack' ),
134
+ 'id' => 'wcj_product_input_fields_in_tags_' . 'global' . '_' . $i,
135
+ 'default' => '',
136
+ 'type' => 'multiselect',
137
+ 'class' => 'chosen_select',
138
+ 'css' => 'width: 450px;',
139
+ 'options' => $product_tags,
140
+ ),
141
+ array(
142
+ 'title' => __( 'Product Tags - Exclude', 'woocommerce-jetpack' ),
143
+ 'desc' => __( 'Product tags to exclude.', 'woocommerce-jetpack' ),
144
+ 'desc_tip' => __( 'Leave blank to include all products.', 'woocommerce-jetpack' ),
145
+ 'id' => 'wcj_product_input_fields_ex_tags_' . 'global' . '_' . $i,
146
+ 'default' => '',
147
+ 'type' => 'multiselect',
148
+ 'class' => 'chosen_select',
149
+ 'css' => 'width: 450px;',
150
+ 'options' => $product_tags,
151
+ ),
152
+ wcj_get_settings_as_multiselect_or_text(
153
+ array(
154
+ 'title' => __( 'Products - Include', 'woocommerce-jetpack' ),
155
+ 'desc' => __( 'Products to include.', 'woocommerce-jetpack' ),
156
+ 'desc_tip' => __( 'Leave blank to include all products.', 'woocommerce-jetpack' ),
157
+ 'id' => 'wcj_product_input_fields_in_products_' . 'global' . '_' . $i,
158
+ 'default' => '',
159
+ 'css' => 'width: 450px;',
160
+ ),
161
+ $products,
162
+ $is_multiselect_products
163
+ ),
164
+ wcj_get_settings_as_multiselect_or_text(
165
+ array(
166
+ 'title' => __( 'Products - Exclude', 'woocommerce-jetpack' ),
167
+ 'desc' => __( 'Products to exclude.', 'woocommerce-jetpack' ),
168
+ 'desc_tip' => __( 'Leave blank to include all products.', 'woocommerce-jetpack' ),
169
+ 'id' => 'wcj_product_input_fields_ex_products_' . 'global' . '_' . $i,
170
+ 'default' => '',
171
+ 'css' => 'width: 450px;',
172
+ ),
173
+ $products,
174
+ $is_multiselect_products
175
+ ),
176
+ array(
177
+ 'type' => 'sectionend',
178
+ 'id' => 'wcj_product_input_fields_global_options_' . $i,
179
+ ),
180
+ ) );
181
  }
182
  $settings = array_merge( $settings, array(
 
 
 
 
183
  array(
184
  'title' => __( 'Frontend View Options', 'woocommerce-jetpack' ),
185
  'type' => 'title',
186
  'id' => 'wcj_product_input_fields_frontend_view_options',
187
  ),
188
+ array(
189
+ 'title' => __( 'Position on Single Product Page', 'woocommerce-jetpack' ),
190
+ 'id' => 'wcj_product_input_fields_position',
191
+ 'default' => 'woocommerce_before_add_to_cart_button',
192
+ 'type' => 'select',
193
+ 'options' => array(
194
+ 'woocommerce_before_add_to_cart_button' => __( 'Before add to cart button', 'woocommerce-jetpack' ),
195
+ 'woocommerce_after_add_to_cart_button' => __( 'After add to cart button', 'woocommerce-jetpack' ),
196
+ ),
197
+ ),
198
+ array(
199
+ 'desc' => __( 'Position priority', 'woocommerce-jetpack' ),
200
+ 'id' => 'wcj_product_input_fields_position_priority',
201
+ 'default' => 100,
202
+ 'type' => 'number',
203
+ ),
204
  array(
205
  'title' => __( 'HTML Template - Start', 'woocommerce-jetpack' ),
206
  'id' => 'wcj_product_input_fields_start_template',
includes/settings/wcj-settings-product-tabs.php CHANGED
@@ -2,9 +2,10 @@
2
  /**
3
  * Booster for WooCommerce Settings - Product Tabs
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
 
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
@@ -12,11 +13,18 @@ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
12
  $settings = array(
13
  // Global Custom Tabs
14
  array(
15
- 'title' => __( 'Custom Product Tabs Options', 'woocommerce-jetpack' ),
16
  'type' => 'title',
17
  'desc' => __( 'This section lets you add custom single product tabs.', 'woocommerce-jetpack' ),
18
  'id' => 'wcj_custom_product_tabs_options',
19
  ),
 
 
 
 
 
 
 
20
  array(
21
  'title' => __( 'Custom Product Tabs Number', 'woocommerce-jetpack' ),
22
  'desc_tip' => __( 'Click "Save changes" after you change this number.', 'woocommerce-jetpack' ),
@@ -47,10 +55,17 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_cus
47
  'type' => 'text',
48
  'css' => 'width:30%;min-width:300px;',
49
  ),
 
 
 
 
 
 
 
50
  array(
51
  'desc' => __( 'Priority (i.e. Order)', 'woocommerce-jetpack' ),
52
  'id' => 'wcj_custom_product_tabs_priority_global_' . $i,
53
- 'default' => (40 + $i - 1),
54
  'type' => 'number',
55
  ),
56
  array(
@@ -129,6 +144,10 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_cus
129
  'type' => 'multiselect',
130
  'options' => $product_tags_options,
131
  ),
 
 
 
 
132
  array(
133
  'desc' => __( 'Comma separated PRODUCT IDs to HIDE this tab', 'woocommerce-jetpack' ) . '. <strong><em>' . __( 'Deprecated', 'woocommerce-jetpack' ) . '!</em></strong>',
134
  'desc_tip' => __( 'To hide this tab from some products, enter product IDs here.', 'woocommerce-jetpack' ),
@@ -137,6 +156,10 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_cus
137
  'type' => 'text',
138
  'css' => 'width:30%;min-width:300px;',
139
  ),
 
 
 
 
140
  array(
141
  'desc' => __( 'Comma separated PRODUCT IDs to SHOW this tab', 'woocommerce-jetpack' ) . '. <strong><em>' . __( 'Deprecated', 'woocommerce-jetpack' ) . '!</em></strong>',
142
  'desc_tip' => __( 'To show this tab only for some products, enter product IDs here.', 'woocommerce-jetpack' ),
@@ -145,6 +168,10 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_cus
145
  'type' => 'text',
146
  'css' => 'width:30%;min-width:300px;',
147
  ),
 
 
 
 
148
  array(
149
  'desc' => __( 'Comma separated CATEGORY IDs to HIDE this tab', 'woocommerce-jetpack' ) . '. <strong><em>' . __( 'Deprecated', 'woocommerce-jetpack' ) . '!</em></strong>',
150
  'desc_tip' => __( 'To hide this tab from some categories, enter category IDs here.', 'woocommerce-jetpack' ),
@@ -153,6 +180,10 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_cus
153
  'type' => 'text',
154
  'css' => 'width:30%;min-width:300px;',
155
  ),
 
 
 
 
156
  array(
157
  'desc' => __( 'Comma separated CATEGORY IDs to SHOW this tab', 'woocommerce-jetpack' ) . '. <strong><em>' . __( 'Deprecated', 'woocommerce-jetpack' ) . '!</em></strong>',
158
  'desc_tip' => __( 'To show this tab only for some categories, enter category IDs here.', 'woocommerce-jetpack' ),
@@ -161,8 +192,8 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_cus
161
  'type' => 'text',
162
  'css' => 'width:30%;min-width:300px;',
163
  ),
164
- )
165
- );
166
  }
167
  $settings = array_merge( $settings, array(
168
  array(
@@ -216,6 +247,13 @@ for ( $i = 1; $i <= apply_filters( 'booster_get_option', 1, get_option( 'wcj_cus
216
  'type' => 'text',
217
  'css' => 'width:30%;min-width:300px;',
218
  ),
 
 
 
 
 
 
 
219
  array(
220
  'desc' => __( 'Default Priority (i.e. Order)', 'woocommerce-jetpack' ),
221
  'id' => 'wcj_custom_product_tabs_priority_local_default_' . $i,
@@ -320,7 +358,7 @@ $settings = array_merge( $settings, array(
320
  'type' => 'checkbox',
321
  ),
322
  array(
323
- 'desc' => __( 'Title.', 'woocommerce-jetpack' ),
324
  'desc_tip' => __( 'Leave blank for WooCommerce defaults', 'woocommerce-jetpack' ),
325
  'id' => 'wcj_product_info_product_tabs_description_title',
326
  'default' => '',
@@ -330,7 +368,7 @@ $settings = array_merge( $settings, array(
330
  'id' => 'wcj_product_info_product_tabs_description_priority',
331
  'default' => 10,
332
  'type' => 'number',
333
- 'desc' => __( 'Priority (i.e. Order).', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
334
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
335
  ),
336
  array(
@@ -341,7 +379,7 @@ $settings = array_merge( $settings, array(
341
  'type' => 'checkbox',
342
  ),
343
  array(
344
- 'desc' => __( 'Title.', 'woocommerce-jetpack' ),
345
  'desc_tip' => __( 'Leave blank for WooCommerce defaults', 'woocommerce-jetpack' ),
346
  'id' => 'wcj_product_info_product_tabs_additional_information_title',
347
  'default' => '',
@@ -351,7 +389,7 @@ $settings = array_merge( $settings, array(
351
  'id' => 'wcj_product_info_product_tabs_additional_information_priority',
352
  'default' => 20,
353
  'type' => 'number',
354
- 'desc' => __( 'Priority (i.e. Order).', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
355
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
356
  ),
357
  array(
@@ -362,7 +400,7 @@ $settings = array_merge( $settings, array(
362
  'type' => 'checkbox',
363
  ),
364
  array(
365
- 'desc' => __( 'Title.', 'woocommerce-jetpack' ),
366
  'desc_tip' => __( 'Leave blank for WooCommerce defaults', 'woocommerce-jetpack' ),
367
  'id' => 'wcj_product_info_product_tabs_reviews_title',
368
  'default' => '',
@@ -372,7 +410,7 @@ $settings = array_merge( $settings, array(
372
  'id' => 'wcj_product_info_product_tabs_reviews_priority',
373
  'default' => 30,
374
  'type' => 'number',
375
- 'desc' => __( 'Priority (i.e. Order).', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
376
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
377
  ),
378
  array(
2
  /**
3
  * Booster for WooCommerce Settings - Product Tabs
4
  *
5
+ * @version 3.1.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
+ * @todo clean up
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
  $settings = array(
14
  // Global Custom Tabs
15
  array(
16
+ 'title' => __( 'Custom Product Tabs - All Products', 'woocommerce-jetpack' ),
17
  'type' => 'title',
18
  'desc' => __( 'This section lets you add custom single product tabs.', 'woocommerce-jetpack' ),
19
  'id' => 'wcj_custom_product_tabs_options',
20
  ),
21
+ array(
22
+ 'title' => __( 'Custom Product Tabs - All Products', 'woocommerce-jetpack' ),
23
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
24
+ 'type' => 'checkbox',
25
+ 'id' => 'wcj_custom_product_tabs_global_enabled',
26
+ 'default' => 'yes',
27
+ ),
28
  array(
29
  'title' => __( 'Custom Product Tabs Number', 'woocommerce-jetpack' ),
30
  'desc_tip' => __( 'Click "Save changes" after you change this number.', 'woocommerce-jetpack' ),
55
  'type' => 'text',
56
  'css' => 'width:30%;min-width:300px;',
57
  ),
58
+ array(
59
+ 'desc' => __( 'Key', 'woocommerce-jetpack' ),
60
+ 'desc_tip' => __( 'Make sure it\'s unique for each tab.', 'woocommerce-jetpack' ),
61
+ 'id' => 'wcj_custom_product_tabs_key_global_' . $i,
62
+ 'default' => 'global_' . $i,
63
+ 'type' => 'text',
64
+ ),
65
  array(
66
  'desc' => __( 'Priority (i.e. Order)', 'woocommerce-jetpack' ),
67
  'id' => 'wcj_custom_product_tabs_priority_global_' . $i,
68
+ 'default' => ( 40 + $i - 1 ),
69
  'type' => 'number',
70
  ),
71
  array(
144
  'type' => 'multiselect',
145
  'options' => $product_tags_options,
146
  ),
147
+ )
148
+ );
149
+ if ( '' != get_option( 'wcj_custom_product_tabs_title_global_hide_in_product_ids_' . $i, '' ) ) {
150
+ $settings = array_merge( $settings, array(
151
  array(
152
  'desc' => __( 'Comma separated PRODUCT IDs to HIDE this tab', 'woocommerce-jetpack' ) . '. <strong><em>' . __( 'Deprecated', 'woocommerce-jetpack' ) . '!</em></strong>',
153
  'desc_tip' => __( 'To hide this tab from some products, enter product IDs here.', 'woocommerce-jetpack' ),
156
  'type' => 'text',
157
  'css' => 'width:30%;min-width:300px;',
158
  ),
159
+ ) );
160
+ }
161
+ if ( '' != get_option( 'wcj_custom_product_tabs_title_global_show_in_product_ids_' . $i, '' ) ) {
162
+ $settings = array_merge( $settings, array(
163
  array(
164
  'desc' => __( 'Comma separated PRODUCT IDs to SHOW this tab', 'woocommerce-jetpack' ) . '. <strong><em>' . __( 'Deprecated', 'woocommerce-jetpack' ) . '!</em></strong>',
165
  'desc_tip' => __( 'To show this tab only for some products, enter product IDs here.', 'woocommerce-jetpack' ),
168
  'type' => 'text',
169
  'css' => 'width:30%;min-width:300px;',
170
  ),
171
+ ) );
172
+ }
173
+ if ( '' != get_option( 'wcj_custom_product_tabs_title_global_hide_in_cats_ids_' . $i, '' ) ) {
174
+ $settings = array_merge( $settings, array(
175
  array(
176
  'desc' => __( 'Comma separated CATEGORY IDs to HIDE this tab', 'woocommerce-jetpack' ) . '. <strong><em>' . __( 'Deprecated', 'woocommerce-jetpack' ) . '!</em></strong>',
177
  'desc_tip' => __( 'To hide this tab from some categories, enter category IDs here.', 'woocommerce-jetpack' ),
180
  'type' => 'text',
181
  'css' => 'width:30%;min-width:300px;',
182
  ),
183
+ ) );
184
+ }
185
+ if ( '' != get_option( 'wcj_custom_product_tabs_title_global_show_in_cats_ids_' . $i, '' ) ) {
186
+ $settings = array_merge( $settings, array(
187
  array(
188
  'desc' => __( 'Comma separated CATEGORY IDs to SHOW this tab', 'woocommerce-jetpack' ) . '. <strong><em>' . __( 'Deprecated', 'woocommerce-jetpack' ) . '!</em></strong>',
189
  'desc_tip' => __( 'To show this tab only for some categories, enter category IDs here.', 'woocommerce-jetpack' ),
192
  'type' => 'text',
193
  'css' => 'width:30%;min-width:300px;',
194
  ),
195
+ ) );
196
+ }
197
  }
198
  $settings = array_merge( $settings, array(
199
  array(
247
  'type' => 'text',
248
  'css' => 'width:30%;min-width:300px;',
249
  ),
250
+ array(
251
+ 'desc' => __( 'Default Key', 'woocommerce-jetpack' ),
252
+ 'desc_tip' => __( 'Make sure it\'s unique for each tab.', 'woocommerce-jetpack' ),
253
+ 'id' => 'wcj_custom_product_tabs_key_local_default_' . $i,
254
+ 'default' => 'local_' . $i,
255
+ 'type' => 'text',
256
+ ),
257
  array(
258
  'desc' => __( 'Default Priority (i.e. Order)', 'woocommerce-jetpack' ),
259
  'id' => 'wcj_custom_product_tabs_priority_local_default_' . $i,
358
  'type' => 'checkbox',
359
  ),
360
  array(
361
+ 'desc' => __( 'Title', 'woocommerce-jetpack' ),
362
  'desc_tip' => __( 'Leave blank for WooCommerce defaults', 'woocommerce-jetpack' ),
363
  'id' => 'wcj_product_info_product_tabs_description_title',
364
  'default' => '',
368
  'id' => 'wcj_product_info_product_tabs_description_priority',
369
  'default' => 10,
370
  'type' => 'number',
371
+ 'desc' => __( 'Priority (i.e. Order)', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
372
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
373
  ),
374
  array(
379
  'type' => 'checkbox',
380
  ),
381
  array(
382
+ 'desc' => __( 'Title', 'woocommerce-jetpack' ),
383
  'desc_tip' => __( 'Leave blank for WooCommerce defaults', 'woocommerce-jetpack' ),
384
  'id' => 'wcj_product_info_product_tabs_additional_information_title',
385
  'default' => '',
389
  'id' => 'wcj_product_info_product_tabs_additional_information_priority',
390
  'default' => 20,
391
  'type' => 'number',
392
+ 'desc' => __( 'Priority (i.e. Order)', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
393
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
394
  ),
395
  array(
400
  'type' => 'checkbox',
401
  ),
402
  array(
403
+ 'desc' => __( 'Title', 'woocommerce-jetpack' ),
404
  'desc_tip' => __( 'Leave blank for WooCommerce defaults', 'woocommerce-jetpack' ),
405
  'id' => 'wcj_product_info_product_tabs_reviews_title',
406
  'default' => '',
410
  'id' => 'wcj_product_info_product_tabs_reviews_priority',
411
  'default' => 30,
412
  'type' => 'number',
413
+ 'desc' => __( 'Priority (i.e. Order)', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_get_message', '', 'desc' ),
414
  'custom_attributes' => apply_filters( 'booster_get_message', '', 'readonly' ),
415
  ),
416
  array(
includes/shortcodes/class-wcj-general-shortcodes.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes - General
4
  *
5
- * @version 2.9.1
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,36 +15,37 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 2.9.1
19
  */
20
  function __construct() {
21
 
22
  $this->the_shortcodes = array(
23
- 'wcj_site_url',
24
- 'wcj_current_date',
25
- 'wcj_current_time',
26
- 'wcj_current_datetime',
27
- 'wcj_current_timestamp',
28
- // 'wcj_image',
29
- 'wcj_cart_items_total_weight',
30
  'wcj_cart_items_total_quantity',
 
31
  'wcj_cart_total',
32
- 'wcj_wpml',
33
- 'wcj_wpml_translate',
34
  'wcj_country_select_drop_down_list',
 
 
35
  'wcj_currency_select_drop_down_list',
36
- 'wcj_currency_select_radio_list',
37
  'wcj_currency_select_link_list',
38
- 'wcj_text',
39
- 'wcj_tcpdf_pagebreak',
40
- 'wcj_get_left_to_free_shipping',
41
- 'wcj_wholesale_price_table',
 
42
  'wcj_customer_billing_country',
43
- 'wcj_customer_shipping_country',
44
  'wcj_customer_meta',
 
45
  'wcj_empty_cart_button',
46
- 'wcj_currency_exchange_rate',
47
- 'wcj_currency_exchange_rates_table',
 
 
 
 
 
 
 
48
  );
49
 
50
  $this->the_atts = array(
@@ -70,12 +71,44 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
70
  'default' => '',
71
  'from' => '',
72
  'to' => '',
 
 
73
  );
74
 
75
  parent::__construct();
76
 
77
  }
78
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  /**
80
  * wcj_site_url.
81
  *
@@ -236,7 +269,7 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
236
  /**
237
  * wcj_wholesale_price_table (global only).
238
  *
239
- * @version 2.5.7
240
  * @since 2.4.8
241
  */
242
  function wcj_wholesale_price_table( $atts ) {
@@ -282,7 +315,7 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
282
  );
283
  $data_discount[] = ( 'fixed' === get_option( 'wcj_wholesale_price_discount_type', 'percent' ) )
284
  ? '-' . wc_price( $wholesale_price_level['discount'] ) : '-' . $wholesale_price_level['discount'] . '%';
285
- $columns_styles[] = 'text-align: center;';
286
  }
287
 
288
  $table_rows = array( $data_qty, $data_discount, );
2
  /**
3
  * Booster for WooCommerce - Shortcodes - General
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.1.0
19
  */
20
  function __construct() {
21
 
22
  $this->the_shortcodes = array(
 
 
 
 
 
 
 
23
  'wcj_cart_items_total_quantity',
24
+ 'wcj_cart_items_total_weight',
25
  'wcj_cart_total',
 
 
26
  'wcj_country_select_drop_down_list',
27
+ 'wcj_currency_exchange_rate',
28
+ 'wcj_currency_exchange_rates_table',
29
  'wcj_currency_select_drop_down_list',
 
30
  'wcj_currency_select_link_list',
31
+ 'wcj_currency_select_radio_list',
32
+ 'wcj_current_date',
33
+ 'wcj_current_datetime',
34
+ 'wcj_current_time',
35
+ 'wcj_current_timestamp',
36
  'wcj_customer_billing_country',
 
37
  'wcj_customer_meta',
38
+ 'wcj_customer_shipping_country',
39
  'wcj_empty_cart_button',
40
+ 'wcj_get_left_to_free_shipping',
41
+ 'wcj_selector',
42
+ 'wcj_site_url',
43
+ 'wcj_tcpdf_pagebreak',
44
+ 'wcj_text',
45
+ 'wcj_wholesale_price_table',
46
+ 'wcj_wpml',
47
+ 'wcj_wpml_translate',
48
+ // 'wcj_image',
49
  );
50
 
51
  $this->the_atts = array(
71
  'default' => '',
72
  'from' => '',
73
  'to' => '',
74
+ 'columns_style' => 'text-align: center;',
75
+ 'selector_type' => 'country',
76
  );
77
 
78
  parent::__construct();
79
 
80
  }
81
 
82
+ /**
83
+ * wcj_selector.
84
+ *
85
+ * @version 3.1.0
86
+ * @since 3.1.0
87
+ * @todo (maybe) add more selector types (e.g.: currency)
88
+ * @todo (maybe) remove country switcher and currency switcher shortcodes and use this shortcode instead
89
+ */
90
+ function wcj_selector( $atts ) {
91
+ $html = '';
92
+ $options = '';
93
+ $selected_value = ( isset( $_REQUEST[ 'wcj_' . $atts['selector_type'] . '_selector' ] ) ?
94
+ $_REQUEST[ 'wcj_' . $atts['selector_type'] . '_selector' ] :
95
+ wcj_session_get( 'wcj_selected_' . $atts['selector_type'] )
96
+ );
97
+ switch ( $atts['selector_type'] ) {
98
+ default: // 'country'
99
+ $options = wcj_get_countries();
100
+ asort( $options );
101
+ }
102
+ foreach ( $options as $value => $title ) {
103
+ $html .= '<option value="' . $value . '" ' . selected( $selected_value, $value, false ) . '>' . $title . '</option>';
104
+ }
105
+ return '<form method="post" action="">' .
106
+ '<select name="wcj_' . $atts['selector_type'] . '_selector" class="wcj_' . $atts['selector_type'] . '_selector" onchange="this.form.submit()">' .
107
+ $html .
108
+ '</select>' .
109
+ '</form>';
110
+ }
111
+
112
  /**
113
  * wcj_site_url.
114
  *
269
  /**
270
  * wcj_wholesale_price_table (global only).
271
  *
272
+ * @version 3.1.0
273
  * @since 2.4.8
274
  */
275
  function wcj_wholesale_price_table( $atts ) {
315
  );
316
  $data_discount[] = ( 'fixed' === get_option( 'wcj_wholesale_price_discount_type', 'percent' ) )
317
  ? '-' . wc_price( $wholesale_price_level['discount'] ) : '-' . $wholesale_price_level['discount'] . '%';
318
+ $columns_styles[] = $atts['columns_style'];
319
  }
320
 
321
  $table_rows = array( $data_qty, $data_discount, );
includes/shortcodes/class-wcj-order-items-shortcodes.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Order Items
4
  *
5
- * @version 3.0.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -27,7 +27,7 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
27
  /**
28
  * add_extra_atts.
29
  *
30
- * @version 2.9.0
31
  */
32
  function add_extra_atts( $atts ) {
33
  $modified_atts = array_merge( array(
@@ -58,6 +58,7 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
58
  'insert_page_break' => '',
59
  'multiply_cost' => 1,
60
  'multiply_profit' => 1,
 
61
  ), $atts );
62
  return $modified_atts;
63
  }
@@ -272,7 +273,7 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
272
  /**
273
  * wcj_order_items_table.
274
  *
275
- * @version 3.0.0
276
  */
277
  function wcj_order_items_table( $atts, $content = '' ) {
278
 
@@ -291,7 +292,14 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
291
  } */
292
 
293
  // The Items
294
- $the_items = $the_order->get_items();
 
 
 
 
 
 
 
295
 
296
  // Shipping as item
297
  if ( '' != $atts['shipping_as_item'] && $the_order->get_total_shipping() > 0 ) {
@@ -381,6 +389,11 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
381
  case 'product_sale_price_multiply_qty':
382
  $cell_data = ( is_object( $the_product ) ) ? $this->wcj_price_shortcode( $the_product->get_sale_price() * $item['qty'], $atts ) : '';
383
  break;
 
 
 
 
 
384
  case 'item_tax_class':
385
  case 'tax_class':
386
  $cell_data = ( isset( $item['tax_class'] ) ) ? $this->get_tax_class_name( $item['tax_class'] ) : '';
@@ -410,7 +423,7 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
410
  // "WooCommerce TM Extra Product Options" plugin options
411
  // todo - this will show options prices in shop's default currency only (must use 'price_per_currency' to show prices in order's currency).
412
  $tmcartepo_data = ( WCJ_IS_WC_VERSION_BELOW_3 ?
413
- ( isset( $item['tmcartepo_data'] ) ? unserialize( $item['tmcartepo_data'] ) : '' ) :
414
  $item->get_meta( '_tmcartepo_data' )
415
  );
416
  if ( ! empty( $tmcartepo_data ) ) {
@@ -515,6 +528,15 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
515
  case 'item_quantity':
516
  $cell_data = $atts['quantity_prefix'] . $item['qty'];
517
  break;
 
 
 
 
 
 
 
 
 
518
  case 'item_total_tax_excl':
519
  $cell_data = $this->wcj_price_shortcode( $the_order->get_item_total( $item, false, true ), $atts );
520
  break;
@@ -633,6 +655,10 @@ class WCJ_Order_Items_Shortcodes extends WCJ_Shortcodes {
633
  }
634
  }
635
 
 
 
 
 
636
  $table_html_args = array(
637
  'table_class' => $atts['table_class'],
638
  'table_heading_type' => 'horizontal',
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Order Items
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
27
  /**
28
  * add_extra_atts.
29
  *
30
+ * @version 3.1.0
31
  */
32
  function add_extra_atts( $atts ) {
33
  $modified_atts = array_merge( array(
58
  'insert_page_break' => '',
59
  'multiply_cost' => 1,
60
  'multiply_profit' => 1,
61
+ 'refunded_items_table' => 'no',
62
  ), $atts );
63
  return $modified_atts;
64
  }
273
  /**
274
  * wcj_order_items_table.
275
  *
276
+ * @version 3.1.0
277
  */
278
  function wcj_order_items_table( $atts, $content = '' ) {
279
 
292
  } */
293
 
294
  // The Items
295
+ $the_items = array();
296
+ if ( 'yes' === $atts['refunded_items_table'] ) {
297
+ foreach ( $this->the_order->get_refunds() as $_refund ) {
298
+ $the_items = array_merge( $the_items, $_refund->get_items() );
299
+ }
300
+ } else {
301
+ $the_items = $the_order->get_items();
302
+ }
303
 
304
  // Shipping as item
305
  if ( '' != $atts['shipping_as_item'] && $the_order->get_total_shipping() > 0 ) {
389
  case 'product_sale_price_multiply_qty':
390
  $cell_data = ( is_object( $the_product ) ) ? $this->wcj_price_shortcode( $the_product->get_sale_price() * $item['qty'], $atts ) : '';
391
  break;
392
+ case 'product_categories':
393
+ $cell_data = ( is_object( $the_product ) ) ?
394
+ strip_tags( ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_product->get_categories() : wc_get_product_category_list( $item['product_id'] ) ) ) :
395
+ '';
396
+ break;
397
  case 'item_tax_class':
398
  case 'tax_class':
399
  $cell_data = ( isset( $item['tax_class'] ) ) ? $this->get_tax_class_name( $item['tax_class'] ) : '';
423
  // "WooCommerce TM Extra Product Options" plugin options
424
  // todo - this will show options prices in shop's default currency only (must use 'price_per_currency' to show prices in order's currency).
425
  $tmcartepo_data = ( WCJ_IS_WC_VERSION_BELOW_3 ?
426
+ ( isset( $item['tmcartepo_data'] ) ? maybe_unserialize( $item['tmcartepo_data'] ) : '' ) :
427
  $item->get_meta( '_tmcartepo_data' )
428
  );
429
  if ( ! empty( $tmcartepo_data ) ) {
528
  case 'item_quantity':
529
  $cell_data = $atts['quantity_prefix'] . $item['qty'];
530
  break;
531
+ case 'item_quantity_refunded':
532
+ $cell_data = ( ! $item['is_custom'] && $item_id ? $this->the_order->get_qty_refunded_for_item( $item_id ) : '' );
533
+ break;
534
+ case 'item_quantity_excl_refunded':
535
+ $cell_data = ( ! $item['is_custom'] && $item_id ? ( $item['qty'] + $this->the_order->get_qty_refunded_for_item( $item_id ) ) : '' );
536
+ break;
537
+ case 'item_total_refunded':
538
+ $cell_data = ( ! $item['is_custom'] && $item_id ? $this->wcj_price_shortcode( $this->the_order->get_total_refunded_for_item( $item_id ), $atts ) : '' );
539
+ break;
540
  case 'item_total_tax_excl':
541
  $cell_data = $this->wcj_price_shortcode( $the_order->get_item_total( $item, false, true ), $atts );
542
  break;
655
  }
656
  }
657
 
658
+ if ( empty( $data ) ) {
659
+ return '';
660
+ }
661
+
662
  $table_html_args = array(
663
  'table_class' => $atts['table_class'],
664
  'table_heading_type' => 'horizontal',
includes/shortcodes/class-wcj-orders-shortcodes.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Orders
4
  *
5
- * @version 3.0.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,67 +15,73 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 3.0.0
19
  */
20
  function __construct() {
21
 
22
  $this->the_shortcodes = array(
23
- 'wcj_order_status',
24
- 'wcj_order_status_label',
25
- 'wcj_order_date',
26
- 'wcj_order_time',
27
- 'wcj_order_number',
28
- 'wcj_order_id',
29
  'wcj_order_billing_address',
30
- 'wcj_order_billing_phone',
31
  'wcj_order_billing_country_name',
32
- 'wcj_order_shipping_country_name',
33
  'wcj_order_checkout_field',
34
- 'wcj_order_shipping_address',
35
- 'wcj_order_customer_note',
36
  'wcj_order_custom_field',
37
  'wcj_order_custom_meta_field',
38
- 'wcj_order_meta',
39
- 'wcj_order_items_meta',
 
 
 
 
 
 
 
40
  'wcj_order_items',
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  'wcj_order_subtotal',
 
42
  'wcj_order_subtotal_plus_shipping',
43
- 'wcj_order_total_discount',
44
- // 'wcj_order_cart_discount',
45
- 'wcj_order_shipping_tax',
46
- 'wcj_order_taxes_html',
47
  'wcj_order_tax_by_class',
48
- 'wcj_order_total_tax',
49
- 'wcj_order_total_tax_percent',
50
  'wcj_order_total',
51
- 'wcj_order_total_excl_shipping',
52
  'wcj_order_total_by_tax_class',
53
- 'wcj_order_subtotal_by_tax_class',
54
- 'wcj_order_currency',
55
- 'wcj_order_total_in_words',
56
  'wcj_order_total_excl_tax',
57
- 'wcj_order_shipping_price',
58
- 'wcj_order_total_refunded',
59
  'wcj_order_total_fees',
60
  'wcj_order_total_fees_incl_tax',
61
  'wcj_order_total_fees_tax',
62
- 'wcj_order_fee',
63
- 'wcj_order_fees_html',
64
- 'wcj_order_payment_method',
65
- 'wcj_order_payment_method_transaction_id',
66
- 'wcj_order_shipping_method',
67
- 'wcj_order_items_total_weight', // deprecated - use 'wcj_order_total_weight' instead
68
- 'wcj_order_items_total_quantity',
69
- 'wcj_order_items_total_number',
70
- 'wcj_order_function',
71
- 'wcj_order_total_width',
72
  'wcj_order_total_height',
 
73
  'wcj_order_total_length',
 
 
 
 
 
74
  'wcj_order_total_weight',
75
- 'wcj_order_coupons',
76
- 'wcj_order_customer_user',
77
- 'wcj_order_customer_user_roles',
78
- 'wcj_order_customer_meta',
79
  );
80
 
81
  parent::__construct();
@@ -84,7 +90,7 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
84
  /**
85
  * add_extra_atts.
86
  *
87
- * @version 2.9.0
88
  */
89
  function add_extra_atts( $atts ) {
90
  $modified_atts = array_merge( array(
@@ -110,6 +116,13 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
110
  'meta_key' => '',
111
  'tax_class' => '',
112
  'fallback_billing_address' => 'no',
 
 
 
 
 
 
 
113
  ), $atts );
114
 
115
  return $modified_atts;
@@ -165,6 +178,116 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
165
  return ( 'yes' === $atts['hide_if_zero'] && 0 == $raw_price ) ? '' : wcj_price( $raw_price, wcj_get_order_currency( $this->the_order ), $atts['hide_currency'] );
166
  }
167
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  /**
169
  * wcj_order_customer_meta.
170
  *
@@ -680,19 +803,19 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
680
  /**
681
  * wcj_order_date.
682
  *
683
- * @version 2.7.0
684
  */
685
  function wcj_order_date( $atts ) {
686
- return date_i18n( $atts['date_format'], strtotime( ( WCJ_IS_WC_VERSION_BELOW_3 ? $this->the_order->order_date : $this->the_order->get_date_created() ) ) );
687
  }
688
 
689
  /**
690
  * wcj_order_time.
691
  *
692
- * @version 2.7.0
693
  */
694
  function wcj_order_time( $atts ) {
695
- return date_i18n( $atts['time_format'], strtotime( ( WCJ_IS_WC_VERSION_BELOW_3 ? $this->the_order->order_date : $this->the_order->get_date_created() ) ) );
696
  }
697
 
698
  /**
@@ -798,16 +921,6 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
798
  return number_format( $order_total_tax_percent, $atts['precision'] );
799
  }
800
 
801
- /**
802
- * wcj_order_total_refunded.
803
- *
804
- * @version 2.5.3
805
- * @since 2.5.3
806
- */
807
- function wcj_order_total_refunded( $atts ) {
808
- return $this->wcj_price_shortcode( $this->the_order->get_total_refunded(), $atts );
809
- }
810
-
811
  /**
812
  * wcj_order_subtotal_by_tax_class.
813
  *
@@ -914,6 +1027,16 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
914
  return $this->wcj_price_shortcode( $the_subtotal, $atts );
915
  }
916
 
 
 
 
 
 
 
 
 
 
 
917
  /**
918
  * wcj_order_total_excl_tax.
919
  *
@@ -949,6 +1072,8 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
949
 
950
  /**
951
  * wcj_order_total.
 
 
952
  */
953
  function wcj_order_total( $atts ) {
954
  $order_total = ( true === $atts['excl_tax'] ) ? $this->the_order->get_total() - $this->the_order->get_total_tax() : $this->the_order->get_total();
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Orders
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.1.0
19
  */
20
  function __construct() {
21
 
22
  $this->the_shortcodes = array(
 
 
 
 
 
 
23
  'wcj_order_billing_address',
 
24
  'wcj_order_billing_country_name',
25
+ 'wcj_order_billing_phone',
26
  'wcj_order_checkout_field',
27
+ 'wcj_order_coupons',
28
+ 'wcj_order_currency',
29
  'wcj_order_custom_field',
30
  'wcj_order_custom_meta_field',
31
+ 'wcj_order_customer_meta',
32
+ 'wcj_order_customer_note',
33
+ 'wcj_order_customer_user',
34
+ 'wcj_order_customer_user_roles',
35
+ 'wcj_order_date',
36
+ 'wcj_order_fee',
37
+ 'wcj_order_fees_html',
38
+ 'wcj_order_function',
39
+ 'wcj_order_id',
40
  'wcj_order_items',
41
+ 'wcj_order_items_meta',
42
+ 'wcj_order_items_total_number',
43
+ 'wcj_order_items_total_quantity',
44
+ 'wcj_order_items_total_weight', // deprecated - use 'wcj_order_total_weight' instead
45
+ 'wcj_order_meta',
46
+ 'wcj_order_number',
47
+ 'wcj_order_payment_method',
48
+ 'wcj_order_payment_method_transaction_id',
49
+ 'wcj_order_refunds_table',
50
+ 'wcj_order_remaining_refund_amount',
51
+ 'wcj_order_shipping_address',
52
+ 'wcj_order_shipping_country_name',
53
+ 'wcj_order_shipping_method',
54
+ 'wcj_order_shipping_price',
55
+ 'wcj_order_shipping_tax',
56
+ 'wcj_order_status',
57
+ 'wcj_order_status_label',
58
  'wcj_order_subtotal',
59
+ 'wcj_order_subtotal_by_tax_class',
60
  'wcj_order_subtotal_plus_shipping',
61
+ 'wcj_order_subtotal_to_display',
 
 
 
62
  'wcj_order_tax_by_class',
63
+ 'wcj_order_taxes_html',
64
+ 'wcj_order_time',
65
  'wcj_order_total',
 
66
  'wcj_order_total_by_tax_class',
67
+ 'wcj_order_total_discount',
68
+ 'wcj_order_total_excl_shipping',
 
69
  'wcj_order_total_excl_tax',
 
 
70
  'wcj_order_total_fees',
71
  'wcj_order_total_fees_incl_tax',
72
  'wcj_order_total_fees_tax',
73
+ 'wcj_order_total_formatted',
 
 
 
 
 
 
 
 
 
74
  'wcj_order_total_height',
75
+ 'wcj_order_total_in_words',
76
  'wcj_order_total_length',
77
+ 'wcj_order_total_shipping_refunded',
78
+ 'wcj_order_total_refunded',
79
+ 'wcj_order_total_tax',
80
+ 'wcj_order_total_tax_percent',
81
+ 'wcj_order_total_tax_refunded',
82
  'wcj_order_total_weight',
83
+ 'wcj_order_total_width',
84
+ // 'wcj_order_cart_discount',
 
 
85
  );
86
 
87
  parent::__construct();
90
  /**
91
  * add_extra_atts.
92
  *
93
+ * @version 3.1.0
94
  */
95
  function add_extra_atts( $atts ) {
96
  $modified_atts = array_merge( array(
116
  'meta_key' => '',
117
  'tax_class' => '',
118
  'fallback_billing_address' => 'no',
119
+ 'tax_display' => '',
120
+ 'table_class' => '',
121
+ 'columns_styles' => '',
122
+ 'columns_titles' => '',
123
+ 'columns' => '',
124
+ 'price_prefix' => '',
125
+ 'display_refunded' => 'yes',
126
  ), $atts );
127
 
128
  return $modified_atts;
178
  return ( 'yes' === $atts['hide_if_zero'] && 0 == $raw_price ) ? '' : wcj_price( $raw_price, wcj_get_order_currency( $this->the_order ), $atts['hide_currency'] );
179
  }
180
 
181
+ /**
182
+ * wcj_order_total_formatted.
183
+ *
184
+ * @version 3.1.0
185
+ * @since 3.1.0
186
+ */
187
+ function wcj_order_total_formatted( $atts ) {
188
+ return $this->the_order->get_formatted_order_total( $atts['tax_display'], ( 'yes' === $atts['display_refunded'] ) );
189
+ }
190
+
191
+ /**
192
+ * wcj_order_remaining_refund_amount.
193
+ *
194
+ * @version 3.1.0
195
+ * @since 3.1.0
196
+ */
197
+ function wcj_order_remaining_refund_amount( $atts ) {
198
+ return $this->wcj_price_shortcode( $this->the_order->get_remaining_refund_amount(), $atts );
199
+ }
200
+
201
+ /**
202
+ * wcj_order_refunds_table.
203
+ *
204
+ * @version 3.1.0
205
+ * @since 3.1.0
206
+ * @todo add `refund_items_or_reason_or_title` column
207
+ * @todo add `refund_items_quantities` column (`$_item->get_quantity()`)
208
+ * @todo check `$atts['columns']` etc. before starting
209
+ * @todo (maybe) move to new `class-wcj-orders-refunded-shortcodes.php` file
210
+ */
211
+ function wcj_order_refunds_table( $atts ) {
212
+ $columns = ( '' == $atts['columns'] ? array() : explode( '|', $atts['columns'] ) );
213
+ $table_data = array();
214
+ $i = 1;
215
+ foreach ( $this->the_order->get_refunds() as $_refund ) {
216
+ $row = array();
217
+ foreach ( $columns as $column ) {
218
+ $cell = '';
219
+ switch ( $column ) {
220
+ case 'refund_number':
221
+ $cell = $i;
222
+ break;
223
+ case 'refund_title':
224
+ $cell = $_refund->get_post_title();
225
+ break;
226
+ case 'refund_reason':
227
+ $cell = $_refund->get_reason();
228
+ break;
229
+ case 'refund_reason_or_title':
230
+ $reason = $_refund->get_reason();
231
+ $cell = ( '' != $reason ? $reason : $_refund->get_post_title() );
232
+ break;
233
+ case 'refund_amount':
234
+ $cell = $atts['price_prefix'] . $_refund->get_formatted_refund_amount();
235
+ break;
236
+ case 'refund_items':
237
+ $_items = array();
238
+ foreach ( $_refund->get_items() as $_item ) {
239
+ $_items[] = $_item->get_name() . ' x ' . $_item->get_quantity() * -1;
240
+ }
241
+ $cell = ( ! empty( $_items ) ? implode( '<br>', $_items ) : '' );
242
+ break;
243
+ }
244
+ $row[] = $cell;
245
+ $i++;
246
+ }
247
+ $table_data[] = $row;
248
+ }
249
+ return ( ! empty( $table_data ) ?
250
+ wcj_get_table_html(
251
+ array_merge( array( ( '' == $atts['columns_titles'] ? array() : explode( '|', $atts['columns_titles'] ) ) ), $table_data ),
252
+ array(
253
+ 'table_class' => $atts['table_class'],
254
+ 'columns_styles' => ( '' == $atts['columns_styles'] ? array() : explode( '|', $atts['columns_styles'] ) ),
255
+ )
256
+ ) :
257
+ ''
258
+ );
259
+ }
260
+
261
+ /**
262
+ * wcj_order_total_tax_refunded.
263
+ *
264
+ * @version 3.1.0
265
+ * @since 3.1.0
266
+ */
267
+ function wcj_order_total_tax_refunded( $atts ) {
268
+ return $this->wcj_price_shortcode( $this->the_order->get_total_tax_refunded(), $atts );
269
+ }
270
+
271
+ /**
272
+ * wcj_order_total_shipping_refunded.
273
+ *
274
+ * @version 3.1.0
275
+ * @since 3.1.0
276
+ */
277
+ function wcj_order_total_shipping_refunded( $atts ) {
278
+ return $this->wcj_price_shortcode( $this->the_order->get_total_shipping_refunded(), $atts );
279
+ }
280
+
281
+ /**
282
+ * wcj_order_total_refunded.
283
+ *
284
+ * @version 2.5.3
285
+ * @since 2.5.3
286
+ */
287
+ function wcj_order_total_refunded( $atts ) {
288
+ return $this->wcj_price_shortcode( $this->the_order->get_total_refunded(), $atts );
289
+ }
290
+
291
  /**
292
  * wcj_order_customer_meta.
293
  *
803
  /**
804
  * wcj_order_date.
805
  *
806
+ * @version 3.1.0
807
  */
808
  function wcj_order_date( $atts ) {
809
+ return date_i18n( $atts['date_format'], strtotime( wcj_get_order_date( $this->the_order ) ) );
810
  }
811
 
812
  /**
813
  * wcj_order_time.
814
  *
815
+ * @version 3.1.0
816
  */
817
  function wcj_order_time( $atts ) {
818
+ return date_i18n( $atts['time_format'], strtotime( wcj_get_order_date( $this->the_order ) ) );
819
  }
820
 
821
  /**
921
  return number_format( $order_total_tax_percent, $atts['precision'] );
922
  }
923
 
 
 
 
 
 
 
 
 
 
 
924
  /**
925
  * wcj_order_subtotal_by_tax_class.
926
  *
1027
  return $this->wcj_price_shortcode( $the_subtotal, $atts );
1028
  }
1029
 
1030
+ /**
1031
+ * wcj_order_subtotal_to_display.
1032
+ *
1033
+ * @version 3.1.0
1034
+ * @since 3.1.0
1035
+ */
1036
+ function wcj_order_subtotal_to_display( $atts ) {
1037
+ return $this->the_order->get_subtotal_to_display( false, $atts['tax_display'] );
1038
+ }
1039
+
1040
  /**
1041
  * wcj_order_total_excl_tax.
1042
  *
1072
 
1073
  /**
1074
  * wcj_order_total.
1075
+ *
1076
+ * @todo (maybe) add attribute to deduct refunded (check `get_total_refunded()`, `get_total_tax_refunded()`, `get_total_shipping_refunded()`)
1077
  */
1078
  function wcj_order_total( $atts ) {
1079
  $order_total = ( true === $atts['excl_tax'] ) ? $this->the_order->get_total() - $this->the_order->get_total_tax() : $this->the_order->get_total();
includes/shortcodes/class-wcj-products-shortcodes.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Products
4
  *
5
- * @version 2.9.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,56 +15,56 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 2.9.0
19
  */
20
  function __construct() {
21
 
22
  $this->the_shortcodes = array(
23
- 'wcj_product_id',
24
- 'wcj_product_author_avatar',
25
  'wcj_product_author',
 
26
  'wcj_product_author_link',
27
  'wcj_product_author_link_all_posts',
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  'wcj_product_image',
29
  'wcj_product_image_url',
30
- 'wcj_product_gallery_image_url',
31
- 'wcj_product_url',
32
- 'wcj_product_price',
33
- 'wcj_product_wholesale_price_table', // WooCommerce Wholesale Price
34
- 'wcj_product_sku',
35
- 'wcj_product_title',
36
- 'wcj_product_weight',
37
- 'wcj_product_excerpt',
38
- 'wcj_product_description',
39
- 'wcj_product_short_description',
40
- 'wcj_product_custom_field',
41
  'wcj_product_meta',
42
- 'wcj_product_you_save',
43
- 'wcj_product_you_save_percent',
44
- 'wcj_product_tags',
45
  'wcj_product_purchase_price', // WooCommerce Product Cost Price
46
- 'wcj_product_total_sales',
 
47
  'wcj_product_shipping_class',
48
- 'wcj_product_dimensions',
49
- 'wcj_product_length',
50
- 'wcj_product_width',
51
- 'wcj_product_height',
52
- 'wcj_product_formatted_name',
53
  'wcj_product_stock_availability',
54
- 'wcj_product_tax_class',
55
- 'wcj_product_average_rating',
56
- 'wcj_product_categories',
57
- 'wcj_product_categories_names',
58
- 'wcj_product_categories_urls',
59
- 'wcj_product_list_attributes',
60
- 'wcj_product_list_attribute',
61
  'wcj_product_stock_quantity',
62
- 'wcj_product_sale_price',
63
- 'wcj_product_regular_price',
64
  'wcj_product_time_since_last_sale',
65
- 'wcj_product_price_including_tax',
66
- 'wcj_product_price_excluding_tax',
67
- 'wcj_product_available_variations',
 
 
 
 
 
68
  );
69
 
70
  $this->the_atts = array(
@@ -103,6 +103,7 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
103
  'avatar_size' => 96,
104
  'count_variations' => 'no',
105
  'variations' => 'no',
 
106
  );
107
 
108
  parent::__construct();
@@ -691,7 +692,7 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
691
  /**
692
  * wcj_product_wholesale_price_table.
693
  *
694
- * @version 2.7.0
695
  */
696
  function wcj_product_wholesale_price_table( $atts ) {
697
 
@@ -817,7 +818,7 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
817
  }
818
  }
819
 
820
- $columns_styles[] = 'text-align: center;';
821
  }
822
 
823
  $table_rows = array( $data_qty, );
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Products
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.1.0
19
  */
20
  function __construct() {
21
 
22
  $this->the_shortcodes = array(
 
 
23
  'wcj_product_author',
24
+ 'wcj_product_author_avatar',
25
  'wcj_product_author_link',
26
  'wcj_product_author_link_all_posts',
27
+ 'wcj_product_available_variations',
28
+ 'wcj_product_average_rating',
29
+ 'wcj_product_categories',
30
+ 'wcj_product_categories_names',
31
+ 'wcj_product_categories_urls',
32
+ 'wcj_product_custom_field',
33
+ 'wcj_product_description',
34
+ 'wcj_product_dimensions',
35
+ 'wcj_product_excerpt',
36
+ 'wcj_product_formatted_name',
37
+ 'wcj_product_gallery_image_url',
38
+ 'wcj_product_height',
39
+ 'wcj_product_id',
40
  'wcj_product_image',
41
  'wcj_product_image_url',
42
+ 'wcj_product_length',
43
+ 'wcj_product_list_attribute',
44
+ 'wcj_product_list_attributes',
 
 
 
 
 
 
 
 
45
  'wcj_product_meta',
46
+ 'wcj_product_price',
47
+ 'wcj_product_price_excluding_tax',
48
+ 'wcj_product_price_including_tax',
49
  'wcj_product_purchase_price', // WooCommerce Product Cost Price
50
+ 'wcj_product_regular_price',
51
+ 'wcj_product_sale_price',
52
  'wcj_product_shipping_class',
53
+ 'wcj_product_short_description',
54
+ 'wcj_product_sku',
 
 
 
55
  'wcj_product_stock_availability',
 
 
 
 
 
 
 
56
  'wcj_product_stock_quantity',
57
+ 'wcj_product_tags',
58
+ 'wcj_product_tax_class',
59
  'wcj_product_time_since_last_sale',
60
+ 'wcj_product_title',
61
+ 'wcj_product_total_sales',
62
+ 'wcj_product_url',
63
+ 'wcj_product_weight',
64
+ 'wcj_product_wholesale_price_table', // WooCommerce Wholesale Price
65
+ 'wcj_product_width',
66
+ 'wcj_product_you_save',
67
+ 'wcj_product_you_save_percent',
68
  );
69
 
70
  $this->the_atts = array(
103
  'avatar_size' => 96,
104
  'count_variations' => 'no',
105
  'variations' => 'no',
106
+ 'columns_style' => 'text-align: center;',
107
  );
108
 
109
  parent::__construct();
692
  /**
693
  * wcj_product_wholesale_price_table.
694
  *
695
+ * @version 3.1.0
696
  */
697
  function wcj_product_wholesale_price_table( $atts ) {
698
 
818
  }
819
  }
820
 
821
+ $columns_styles[] = $atts['columns_style'];
822
  }
823
 
824
  $table_rows = array( $data_qty, );
includes/shortcodes/class-wcj-shortcodes.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes
4
  *
5
- * @version 2.8.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -57,7 +57,7 @@ class WCJ_Shortcodes {
57
  /**
58
  * wcj_shortcode.
59
  *
60
- * @version 2.8.0
61
  * @todo `time` - weekly, e.g. 8:00-19:59;8:00-19:59;8:00-19:59;8:00-19:59;8:00-9:59,12:00-17:59;-;-;
62
  * @todo (maybe) - `return $atts['on_empty'];` everywhere instead of `return '';`
63
  */
@@ -73,27 +73,27 @@ class WCJ_Shortcodes {
73
 
74
  // Merge atts with global defaults
75
  $global_defaults = array(
76
- 'before' => '',
77
- 'after' => '',
78
- 'visibility' => '', // user_visibility
79
- 'wrong_user_text' => '<p>' . __( 'Wrong user role!', 'woocommerce-jetpack' ) . '</p>',
80
- // 'login_text' => __( 'Login', 'woocommerce-jetpack' ),
81
- 'site_visibility' => '',
82
- 'location' => '', // user_location
83
- 'not_location' => '', // user_location
84
- 'wpml_language' => '',
85
- 'wpml_not_language' => '',
86
- 'billing_country' => '',
87
- 'not_billing_country' => '',
88
- 'payment_method' => '',
89
- 'not_payment_method' => '',
90
- 'module' => '',
91
- 'find' => '',
92
- 'replace' => '',
93
- 'strip_tags' => 'no',
94
- 'on_empty' => '',
95
- 'on_zero' => 0,
96
- 'time' => '',
97
  );
98
  $atts = array_merge( $global_defaults, $atts );
99
 
@@ -136,11 +136,18 @@ class WCJ_Shortcodes {
136
  }
137
  }
138
  if ( ! $is_iser_visibility_ok ) {
139
- // return '<p><a href="' . wp_login_url( get_permalink() ) . '" title="' . $atts['login_text'] . '">' . $atts['login_text'] . '</a></p>';
140
  if ( ! is_user_logged_in() ) {
141
- ob_start();
142
- woocommerce_login_form();
143
- return ob_get_clean();
 
 
 
 
 
 
 
 
144
  } else {
145
  return $atts['wrong_user_text'];
146
  }
@@ -276,23 +283,13 @@ class WCJ_Shortcodes {
276
  /**
277
  * wcj_get_user_location.
278
  *
279
- * @version 2.5.0
 
280
  */
281
  function wcj_get_user_location() {
282
- $country = '';
283
- if ( isset( $_GET['country'] ) && '' != $_GET['country'] && wcj_is_user_role( 'administrator' ) ) {
284
- $country = $_GET['country'];
285
- } else {
286
- // Get the country by IP
287
- $location = WC_Geolocation::geolocate_ip();
288
- // Base fallback
289
- if ( empty( $location['country'] ) ) {
290
- $location = wc_format_country_state_string( apply_filters( 'woocommerce_customer_default_location', get_option( 'woocommerce_default_country' ) ) );
291
- }
292
- $country = ( isset( $location['country'] ) ) ? $location['country'] : '';
293
- }
294
- return $country;
295
  }
 
296
  }
297
 
298
  endif;
2
  /**
3
  * Booster for WooCommerce - Shortcodes
4
  *
5
+ * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
57
  /**
58
  * wcj_shortcode.
59
  *
60
+ * @version 3.1.0
61
  * @todo `time` - weekly, e.g. 8:00-19:59;8:00-19:59;8:00-19:59;8:00-19:59;8:00-9:59,12:00-17:59;-;-;
62
  * @todo (maybe) - `return $atts['on_empty'];` everywhere instead of `return '';`
63
  */
73
 
74
  // Merge atts with global defaults
75
  $global_defaults = array(
76
+ 'before' => '',
77
+ 'after' => '',
78
+ 'visibility' => '', // user_visibility
79
+ 'wrong_user_text' => '', // '<p>' . __( 'Wrong user role!', 'woocommerce-jetpack' ) . '</p>',
80
+ 'wrong_user_text_not_logged_in' => '',
81
+ 'site_visibility' => '',
82
+ 'location' => '', // user_location
83
+ 'not_location' => '', // user_location
84
+ 'wpml_language' => '',
85
+ 'wpml_not_language' => '',
86
+ 'billing_country' => '',
87
+ 'not_billing_country' => '',
88
+ 'payment_method' => '',
89
+ 'not_payment_method' => '',
90
+ 'module' => '',
91
+ 'find' => '',
92
+ 'replace' => '',
93
+ 'strip_tags' => 'no',
94
+ 'on_empty' => '',
95
+ 'on_zero' => 0,
96
+ 'time' => '',
97
  );
98
  $atts = array_merge( $global_defaults, $atts );
99
 
136
  }
137
  }
138
  if ( ! $is_iser_visibility_ok ) {
 
139
  if ( ! is_user_logged_in() ) {
140
+ $login_form = '';
141
+ $login_url = '';
142
+ if ( false !== strpos( $atts['wrong_user_text_not_logged_in'], '%login_form%' ) ) {
143
+ ob_start();
144
+ woocommerce_login_form();
145
+ $login_form = ob_get_clean();
146
+ }
147
+ if ( false !== strpos( $atts['wrong_user_text_not_logged_in'], '%login_url%' ) ) {
148
+ $login_url = wp_login_url( get_permalink() );
149
+ }
150
+ return str_replace( array( '%login_form%', '%login_url%' ), array( $login_form, $login_url ), $atts['wrong_user_text_not_logged_in'] );
151
  } else {
152
  return $atts['wrong_user_text'];
153
  }
283
  /**
284
  * wcj_get_user_location.
285
  *
286
+ * @version 3.1.0
287
+ * @todo (maybe) move this to global functions
288
  */
289
  function wcj_get_user_location() {
290
+ return ( isset( $_GET['country'] ) && '' != $_GET['country'] && wcj_is_user_role( 'administrator' ) ? $_GET['country'] : wcj_get_country_by_ip() );
 
 
 
 
 
 
 
 
 
 
 
 
291
  }
292
+
293
  }
294
 
295
  endif;
includes/templates/cart-empty.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Empty cart page
4
+ *
5
+ * This template can be overridden by copying it to yourtheme/woocommerce/cart/cart-empty.php.
6
+ *
7
+ * HOWEVER, on occasion WooCommerce will need to update template files and you
8
+ * (the theme developer) will need to copy the new files to your theme to
9
+ * maintain compatibility. We try to do this as little as possible, but it does
10
+ * happen. When this occurs the version of the template file will be bumped and
11
+ * the readme will list any important changes.
12
+ *
13
+ * @see https://docs.woocommerce.com/document/template-structure/
14
+ * @author WooThemes
15
+ * @package WooCommerce/Templates
16
+ * @version 3.1.0
17
+ */
18
+
19
+ if ( ! defined( 'ABSPATH' ) ) {
20
+ exit; // Exit if accessed directly
21
+ }
22
+
23
+ wc_print_notices();
24
+
25
+ /**
26
+ * @hooked wc_empty_cart_message - 10
27
+ */
28
+ do_action( 'woocommerce_cart_is_empty' );
29
+
30
+ if ( wc_get_page_id( 'shop' ) > 0 ) : ?>
31
+ <p class="return-to-shop">
32
+ <a class="button wc-backward" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>">
33
+ <?php echo apply_filters( 'wcj_return_to_shop_text', __( 'Return to shop', 'woocommerce' ) ); ?>
34
+ </a>
35
+ </p>
36
+ <?php endif; ?>
includes/widgets/class-wcj-widget-country-switcher.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Widget - Country Switcher
4
  *
5
- * @version 2.5.5
6
  * @since 2.4.8
7
  * @author Algoritmika Ltd.
8
  */
@@ -11,117 +11,89 @@ if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
  if ( ! class_exists( 'WCJ_Widget_Country_Switcher' ) ) :
13
 
14
- class WCJ_Widget_Country_Switcher extends WP_Widget {
15
 
16
  /**
17
- * Sets up the widgets name etc
 
 
 
18
  */
19
- function __construct() {
20
- $widget_ops = array(
21
- 'classname' => 'wcj_widget_country_switcher',
22
- 'description' => __( 'Booster: Country Switcher Widget', 'woocommerce-jetpack' ),
23
- );
24
- parent::__construct( 'wcj_widget_country_switcher', __( 'Booster - Country Switcher', 'woocommerce-jetpack' ), $widget_ops );
 
 
 
25
  }
26
 
27
  /**
28
- * Outputs the content of the widget
29
  *
30
- * @version 2.5.5
31
- * @param array $args
32
- * @param array $instance
33
  */
34
- function widget( $args, $instance ) {
35
- // outputs the content of the widget
36
- echo $args['before_widget'];
37
- if ( ! empty( $instance['title'] ) ) {
38
- echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
39
- }
40
  if ( ! wcj_is_module_enabled( 'price_by_country' ) ) {
41
- echo __( 'Prices and Currencies by Country module not enabled!', 'woocommerce-jetpack' );
42
  } elseif ( 'by_ip' === get_option( 'wcj_price_by_country_customer_country_detection_method', 'by_ip' ) ) {
43
- echo __( 'Customer Country Detection Method must include "by user selection"!', 'woocommerce-jetpack' );
44
  } else {
45
  if ( ! isset( $instance['replace_with_currency'] ) ) {
46
  $instance['replace_with_currency'] = 'no';
47
  }
48
- echo do_shortcode( '[wcj_country_select_drop_down_list countries="' . $instance['countries'] . '" replace_with_currency="' . $instance['replace_with_currency'] . '"]' );
49
- /* switch ( $instance['switcher_type'] ) {
50
- case 'link_list':
51
- echo do_shortcode( '[wcj_currency_select_link_list]' );
52
- break;
53
- case 'radio_list':
54
- echo do_shortcode( '[wcj_currency_select_radio_list]' );
55
- break;
56
- default:
57
- echo do_shortcode( '[wcj_currency_select_drop_down_list]' );
58
- break;
59
- } */
60
  }
61
- echo $args['after_widget'];
62
  }
63
 
64
  /**
65
- * Outputs the options form on admin
66
  *
67
- * @version 2.5.5
68
- * @param array $instance The widget options
 
69
  */
70
- function form( $instance ) {
71
- // outputs the options form on admin
72
- $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
73
- $countries = ! empty( $instance['countries'] ) ? $instance['countries'] : '';
74
- $replace_with_currency = ! empty( $instance['replace_with_currency'] ) ? $instance['replace_with_currency'] : 'no';
75
- // $switcher_type = ! empty( $instance['switcher_type'] ) ? $instance['switcher_type'] : 'drop_down';
76
- ?>
77
- <p>
78
- <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
79
- <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
80
- </p>
81
- <p>
82
- <label for="<?php echo $this->get_field_id( 'countries' ); ?>"><?php _e( 'Countries:' ); ?></label>
83
- <input class="widefat" id="<?php echo $this->get_field_id( 'countries' ); ?>" name="<?php echo $this->get_field_name( 'countries' ); ?>" type="text" value="<?php echo esc_attr( $countries ); ?>">
84
- </p>
85
- <p>
86
- <label for="<?php echo $this->get_field_id( 'replace_with_currency' ); ?>"><?php _e( 'Replace with currency:' ); ?></label>
87
- <select class="widefat" id="<?php echo $this->get_field_id( 'replace_with_currency' ); ?>" name="<?php echo $this->get_field_name( 'replace_with_currency' ); ?>">
88
- <option value="no" <?php selected( $replace_with_currency, 'no' ); ?>><?php echo __( 'No', 'woocommerce-jetpack' ); ?>
89
- <option value="yes" <?php selected( $replace_with_currency, 'yes' ); ?>><?php echo __( 'Yes', 'woocommerce-jetpack' ); ?>
90
- </select>
91
- </p>
92
- <?php /*<p>
93
- <label for="<?php echo $this->get_field_id( 'switcher_type' ); ?>"><?php _e( 'Type:' ); ?></label>
94
- <select class="widefat" id="<?php echo $this->get_field_id( 'switcher_type' ); ?>" name="<?php echo $this->get_field_name( 'switcher_type' ); ?>">
95
- <option value="drop_down" <?php selected( $switcher_type, 'drop_down' ); ?>><?php echo __( 'Drop down', 'woocommerce-jetpack' ); ?>
96
- <option value="radio_list" <?php selected( $switcher_type, 'radio_list' ); ?>><?php echo __( 'Radio list', 'woocommerce-jetpack' ); ?>
97
- <option value="link_list" <?php selected( $switcher_type, 'link_list' ); ?>><?php echo __( 'Link list', 'woocommerce-jetpack' ); ?>
98
- </select>
99
- </p>*/ ?>
100
- <?php
101
  }
102
 
103
- /**
104
- * Processing widget options on save
105
- *
106
- * @version 2.5.5
107
- * @param array $new_instance The new options
108
- * @param array $old_instance The previous options
109
- */
110
- function update( $new_instance, $old_instance ) {
111
- // processes widget options to be saved
112
- $instance = array();
113
- $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
114
- $instance['countries'] = ( ! empty( $new_instance['countries'] ) ) ? $new_instance['countries'] : '';
115
- $instance['replace_with_currency'] = ( ! empty( $new_instance['replace_with_currency'] ) ) ? $new_instance['replace_with_currency'] : 'no';
116
- // $instance['switcher_type'] = ( ! empty( $new_instance['switcher_type'] ) ) ? $new_instance['switcher_type'] : 'drop_down';
117
- return $instance;
118
- }
119
  }
120
 
121
  endif;
122
 
123
- // register WCJ_Widget_Country_Switcher widget
124
  if ( ! function_exists( 'register_wcj_widget_country_switcher' ) ) {
 
 
 
125
  function register_wcj_widget_country_switcher() {
126
  register_widget( 'WCJ_Widget_Country_Switcher' );
127
  }
2
  /**
3
  * Booster for WooCommerce - Widget - Country Switcher
4
  *
5
+ * @version 3.1.0
6
  * @since 2.4.8
7
  * @author Algoritmika Ltd.
8
  */
11
 
12
  if ( ! class_exists( 'WCJ_Widget_Country_Switcher' ) ) :
13
 
14
+ class WCJ_Widget_Country_Switcher extends WCJ_Widget {
15
 
16
  /**
17
+ * get_data.
18
+ *
19
+ * @version 3.1.0
20
+ * @since 3.1.0
21
  */
22
+ function get_data( $id ) {
23
+ switch ( $id ) {
24
+ case 'id_base':
25
+ return 'wcj_widget_country_switcher';
26
+ case 'name':
27
+ return __( 'Booster - Country Switcher', 'woocommerce-jetpack' );
28
+ case 'description':
29
+ return __( 'Booster: Country Switcher Widget', 'woocommerce-jetpack' );
30
+ }
31
  }
32
 
33
  /**
34
+ * get_content.
35
  *
36
+ * @version 3.1.0
37
+ * @since 3.1.0
 
38
  */
39
+ function get_content( $instance ) {
 
 
 
 
 
40
  if ( ! wcj_is_module_enabled( 'price_by_country' ) ) {
41
+ return __( 'Prices and Currencies by Country module not enabled!', 'woocommerce-jetpack' );
42
  } elseif ( 'by_ip' === get_option( 'wcj_price_by_country_customer_country_detection_method', 'by_ip' ) ) {
43
+ return __( 'Customer Country Detection Method must include "by user selection"!', 'woocommerce-jetpack' );
44
  } else {
45
  if ( ! isset( $instance['replace_with_currency'] ) ) {
46
  $instance['replace_with_currency'] = 'no';
47
  }
48
+ return do_shortcode( '[wcj_country_select_drop_down_list countries="' . $instance['countries'] . '" replace_with_currency="' . $instance['replace_with_currency'] . '"]' );
 
 
 
 
 
 
 
 
 
 
 
49
  }
 
50
  }
51
 
52
  /**
53
+ * get_options.
54
  *
55
+ * @version 3.1.0
56
+ * @since 3.1.0
57
+ * @todo (maybe) `switcher_type`
58
  */
59
+ function get_options() {
60
+ return array(
61
+ array(
62
+ 'title' => __( 'Title', 'woocommerce-jetpack' ),
63
+ 'id' => 'title',
64
+ 'default' => '',
65
+ 'type' => 'text',
66
+ 'class' => 'widefat',
67
+ ),
68
+ array(
69
+ 'title' => __( 'Countries', 'woocommerce-jetpack' ),
70
+ 'id' => 'countries',
71
+ 'default' => '',
72
+ 'type' => 'text',
73
+ 'class' => 'widefat',
74
+ ),
75
+ array(
76
+ 'title' => __( 'Replace with currency', 'woocommerce-jetpack' ),
77
+ 'id' => 'replace_with_currency',
78
+ 'default' => 'no',
79
+ 'type' => 'select',
80
+ 'class' => 'widefat',
81
+ 'options' => array(
82
+ 'no' => __( 'No', 'woocommerce-jetpack' ),
83
+ 'yes' => __( 'Yes', 'woocommerce-jetpack' ),
84
+ ),
85
+ ),
86
+ );
 
 
 
87
  }
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  }
90
 
91
  endif;
92
 
 
93
  if ( ! function_exists( 'register_wcj_widget_country_switcher' ) ) {
94
+ /**
95
+ * Register WCJ_Widget_Country_Switcher widget.
96
+ */
97
  function register_wcj_widget_country_switcher() {
98
  register_widget( 'WCJ_Widget_Country_Switcher' );
99
  }
includes/widgets/class-wcj-widget-left-to-free-shipping.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Widget - Left to Free Shipping
4
  *
5
- * @version 2.4.4
6
  * @since 2.4.4
7
  * @author Algoritmika Ltd.
8
  */
@@ -11,73 +11,68 @@ if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
  if ( ! class_exists( 'WCJ_Widget_Left_to_Free_Shipping' ) ) :
13
 
14
- class WCJ_Widget_Left_to_Free_Shipping extends WP_Widget {
15
 
16
  /**
17
- * Sets up the widgets name etc
18
- */
19
- function __construct() {
20
- $widget_ops = array(
21
- 'classname' => 'wcj_widget_left_to_free_shipping',
22
- 'description' => __( 'Booster: Left to Free Shipping Widget', 'woocommerce-jetpack' ),
23
- );
24
- parent::__construct( 'wcj_widget_left_to_free_shipping', __( 'Booster - Left to Free Shipping', 'woocommerce-jetpack' ), $widget_ops );
25
- }
26
-
27
- /**
28
- * Outputs the content of the widget
29
  *
30
- * @param array $args
31
- * @param array $instance
32
  */
33
- function widget( $args, $instance ) {
34
- // outputs the content of the widget
35
- echo $args['before_widget'];
36
- if ( ! empty( $instance['title'] ) ) {
37
- echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
 
 
 
38
  }
39
- echo wcj_get_left_to_free_shipping( $instance['content'] );
40
- echo $args['after_widget'];
41
  }
42
 
43
  /**
44
- * Outputs the options form on admin
45
  *
46
- * @param array $instance The widget options
 
47
  */
48
- function form( $instance ) {
49
- // outputs the options form on admin
50
- $title = ! empty( $instance['title'] ) ? $instance['title'] : __( 'Left to Free Shipping', 'woocommerce-jetpack' );
51
- $content = ! empty( $instance['content'] ) ? $instance['content'] : __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' );
52
- ?>
53
- <p>
54
- <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
55
- <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
56
- <label for="<?php echo $this->get_field_id( 'content' ); ?>"><?php _e( 'Content:' ); ?></label>
57
- <input class="widefat" id="<?php echo $this->get_field_id( 'content' ); ?>" name="<?php echo $this->get_field_name( 'content' ); ?>" type="text" value="<?php echo esc_attr( $content ); ?>">
58
- </p>
59
- <?php
60
  }
61
 
62
  /**
63
- * Processing widget options on save
64
  *
65
- * @param array $new_instance The new options
66
- * @param array $old_instance The previous options
67
  */
68
- function update( $new_instance, $old_instance ) {
69
- // processes widget options to be saved
70
- $instance = array();
71
- $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
72
- $instance['content'] = ( ! empty( $new_instance['content'] ) ) ? strip_tags( $new_instance['content'] ) : '';
73
- return $instance;
 
 
 
 
 
 
 
 
 
 
 
74
  }
 
75
  }
76
 
77
  endif;
78
 
79
- // register WCJ_Widget_Left_to_Free_Shipping widget
80
  if ( ! function_exists( 'register_wcj_widget_left_to_free_shipping' ) ) {
 
 
 
81
  function register_wcj_widget_left_to_free_shipping() {
82
  register_widget( 'WCJ_Widget_Left_to_Free_Shipping' );
83
  }
2
  /**
3
  * Booster for WooCommerce - Widget - Left to Free Shipping
4
  *
5
+ * @version 3.1.0
6
  * @since 2.4.4
7
  * @author Algoritmika Ltd.
8
  */
11
 
12
  if ( ! class_exists( 'WCJ_Widget_Left_to_Free_Shipping' ) ) :
13
 
14
+ class WCJ_Widget_Left_to_Free_Shipping extends WCJ_Widget {
15
 
16
  /**
17
+ * get_data.
 
 
 
 
 
 
 
 
 
 
 
18
  *
19
+ * @version 3.1.0
20
+ * @since 3.1.0
21
  */
22
+ function get_data( $id ) {
23
+ switch ( $id ) {
24
+ case 'id_base':
25
+ return 'wcj_widget_left_to_free_shipping';
26
+ case 'name':
27
+ return __( 'Booster - Left to Free Shipping', 'woocommerce-jetpack' );
28
+ case 'description':
29
+ return __( 'Booster: Left to Free Shipping Widget', 'woocommerce-jetpack' );
30
  }
 
 
31
  }
32
 
33
  /**
34
+ * get_content.
35
  *
36
+ * @version 3.1.0
37
+ * @since 3.1.0
38
  */
39
+ function get_content( $instance ) {
40
+ return wcj_get_left_to_free_shipping( $instance['content'] );
 
 
 
 
 
 
 
 
 
 
41
  }
42
 
43
  /**
44
+ * get_options.
45
  *
46
+ * @version 3.1.0
47
+ * @since 3.1.0
48
  */
49
+ function get_options() {
50
+ return array(
51
+ array(
52
+ 'title' => __( 'Title', 'woocommerce-jetpack' ),
53
+ 'id' => 'title',
54
+ 'default' => '', // __( 'Left to Free Shipping', 'woocommerce-jetpack' ),
55
+ 'type' => 'text',
56
+ 'class' => 'widefat',
57
+ ),
58
+ array(
59
+ 'title' => __( 'Content', 'woocommerce-jetpack' ),
60
+ 'id' => 'content',
61
+ 'default' => __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' ),
62
+ 'type' => 'text',
63
+ 'class' => 'widefat',
64
+ ),
65
+ );
66
  }
67
+
68
  }
69
 
70
  endif;
71
 
 
72
  if ( ! function_exists( 'register_wcj_widget_left_to_free_shipping' ) ) {
73
+ /**
74
+ * Register WCJ_Widget_Left_to_Free_Shipping widget.
75
+ */
76
  function register_wcj_widget_left_to_free_shipping() {
77
  register_widget( 'WCJ_Widget_Left_to_Free_Shipping' );
78
  }
includes/widgets/class-wcj-widget-multicurrency.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Widget - Multicurrency
4
  *
5
- * @version 2.5.0
6
  * @since 2.4.3
7
  * @author Algoritmika Ltd.
8
  */
@@ -11,96 +11,84 @@ if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
  if ( ! class_exists( 'WCJ_Widget_Multicurrency' ) ) :
13
 
14
- class WCJ_Widget_Multicurrency extends WP_Widget {
15
 
16
  /**
17
- * Sets up the widgets name etc
 
 
 
18
  */
19
- function __construct() {
20
- $widget_ops = array(
21
- 'classname' => 'wcj_widget_multicurrency',
22
- 'description' => __( 'Booster: Multicurrency Switcher Widget', 'woocommerce-jetpack' ),
23
- );
24
- parent::__construct( 'wcj_widget_multicurrency', __( 'Booster - Multicurrency Switcher', 'woocommerce-jetpack' ), $widget_ops );
 
 
 
25
  }
26
 
27
  /**
28
- * Outputs the content of the widget
29
  *
30
- * @version 2.5.0
31
- * @param array $args
32
- * @param array $instance
33
  */
34
- function widget( $args, $instance ) {
35
- // outputs the content of the widget
36
- echo $args['before_widget'];
37
- if ( ! empty( $instance['title'] ) ) {
38
- echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
39
- }
40
  if ( ! wcj_is_module_enabled( 'multicurrency' ) ) {
41
- echo __( 'Multicurrency module not enabled!', 'woocommerce-jetpack' );
42
  } else {
43
  switch ( $instance['switcher_type'] ) {
44
  case 'link_list':
45
- echo do_shortcode( '[wcj_currency_select_link_list]' );
46
- break;
47
  case 'radio_list':
48
- echo do_shortcode( '[wcj_currency_select_radio_list]' );
49
- break;
50
- default:
51
- echo do_shortcode( '[wcj_currency_select_drop_down_list]' );
52
- break;
53
  }
54
  }
55
- echo $args['after_widget'];
56
  }
57
 
58
  /**
59
- * Outputs the options form on admin
60
  *
61
- * @version 2.4.5
62
- * @param array $instance The widget options
63
  */
64
- function form( $instance ) {
65
- // outputs the options form on admin
66
- $title = ! empty( $instance['title'] ) ? $instance['title'] : '';
67
- $switcher_type = ! empty( $instance['switcher_type'] ) ? $instance['switcher_type'] : 'drop_down';
68
- ?>
69
- <p>
70
- <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php _e( 'Title:' ); ?></label>
71
- <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
72
- </p>
73
- <p>
74
- <label for="<?php echo $this->get_field_id( 'switcher_type' ); ?>"><?php _e( 'Type:' ); ?></label>
75
- <select class="widefat" id="<?php echo $this->get_field_id( 'switcher_type' ); ?>" name="<?php echo $this->get_field_name( 'switcher_type' ); ?>">
76
- <option value="drop_down" <?php selected( $switcher_type, 'drop_down' ); ?>><?php echo __( 'Drop down', 'woocommerce-jetpack' ); ?>
77
- <option value="radio_list" <?php selected( $switcher_type, 'radio_list' ); ?>><?php echo __( 'Radio list', 'woocommerce-jetpack' ); ?>
78
- <option value="link_list" <?php selected( $switcher_type, 'link_list' ); ?>><?php echo __( 'Link list', 'woocommerce-jetpack' ); ?>
79
- </select>
80
- </p>
81
- <?php
 
 
 
 
82
  }
83
 
84
- /**
85
- * Processing widget options on save
86
- *
87
- * @version 2.4.5
88
- * @param array $new_instance The new options
89
- * @param array $old_instance The previous options
90
- */
91
- function update( $new_instance, $old_instance ) {
92
- // processes widget options to be saved
93
- $instance = array();
94
- $instance['title'] = ( ! empty( $new_instance['title'] ) ) ? strip_tags( $new_instance['title'] ) : '';
95
- $instance['switcher_type'] = ( ! empty( $new_instance['switcher_type'] ) ) ? $new_instance['switcher_type'] : 'drop_down';
96
- return $instance;
97
- }
98
  }
99
 
100
  endif;
101
 
102
- // register WCJ_Widget_Multicurrency widget
103
  if ( ! function_exists( 'register_wcj_widget_multicurrency' ) ) {
 
 
 
104
  function register_wcj_widget_multicurrency() {
105
  register_widget( 'WCJ_Widget_Multicurrency' );
106
  }
2
  /**
3
  * Booster for WooCommerce - Widget - Multicurrency
4
  *
5
+ * @version 3.1.0
6
  * @since 2.4.3
7
  * @author Algoritmika Ltd.
8
  */
11
 
12
  if ( ! class_exists( 'WCJ_Widget_Multicurrency' ) ) :
13
 
14
+ class WCJ_Widget_Multicurrency extends WCJ_Widget {
15
 
16
  /**
17
+ * get_data.
18
+ *
19
+ * @version 3.1.0
20
+ * @since 3.1.0
21
  */
22
+ function get_data( $id ) {
23
+ switch ( $id ) {
24
+ case 'id_base':
25
+ return 'wcj_widget_multicurrency';
26
+ case 'name':
27
+ return __( 'Booster - Multicurrency Switcher', 'woocommerce-jetpack' );
28
+ case 'description':
29
+ return __( 'Booster: Multicurrency Switcher Widget', 'woocommerce-jetpack' );
30
+ }
31
  }
32
 
33
  /**
34
+ * get_content.
35
  *
36
+ * @version 3.1.0
37
+ * @since 3.1.0
 
38
  */
39
+ function get_content( $instance ) {
 
 
 
 
 
40
  if ( ! wcj_is_module_enabled( 'multicurrency' ) ) {
41
+ return __( 'Multicurrency module not enabled!', 'woocommerce-jetpack' );
42
  } else {
43
  switch ( $instance['switcher_type'] ) {
44
  case 'link_list':
45
+ return do_shortcode( '[wcj_currency_select_link_list]' );
 
46
  case 'radio_list':
47
+ return do_shortcode( '[wcj_currency_select_radio_list]' );
48
+ default: // 'drop_down'
49
+ return do_shortcode( '[wcj_currency_select_drop_down_list]' );
 
 
50
  }
51
  }
 
52
  }
53
 
54
  /**
55
+ * get_options.
56
  *
57
+ * @version 3.1.0
58
+ * @since 3.1.0
59
  */
60
+ function get_options() {
61
+ return array(
62
+ array(
63
+ 'title' => __( 'Title', 'woocommerce-jetpack' ),
64
+ 'id' => 'title',
65
+ 'default' => '',
66
+ 'type' => 'text',
67
+ 'class' => 'widefat',
68
+ ),
69
+ array(
70
+ 'title' => __( 'Type', 'woocommerce-jetpack' ),
71
+ 'id' => 'switcher_type',
72
+ 'default' => 'drop_down',
73
+ 'type' => 'select',
74
+ 'options' => array(
75
+ 'drop_down' => __( 'Drop down', 'woocommerce-jetpack' ),
76
+ 'radio_list' => __( 'Radio list', 'woocommerce-jetpack' ),
77
+ 'link_list' => __( 'Link list', 'woocommerce-jetpack' ),
78
+ ),
79
+ 'class' => 'widefat',
80
+ ),
81
+ );
82
  }
83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
84
  }
85
 
86
  endif;
87
 
 
88
  if ( ! function_exists( 'register_wcj_widget_multicurrency' ) ) {
89
+ /**
90
+ * Register WCJ_Widget_Multicurrency widget.
91
+ */
92
  function register_wcj_widget_multicurrency() {
93
  register_widget( 'WCJ_Widget_Multicurrency' );
94
  }
includes/widgets/class-wcj-widget-selector.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Widget - Selector
4
+ *
5
+ * @version 3.1.0
6
+ * @since 3.1.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit;
11
+
12
+ if ( ! class_exists( 'WCJ_Widget_Selector' ) ) :
13
+
14
+ class WCJ_Widget_Selector extends WCJ_Widget {
15
+
16
+ /**
17
+ * get_data.
18
+ *
19
+ * @version 3.1.0
20
+ * @since 3.1.0
21
+ */
22
+ function get_data( $id ) {
23
+ switch ( $id ) {
24
+ case 'id_base':
25
+ return 'wcj_widget_selector';
26
+ case 'name':
27
+ return __( 'Booster - Selector', 'woocommerce-jetpack' );
28
+ case 'description':
29
+ return __( 'Booster: Selector Widget', 'woocommerce-jetpack' ) . ' (' . __( 'currently for "Product Visibility by Country" module only', 'woocommerce-jetpack' ) . ')';
30
+ }
31
+ }
32
+
33
+ /**
34
+ * get_content.
35
+ *
36
+ * @version 3.1.0
37
+ * @since 3.1.0
38
+ */
39
+ function get_content( $instance ) {
40
+ return do_shortcode( '[wcj_selector selector_type="' . $instance['selector_type'] . '"]' );
41
+ }
42
+
43
+ /**
44
+ * get_options.
45
+ *
46
+ * @version 3.1.0
47
+ * @since 3.1.0
48
+ */
49
+ function get_options() {
50
+ return array(
51
+ array(
52
+ 'title' => __( 'Title', 'woocommerce-jetpack' ),
53
+ 'id' => 'title',
54
+ 'default' => '',
55
+ 'type' => 'text',
56
+ 'class' => 'widefat',
57
+ ),
58
+ array(
59
+ 'title' => __( 'Selector Type', 'woocommerce-jetpack' ),
60
+ 'id' => 'selector_type',
61
+ 'default' => 'country',
62
+ 'type' => 'select',
63
+ 'options' => array(
64
+ 'country' => __( 'Countries', 'woocommerce-jetpack' ),
65
+ ),
66
+ 'class' => 'widefat',
67
+ ),
68
+ );
69
+ }
70
+
71
+ }
72
+
73
+ endif;
74
+
75
+ if ( ! function_exists( 'register_wcj_widget_selector' ) ) {
76
+ /**
77
+ * Register WCJ_Widget_Selector widget.
78
+ *
79
+ * @version 3.1.0
80
+ * @since 3.1.0
81
+ */
82
+ function register_wcj_widget_selector() {
83
+ register_widget( 'WCJ_Widget_Selector' );
84
+ }
85
+ }
86
+ add_action( 'widgets_init', 'register_wcj_widget_selector' );
includes/widgets/class-wcj-widget.php ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Widget
4
+ *
5
+ * @version 3.1.0
6
+ * @since 3.1.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit;
11
+
12
+ if ( ! class_exists( 'WCJ_Widget' ) ) :
13
+
14
+ class WCJ_Widget extends WP_Widget {
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 3.1.0
20
+ * @since 3.1.0
21
+ */
22
+ function __construct() {
23
+ $widget_options = array(
24
+ 'classname' => $this->get_data( 'id_base' ),
25
+ 'description' => $this->get_data( 'description' ),
26
+ );
27
+ parent::__construct( $widget_options['classname'], $this->get_data( 'name' ), $widget_options );
28
+ }
29
+
30
+ /**
31
+ * Outputs the content of the widget.
32
+ *
33
+ * @version 3.1.0
34
+ * @since 3.1.0
35
+ * @param array $args
36
+ * @param array $instance
37
+ */
38
+ function widget( $args, $instance ) {
39
+ $html = '';
40
+ $html .= $args['before_widget'];
41
+ if ( ! empty( $instance['title'] ) ) {
42
+ $html .= $args['before_title'] . apply_filters( 'widget_title', $instance['title'] ) . $args['after_title'];
43
+ }
44
+ $html .= $this->get_content( $instance );
45
+ $html .= $args['after_widget'];
46
+ echo $html;
47
+ }
48
+
49
+ /**
50
+ * Outputs the options form on admin.
51
+ *
52
+ * @version 3.1.0
53
+ * @since 3.1.0
54
+ * @param array $instance The widget options
55
+ * @todo add more types (not only text etc. and select)
56
+ */
57
+ function form( $instance ) {
58
+ $html = '';
59
+ foreach ( $this->get_options() as $option ) {
60
+ $field_value = /* esc_attr */( ( ! empty( $instance[ $option['id'] ] ) ? $instance[ $option['id'] ] : $option['default'] ) );
61
+ $field_id = $this->get_field_id( $option['id'] );
62
+ $field_name = $this->get_field_name( $option['id'] );
63
+ $field_type = $option['type'];
64
+ $field_desc = ( isset( $option['desc'] ) ? '<br>' . '<em>' . $option['desc'] . '</em>' . '<br>' : '' );
65
+ $field_class = ( isset( $option['class'] ) ? $option['class'] : '' );
66
+ $field_style = ( isset( $option['style'] ) ? $option['style'] : '' );
67
+ $html .= '<label for="' . $field_id . '">' . $option['title'] . '</label>';
68
+ switch ( $field_type ) {
69
+ case 'select':
70
+ $options_html = '';
71
+ foreach ( $option['options'] as $select_option_id => $select_option_title ) {
72
+ $options_html .= '<option value="' . $select_option_id . '" ' . selected( $select_option_id, $field_value, false ) . '>' .
73
+ $select_option_title . '</option>';
74
+ }
75
+ $html .= '<select class="' . $field_class . '" style="' . $field_style . '" id="' . $field_id . '" name="' . $field_name . '"' . '>' .
76
+ $options_html . '</select>';
77
+ break;
78
+ default: // 'text' etc.
79
+ $html .= '<input class="' . $field_class . '" style="' . $field_style . '" id="' . $field_id . '" name="' . $field_name . '"' .
80
+ ' type="' . $field_type . '" value="' . $field_value . '">';
81
+ }
82
+ $html .= $field_desc;
83
+ }
84
+ echo '<p>' . $html . '</p>';
85
+ }
86
+
87
+ /**
88
+ * Processing widget options on save.
89
+ *
90
+ * @version 3.1.0
91
+ * @since 3.1.0
92
+ * @param array $new_instance The new options
93
+ * @param array $old_instance The previous options
94
+ */
95
+ function update( $new_instance, $old_instance ) {
96
+ $instance = array();
97
+ foreach ( $this->get_options() as $option ) {
98
+ $instance[ $option['id'] ] = ( ! empty( $new_instance[ $option['id'] ] ) ? /* strip_tags */( $new_instance[ $option['id'] ] ) : $option['default'] );
99
+ }
100
+ return $instance;
101
+ }
102
+ }
103
+
104
+ endif;
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: algoritmika,anbinder
3
  Tags: woocommerce,booster for woocommerce,woocommerce jetpack
4
  Requires at least: 4.4
5
  Tested up to: 4.8
6
- Stable tag: 3.0.1
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -167,6 +167,80 @@ You can see the differences between versions in this [table](https://booster.io/
167
 
168
  == Changelog ==
169
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
  = 3.0.1 - 03/08/2017 =
171
  * Dev - CART & CHECKOUT - Cart Customization - "Change Empty Cart Return to shop Button Link" option added.
172
  * Dev - PAYMENT GATEWAYS - Custom Gateways - `required` attribute added to `[wcj_input_field]` shortcode.
3
  Tags: woocommerce,booster for woocommerce,woocommerce jetpack
4
  Requires at least: 4.4
5
  Tested up to: 4.8
6
+ Stable tag: 3.1.0
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
167
 
168
  == Changelog ==
169
 
170
+ = 3.1.0 - 11/09/2017 =
171
+ * Dev - Shortcodes - `visibility` attribute - `wrong_user_text` attribute set to empty string by default now; `wrong_user_text_not_logged_in` attribute added (defaults to empty string).
172
+ * Dev - Shortcodes - `location` and `not_location` attributes - `wcj_get_user_location()` - Code refactoring.
173
+ * Dev - Shortcodes - General - `[wcj_wholesale_price_table]` - `columns_style` attribute added.
174
+ * Dev - Shortcodes - General - `[wcj_selector]` - shortcode added.
175
+ * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - WooCommerce v3.x.x compatibility - `unserialize()` replaced with `maybe_unserialize()` for "WooCommerce TM Extra Product Options" plugin data.
176
+ * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - `columns` - `product_categories` column added.
177
+ * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - `columns` - `item_quantity_refunded` and `item_quantity_excl_refunded` columns added.
178
+ * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - `columns` - `item_total_refunded` column added.
179
+ * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - `refunded_items_table` attribute added.
180
+ * Dev - Shortcodes - Orders - `[wcj_order_items_table]` - Returning empty string if no items found.
181
+ * Dev - Shortcodes - Orders - `[wcj_order_refunds_table]` shortcode added.
182
+ * Dev - Shortcodes - Orders - `[wcj_order_total_shipping_refunded]` shortcode added.
183
+ * Dev - Shortcodes - Orders - `[wcj_order_total_tax_refunded]` shortcode added.
184
+ * Dev - Shortcodes - Orders - `[wcj_order_subtotal_to_display]` shortcode added.
185
+ * Dev - Shortcodes - Orders - `[wcj_order_total_formatted]` shortcode added.
186
+ * Dev - Shortcodes - Orders - `[wcj_order_remaining_refund_amount]` shortcode added.
187
+ * Dev - Shortcodes - Products - `[wcj_product_wholesale_price_table]` - `columns_style` attribute added.
188
+ * Dev - Widgets - Code refactoring (now as `WCJ_Widget` child classes).
189
+ * Dev - Widgets - "Booster - Selector" widget added.
190
+ * Dev - PRICES & CURRENCIES - Global Discount - "Exclude Product Categories" and "Include/Exclude Product Tags/Products" options added.
191
+ * Dev - PRICES & CURRENCIES - Global Discount - Code refactoring, clean up and fixes.
192
+ * Dev - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - Added "WooCommerce Product Add-ons" plugin compatibility.
193
+ * Dev - PRICES & CURRENCIES - Multicurrency Product Base Price - "Advanced: Saved Calculated Products Prices" option added.
194
+ * Dev - PRICES & CURRENCIES - Multicurrency Product Base Price - "Round Prices" options added.
195
+ * Dev - PRICES & CURRENCIES - Wholesale Price - Minimum quantity for applied discount changed from 1 to 0.
196
+ * Dev - PRODUCTS - Product Add to Cart - Variable Radio Buttons - Formatting options added.
197
+ * Dev - PRODUCTS - Product Info - Advanced - "Extra Filters" option added.
198
+ * Dev - PRODUCTS - Product Input Fields - Frontend View Options - "Position on Single Product Page" options added.
199
+ * Dev - PRODUCTS - Product Input Fields - Fields Options - "Order" option added.
200
+ * Dev - PRODUCTS - Product Input Fields - Additional check for `is_string( $value )` added.
201
+ * Dev - PRODUCTS - Product Input Fields - Values refilled after add to cart.
202
+ * Dev - PRODUCTS - Product Input Fields - All Products - "Categories/Tags/Products to include/exclude" options added.
203
+ * Dev - PRODUCTS - Product Input Fields - Settings restyled.
204
+ * Dev - PRODUCTS - Product Input Fields - Code refactoring and cleanup.
205
+ * Dev - PRODUCTS - Product Tabs - "Key" option added.
206
+ * Dev - PRODUCTS - Product Tabs - Code refactoring, cleanup and minor fixes.
207
+ * Dev - PRODUCTS - Product Tabs - Deprecated options not displayed (if empty).
208
+ * Dev - PRODUCTS - Product Tabs - `do_shortcode` added when checking for empty content (before displaying the tab).
209
+ * Fix - PRODUCTS - Product Visibility by Country / by User Role - Getting `post__not_in` from query (instead of starting with empty array).
210
+ * Fix - PRODUCTS - Product Visibility by Country - "European Union" selection fixed.
211
+ * Dev - PRODUCTS - Product Visibility by Country - "User Country Selection Method" option added.
212
+ * Dev - PRODUCTS - Product Visibility by Country - Code refactoring.
213
+ * Dev - PRODUCTS - Product Visibility by Country - Settings restyled and descriptions added.
214
+ * Dev - PRODUCTS - Product Visibility by User Role - Descriptions added.
215
+ * Dev - CART & CHECKOUT - Cart Customization - Change Empty Cart "Return to shop" Button Text - "Method" option added.
216
+ * Dev - CART & CHECKOUT - Checkout Core Fields - "Override Default Address Fields" and "Override Country Locale Fields" options added.
217
+ * Dev - CART & CHECKOUT - Checkout Core Fields - "Account Username", "Account Password-2" fields added.
218
+ * Dev - CART & CHECKOUT - Checkout Customization - "Customize order received message" options added.
219
+ * Dev - PAYMENT GATEWAYS - Gateways per Product or Category - "Use List Instead of Comma Separated Text for Products in Settings" support added.
220
+ * Dev - SHIPPING & ORDERS - Left to Free Shipping - Settings restyled.
221
+ * Dev - SHIPPING & ORDERS - Order Numbers - Code refactoring and clean up.
222
+ * Dev - SHIPPING & ORDERS - Order Numbers - Skipping order number generation for `auto-draft` orders.
223
+ * Dev - SHIPPING & ORDERS - Order Numbers - Order Tracking - Removed sanitizing order id (was added in WC v3.1.0).
224
+ * Dev - SHIPPING & ORDERS - Order Numbers - Order Tracking - `WP_Query` optimized to return `ids` only.
225
+ * Dev - SHIPPING & ORDERS - Order Numbers - Orders Renumerate - `WP_Query` optimized to return `ids` only.
226
+ * Dev - PDF INVOICING & PACKING SLIPS - Checking for `ZipArchive` to exist before generating ZIPs.
227
+ * Dev - PDF INVOICING & PACKING SLIPS - Default values added to `get_option()` calls.
228
+ * Dev - PDF INVOICING & PACKING SLIPS - Display & Misc. - "Admin Title" option added.
229
+ * Dev - PDF INVOICING & PACKING SLIPS - General - "Create on Order Partially Refunded" and "Create on Order Status Refunded and/or Order Partially Refunded" added.
230
+ * Dev - PDF INVOICING & PACKING SLIPS - Email Options - "Customer - Partially Refunded Order" email added.
231
+ * Dev - PDF INVOICING & PACKING SLIPS - Invoices Report Tool - Code refactoring, clean up, minor changes. Tool settings restyled.
232
+ * Dev - PDF INVOICING & PACKING SLIPS - Invoices Report Tool - "Reports Filename", "CSV Separator", "CSV UTF-8 BOM", "Replace Periods with Commas in CSV Data" options added.
233
+ * Dev - PDF INVOICING & PACKING SLIPS - Code factoring, clean up and minor fixes. Settings restyled.
234
+ * Dev - EMAILS & MISC. - Admin Bar - "Booster: Active" admin bar added.
235
+ * Dev - EMAILS & MISC. - Custom Emails - "Wrap in WC Email Template" option added.
236
+ * Dev - EMAILS & MISC. - Custom Emails - Code refactoring, clean up etc. Settings page restyled.
237
+ * Dev - EMAILS & MISC. - Custom Emails - WooCommerce v3.x.x compatibility - `billing_email`, `order_date`, `post`.
238
+ * Dev - EMAILS & MISC. - Email Verification - Settings restyled.
239
+ * Dev - EMAILS & MISC. - Email Verification - "Verified" column added to admin users list.
240
+ * Dev - EMAILS & MISC. - Email Verification - "Verification Email Template" options added.
241
+ * Dev - EMAILS & MISC. - Email Verification - `serialize()` and `unserialize()` replaced with `json_encode()` and `json_decode()`.
242
+ * Dev - EMAILS & MISC. - General - "Session Type in Booster" option added.
243
+
244
  = 3.0.1 - 03/08/2017 =
245
  * Dev - CART & CHECKOUT - Cart Customization - "Change Empty Cart Return to shop Button Link" option added.
246
  * Dev - PAYMENT GATEWAYS - Custom Gateways - `required` attribute added to `[wcj_input_field]` shortcode.
woocommerce-jetpack.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: https://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
- Version: 3.0.1
7
  Author: Algoritmika Ltd
8
  Author URI: https://booster.io
9
  Text Domain: woocommerce-jetpack
@@ -64,7 +64,7 @@ require_once( 'includes/constants/wcj-constants.php' );
64
  * Main WC_Jetpack Class
65
  *
66
  * @class WC_Jetpack
67
- * @version 3.0.0
68
  */
69
  final class WC_Jetpack {
70
 
@@ -74,7 +74,7 @@ final class WC_Jetpack {
74
  * @var string
75
  * @since 2.4.7
76
  */
77
- public $version = '3.0.1';
78
 
79
  /**
80
  * @var WC_Jetpack The single instance of the class
@@ -241,7 +241,7 @@ final class WC_Jetpack {
241
  /**
242
  * Include required core files used in admin and on the frontend.
243
  *
244
- * @version 3.0.0
245
  */
246
  function includes() {
247
 
@@ -266,9 +266,11 @@ final class WC_Jetpack {
266
  $this->include_shortcodes();
267
 
268
  // Widgets
 
269
  include_once( 'includes/widgets/class-wcj-widget-multicurrency.php' );
270
  include_once( 'includes/widgets/class-wcj-widget-country-switcher.php' );
271
  include_once( 'includes/widgets/class-wcj-widget-left-to-free-shipping.php' );
 
272
 
273
  // Modules and Submodules
274
  $this->include_modules();
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: https://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
+ Version: 3.1.0
7
  Author: Algoritmika Ltd
8
  Author URI: https://booster.io
9
  Text Domain: woocommerce-jetpack
64
  * Main WC_Jetpack Class
65
  *
66
  * @class WC_Jetpack
67
+ * @version 3.1.0
68
  */
69
  final class WC_Jetpack {
70
 
74
  * @var string
75
  * @since 2.4.7
76
  */
77
+ public $version = '3.1.0';
78
 
79
  /**
80
  * @var WC_Jetpack The single instance of the class
241
  /**
242
  * Include required core files used in admin and on the frontend.
243
  *
244
+ * @version 3.1.0
245
  */
246
  function includes() {
247
 
266
  $this->include_shortcodes();
267
 
268
  // Widgets
269
+ include_once( 'includes/widgets/class-wcj-widget.php' );
270
  include_once( 'includes/widgets/class-wcj-widget-multicurrency.php' );
271
  include_once( 'includes/widgets/class-wcj-widget-country-switcher.php' );
272
  include_once( 'includes/widgets/class-wcj-widget-left-to-free-shipping.php' );
273
+ include_once( 'includes/widgets/class-wcj-widget-selector.php' );
274
 
275
  // Modules and Submodules
276
  $this->include_modules();