Booster for WooCommerce - Version 2.5.3

Version Description

  • 04/07/2016 =
  • Dev - Shortcodes - Orders - [wcj_order_total_refunded] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_taxes_html] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_items_meta] shortcode added.
  • Dev - PRICES & CURRENCIES - Currency Exchange Rates - "Logging" option removed.
  • Fix - PRICES & CURRENCIES - Prices and Currencies by Country - Price Filter widget fixed. add_hooks() function moved from init hook to constructor.
  • Dev - PRICES & CURRENCIES - Price by User Role - Class functions replaced with global functions.
  • Dev - PRODUCTS - Bookings - "Hide Quantity Selector" option added.
  • Dev - PRODUCTS - Product Add to Cart - "Open External Products on Add to Cart in New Window" option added.
  • Dev - PRODUCTS - Product Addons - Initial module release.
  • Fix - PRODUCTS - Product by User - Settings moved to init hook. This caused "wp-admin show white screen and no errors" on some servers (or "Fatal error: Call to undefined function wp_get_current_user() in ..." message if debug enabled).
  • Dev - PRODUCTS - Product by User - Class functions replaced with global functions.
  • Dev - PRODUCTS - Product Listings - "Products per Page" options added.
  • Fix - PRODUCTS - Product Input Fields - output_custom_input_fields_in_admin_order() for shipping bug fixed.
  • Dev - PRODUCTS - SKU - "Allow Duplicate SKUs" option added.
  • Dev - PAYMENT GATEWAYS - Gateways by User Role - Initial module release.
  • Dev - SHIPPING & ORDERS - Orders - "Custom Columns" options added.
  • Dev - SHIPPING & ORDERS - Orders - Settings moved to init hook.
  • Dev - SHIPPING & ORDERS - Orders - Order Minimum Amount - "By user role" options added. All order minimum amount hooks moved to init action.
  • Fix - SHIPPING & ORDERS - Shipping - Hide if free is available - Fixed to work with WooCommerce since version 2.6.0. "Hide local delivery when free is available" option removed.
  • Fix - SHIPPING & ORDERS - Shipping - Left to Free Shipping - Fixed to work with WooCommerce since version 2.6.0.
  • Dev - PDF INVOICING & PACKING SLIPS - Invoices Report - Added "Refunds" column to the table.
  • Dev - EMAILS & MISC. - Emails - Custom Emails - do_shortcode added to custom email recipient.
  • Dev - EMAILS & MISC. - General - "Export Products" tool added.
  • Dev - EMAILS & MISC. - General - "Add/Manage Custom Roles" tool moved from "Price by User Role" module.
  • Dev - EMAILS & MISC. - Reports - Monthly Sales - Major code refactoring. New data added.
  • Tweak - Rating message added.
  • Tweak - Module's documentation button on new line.
  • Tweak - Depreciated module message updated.
  • Tweak - PRODUCTS - Product Add to Cart - Module description updated.
  • Tweak - PRODUCTS - Product by User - Module and admin settings descriptions updated.
  • Tweak - PRODUCTS - Product Info - Moved to EMAILS & MISC. Renamed to "Product Info V1". "Product Info V2" renamed to "Product Info".
Download this release

Release Info

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

Code changes from version 2.5.2 to 2.5.3

Files changed (35) hide show
  1. assets/images/5-rockets.png +0 -0
  2. assets/images/rocket-icon.png +0 -0
  3. includes/admin/class-wc-settings-jetpack.php +6 -6
  4. includes/admin/wcj-modules-cats.php +4 -2
  5. includes/class-wcj-add-to-cart.php +57 -58
  6. includes/class-wcj-currency-exchange-rates.php +4 -4
  7. includes/class-wcj-general.php +144 -12
  8. includes/class-wcj-orders.php +208 -34
  9. includes/class-wcj-payment-gateways-by-user-role.php +149 -0
  10. includes/class-wcj-price-by-country.php +56 -3
  11. includes/class-wcj-price-by-user-role.php +13 -105
  12. includes/class-wcj-product-add-to-cart.php +85 -5
  13. includes/class-wcj-product-addons.php +472 -0
  14. includes/class-wcj-product-bookings.php +23 -5
  15. includes/class-wcj-product-by-user.php +27 -24
  16. includes/class-wcj-product-custom-info.php +3 -3
  17. includes/class-wcj-product-info.php +3 -3
  18. includes/class-wcj-product-listings.php +146 -6
  19. includes/class-wcj-reports.php +3 -3
  20. includes/class-wcj-shipping.php +31 -28
  21. includes/class-wcj-sku.php +26 -3
  22. includes/classes/class-wcj-module.php +60 -4
  23. includes/css/wcj-admin.css +10 -0
  24. includes/emails/class-wc-email-wcj-custom.php +23 -12
  25. includes/exchange-rates/class-wcj-exchange-rates-crons.php +10 -4
  26. includes/functions/wcj-functions.php +305 -14
  27. includes/input-fields/class-wcj-product-input-fields-abstract.php +6 -2
  28. includes/js/wcj-product-addons.js +61 -0
  29. includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php +4 -2
  30. includes/price-by-country/class-wcj-price-by-country-core.php +45 -101
  31. includes/reports/wcj-class-reports-monthly-sales.php +187 -87
  32. includes/shipping/class-wc-shipping-wcj-custom.php +3 -3
  33. includes/shortcodes/class-wcj-orders-shortcodes.php +57 -2
  34. readme.txt +41 -6
  35. woocommerce-jetpack.php +34 -11
assets/images/5-rockets.png ADDED
Binary file
assets/images/rocket-icon.png ADDED
Binary file
includes/admin/class-wc-settings-jetpack.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Settings class.
6
  *
7
- * @version 2.5.2
8
  * @since 1.0.0
9
  * @author Algoritmika Ltd.
10
  */
@@ -254,7 +254,7 @@ class WC_Settings_Jetpack extends WC_Settings_Page {
254
  /**
255
  * Output the settings.
256
  *
257
- * @version 2.5.2
258
  */
259
  function output() {
260
 
@@ -268,14 +268,14 @@ class WC_Settings_Jetpack extends WC_Settings_Page {
268
  ? false : true;
269
 
270
  // Depreciated message
271
- $depreciated_modules = array(
272
- 'product_info' => 'Product Info V2',
273
  );
274
- if ( array_key_exists( $current_section, $depreciated_modules ) ) {
275
  echo '<div id="wcj_message" class="error">';
276
  echo '<p>';
277
  echo '<strong>';
278
- echo sprintf( __( 'Please note that current module is depreciated and will be removed in future updates. Please use <em>%s</em> module instead.', 'woocommerce-jetpack' ), $depreciated_modules[ $current_section ] );
279
  echo '</strong>';
280
  echo '</p>';
281
  echo '</div>';
4
  *
5
  * The WooCommerce Jetpack Settings class.
6
  *
7
+ * @version 2.5.3
8
  * @since 1.0.0
9
  * @author Algoritmika Ltd.
10
  */
254
  /**
255
  * Output the settings.
256
  *
257
+ * @version 2.5.3
258
  */
259
  function output() {
260
 
268
  ? false : true;
269
 
270
  // Depreciated message
271
+ $depreciated_modules_and_links = array(
272
+ 'product_info' => '<a href="' . admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=products&section=product_custom_info' ) . '">' . __( 'Product Info', 'woocommerce-jetpack' ) . '</a>',
273
  );
274
+ if ( array_key_exists( $current_section, $depreciated_modules_and_links ) ) {
275
  echo '<div id="wcj_message" class="error">';
276
  echo '<p>';
277
  echo '<strong>';
278
+ echo sprintf( __( 'Please note that current <em>%s</em> module is depreciated and will be removed in future updates. Please use <em>%s</em> module instead.', 'woocommerce-jetpack' ), WCJ()->modules[ $current_section ]->short_desc, $depreciated_modules_and_links[ $current_section ] );
279
  echo '</strong>';
280
  echo '</p>';
281
  echo '</div>';
includes/admin/wcj-modules-cats.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Modules Array.
6
  *
7
- * @version 2.5.2
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
@@ -60,7 +60,6 @@ return array(
60
  'product_listings',
61
  'product_tabs',
62
  'product_custom_info',
63
- 'product_info',
64
  'related_products',
65
  'sorting',
66
  'sku',
@@ -69,6 +68,7 @@ return array(
69
  'purchase_data',
70
  'product_bookings',
71
  'crowdfunding',
 
72
  'product_images',
73
  'product_by_country',
74
  'product_by_user',
@@ -100,6 +100,7 @@ return array(
100
  'payment_gateways_currency',
101
  'payment_gateways_min_max',
102
  'payment_gateways_by_country',
 
103
  ),
104
  ),
105
 
@@ -145,6 +146,7 @@ return array(
145
  'emails',
146
  'wpml',
147
  // 'pdf_invoices',
 
148
  ),
149
  ),
150
 
4
  *
5
  * The WooCommerce Modules Array.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
60
  'product_listings',
61
  'product_tabs',
62
  'product_custom_info',
 
63
  'related_products',
64
  'sorting',
65
  'sku',
68
  'purchase_data',
69
  'product_bookings',
70
  'crowdfunding',
71
+ 'product_addons',
72
  'product_images',
73
  'product_by_country',
74
  'product_by_user',
100
  'payment_gateways_currency',
101
  'payment_gateways_min_max',
102
  'payment_gateways_by_country',
103
+ 'payment_gateways_by_user_role',
104
  ),
105
  ),
106
 
146
  'emails',
147
  'wpml',
148
  // 'pdf_invoices',
149
+ 'product_info',
150
  ),
151
  ),
152
 
includes/class-wcj-add-to-cart.php CHANGED
@@ -44,39 +44,39 @@ class WCJ_Add_To_Cart extends WCJ_Module {
44
  $settings[] = array( 'title' => __( 'Per Product Type Options', 'woocommerce-jetpack' ), 'type' => 'title', 'desc' => 'This sections lets you set text for add to cart button for various products types and various conditions.', 'id' => 'wcj_add_to_cart_text_options' );
45
 
46
  $settings[] = array(
47
- 'title' => __( 'Per Product Labels', 'woocommerce-jetpack' ),
48
- 'desc' => __( 'Enable Section', 'woocommerce-jetpack' ),
49
- 'id' => 'wcj_add_to_cart_text_enabled',
50
- 'default' => 'no',
51
- 'type' => 'checkbox',
52
  );
53
 
54
  $groups_by_product_type = array(
55
 
56
  array(
57
- 'id' => 'simple',
58
- 'title' => __( 'Simple product', 'woocommerce-jetpack' ),
59
- 'default' => 'Add to cart',
60
  ),
61
  array(
62
- 'id' => 'variable',
63
- 'title' => __( 'Variable product', 'woocommerce-jetpack' ),
64
- 'default' => 'Select options',
65
  ),
66
  array(
67
- 'id' => 'external',
68
- 'title' => __( 'External product', 'woocommerce-jetpack' ),
69
- 'default' => 'Buy product',
70
  ),
71
  array(
72
- 'id' => 'grouped',
73
- 'title' => __( 'Grouped product', 'woocommerce-jetpack' ),
74
- 'default' => 'View products',
75
  ),
76
  array(
77
- 'id' => 'other',
78
- 'title' => __( 'Other product', 'woocommerce-jetpack' ),
79
- 'default' => 'Read more',
80
  ),
81
  );
82
 
@@ -223,15 +223,14 @@ class WCJ_Add_To_Cart extends WCJ_Module {
223
  'default' => 1,
224
  'type' => 'custom_number',
225
  'desc' => apply_filters( 'get_wc_jetpack_plus_message', '', 'desc' ),
226
- 'custom_attributes'
227
- => array_merge(
228
- is_array( apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' ) ) ? apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' ) : array(),
229
- array(
230
- 'step' => '1',
231
- 'min' => '1',
232
- )
233
- ),
234
- 'css' => 'width:100px;',
235
  ),
236
  );
237
 
@@ -255,47 +254,47 @@ class WCJ_Add_To_Cart extends WCJ_Module {
255
 
256
  $settings = array_merge( $settings, array(
257
  array(
258
- 'title' => __( 'Group', 'woocommerce-jetpack' ) . ' #' . $i,
259
- 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
260
- 'id' => 'wcj_add_to_cart_per_category_enabled_group_' . $i,
261
- 'default' => 'yes',
262
- 'type' => 'checkbox',
263
  ),
264
  /* array(
265
- 'title' => '',
266
- 'desc' => __( 'Product Category IDs List', 'woocommerce-jetpack' ),
267
- 'desc_tip' => __( 'Comma separated list of product category IDs.', 'woocommerce-jetpack' ),
268
- 'id' => 'wcj_add_to_cart_per_category_group_' . $i,
269
- 'default' => '',
270
- 'type' => 'text',
271
- 'css' => 'width:30%;min-width:300px;',
272
  ), */
273
  array(
274
- 'title' => '',
275
- 'desc' => __( 'categories', 'woocommerce-jetpack' ),
276
  'desc_tip' => __( '', 'woocommerce-jetpack' ),
277
- 'id' => 'wcj_add_to_cart_per_category_ids_group_' . $i,
278
- 'default' => '',
279
- 'type' => 'multiselect',
280
  'class' => 'chosen_select',
281
  'css' => 'width: 450px;',
282
  'options' => $product_cats,
283
  ),
284
  array(
285
- 'title' => '',
286
- 'desc' => __( 'Button text - single product view', 'woocommerce-jetpack' ),
287
- 'id' => 'wcj_add_to_cart_per_category_text_single_group_' . $i,
288
- 'default' => '',
289
- 'type' => 'textarea',
290
- 'css' => 'width:20%;min-width:200px;',
291
  ),
292
  array(
293
- 'title' => '',
294
- 'desc' => __( 'Button text - product archive (category) view', 'woocommerce-jetpack' ),
295
- 'id' => 'wcj_add_to_cart_per_category_text_archive_group_' . $i,
296
- 'default' => '',
297
- 'type' => 'textarea',
298
- 'css' => 'width:20%;min-width:200px;',
299
  ),
300
  ) );
301
  }
44
  $settings[] = array( 'title' => __( 'Per Product Type Options', 'woocommerce-jetpack' ), 'type' => 'title', 'desc' => 'This sections lets you set text for add to cart button for various products types and various conditions.', 'id' => 'wcj_add_to_cart_text_options' );
45
 
46
  $settings[] = array(
47
+ 'title' => __( 'Per Product Labels', 'woocommerce-jetpack' ),
48
+ 'desc' => __( 'Enable Section', 'woocommerce-jetpack' ),
49
+ 'id' => 'wcj_add_to_cart_text_enabled',
50
+ 'default' => 'no',
51
+ 'type' => 'checkbox',
52
  );
53
 
54
  $groups_by_product_type = array(
55
 
56
  array(
57
+ 'id' => 'simple',
58
+ 'title' => __( 'Simple product', 'woocommerce-jetpack' ),
59
+ 'default' => 'Add to cart',
60
  ),
61
  array(
62
+ 'id' => 'variable',
63
+ 'title' => __( 'Variable product', 'woocommerce-jetpack' ),
64
+ 'default' => 'Select options',
65
  ),
66
  array(
67
+ 'id' => 'external',
68
+ 'title' => __( 'External product', 'woocommerce-jetpack' ),
69
+ 'default' => 'Buy product',
70
  ),
71
  array(
72
+ 'id' => 'grouped',
73
+ 'title' => __( 'Grouped product', 'woocommerce-jetpack' ),
74
+ 'default' => 'View products',
75
  ),
76
  array(
77
+ 'id' => 'other',
78
+ 'title' => __( 'Other product', 'woocommerce-jetpack' ),
79
+ 'default' => 'Read more',
80
  ),
81
  );
82
 
223
  'default' => 1,
224
  'type' => 'custom_number',
225
  'desc' => apply_filters( 'get_wc_jetpack_plus_message', '', 'desc' ),
226
+ 'custom_attributes' => array_merge(
227
+ is_array( apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' ) ) ? apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' ) : array(),
228
+ array(
229
+ 'step' => '1',
230
+ 'min' => '1',
231
+ )
232
+ ),
233
+ 'css' => 'width:100px;',
 
234
  ),
235
  );
236
 
254
 
255
  $settings = array_merge( $settings, array(
256
  array(
257
+ 'title' => __( 'Group', 'woocommerce-jetpack' ) . ' #' . $i,
258
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
259
+ 'id' => 'wcj_add_to_cart_per_category_enabled_group_' . $i,
260
+ 'default' => 'yes',
261
+ 'type' => 'checkbox',
262
  ),
263
  /* array(
264
+ 'title' => '',
265
+ 'desc' => __( 'Product Category IDs List', 'woocommerce-jetpack' ),
266
+ 'desc_tip' => __( 'Comma separated list of product category IDs.', 'woocommerce-jetpack' ),
267
+ 'id' => 'wcj_add_to_cart_per_category_group_' . $i,
268
+ 'default' => '',
269
+ 'type' => 'text',
270
+ 'css' => 'width:30%;min-width:300px;',
271
  ), */
272
  array(
273
+ 'title' => '',
274
+ 'desc' => __( 'categories', 'woocommerce-jetpack' ),
275
  'desc_tip' => __( '', 'woocommerce-jetpack' ),
276
+ 'id' => 'wcj_add_to_cart_per_category_ids_group_' . $i,
277
+ 'default' => '',
278
+ 'type' => 'multiselect',
279
  'class' => 'chosen_select',
280
  'css' => 'width: 450px;',
281
  'options' => $product_cats,
282
  ),
283
  array(
284
+ 'title' => '',
285
+ 'desc' => __( 'Button text - single product view', 'woocommerce-jetpack' ),
286
+ 'id' => 'wcj_add_to_cart_per_category_text_single_group_' . $i,
287
+ 'default' => '',
288
+ 'type' => 'textarea',
289
+ 'css' => 'width:20%;min-width:200px;',
290
  ),
291
  array(
292
+ 'title' => '',
293
+ 'desc' => __( 'Button text - product archive (category) view', 'woocommerce-jetpack' ),
294
+ 'id' => 'wcj_add_to_cart_per_category_text_archive_group_' . $i,
295
+ 'default' => '',
296
+ 'type' => 'textarea',
297
+ 'css' => 'width:20%;min-width:200px;',
298
  ),
299
  ) );
300
  }
includes/class-wcj-currency-exchange-rates.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Currency Exchange Rates class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.3.0
9
  * @author Algoritmika Ltd.
10
  */
@@ -86,7 +86,7 @@ class WCJ_Currency_Exchange_Rates extends WCJ_Module {
86
  /**
87
  * add_currency_exchange_rates_settings.
88
  *
89
- * @version 2.5.2
90
  */
91
  function add_currency_exchange_rates_settings() {
92
 
@@ -160,13 +160,13 @@ class WCJ_Currency_Exchange_Rates extends WCJ_Module {
160
  }
161
  }
162
 
163
- $settings[] = array(
164
  'title' => __( 'Logging', 'woocommerce-jetpack' ),
165
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
166
  'id' => 'wcj_currency_exchange_logging_enabled',
167
  'default' => 'no',
168
  'type' => 'checkbox',
169
- );
170
 
171
  $settings[] = array(
172
  'type' => 'sectionend',
4
  *
5
  * The WooCommerce Jetpack Currency Exchange Rates class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.3.0
9
  * @author Algoritmika Ltd.
10
  */
86
  /**
87
  * add_currency_exchange_rates_settings.
88
  *
89
+ * @version 2.5.3
90
  */
91
  function add_currency_exchange_rates_settings() {
92
 
160
  }
161
  }
162
 
163
+ /* $settings[] = array(
164
  'title' => __( 'Logging', 'woocommerce-jetpack' ),
165
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
166
  'id' => 'wcj_currency_exchange_logging_enabled',
167
  'default' => 'no',
168
  'type' => 'checkbox',
169
+ ); */
170
 
171
  $settings[] = array(
172
  'type' => 'sectionend',
includes/class-wcj-general.php CHANGED
@@ -4,8 +4,9 @@
4
  *
5
  * The WooCommerce Jetpack General class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
 
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
@@ -17,32 +18,41 @@ class WCJ_General extends WCJ_Module {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.5.2
21
  */
22
  public function __construct() {
23
 
24
  $this->id = 'general';
25
  $this->short_desc = __( 'General', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Separate custom CSS for front and back end. Shortcodes in Wordpress text widgets.', 'woocommerce-jetpack' );
27
  $this->link = 'http://booster.io/features/woocommerce-booster-general-tools/';
28
  parent::__construct();
29
 
30
  $this->add_tools( array(
31
  'products_atts' => array(
32
- 'title' => __( 'Products Atts', 'woocommerce-jetpack' ),
33
- 'desc' => __( 'All Products and All Attributes.', 'woocommerce-jetpack' ),
34
  ),
35
  'export_customers' => array(
36
- 'title' => __( 'Export Customers', 'woocommerce-jetpack' ),
37
- 'desc' => __( 'Export Customers.', 'woocommerce-jetpack' ),
38
  ),
39
  'export_customers_from_orders' => array(
40
- 'title' => __( 'Export Customers from Orders', 'woocommerce-jetpack' ),
41
- 'desc' => __( 'Export Customers (extracted from orders).', 'woocommerce-jetpack' ),
42
  ),
43
  'export_orders' => array(
44
- 'title' => __( 'Export Orders', 'woocommerce-jetpack' ),
45
- 'desc' => __( 'Export Orders.', 'woocommerce-jetpack' ),
 
 
 
 
 
 
 
 
 
46
  ),
47
  ) );
48
 
@@ -75,6 +85,63 @@ class WCJ_General extends WCJ_Module {
75
  }
76
  }
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  /**
79
  * get_meta_box_options.
80
  *
@@ -131,7 +198,7 @@ class WCJ_General extends WCJ_Module {
131
  /**
132
  * export.
133
  *
134
- * @version 2.4.8
135
  * @since 2.4.8
136
  */
137
  function export( $tool_id ) {
@@ -146,6 +213,9 @@ class WCJ_General extends WCJ_Module {
146
  case 'orders':
147
  $data = $this->export_orders();
148
  break;
 
 
 
149
  }
150
  return $data;
151
  }
@@ -207,6 +277,16 @@ class WCJ_General extends WCJ_Module {
207
  $this->create_export_tool( 'orders' );
208
  }
209
 
 
 
 
 
 
 
 
 
 
 
210
  /**
211
  * create_export_customers_from_orders_tool.
212
  *
@@ -276,6 +356,58 @@ class WCJ_General extends WCJ_Module {
276
  return $data;
277
  }
278
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
279
  /**
280
  * export_customers_from_orders.
281
  *
4
  *
5
  * The WooCommerce Jetpack General class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
+ * @todo import products tool;
10
  */
11
 
12
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 2.5.3
22
  */
23
  public function __construct() {
24
 
25
  $this->id = 'general';
26
  $this->short_desc = __( 'General', 'woocommerce-jetpack' );
27
+ $this->desc = __( 'Separate custom CSS for front and back end. Shortcodes in Wordpress text widgets. Export tools. Custom roles tool.', 'woocommerce-jetpack' );
28
  $this->link = 'http://booster.io/features/woocommerce-booster-general-tools/';
29
  parent::__construct();
30
 
31
  $this->add_tools( array(
32
  'products_atts' => array(
33
+ 'title' => __( 'Products Atts', 'woocommerce-jetpack' ),
34
+ 'desc' => __( 'All Products and All Attributes.', 'woocommerce-jetpack' ),
35
  ),
36
  'export_customers' => array(
37
+ 'title' => __( 'Export Customers', 'woocommerce-jetpack' ),
38
+ 'desc' => __( 'Export Customers.', 'woocommerce-jetpack' ),
39
  ),
40
  'export_customers_from_orders' => array(
41
+ 'title' => __( 'Export Customers from Orders', 'woocommerce-jetpack' ),
42
+ 'desc' => __( 'Export Customers (extracted from orders).', 'woocommerce-jetpack' ),
43
  ),
44
  'export_orders' => array(
45
+ 'title' => __( 'Export Orders', 'woocommerce-jetpack' ),
46
+ 'desc' => __( 'Export Orders.', 'woocommerce-jetpack' ),
47
+ ),
48
+ 'export_products' => array(
49
+ 'title' => __( 'Export Products', 'woocommerce-jetpack' ),
50
+ 'desc' => __( 'Export Products.', 'woocommerce-jetpack' ),
51
+ ),
52
+ 'custom_roles' => array(
53
+ 'title' => __( 'Add/Manage Custom Roles', 'woocommerce-jetpack' ),
54
+ 'tab_title' => __( 'Custom Roles', 'woocommerce-jetpack' ),
55
+ 'desc' => __( 'Manage Custom Roles.', 'woocommerce-jetpack' ),
56
  ),
57
  ) );
58
 
85
  }
86
  }
87
 
88
+ /**
89
+ * create_custom_roles_tool.
90
+ *
91
+ * @version 2.5.3
92
+ * @since 2.5.3
93
+ */
94
+ function create_custom_roles_tool() {
95
+ if ( isset( $_POST['wcj_add_new_role'] ) ) {
96
+ if (
97
+ ! isset( $_POST['wcj_custom_role_id'] ) || '' == $_POST['wcj_custom_role_id'] ||
98
+ ! isset( $_POST['wcj_custom_role_name'] ) || '' == $_POST['wcj_custom_role_name']
99
+ ) {
100
+ echo '<p style="color:red;font-weight:bold;">' . __( 'Both fields are required!', 'woocommerce-jetpack') . '</p>';
101
+ } else {
102
+ if ( is_numeric( $_POST['wcj_custom_role_id'] ) ) {
103
+ echo '<p style="color:red;font-weight:bold;">' . __( 'Role ID must not be numbers only!', 'woocommerce-jetpack') . '</p>';
104
+ } else {
105
+ $result = add_role( $_POST['wcj_custom_role_id'], $_POST['wcj_custom_role_name'] );
106
+ if ( null !== $result ) {
107
+ echo '<p style="color:green;font-weight:bold;">' . __( 'Role successfully added!', 'woocommerce-jetpack') . '</p>';
108
+ } else {
109
+ echo '<p style="color:red;font-weight:bold;">' . __( 'Role already exists!', 'woocommerce-jetpack') . '</p>';
110
+ }
111
+ }
112
+ }
113
+ }
114
+
115
+ if ( isset( $_GET['wcj_delete_role'] ) && '' != $_GET['wcj_delete_role'] ) {
116
+ remove_role( $_GET['wcj_delete_role'] );
117
+ echo '<p style="color:green;font-weight:bold;">' . sprintf( __( 'Role %s successfully deleted!', 'woocommerce-jetpack'), $_GET['wcj_delete_role'] ) . '</p>';
118
+ }
119
+
120
+ echo $this->get_tool_header_html( 'custom_roles' );
121
+
122
+ $table_data = array();
123
+ $table_data[] = array( __( 'ID', 'woocommerce-jetpack'), __( 'Name', 'woocommerce-jetpack'), __( 'Actions', 'woocommerce-jetpack'), );
124
+ $existing_roles = wcj_get_user_roles();
125
+ $default_wp_wc_roles = array( 'guest', 'administrator', 'editor', 'author', 'contributor', 'subscriber', 'customer', 'shop_manager', );
126
+ foreach ( $existing_roles as $role_key => $role_data ) {
127
+ $delete_html = ( in_array( $role_key, $default_wp_wc_roles ) )
128
+ ? ''
129
+ : '<a href="' . add_query_arg( 'wcj_delete_role', $role_key ). '">' . __( 'Delete', 'woocommerce-jetpack') . '</a>';
130
+ $table_data[] = array( $role_key, $role_data['name'], $delete_html );
131
+ }
132
+ echo '<h3>' . __( 'Existing Roles', 'woocommerce-jetpack') . '</h3>';
133
+ echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) );
134
+
135
+ $table_data = array();
136
+ $table_data[] = array( __( 'ID', 'woocommerce-jetpack'), '<input type="text" name="wcj_custom_role_id">' );
137
+ $table_data[] = array( __( 'Name', 'woocommerce-jetpack'), '<input type="text" name="wcj_custom_role_name">' );
138
+ echo '<h3>' . __( 'Add New Role', 'woocommerce-jetpack') . '</h3>';
139
+ echo '<form method="post" action="' . remove_query_arg( 'wcj_delete_role' ) . '">' .
140
+ wcj_get_table_html( $table_data, array( 'table_class' => 'widefat', 'table_heading_type' => 'vertical', 'table_style' => 'width:20%;min-width:300px;', ) )
141
+ . '<p>' . '<input type="submit" name="wcj_add_new_role" class="button-primary" value="' . __( 'Add', 'woocommerce-jetpack' ) . '">' . '</p>'
142
+ . '</form>';
143
+ }
144
+
145
  /**
146
  * get_meta_box_options.
147
  *
198
  /**
199
  * export.
200
  *
201
+ * @version 2.5.3
202
  * @since 2.4.8
203
  */
204
  function export( $tool_id ) {
213
  case 'orders':
214
  $data = $this->export_orders();
215
  break;
216
+ case 'products':
217
+ $data = $this->export_products();
218
+ break;
219
  }
220
  return $data;
221
  }
277
  $this->create_export_tool( 'orders' );
278
  }
279
 
280
+ /**
281
+ * create_export_products_tool.
282
+ *
283
+ * @version 2.5.3
284
+ * @since 2.5.3
285
+ */
286
+ function create_export_products_tool() {
287
+ $this->create_export_tool( 'products' );
288
+ }
289
+
290
  /**
291
  * create_export_customers_from_orders_tool.
292
  *
356
  return $data;
357
  }
358
 
359
+ /**
360
+ * export_products.
361
+ *
362
+ * @version 2.5.3
363
+ * @since 2.5.3
364
+ */
365
+ function export_products() {
366
+ $data = array();
367
+ $data[] = array(
368
+ __( 'Product ID', 'woocommerce-jetpack' ),
369
+ __( 'Name', 'woocommerce-jetpack' ),
370
+ __( 'SKU', 'woocommerce-jetpack' ),
371
+ __( 'Stock', 'woocommerce-jetpack' ),
372
+ __( 'Regular Price', 'woocommerce-jetpack' ),
373
+ __( 'Sale Price', 'woocommerce-jetpack' ),
374
+ __( 'Price', 'woocommerce-jetpack' ),
375
+ __( 'Type', 'woocommerce-jetpack' ),
376
+ // __( 'Attributes', 'woocommerce-jetpack' ),
377
+ );
378
+ $offset = 0;
379
+ $block_size = 96;
380
+ while( true ) {
381
+ $args = array(
382
+ 'post_type' => 'product',
383
+ 'post_status' => 'any',
384
+ 'posts_per_page' => $block_size,
385
+ 'orderby' => 'date',
386
+ 'order' => 'DESC',
387
+ 'offset' => $offset,
388
+ );
389
+ $loop = new WP_Query( $args );
390
+ if ( ! $loop->have_posts() ) break;
391
+ while ( $loop->have_posts() ) : $loop->the_post();
392
+ $product_id = $loop->post->ID;
393
+ $_product = wc_get_product( $product_id );
394
+ $data[] = array(
395
+ $product_id,
396
+ $_product->get_title(),
397
+ $_product->get_sku(),
398
+ $_product->/* get_total_stock() */get_stock_quantity(),
399
+ $_product->get_regular_price(),
400
+ $_product->get_sale_price(),
401
+ ( $_product->is_type( 'variable' ) || $_product->is_type( 'grouped' ) ? '' : $_product->get_price() ),
402
+ $_product->get_type(),
403
+ // ( ! empty( $_product->get_attributes() ) ? serialize( $_product->get_attributes() ) : '' ),
404
+ );
405
+ endwhile;
406
+ $offset += $block_size;
407
+ }
408
+ return $data;
409
+ }
410
+
411
  /**
412
  * export_customers_from_orders.
413
  *
includes/class-wcj-orders.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Orders class.
6
  *
7
- * @version 2.5.0
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -17,35 +17,32 @@ class WCJ_Orders extends WCJ_Module {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.5.0
21
  */
22
  public function __construct() {
23
 
24
  $this->id = 'orders';
25
  $this->short_desc = __( 'Orders', 'woocommerce-jetpack' );
26
- $this->desc = __( 'Minimum WooCommerce order amount; orders auto-complete; custom admin order list columns.', 'woocommerce-jetpack' );
27
  $this->link = 'http://booster.io/features/woocommerce-orders/';
28
  parent::__construct();
29
 
 
 
30
  if ( $this->is_enabled() ) {
31
 
32
- if ( get_option( 'wcj_order_minimum_amount' ) > 0 ) {
33
- add_action( 'woocommerce_checkout_process', array( $this, 'order_minimum_amount' ) );
34
- add_action( 'woocommerce_before_cart', array( $this, 'order_minimum_amount' ) );
35
- if ( 'yes' === get_option( 'wcj_order_minimum_amount_stop_from_seeing_checkout' ) ) {
36
- add_action( 'wp', array( $this, 'stop_from_seeing_checkout' ), 100 );
37
- // add_action( 'template_redirect', array( $this, 'stop_from_seeing_checkout' ), 100 );
38
- }
39
- }
40
 
 
41
  if ( 'yes' === get_option( 'wcj_order_auto_complete_enabled' ) ) {
42
  add_action( 'woocommerce_thankyou', array( $this, 'auto_complete_order' ) );
43
  }
44
 
 
 
 
45
  if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
46
- // Country column
47
- add_filter( 'manage_edit-shop_order_columns', array( $this, 'add_order_column' ), PHP_INT_MAX );
48
- add_action( 'manage_shop_order_posts_custom_column', array( $this, 'render_order_columns' ), PHP_INT_MAX );
49
  // Country filtering
50
  add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );
51
  add_filter( 'parse_query', array( $this, 'orders_by_country_admin_filter_query' ) );
@@ -53,6 +50,34 @@ class WCJ_Orders extends WCJ_Module {
53
  }
54
  }
55
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
  /**
57
  * Filter the orders in admin based on options
58
  *
@@ -86,9 +111,19 @@ class WCJ_Orders extends WCJ_Module {
86
 
87
  /**
88
  * add_order_column.
 
 
89
  */
90
  function add_order_column( $columns ) {
91
- $columns['country'] = __( 'Country', 'woocommerce-jetpack' );
 
 
 
 
 
 
 
 
92
  return $columns;
93
  }
94
 
@@ -99,20 +134,30 @@ class WCJ_Orders extends WCJ_Module {
99
  $img_src = plugins_url() . '/' . 'woocommerce-jetpack' . '/assets/images/flag-icons/' . strtolower( $country_code ) . '.png';
100
  return '<img src="' . $img_src . '" title="' . wcj_get_country_name_by_code( $country_code ) . '">';
101
  }
 
102
  /**
103
  * Output custom columns for orders
104
- * @param string $column
 
 
105
  */
106
  public function render_order_columns( $column ) {
107
- if ( 'country' != $column ) {
108
- return;
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  }
110
- $order = wc_get_order( get_the_ID() );
111
- // $country_code = wcj_get_customer_country( $order->customer_user );
112
- $country_code = $order->billing_country;
113
- echo ( 2 == strlen( $country_code ) )
114
- ? $this->wcj_get_country_flag_by_code( $country_code ) . ' ' . wcj_get_country_name_by_code( $country_code )
115
- : wcj_get_country_name_by_code( $country_code );
116
  }
117
 
118
  /**
@@ -127,18 +172,45 @@ class WCJ_Orders extends WCJ_Module {
127
  $order->update_status( 'completed' );
128
  }
129
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  /**
131
  * order_minimum_amount.
 
 
132
  */
133
  public function order_minimum_amount() {
134
- $minimum = get_option( 'wcj_order_minimum_amount' );
135
- if ( WC()->cart->total < $minimum ) {
 
 
 
 
136
  if( is_cart() ) {
137
  if ( 'yes' === get_option( 'wcj_order_minimum_amount_cart_notice_enabled' ) ) {
138
  wc_print_notice(
139
  sprintf( apply_filters( 'wcj_get_option_filter', 'You must have an order with a minimum of %s to place your order, your current order total is %s.', get_option( 'wcj_order_minimum_amount_cart_notice_message' ) ),
140
  woocommerce_price( $minimum ),
141
- woocommerce_price( WC()->cart->total )
142
  ),
143
  'notice'
144
  );
@@ -147,7 +219,7 @@ class WCJ_Orders extends WCJ_Module {
147
  wc_add_notice(
148
  sprintf( apply_filters( 'wcj_get_option_filter', 'You must have an order with a minimum of %s to place your order, your current order total is %s.', get_option( 'wcj_order_minimum_amount_error_message' ) ),
149
  woocommerce_price( $minimum ),
150
- woocommerce_price( WC()->cart->total )
151
  ),
152
  'error'
153
  );
@@ -158,7 +230,8 @@ class WCJ_Orders extends WCJ_Module {
158
  /**
159
  * stop_from_seeing_checkout.
160
  *
161
- * @version 2.3.7
 
162
  */
163
  public function stop_from_seeing_checkout( $wp ) {
164
  // if ( is_admin() ) return;
@@ -169,18 +242,49 @@ class WCJ_Orders extends WCJ_Module {
169
  if ( ! isset( $woocommerce->cart ) || ! is_object( $woocommerce->cart ) ) {
170
  return;
171
  }
 
 
 
 
 
 
 
172
  $the_cart_total = isset( $woocommerce->cart->cart_contents_total ) ? $woocommerce->cart->cart_contents_total : 0;
173
- if ( 0 != $the_cart_total && $the_cart_total < get_option( 'wcj_order_minimum_amount' ) && is_checkout() ) {
 
 
 
174
  wp_safe_redirect( $woocommerce->cart->get_cart_url() );
175
  }
176
  }
177
 
178
  /**
179
- * Add settings arrays to Jetpack Settings.
 
 
 
 
 
 
 
 
 
 
180
  *
181
- * @version 2.5.0
182
  */
183
  function get_settings() {
 
 
 
 
 
 
 
 
 
 
 
184
  $settings = array(
185
  array(
186
  'title' => __( 'Order Minimum Amount', 'woocommerce-jetpack' ),
@@ -237,6 +341,36 @@ class WCJ_Orders extends WCJ_Module {
237
  'type' => 'sectionend',
238
  'id' => 'wcj_order_minimum_amount_options',
239
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
240
  array(
241
  'title' => __( 'Orders Auto-Complete', 'woocommerce-jetpack' ),
242
  'type' => 'title',
@@ -268,12 +402,52 @@ class WCJ_Orders extends WCJ_Module {
268
  'default' => 'no',
269
  'type' => 'checkbox',
270
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
271
  array(
272
  'type' => 'sectionend',
273
  'id' => 'wcj_orders_list_custom_columns_options',
274
  ),
275
- );
276
- return $this->add_standard_settings( $settings );
277
  }
278
  }
279
 
4
  *
5
  * The WooCommerce Jetpack Orders class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 2.5.3
21
  */
22
  public function __construct() {
23
 
24
  $this->id = 'orders';
25
  $this->short_desc = __( 'Orders', 'woocommerce-jetpack' );
26
+ $this->desc = __( 'Minimum WooCommerce order amount (optionally by user role); orders auto-complete; custom admin order list columns.', 'woocommerce-jetpack' );
27
  $this->link = 'http://booster.io/features/woocommerce-orders/';
28
  parent::__construct();
29
 
30
+ add_action( 'init', array( $this, 'add_settings_hook' ) );
31
+
32
  if ( $this->is_enabled() ) {
33
 
34
+ // Order minimum amount
35
+ add_action( 'init', array( $this, 'add_order_minimum_amount_hooks' ) );
 
 
 
 
 
 
36
 
37
+ // Order auto complete
38
  if ( 'yes' === get_option( 'wcj_order_auto_complete_enabled' ) ) {
39
  add_action( 'woocommerce_thankyou', array( $this, 'auto_complete_order' ) );
40
  }
41
 
42
+ // Custom columns
43
+ add_filter( 'manage_edit-shop_order_columns', array( $this, 'add_order_column' ), PHP_INT_MAX );
44
+ add_action( 'manage_shop_order_posts_custom_column', array( $this, 'render_order_columns' ), PHP_INT_MAX );
45
  if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
 
 
 
46
  // Country filtering
47
  add_action( 'restrict_manage_posts', array( $this, 'restrict_manage_posts' ) );
48
  add_filter( 'parse_query', array( $this, 'orders_by_country_admin_filter_query' ) );
50
  }
51
  }
52
 
53
+ /**
54
+ * add_order_minimum_amount_hooks.
55
+ *
56
+ * @version 2.5.3
57
+ * @since 2.5.3
58
+ */
59
+ function add_order_minimum_amount_hooks() {
60
+ $is_order_minimum_amount_enabled = false;
61
+ if ( get_option( 'wcj_order_minimum_amount', 0 ) > 0 ) {
62
+ $is_order_minimum_amount_enabled = true;
63
+ } else {
64
+ foreach ( wcj_get_user_roles() as $role_key => $role_data ) {
65
+ if ( get_option( 'wcj_order_minimum_amount_by_user_role_' . $role_key, 0 ) > 0 ) {
66
+ $is_order_minimum_amount_enabled = true;
67
+ break;
68
+ }
69
+ }
70
+ }
71
+ if ( $is_order_minimum_amount_enabled ) {
72
+ add_action( 'woocommerce_checkout_process', array( $this, 'order_minimum_amount' ) );
73
+ add_action( 'woocommerce_before_cart', array( $this, 'order_minimum_amount' ) );
74
+ if ( 'yes' === get_option( 'wcj_order_minimum_amount_stop_from_seeing_checkout' ) ) {
75
+ add_action( 'wp', array( $this, 'stop_from_seeing_checkout' ), 100 );
76
+ // add_action( 'template_redirect', array( $this, 'stop_from_seeing_checkout' ), 100 );
77
+ }
78
+ }
79
+ }
80
+
81
  /**
82
  * Filter the orders in admin based on options
83
  *
111
 
112
  /**
113
  * add_order_column.
114
+ *
115
+ * @version 2.5.3
116
  */
117
  function add_order_column( $columns ) {
118
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
119
+ $columns['country'] = __( 'Country', 'woocommerce-jetpack' );
120
+ }
121
+ $total_number = apply_filters( 'wcj_get_option_filter', 1, get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
122
+ for ( $i = 1; $i <= $total_number; $i++ ) {
123
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
124
+ $columns[ 'wcj_orders_custom_column_' . $i ] = get_option( 'wcj_orders_list_custom_columns_label_' . $i, '' );
125
+ }
126
+ }
127
  return $columns;
128
  }
129
 
134
  $img_src = plugins_url() . '/' . 'woocommerce-jetpack' . '/assets/images/flag-icons/' . strtolower( $country_code ) . '.png';
135
  return '<img src="' . $img_src . '" title="' . wcj_get_country_name_by_code( $country_code ) . '">';
136
  }
137
+
138
  /**
139
  * Output custom columns for orders
140
+ *
141
+ * @version 2.5.3
142
+ * @param string $column
143
  */
144
  public function render_order_columns( $column ) {
145
+ if ( 'country' === $column && 'yes' === get_option( 'wcj_orders_list_custom_columns_country', 'no' ) ) {
146
+ $order = wc_get_order( get_the_ID() );
147
+ // $country_code = wcj_get_customer_country( $order->customer_user );
148
+ $country_code = $order->billing_country;
149
+ echo ( 2 == strlen( $country_code ) )
150
+ ? $this->wcj_get_country_flag_by_code( $country_code ) . ' ' . wcj_get_country_name_by_code( $country_code )
151
+ : wcj_get_country_name_by_code( $country_code );
152
+ }
153
+ $total_number = apply_filters( 'wcj_get_option_filter', 1, get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
154
+ for ( $i = 1; $i <= $total_number; $i++ ) {
155
+ if ( 'yes' === get_option( 'wcj_orders_list_custom_columns_enabled_' . $i, 'no' ) ) {
156
+ if ( 'wcj_orders_custom_column_' . $i === $column ) {
157
+ echo do_shortcode( get_option( 'wcj_orders_list_custom_columns_value_' . $i, '' ) );
158
+ }
159
+ }
160
  }
 
 
 
 
 
 
161
  }
162
 
163
  /**
172
  $order->update_status( 'completed' );
173
  }
174
 
175
+ /**
176
+ * get_order_minimum_amount_with_user_roles.
177
+ *
178
+ * @version 2.5.3
179
+ * @since 2.5.3
180
+ */
181
+ function get_order_minimum_amount_with_user_roles() {
182
+ $minimum = get_option( 'wcj_order_minimum_amount' );
183
+ $current_user_role = wcj_get_current_user_first_role();
184
+ foreach ( wcj_get_user_roles() as $role_key => $role_data ) {
185
+ if ( $role_key === $current_user_role ) {
186
+ $order_minimum_amount_by_user_role = get_option( 'wcj_order_minimum_amount_by_user_role_' . $role_key, 0 );
187
+ if ( $order_minimum_amount_by_user_role > /* $minimum */ 0 ) {
188
+ $minimum = $order_minimum_amount_by_user_role;
189
+ }
190
+ break;
191
+ }
192
+ }
193
+ return $minimum;
194
+ }
195
+
196
  /**
197
  * order_minimum_amount.
198
+ *
199
+ * @version 2.5.3
200
  */
201
  public function order_minimum_amount() {
202
+ $minimum = $this->get_order_minimum_amount_with_user_roles();
203
+ if ( 0 == $minimum ) {
204
+ return;
205
+ }
206
+ $cart_total = WC()->cart->total;
207
+ if ( $cart_total < $minimum ) {
208
  if( is_cart() ) {
209
  if ( 'yes' === get_option( 'wcj_order_minimum_amount_cart_notice_enabled' ) ) {
210
  wc_print_notice(
211
  sprintf( apply_filters( 'wcj_get_option_filter', 'You must have an order with a minimum of %s to place your order, your current order total is %s.', get_option( 'wcj_order_minimum_amount_cart_notice_message' ) ),
212
  woocommerce_price( $minimum ),
213
+ woocommerce_price( $cart_total )
214
  ),
215
  'notice'
216
  );
219
  wc_add_notice(
220
  sprintf( apply_filters( 'wcj_get_option_filter', 'You must have an order with a minimum of %s to place your order, your current order total is %s.', get_option( 'wcj_order_minimum_amount_error_message' ) ),
221
  woocommerce_price( $minimum ),
222
+ woocommerce_price( $cart_total )
223
  ),
224
  'error'
225
  );
230
  /**
231
  * stop_from_seeing_checkout.
232
  *
233
+ * @version 2.5.3
234
+ * @todo cart_contents_total - this is different from value in order_minimum_amount() function
235
  */
236
  public function stop_from_seeing_checkout( $wp ) {
237
  // if ( is_admin() ) return;
242
  if ( ! isset( $woocommerce->cart ) || ! is_object( $woocommerce->cart ) ) {
243
  return;
244
  }
245
+ if ( ! is_checkout() ) {
246
+ return;
247
+ }
248
+ $minimum = $this->get_order_minimum_amount_with_user_roles();
249
+ if ( 0 == $minimum ) {
250
+ return;
251
+ }
252
  $the_cart_total = isset( $woocommerce->cart->cart_contents_total ) ? $woocommerce->cart->cart_contents_total : 0;
253
+ if ( 0 == $the_cart_total ) {
254
+ return;
255
+ }
256
+ if ( $the_cart_total < $minimum ) {
257
  wp_safe_redirect( $woocommerce->cart->get_cart_url() );
258
  }
259
  }
260
 
261
  /**
262
+ * add_settings_hook.
263
+ *
264
+ * @version 2.5.3
265
+ * @since 2.5.3
266
+ */
267
+ function add_settings_hook() {
268
+ add_filter( 'wcj_orders_settings', array( $this, 'add_settings' ) );
269
+ }
270
+
271
+ /**
272
+ * get_settings.
273
  *
274
+ * @version 2.5.3
275
  */
276
  function get_settings() {
277
+ $settings = apply_filters( 'wcj_orders_settings', array() );
278
+ return $this->add_standard_settings( $settings );
279
+ }
280
+
281
+ /**
282
+ * add_settings.
283
+ *
284
+ * @version 2.5.3
285
+ * @since 2.5.3
286
+ */
287
+ function add_settings() {
288
  $settings = array(
289
  array(
290
  'title' => __( 'Order Minimum Amount', 'woocommerce-jetpack' ),
341
  'type' => 'sectionend',
342
  'id' => 'wcj_order_minimum_amount_options',
343
  ),
344
+ array(
345
+ 'title' => __( 'Order Minimum Amount by User Role', 'woocommerce-jetpack' ),
346
+ 'type' => 'title',
347
+ 'id' => 'wcj_order_minimum_amount_by_ser_role_options',
348
+ 'desc' => sprintf( __( 'Custom roles can be added via "Add/Manage Custom Roles" tool in Booster\'s <a href="%s">General</a> module.', 'woocommerce-jetpack' ),
349
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=general' ) ),
350
+ ),
351
+ );
352
+ $c = array( 'guest', 'administrator', 'customer' );
353
+ $is_r = apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' );
354
+ if ( '' == $is_r ) {
355
+ $is_r = array();
356
+ }
357
+ foreach ( wcj_get_user_roles() as $role_key => $role_data ) {
358
+ $settings = array_merge( $settings, array(
359
+ array(
360
+ 'title' => $role_data['name'],
361
+ 'id' => 'wcj_order_minimum_amount_by_user_role_' . $role_key,
362
+ 'default' => 0,
363
+ 'type' => 'number',
364
+ 'custom_attributes' => ( ! in_array( $role_key, $c ) ? array_merge( array( 'step' => '0.0001', 'min' => '0', ), $is_r ) : array( 'step' => '0.0001', 'min' => '0', ) ),
365
+ 'desc_tip' => ( ! in_array( $role_key, $c ) ? apply_filters( 'get_wc_jetpack_plus_message', '', 'desc_no_link' ) : '' ),
366
+ ),
367
+ ) );
368
+ }
369
+ $settings = array_merge( $settings, array(
370
+ array(
371
+ 'type' => 'sectionend',
372
+ 'id' => 'wcj_order_minimum_amount_by_ser_role_options',
373
+ ),
374
  array(
375
  'title' => __( 'Orders Auto-Complete', 'woocommerce-jetpack' ),
376
  'type' => 'title',
402
  'default' => 'no',
403
  'type' => 'checkbox',
404
  ),
405
+ array(
406
+ 'title' => __( 'Custom Columns Total Number', 'woocommerce-jetpack' ),
407
+ 'id' => 'wcj_orders_list_custom_columns_total_number',
408
+ 'default' => 1,
409
+ 'type' => 'custom_number',
410
+ 'desc' => apply_filters( 'get_wc_jetpack_plus_message', '', 'desc' ),
411
+ 'custom_attributes' => array_merge(
412
+ is_array( apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' ) ) ? apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' ) : array(),
413
+ array( 'step' => '1', 'min' => '0', )
414
+ ),
415
+ ),
416
+ ) );
417
+ $total_number = apply_filters( 'wcj_get_option_filter', 1, get_option( 'wcj_orders_list_custom_columns_total_number', 1 ) );
418
+ for ( $i = 1; $i <= $total_number; $i++ ) {
419
+ $settings = array_merge( $settings, array(
420
+ array(
421
+ 'title' => __( 'Custom Column', 'woocommerce-jetpack' ) . ' #' . $i,
422
+ 'desc' => __( 'Enabled', 'woocommerce-jetpack' ),
423
+ 'id' => 'wcj_orders_list_custom_columns_enabled_' . $i,
424
+ 'default' => 'no',
425
+ 'type' => 'checkbox',
426
+ ),
427
+ array(
428
+ 'desc' => __( 'Label', 'woocommerce-jetpack' ),
429
+ 'id' => 'wcj_orders_list_custom_columns_label_' . $i,
430
+ 'default' => '',
431
+ 'type' => 'text',
432
+ 'css' => 'width:300px;',
433
+ ),
434
+ array(
435
+ 'desc' => __( 'Value', 'woocommerce-jetpack' ),
436
+ 'desc_tip' => __( 'You can use shortcodes here.', 'woocommerce-jetpack' ),
437
+ 'id' => 'wcj_orders_list_custom_columns_value_' . $i,
438
+ 'default' => '',
439
+ 'type' => 'text',
440
+ 'css' => 'width:300px;',
441
+ ),
442
+ ) );
443
+ }
444
+ $settings = array_merge( $settings, array(
445
  array(
446
  'type' => 'sectionend',
447
  'id' => 'wcj_orders_list_custom_columns_options',
448
  ),
449
+ ) );
450
+ return $settings;
451
  }
452
  }
453
 
includes/class-wcj-payment-gateways-by-user-role.php ADDED
@@ -0,0 +1,149 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WooCommerce Jetpack Payment Gateways by User Role
4
+ *
5
+ * The WooCommerce Jetpack Payment Gateways by User Role class.
6
+ *
7
+ * @version 2.5.3
8
+ * @since 2.5.3
9
+ * @author Algoritmika Ltd.
10
+ */
11
+
12
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
13
+
14
+ if ( ! class_exists( 'WCJ_Payment_Gateways_By_User_Role' ) ) :
15
+
16
+ class WCJ_Payment_Gateways_By_User_Role extends WCJ_Module {
17
+
18
+ /**
19
+ * Constructor.
20
+ *
21
+ * @version 2.5.3
22
+ * @since 2.5.3
23
+ */
24
+ function __construct() {
25
+
26
+ $this->id = 'payment_gateways_by_user_role';
27
+ $this->short_desc = __( 'Gateways by User Role', 'woocommerce-jetpack' );
28
+ $this->desc = __( 'Set user roles to include/exclude for WooCommerce payment gateways to show up.', 'woocommerce-jetpack' );
29
+ $this->link = 'http://booster.io/features/woocommerce-payment-gateways-by-user-role/';
30
+ parent::__construct();
31
+
32
+ add_action( 'init', array( $this, 'add_settings_hook' ) );
33
+
34
+ if ( $this->is_enabled() ) {
35
+ add_filter( 'woocommerce_available_payment_gateways', array( $this, 'available_payment_gateways' ), PHP_INT_MAX, 1 );
36
+ }
37
+ }
38
+
39
+ /**
40
+ * available_payment_gateways.
41
+ *
42
+ * @version 2.5.3
43
+ * @since 2.5.3
44
+ */
45
+ function available_payment_gateways( $_available_gateways ) {
46
+ foreach ( $_available_gateways as $key => $gateway ) {
47
+ $customer_role = wcj_get_current_user_first_role();
48
+ $include_roles = get_option( 'wcj_gateways_user_roles_include_' . $key, '' );
49
+ if ( ! empty( $include_roles ) && ! in_array( $customer_role, $include_roles ) ) {
50
+ unset( $_available_gateways[ $key ] );
51
+ continue;
52
+ }
53
+ $exclude_roles = get_option( 'wcj_gateways_user_roles_exclude_' . $key, '' );
54
+ if ( ! empty( $exclude_roles ) && in_array( $customer_role, $exclude_roles ) ) {
55
+ unset( $_available_gateways[ $key ] );
56
+ continue;
57
+ }
58
+ }
59
+ return $_available_gateways;
60
+ }
61
+
62
+ /**
63
+ * add_settings_hook.
64
+ *
65
+ * @version 2.5.3
66
+ * @since 2.5.3
67
+ */
68
+ function add_settings_hook() {
69
+ add_filter( 'wcj_payment_gateways_by_user_role_settings', array( $this, 'add_settings' ) );
70
+ }
71
+
72
+ /**
73
+ * add_settings.
74
+ *
75
+ * @version 2.5.3
76
+ * @since 2.5.3
77
+ */
78
+ function add_settings( $settings ) {
79
+ $settings = array();
80
+ $settings[] = array(
81
+ 'title' => __( 'Payment Gateways', 'woocommerce-jetpack' ),
82
+ 'type' => 'title',
83
+ 'desc' => __( 'Leave empty to disable.', 'woocommerce-jetpack' ) . ' ' .
84
+ sprintf( __( 'Custom roles can be added via "Add/Manage Custom Roles" tool in Booster\'s <a href="%s">General</a> module', 'woocommerce-jetpack' ),
85
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=general' ) ),
86
+ 'id' => 'wcj_payment_gateways_by_user_role_gateways_options',
87
+ );
88
+ $user_roles = wcj_get_user_roles_options();
89
+ $gateways = WC()->payment_gateways->payment_gateways();
90
+ foreach ( $gateways as $key => $gateway ) {
91
+ $default_gateways = array( 'bacs' );
92
+ if ( ! empty( $default_gateways ) && ! in_array( $key, $default_gateways ) ) {
93
+ $custom_attributes = apply_filters( 'get_wc_jetpack_plus_message', '', 'disabled' );
94
+ if ( '' == $custom_attributes ) {
95
+ $custom_attributes = array();
96
+ }
97
+ $desc_tip = apply_filters( 'get_wc_jetpack_plus_message', '', 'desc_no_link' );
98
+ } else {
99
+ $custom_attributes = array();
100
+ $desc_tip = '';
101
+ }
102
+ $settings[] = array(
103
+ 'title' => $gateway->title,
104
+ 'desc_tip' => $desc_tip,
105
+ 'desc' => __( 'Include User Roles', 'woocommerce-jetpack' ),
106
+ 'id' => 'wcj_gateways_user_roles_include_' . $key,
107
+ 'default' => '',
108
+ 'type' => 'multiselect',
109
+ 'class' => 'chosen_select',
110
+ 'css' => 'width: 450px;',
111
+ 'options' => $user_roles,
112
+ 'custom_attributes' => $custom_attributes,
113
+ );
114
+ $settings[] = array(
115
+ 'title' => '',
116
+ 'desc_tip' => $desc_tip,
117
+ 'desc' => __( 'Exclude User Roles', 'woocommerce-jetpack' ),
118
+ 'id' => 'wcj_gateways_user_roles_exclude_' . $key,
119
+ 'default' => '',
120
+ 'type' => 'multiselect',
121
+ 'class' => 'chosen_select',
122
+ 'css' => 'width: 450px;',
123
+ 'options' => $user_roles,
124
+ 'custom_attributes' => $custom_attributes,
125
+ );
126
+ }
127
+ $settings[] = array(
128
+ 'type' => 'sectionend',
129
+ 'id' => 'wcj_payment_gateways_by_user_role_gateways_options',
130
+ );
131
+ return $settings;
132
+ }
133
+
134
+ /**
135
+ * get_settings.
136
+ *
137
+ * @version 2.5.3
138
+ * @since 2.5.3
139
+ */
140
+ function get_settings() {
141
+ $settings = array();
142
+ $settings = apply_filters( 'wcj_payment_gateways_by_user_role_settings', $settings );
143
+ return $this->add_standard_settings( $settings );
144
+ }
145
+ }
146
+
147
+ endif;
148
+
149
+ return new WCJ_Payment_Gateways_By_User_Role();
includes/class-wcj-price-by-country.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Price by Country class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -17,7 +17,7 @@ class WCJ_Price_By_Country extends WCJ_Module {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.5.2
21
  */
22
  public function __construct() {
23
 
@@ -56,6 +56,19 @@ class WCJ_Price_By_Country extends WCJ_Module {
56
  include_once( 'price-by-country/class-wcj-price-by-country-local.php' );
57
  }
58
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
59
  }
60
 
61
  if ( is_admin() ) {
@@ -63,10 +76,42 @@ class WCJ_Price_By_Country extends WCJ_Module {
63
  }
64
  }
65
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
66
  /**
67
  * get_settings.
68
  *
69
- * @version 2.5.2
70
  */
71
  function get_settings() {
72
 
@@ -145,6 +190,14 @@ class WCJ_Price_By_Country extends WCJ_Module {
145
  'type' => 'checkbox',
146
  ),
147
 
 
 
 
 
 
 
 
 
148
  array( 'type' => 'sectionend', 'id' => 'wcj_price_by_country_options' ),
149
 
150
  array(
4
  *
5
  * The WooCommerce Jetpack Price by Country class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 2.5.3
21
  */
22
  public function __construct() {
23
 
56
  include_once( 'price-by-country/class-wcj-price-by-country-local.php' );
57
  }
58
  }
59
+
60
+ // Price Filter Widget
61
+ if ( 'yes' === get_option( 'wcj_price_by_country_price_filter_widget_support_enabled', 'no' ) ) {
62
+ if ( 'yes' === get_option( 'wcj_price_by_country_local_enabled', 'yes' ) ) {
63
+ add_action( 'save_post_product', array( $this, 'update_products_price_by_country_product_saved' ), PHP_INT_MAX, 2 );
64
+ add_action( 'woocommerce_ajax_save_product_variations', array( $this, 'update_products_price_by_country_product_saved_ajax' ), PHP_INT_MAX, 1 );
65
+ }
66
+ }
67
+ }
68
+
69
+ // Price Filter Widget
70
+ if ( 'yes' === get_option( 'wcj_price_by_country_price_filter_widget_support_enabled', 'no' ) ) {
71
+ add_action( 'woojetpack_after_settings_save', array( $this, 'update_products_price_by_country_module_saved' ), PHP_INT_MAX, 2 );
72
  }
73
 
74
  if ( is_admin() ) {
76
  }
77
  }
78
 
79
+ /**
80
+ * update_products_price_by_country_module_saved.
81
+ *
82
+ * @version 2.5.3
83
+ * @since 2.5.3
84
+ */
85
+ function update_products_price_by_country_module_saved( $all_sections, $current_section ) {
86
+ if ( 'price_by_country' === $current_section && wcj_is_module_enabled( 'price_by_country' ) ) {
87
+ wcj_update_products_price_by_country();
88
+ }
89
+ }
90
+
91
+ /**
92
+ * update_products_price_by_country_product_saved_ajax.
93
+ *
94
+ * @version 2.5.3
95
+ * @since 2.5.3
96
+ */
97
+ function update_products_price_by_country_product_saved_ajax( $post_id ) {
98
+ wcj_update_products_price_by_country_for_single_product( $post_id );
99
+ }
100
+
101
+ /**
102
+ * update_products_price_by_country_product_saved.
103
+ *
104
+ * @version 2.5.3
105
+ * @since 2.5.3
106
+ */
107
+ function update_products_price_by_country_product_saved( $post_id, $post ) {
108
+ wcj_update_products_price_by_country_for_single_product( $post_id );
109
+ }
110
+
111
  /**
112
  * get_settings.
113
  *
114
+ * @version 2.5.3
115
  */
116
  function get_settings() {
117
 
190
  'type' => 'checkbox',
191
  ),
192
 
193
+ array(
194
+ 'title' => __( 'Price Filter Widget Support', 'woocommerce-jetpack' ),
195
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
196
+ 'id' => 'wcj_price_by_country_price_filter_widget_support_enabled',
197
+ 'default' => 'no',
198
+ 'type' => 'checkbox',
199
+ ),
200
+
201
  array( 'type' => 'sectionend', 'id' => 'wcj_price_by_country_options' ),
202
 
203
  array(
includes/class-wcj-price-by-user-role.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Price by User Role class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.5.0
9
  * @author Algoritmika Ltd.
10
  * @todo Fix "Make Empty Price" option for variable products
@@ -19,7 +19,7 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
19
  /**
20
  * Constructor.
21
  *
22
- * @version 2.5.0
23
  * @since 2.5.0
24
  */
25
  function __construct() {
@@ -30,14 +30,6 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
30
  $this->link = 'http://booster.io/features/woocommerce-price-by-user-role/';
31
  parent::__construct();
32
 
33
- $this->add_tools( array(
34
- 'custom_roles' => array(
35
- 'title' => __( 'Add/Manage Custom Roles', 'woocommerce-jetpack' ),
36
- 'tab_title' => __( 'Custom Roles', 'woocommerce-jetpack' ),
37
- 'desc' => __( 'Manage Custom Roles.', 'woocommerce-jetpack' ),
38
- ),
39
- ) );
40
-
41
  add_action( 'init', array( $this, 'add_settings_hook' ) );
42
 
43
  if ( $this->is_enabled() ) {
@@ -150,7 +142,7 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
150
  );
151
  if ( 'yes' === get_post_meta( $_product->id, '_' . 'wcj_price_by_user_role_per_product_settings_enabled', true ) ) {
152
  foreach ( $products as $product_id => $desc ) {
153
- foreach ( $this->get_user_roles() as $role_key => $role_data ) {
154
  $options = array_merge( $options, array(
155
  array(
156
  'type' => 'title',
@@ -194,63 +186,6 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
194
  return $options;
195
  }
196
 
197
- /**
198
- * create_custom_roles_tool.
199
- *
200
- * @version 2.5.0
201
- * @since 2.5.0
202
- */
203
- function create_custom_roles_tool() {
204
- if ( isset( $_POST['wcj_add_new_role'] ) ) {
205
- if (
206
- ! isset( $_POST['wcj_custom_role_id'] ) || '' == $_POST['wcj_custom_role_id'] ||
207
- ! isset( $_POST['wcj_custom_role_name'] ) || '' == $_POST['wcj_custom_role_name']
208
- ) {
209
- echo '<p style="color:red;font-weight:bold;">' . __( 'Both fields are required!', 'woocommerce-jetpack') . '</p>';
210
- } else {
211
- if ( is_numeric( $_POST['wcj_custom_role_id'] ) ) {
212
- echo '<p style="color:red;font-weight:bold;">' . __( 'Role ID must not be numbers only!', 'woocommerce-jetpack') . '</p>';
213
- } else {
214
- $result = add_role( $_POST['wcj_custom_role_id'], $_POST['wcj_custom_role_name'] );
215
- if ( null !== $result ) {
216
- echo '<p style="color:green;font-weight:bold;">' . __( 'Role successfully added!', 'woocommerce-jetpack') . '</p>';
217
- } else {
218
- echo '<p style="color:red;font-weight:bold;">' . __( 'Role already exists!', 'woocommerce-jetpack') . '</p>';
219
- }
220
- }
221
- }
222
- }
223
-
224
- if ( isset( $_GET['wcj_delete_role'] ) && '' != $_GET['wcj_delete_role'] ) {
225
- remove_role( $_GET['wcj_delete_role'] );
226
- echo '<p style="color:green;font-weight:bold;">' . sprintf( __( 'Role %s successfully deleted!', 'woocommerce-jetpack'), $_GET['wcj_delete_role'] ) . '</p>';
227
- }
228
-
229
- echo $this->get_tool_header_html( 'custom_roles' );
230
-
231
- $table_data = array();
232
- $table_data[] = array( __( 'ID', 'woocommerce-jetpack'), __( 'Name', 'woocommerce-jetpack'), __( 'Actions', 'woocommerce-jetpack'), );
233
- $existing_roles = $this->get_user_roles();
234
- $default_wp_wc_roles = array( 'guest', 'administrator', 'editor', 'author', 'contributor', 'subscriber', 'customer', 'shop_manager', );
235
- foreach ( $existing_roles as $role_key => $role_data ) {
236
- $delete_html = ( in_array( $role_key, $default_wp_wc_roles ) )
237
- ? ''
238
- : '<a href="' . add_query_arg( 'wcj_delete_role', $role_key ). '">' . __( 'Delete', 'woocommerce-jetpack') . '</a>';
239
- $table_data[] = array( $role_key, $role_data['name'], $delete_html );
240
- }
241
- echo '<h3>' . __( 'Existing Roles', 'woocommerce-jetpack') . '</h3>';
242
- echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped' ) );
243
-
244
- $table_data = array();
245
- $table_data[] = array( __( 'ID', 'woocommerce-jetpack'), '<input type="text" name="wcj_custom_role_id">' );
246
- $table_data[] = array( __( 'Name', 'woocommerce-jetpack'), '<input type="text" name="wcj_custom_role_name">' );
247
- echo '<h3>' . __( 'Add New Role', 'woocommerce-jetpack') . '</h3>';
248
- echo '<form method="post" action="' . remove_query_arg( 'wcj_delete_role' ) . '">' .
249
- wcj_get_table_html( $table_data, array( 'table_class' => 'widefat', 'table_heading_type' => 'vertical', 'table_style' => 'width:20%;min-width:300px;', ) )
250
- . '<p>' . '<input type="submit" name="wcj_add_new_role" class="button-primary" value="' . __( 'Add', 'woocommerce-jetpack' ) . '">' . '</p>'
251
- . '</form>';
252
- }
253
-
254
  /**
255
  * add_hooks.
256
  *
@@ -277,12 +212,12 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
277
  /**
278
  * change_price_by_role_shipping.
279
  *
280
- * @version 2.5.2
281
  * @since 2.5.0
282
  */
283
  function change_price_by_role_shipping( $package_rates, $package ) {
284
  if ( 'yes' === get_option( 'wcj_price_by_user_role_shipping_enabled', 'no' ) ) {
285
- $current_user_role = $this->get_current_user_role();
286
  $koef = get_option( 'wcj_price_by_user_role_' . $current_user_role, 1 );
287
  $modified_package_rates = array();
288
  foreach ( $package_rates as $id => $package_rate ) {
@@ -329,12 +264,12 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
329
  /**
330
  * change_price_by_role.
331
  *
332
- * @version 2.5.2
333
  * @since 2.5.0
334
  */
335
  function change_price_by_role( $price, $_product ) {
336
 
337
- $current_user_role = $this->get_current_user_role();
338
 
339
  // Per product
340
  if ( 'yes' === get_option( 'wcj_price_by_user_role_per_product_enabled', 'yes' ) ) {
@@ -376,11 +311,11 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
376
  /**
377
  * get_variation_prices_hash.
378
  *
379
- * @version 2.5.2
380
  * @since 2.5.0
381
  */
382
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
383
- $user_role = $this->get_current_user_role();
384
  $koef = get_option( 'wcj_price_by_user_role_' . $user_role, 1 );
385
  $is_empty = get_option( 'wcj_price_by_user_role_empty_price_' . $user_role, 'no' );
386
  $price_hash['wcj_user_role'] = array(
@@ -392,35 +327,6 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
392
  return $price_hash;
393
  }
394
 
395
- /**
396
- * get_current_user_role.
397
- *
398
- * @version 2.5.0
399
- * @since 2.5.0
400
- */
401
- function get_current_user_role() {
402
- $current_user = wp_get_current_user();
403
- return ( isset( $current_user->roles[0] ) && '' != $current_user->roles[0] ) ? $current_user->roles[0] : 'guest';
404
- }
405
-
406
- /**
407
- * get_user_roles.
408
- *
409
- * @version 2.5.0
410
- * @since 2.5.0
411
- */
412
- function get_user_roles() {
413
- global $wp_roles;
414
- $all_roles = $wp_roles->roles;
415
- $all_roles = apply_filters( 'editable_roles', $all_roles );
416
- $all_roles = array_merge( array(
417
- 'guest' => array(
418
- 'name' => __( 'Guest', 'woocommerce-jetpack' ),
419
- 'capabilities' => array(),
420
- ) ), $all_roles );
421
- return $all_roles;
422
- }
423
-
424
  /**
425
  * add_settings_hook.
426
  *
@@ -445,7 +351,7 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
445
  /**
446
  * add_settings.
447
  *
448
- * @version 2.5.2
449
  * @since 2.5.0
450
  */
451
  function add_settings() {
@@ -480,9 +386,11 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
480
  $settings[] = array(
481
  'title' => __( 'Roles & Multipliers', 'woocommerce-jetpack' ),
482
  'type' => 'title',
 
 
483
  'id' => 'wcj_price_by_user_role_multipliers_options',
484
  );
485
- foreach ( $this->get_user_roles() as $role_key => $role_data ) {
486
  $settings = array_merge( $settings, array(
487
  array(
488
  'title' => $role_data['name'],
4
  *
5
  * The WooCommerce Jetpack Price by User Role class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.5.0
9
  * @author Algoritmika Ltd.
10
  * @todo Fix "Make Empty Price" option for variable products
19
  /**
20
  * Constructor.
21
  *
22
+ * @version 2.5.3
23
  * @since 2.5.0
24
  */
25
  function __construct() {
30
  $this->link = 'http://booster.io/features/woocommerce-price-by-user-role/';
31
  parent::__construct();
32
 
 
 
 
 
 
 
 
 
33
  add_action( 'init', array( $this, 'add_settings_hook' ) );
34
 
35
  if ( $this->is_enabled() ) {
142
  );
143
  if ( 'yes' === get_post_meta( $_product->id, '_' . 'wcj_price_by_user_role_per_product_settings_enabled', true ) ) {
144
  foreach ( $products as $product_id => $desc ) {
145
+ foreach ( wcj_get_user_roles() as $role_key => $role_data ) {
146
  $options = array_merge( $options, array(
147
  array(
148
  'type' => 'title',
186
  return $options;
187
  }
188
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  /**
190
  * add_hooks.
191
  *
212
  /**
213
  * change_price_by_role_shipping.
214
  *
215
+ * @version 2.5.3
216
  * @since 2.5.0
217
  */
218
  function change_price_by_role_shipping( $package_rates, $package ) {
219
  if ( 'yes' === get_option( 'wcj_price_by_user_role_shipping_enabled', 'no' ) ) {
220
+ $current_user_role = wcj_get_current_user_first_role();
221
  $koef = get_option( 'wcj_price_by_user_role_' . $current_user_role, 1 );
222
  $modified_package_rates = array();
223
  foreach ( $package_rates as $id => $package_rate ) {
264
  /**
265
  * change_price_by_role.
266
  *
267
+ * @version 2.5.3
268
  * @since 2.5.0
269
  */
270
  function change_price_by_role( $price, $_product ) {
271
 
272
+ $current_user_role = wcj_get_current_user_first_role();
273
 
274
  // Per product
275
  if ( 'yes' === get_option( 'wcj_price_by_user_role_per_product_enabled', 'yes' ) ) {
311
  /**
312
  * get_variation_prices_hash.
313
  *
314
+ * @version 2.5.3
315
  * @since 2.5.0
316
  */
317
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
318
+ $user_role = wcj_get_current_user_first_role();
319
  $koef = get_option( 'wcj_price_by_user_role_' . $user_role, 1 );
320
  $is_empty = get_option( 'wcj_price_by_user_role_empty_price_' . $user_role, 'no' );
321
  $price_hash['wcj_user_role'] = array(
327
  return $price_hash;
328
  }
329
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  /**
331
  * add_settings_hook.
332
  *
351
  /**
352
  * add_settings.
353
  *
354
+ * @version 2.5.3
355
  * @since 2.5.0
356
  */
357
  function add_settings() {
386
  $settings[] = array(
387
  'title' => __( 'Roles & Multipliers', 'woocommerce-jetpack' ),
388
  'type' => 'title',
389
+ 'desc' => sprintf( __( 'Custom roles can be added via "Add/Manage Custom Roles" tool in Booster\'s <a href="%s">General</a> module.', 'woocommerce-jetpack' ),
390
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=general' ) ),
391
  'id' => 'wcj_price_by_user_role_multipliers_options',
392
  );
393
+ foreach ( wcj_get_user_roles() as $role_key => $role_data ) {
394
  $settings = array_merge( $settings, array(
395
  array(
396
  'title' => $role_data['name'],
includes/class-wcj-product-add-to-cart.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Product Add To Cart class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
@@ -18,13 +18,18 @@ class WCJ_Product_Add_To_Cart extends WCJ_Module {
18
  /**
19
  * Constructor.
20
  *
21
- * @version 2.5.2
22
  */
23
  public function __construct() {
24
 
25
  $this->id = 'product_add_to_cart';
26
  $this->short_desc = __( 'Product Add to Cart', 'woocommerce-jetpack' );
27
- $this->desc = __( 'Set any local url to redirect to on WooCommerce Add to Cart. Automatically add to cart on product visit. Display radio buttons instead of drop box for variable products.', 'woocommerce-jetpack' );
 
 
 
 
 
28
  $this->link = 'http://booster.io/features/woocommerce-product-add-to-cart/';
29
  parent::__construct();
30
 
@@ -58,9 +63,60 @@ class WCJ_Product_Add_To_Cart extends WCJ_Module {
58
  add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'add_to_cart_button_disable_end' ), PHP_INT_MAX, 0 );
59
  add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'add_to_cart_button_loop_disable' ), PHP_INT_MAX, 2 );
60
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  }
62
  }
63
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  /**
65
  * add_to_cart_button_loop_disable.
66
  *
@@ -209,7 +265,7 @@ class WCJ_Product_Add_To_Cart extends WCJ_Module {
209
  /**
210
  * get_settings.
211
  *
212
- * @version 2.5.2
213
  */
214
  function get_settings() {
215
  $settings = array(
@@ -304,7 +360,7 @@ class WCJ_Product_Add_To_Cart extends WCJ_Module {
304
  'id' => 'wcj_add_to_cart_button_options',
305
  ),
306
  array(
307
- 'title' => __( 'Add to Cart Buttons on per Product Basis', 'woocommerce-jetpack' ),
308
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
309
  'desc_tip' => __( 'This will add meta box to each product\'s edit page', 'woocommerce-jetpack' ),
310
  'id' => 'wcj_add_to_cart_button_per_product_enabled',
@@ -315,6 +371,30 @@ class WCJ_Product_Add_To_Cart extends WCJ_Module {
315
  'type' => 'sectionend',
316
  'id' => 'wcj_add_to_cart_button_options',
317
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
318
  );
319
  return $this->add_standard_settings( $settings );
320
  }
4
  *
5
  * The WooCommerce Jetpack Product Add To Cart class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 2.5.3
22
  */
23
  public function __construct() {
24
 
25
  $this->id = 'product_add_to_cart';
26
  $this->short_desc = __( 'Product Add to Cart', 'woocommerce-jetpack' );
27
+ $this->desc = __( 'Set any local url to redirect to on WooCommerce Add to Cart.', 'woocommerce-jetpack' )
28
+ . ' ' . __( 'Automatically add to cart on product visit.', 'woocommerce-jetpack' )
29
+ . ' ' . __( 'Display radio buttons instead of drop box for variable products.', 'woocommerce-jetpack' )
30
+ . ' ' . __( 'Disable quantity input.', 'woocommerce-jetpack' )
31
+ . ' ' . __( 'Disable add to cart button on per product basis.', 'woocommerce-jetpack' )
32
+ . ' ' . __( 'Open external products on add to cart in new window.', 'woocommerce-jetpack' );
33
  $this->link = 'http://booster.io/features/woocommerce-product-add-to-cart/';
34
  parent::__construct();
35
 
63
  add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'add_to_cart_button_disable_end' ), PHP_INT_MAX, 0 );
64
  add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'add_to_cart_button_loop_disable' ), PHP_INT_MAX, 2 );
65
  }
66
+
67
+ // External Products
68
+ if ( 'yes' === get_option( 'wcj_add_to_cart_button_external_open_new_window_single', 'no' ) ) {
69
+ add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'replace_external_with_custom_add_to_cart_on_single_start' ), PHP_INT_MAX );
70
+ add_action( 'woocommerce_after_add_to_cart_button', array( $this, 'replace_external_with_custom_add_to_cart_on_single_end' ), PHP_INT_MAX );
71
+ }
72
+ if ( 'yes' === get_option( 'wcj_add_to_cart_button_external_open_new_window_loop', 'no' ) ) {
73
+ add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'replace_external_with_custom_add_to_cart_in_loop' ), PHP_INT_MAX );
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * replace_external_with_custom_add_to_cart_on_single_start.
80
+ *
81
+ * @version 2.5.3
82
+ * @since 2.5.3
83
+ */
84
+ function replace_external_with_custom_add_to_cart_on_single_start() {
85
+ global $product;
86
+ if ( $product->is_type( 'external' ) ) {
87
+ ob_start();
88
  }
89
  }
90
 
91
+ /**
92
+ * replace_external_with_custom_add_to_cart_on_single_end.
93
+ *
94
+ * @version 2.5.3
95
+ * @since 2.5.3
96
+ */
97
+ function replace_external_with_custom_add_to_cart_on_single_end() {
98
+ global $product;
99
+ if ( $product->is_type( 'external' ) ) {
100
+ $button_html = ob_get_contents();
101
+ ob_end_clean();
102
+ echo str_replace( '<a href=', '<a target="_blank" href=', $button_html );
103
+ }
104
+ }
105
+
106
+ /**
107
+ * replace_external_with_custom_add_to_cart_in_loop.
108
+ *
109
+ * @version 2.5.3
110
+ * @since 2.5.3
111
+ */
112
+ function replace_external_with_custom_add_to_cart_in_loop( $link_html ) {
113
+ global $product;
114
+ if ( $product->is_type( 'external' ) ) {
115
+ $link_html = str_replace( '<a rel=', '<a target="_blank" rel=', $link_html );
116
+ }
117
+ return $link_html;
118
+ }
119
+
120
  /**
121
  * add_to_cart_button_loop_disable.
122
  *
265
  /**
266
  * get_settings.
267
  *
268
+ * @version 2.5.3
269
  */
270
  function get_settings() {
271
  $settings = array(
360
  'id' => 'wcj_add_to_cart_button_options',
361
  ),
362
  array(
363
+ 'title' => __( 'Enable/Disable Add to Cart Buttons on per Product Basis', 'woocommerce-jetpack' ),
364
  'desc' => __( 'Enable', 'woocommerce-jetpack' ),
365
  'desc_tip' => __( 'This will add meta box to each product\'s edit page', 'woocommerce-jetpack' ),
366
  'id' => 'wcj_add_to_cart_button_per_product_enabled',
371
  'type' => 'sectionend',
372
  'id' => 'wcj_add_to_cart_button_options',
373
  ),
374
+ array(
375
+ 'title' => __( 'External Products', 'woocommerce-jetpack' ),
376
+ 'type' => 'title',
377
+ 'id' => 'wcj_add_to_cart_button_external_product_options',
378
+ ),
379
+ array(
380
+ 'title' => __( 'Open External Products on Add to Cart in New Window', 'woocommerce-jetpack' ),
381
+ 'desc' => __( 'Enable on Single Product Pages', 'woocommerce-jetpack' ),
382
+ 'id' => 'wcj_add_to_cart_button_external_open_new_window_single',
383
+ 'default' => 'no',
384
+ 'type' => 'checkbox',
385
+ 'checkboxgroup' => 'start',
386
+ ),
387
+ array(
388
+ 'desc' => __( 'Enable on Category/Archive Pages', 'woocommerce-jetpack' ),
389
+ 'id' => 'wcj_add_to_cart_button_external_open_new_window_loop',
390
+ 'default' => 'no',
391
+ 'type' => 'checkbox',
392
+ 'checkboxgroup' => 'end',
393
+ ),
394
+ array(
395
+ 'type' => 'sectionend',
396
+ 'id' => 'wcj_add_to_cart_button_external_product_options',
397
+ ),
398
  );
399
  return $this->add_standard_settings( $settings );
400
  }
includes/class-wcj-product-addons.php ADDED
@@ -0,0 +1,472 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * WooCommerce Jetpack Product Addons
4
+ *
5
+ * The WooCommerce Jetpack Product Addons class.
6
+ *
7
+ * @version 2.5.3
8
+ * @since 2.5.3
9
+ * @author Algoritmika Ltd.
10
+ * @todo admin order view (names);
11
+ */
12
+
13
+ if ( ! defined( 'ABSPATH' ) ) exit;
14
+
15
+ if ( ! class_exists( 'WCJ_Product_Addons' ) ) :
16
+
17
+ class WCJ_Product_Addons extends WCJ_Module {
18
+
19
+ /**
20
+ * Constructor.
21
+ *
22
+ * @version 2.5.3
23
+ * @since 2.5.3
24
+ */
25
+ function __construct() {
26
+
27
+ $this->id = 'product_addons';
28
+ $this->short_desc = __( 'Product Addons', 'woocommerce-jetpack' );
29
+ $this->desc = __( 'Add (paid/free/discount) addons to WooCommerce products.', 'woocommerce-jetpack' );
30
+ $this->link = 'http://booster.io/features/woocommerce-product-addons/';
31
+ parent::__construct();
32
+
33
+ if ( $this->is_enabled() ) {
34
+ if ( 'yes' === get_option( 'wcj_product_addons_per_product_enabled', 'no' ) ) {
35
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
36
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
37
+ add_filter( 'wcj_save_meta_box_value', array( $this, 'save_meta_box_value' ), PHP_INT_MAX, 3 );
38
+ add_action( 'admin_notices', array( $this, 'admin_notices' ) );
39
+ $this->co = 'wcj_product_addons_per_product_settings_enabled';
40
+ }
41
+ if ( ! is_admin() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) {
42
+ if ( 'yes' === get_option( 'wcj_product_addons_ajax_enabled', 'no' ) ) {
43
+ // Scripts
44
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
45
+ add_action( 'wp_ajax_product_addons_price_change', array( $this, 'price_change_ajax' ) );
46
+ add_action( 'wp_ajax_nopriv_product_addons_price_change', array( $this, 'price_change_ajax' ) );
47
+ }
48
+ // Single Page
49
+ add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'add_addons_to_frontend' ), PHP_INT_MAX );
50
+ // Add to cart
51
+ add_filter( 'woocommerce_add_cart_item_data', array( $this, 'add_addons_price_to_cart_item_data' ), PHP_INT_MAX, 3 );
52
+ add_filter( 'woocommerce_add_cart_item', array( $this, 'add_addons_price_to_cart_item' ), PHP_INT_MAX, 2 );
53
+ add_filter( 'woocommerce_get_cart_item_from_session', array( $this, 'get_cart_item_addons_price_from_session' ), PHP_INT_MAX, 3 );
54
+ // Prices
55
+ add_filter( 'woocommerce_get_price', array( $this, 'change_price' ), PHP_INT_MAX - 100, 2 );
56
+ // Show details at cart, order details, emails
57
+ add_filter( 'woocommerce_cart_item_name', array( $this, 'add_info_to_cart_item_name' ), PHP_INT_MAX, 3 );
58
+ add_filter( 'woocommerce_order_item_name', array( $this, 'add_info_to_order_item_name' ), PHP_INT_MAX, 2 );
59
+ add_action( 'woocommerce_add_order_item_meta', array( $this, 'add_info_to_order_item_meta' ), PHP_INT_MAX, 3 );
60
+ }
61
+ }
62
+ }
63
+
64
+ /**
65
+ * get_the_notice.
66
+ *
67
+ * @version 2.5.3
68
+ * @since 2.5.3
69
+ */
70
+ function get_the_notice() {
71
+ return __( 'Booster: Free plugin\'s version is limited to only three products with per product addons enabled at a time. You will need to get <a href="http://booster.io/plus/" target="_blank">Booster Plus</a> to add unlimited number of products with per product addons.', 'woocommerce-jetpack' );
72
+ }
73
+
74
+ /**
75
+ * price_change_ajax.
76
+ *
77
+ * @version 2.5.3
78
+ * @since 2.5.3
79
+ */
80
+ function price_change_ajax( $param ) {
81
+ $the_product = wc_get_product( $_POST['product_id'] );
82
+ $get_price_method = 'get_price_' . get_option( 'woocommerce_tax_display_shop' ) . 'uding_tax';
83
+ $the_price = $the_product->$get_price_method();
84
+ $parent_product_id = ( $the_product->is_type( 'variation' ) ) ? wp_get_post_parent_id( $_POST['product_id'] ) : $_POST['product_id'];
85
+ $addons = $this->get_product_addons( $parent_product_id );
86
+ $the_addons_price = 0;
87
+ foreach ( $addons as $addon ) {
88
+ if ( isset( $_POST[ $addon['checkbox_key'] ] ) ) {
89
+ $the_addons_price += $addon['price_value'];
90
+ }
91
+ }
92
+ if ( 0 != $the_addons_price ) {
93
+ echo wc_price( $the_price + $the_addons_price );
94
+ } else {
95
+ echo $the_product->get_price_html();
96
+ }
97
+ wp_die();
98
+ }
99
+
100
+ /**
101
+ * enqueue_scripts.
102
+ *
103
+ * @version 2.5.3
104
+ * @since 2.5.3
105
+ */
106
+ function enqueue_scripts() {
107
+ if ( is_product() ) {
108
+ $the_product = wc_get_product();
109
+ $addons = $this->get_product_addons( $the_product->id );
110
+ if ( ! empty( $addons ) ) {
111
+ wp_enqueue_script( 'wcj-product-addons', wcj_plugin_url() . '/includes/js/wcj-product-addons.js', array(), false, true );
112
+ wp_localize_script( 'wcj-product-addons', 'ajax_object', array(
113
+ 'ajax_url' => admin_url( 'admin-ajax.php' ),
114
+ 'product_id' => get_the_ID(),
115
+ ) );
116
+ }
117
+ }
118
+ }
119
+
120
+ /**
121
+ * get_product_addons.
122
+ *
123
+ * @version 2.5.3
124
+ * @since 2.5.3
125
+ */
126
+ function get_product_addons( $product_id ) {
127
+ $addons = array();
128
+ // All Products
129
+ if ( 'yes' === get_option( 'wcj_product_addons_all_products_enabled', 'no' ) ) {
130
+ $total_number = apply_filters( 'wcj_get_option_filter', 1, get_option( 'wcj_product_addons_all_products_total_number', 1 ) );
131
+ for ( $i = 1; $i <= $total_number; $i++ ) {
132
+ if ( 'yes' === get_option( 'wcj_product_addons_all_products_enabled_' . $i, 'yes' ) ) {
133
+ $addons[] = array(
134
+ // 'scope' => 'all_products',
135
+ // 'index' => $i,
136
+ 'checkbox_key' => 'wcj_product_all_products_addons_' . $i,
137
+ 'price_key' => 'wcj_product_all_products_addons_price_' . $i,
138
+ 'label_key' => 'wcj_product_all_products_addons_label_' . $i,
139
+ 'price_value' => get_option( 'wcj_product_addons_all_products_price_' . $i ),
140
+ 'label_value' => get_option( 'wcj_product_addons_all_products_label_' . $i ),
141
+ );
142
+ }
143
+ }
144
+ }
145
+ // Per product
146
+ if ( 'yes' === get_option( 'wcj_product_addons_per_product_enabled', 'no' ) ) {
147
+ if ( 'yes' === get_post_meta( $product_id, '_' . 'wcj_product_addons_per_product_settings_enabled', true ) ) {
148
+ $total_number = get_post_meta( $product_id, '_' . 'wcj_product_addons_per_product_total_number', true );
149
+ for ( $i = 1; $i <= $total_number; $i++ ) {
150
+ if ( 'yes' === get_post_meta( $product_id, '_' . 'wcj_product_addons_per_product_enabled_' . $i, true ) ) {
151
+ $addons[] = array(
152
+ // 'scope' => 'per_product',
153
+ // 'index' => $i,
154
+ 'checkbox_key' => 'wcj_product_per_product_addons_' . $i,
155
+ 'price_key' => 'wcj_product_per_product_addons_price_' . $i,
156
+ 'label_key' => 'wcj_product_per_product_addons_label_' . $i,
157
+ 'price_value' => get_post_meta( $product_id, '_' . 'wcj_product_addons_per_product_price_' . $i, true ),
158
+ 'label_value' => get_post_meta( $product_id, '_' . 'wcj_product_addons_per_product_label_' . $i, true ),
159
+ );
160
+ }
161
+ }
162
+ }
163
+ }
164
+ return $addons;
165
+ }
166
+
167
+ /**
168
+ * add_info_to_order_item_meta.
169
+ *
170
+ * @version 2.5.3
171
+ * @since 2.5.3
172
+ */
173
+ function add_info_to_order_item_meta( $item_id, $values, $cart_item_key ) {
174
+ $addons = $this->get_product_addons( $values['product_id'] );
175
+ foreach ( $addons as $addon ) {
176
+ if ( isset( $values[ $addon['price_key'] ] ) ) {
177
+ wc_add_order_item_meta( $item_id, '_' . $addon['price_key'], $values[ $addon['price_key'] ] );
178
+ wc_add_order_item_meta( $item_id, '_' . $addon['label_key'], $values[ $addon['label_key'] ] );
179
+ }
180
+ }
181
+ }
182
+
183
+ /**
184
+ * Adds info to order details (and emails).
185
+ *
186
+ * @version 2.5.3
187
+ * @since 2.5.3
188
+ */
189
+ function add_info_to_order_item_name( $name, $item, $is_cart = false ) {
190
+ if ( $is_cart ) {
191
+ $name .= '<dl class="variation">';
192
+ }
193
+ $addons = $this->get_product_addons( $item['product_id'] );
194
+ foreach ( $addons as $addon ) {
195
+ if ( isset( $item[ $addon['price_key'] ] ) ) {
196
+ if ( $is_cart ) {
197
+ $name .= '<dt>' . $item[ $addon['label_key'] ] . ':' . '</dt>';
198
+ $name .= '<dd>' . wc_price( $item[ $addon['price_key'] ] ) . '</dd>';
199
+ } else {
200
+ $name .= ' | ' . $item[ $addon['label_key'] ] . ': ' . wc_price( $item[ $addon['price_key'] ] );
201
+ }
202
+ }
203
+ }
204
+ if ( $is_cart ) {
205
+ $name .= '</dl>';
206
+ }
207
+ return $name;
208
+ }
209
+
210
+ /**
211
+ * Adds info to cart item details.
212
+ *
213
+ * @version 2.5.3
214
+ * @since 2.5.3
215
+ */
216
+ function add_info_to_cart_item_name( $name, $cart_item, $cart_item_key ) {
217
+ return $this->add_info_to_order_item_name( $name, $cart_item, true );
218
+ }
219
+
220
+ /**
221
+ * change_price.
222
+ *
223
+ * @version 2.5.3
224
+ * @since 2.5.3
225
+ */
226
+ function change_price( $price, $_product ) {
227
+ $addons = $this->get_product_addons( $_product->id );
228
+ foreach ( $addons as $addon ) {
229
+ if ( isset( $_product->$addon['price_key'] ) ) {
230
+ $price += $_product->$addon['price_key'];
231
+ }
232
+ }
233
+ return $price;
234
+ }
235
+
236
+ /**
237
+ * add_addons_price_to_cart_item.
238
+ *
239
+ * @version 2.5.3
240
+ * @since 2.5.3
241
+ */
242
+ function add_addons_price_to_cart_item( $cart_item_data, $cart_item_key ) {
243
+ $addons = $this->get_product_addons( $cart_item_data['data']->product_id );
244
+ foreach ( $addons as $addon ) {
245
+ if ( isset( $cart_item_data[ $addon['price_key'] ] ) ) {
246
+ $cart_item_data['data']->$addon['price_key'] = $cart_item_data[ $addon['price_key'] ];
247
+ }
248
+ }
249
+ return $cart_item_data;
250
+ }
251
+
252
+ /**
253
+ * get_cart_item_addons_price_from_session.
254
+ *
255
+ * @version 2.5.3
256
+ * @since 2.5.3
257
+ */
258
+ function get_cart_item_addons_price_from_session( $item, $values, $addon ) {
259
+ $addons = $this->get_product_addons( $item['product_id'] );
260
+ foreach ( $addons as $addon ) {
261
+ if ( array_key_exists( $addon['price_key'], $values ) ) {
262
+ $item['data']->$addon['price_key'] = $values[ $addon['price_key'] ];
263
+ }
264
+ }
265
+ return $item;
266
+ }
267
+
268
+ /**
269
+ * add_addons_price_to_cart_item_data.
270
+ *
271
+ * @version 2.5.3
272
+ * @since 2.5.3
273
+ */
274
+ function add_addons_price_to_cart_item_data( $cart_item_data, $product_id, $variation_id ) {
275
+ $addons = $this->get_product_addons( $product_id );
276
+ foreach ( $addons as $addon ) {
277
+ if ( isset( $_POST[ $addon['checkbox_key'] ] ) ) {
278
+ $cart_item_data[ $addon['price_key'] ] = $addon['price_value'];
279
+ $cart_item_data[ $addon['label_key'] ] = $addon['label_value'];
280
+ }
281
+ }
282
+ return $cart_item_data;
283
+ }
284
+
285
+ /**
286
+ * add_addons_to_frontend.
287
+ *
288
+ * @version 2.5.3
289
+ * @since 2.5.3
290
+ */
291
+ function add_addons_to_frontend() {
292
+ $html = '';
293
+ $addons = $this->get_product_addons( get_the_ID() );
294
+ foreach ( $addons as $addon ) {
295
+ $is_checked = isset( $_POST[ $addon['checkbox_key'] ] ) ? ' checked' : '';
296
+ $html .= '<p>' .
297
+ '<input type="checkbox" id="' . $addon['checkbox_key'] . '" name="' . $addon['checkbox_key'] . '"' . $is_checked . '>' . ' ' .
298
+ '<label for="' . $addon['checkbox_key'] . '">' . $addon['label_value'] . ' ('. wc_price( $addon['price_value'] ) . ')' . '</label>' .
299
+ '</p>';
300
+ }
301
+ // Output
302
+ if ( ! empty( $html ) ) {
303
+ echo '<div id="wcj_product_addons">' . $html . '</div>';
304
+ }
305
+ }
306
+
307
+ /**
308
+ * get_meta_box_options.
309
+ *
310
+ * @version 2.5.3
311
+ * @since 2.5.3
312
+ */
313
+ function get_meta_box_options() {
314
+ $options = array(
315
+ array(
316
+ 'name' => 'wcj_product_addons_per_product_settings_enabled',
317
+ 'default' => 'no',
318
+ 'type' => 'select',
319
+ 'options' => array(
320
+ 'yes' => __( 'Yes', 'woocommerce-jetpack' ),
321
+ 'no' => __( 'No', 'woocommerce-jetpack' ),
322
+ ),
323
+ 'title' => __( 'Enabled', 'woocommerce-jetpack' ),
324
+ ),
325
+ array(
326
+ 'name' => 'wcj_product_addons_per_product_total_number',
327
+ 'default' => 0,
328
+ 'type' => 'number',
329
+ 'title' => __( 'Product Addons Total Number', 'woocommerce-jetpack' ),
330
+ ),
331
+ );
332
+ $total_number = get_post_meta( get_the_ID(), '_' . 'wcj_product_addons_per_product_total_number', true );
333
+ for ( $i = 1; $i <= $total_number; $i++ ) {
334
+ $options = array_merge( $options, array(
335
+ array(
336
+ 'title' => __( 'Product Addon', 'woocommerce-jetpack' ) . ' #' . $i . ' - ' . __( 'Enable', 'woocommerce-jetpack' ),
337
+ 'name' => 'wcj_product_addons_per_product_enabled_' . $i,
338
+ 'default' => 'yes',
339
+ 'type' => 'select',
340
+ 'options' => array(
341
+ 'yes' => __( 'Yes', 'woocommerce-jetpack' ),
342
+ 'no' => __( 'No', 'woocommerce-jetpack' ),
343
+ ),
344
+ ),
345
+ array(
346
+ 'title' => __( 'Label', 'woocommerce-jetpack' ),
347
+ 'name' => 'wcj_product_addons_per_product_label_' . $i,
348
+ 'default' => '',
349
+ 'type' => 'text',
350
+ ),
351
+ array(
352
+ 'title' => __( 'Price', 'woocommerce-jetpack' ),
353
+ 'name' => 'wcj_product_addons_per_product_price_' . $i,
354
+ 'default' => 0,
355
+ 'type' => 'price',
356
+ ),
357
+ ) );
358
+ }
359
+ return $options;
360
+ }
361
+
362
+ /**
363
+ * get_settings.
364
+ *
365
+ * @version 2.5.3
366
+ * @since 2.5.3
367
+ */
368
+ function get_settings() {
369
+ $settings = array();
370
+ $settings = array_merge( $settings, array(
371
+ array(
372
+ 'title' => __( 'Per Product Options', 'woocommerce-jetpack' ),
373
+ 'type' => 'title',
374
+ 'id' => 'wcj_product_addons_per_product_options',
375
+ ),
376
+ array(
377
+ 'title' => __( 'Enable per Product Addons', 'woocommerce-jetpack' ),
378
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
379
+ 'desc_tip' => __( 'When enabled, this will add new "Booster: Product Addons" meta box to each product\'s edit page.', 'woocommerce-jetpack' ),
380
+ 'id' => 'wcj_product_addons_per_product_enabled',
381
+ 'default' => 'no',
382
+ 'type' => 'checkbox',
383
+ ),
384
+ array(
385
+ 'type' => 'sectionend',
386
+ 'id' => 'wcj_product_addons_per_product_options',
387
+ ),
388
+ ) );
389
+ $settings = array_merge( $settings, array(
390
+ array(
391
+ 'title' => __( 'All Product Options', 'woocommerce-jetpack' ),
392
+ 'type' => 'title',
393
+ 'id' => 'wcj_product_addons_all_products_options',
394
+ ),
395
+ array(
396
+ 'title' => __( 'Enable All Products Addons', 'woocommerce-jetpack' ),
397
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
398
+ 'desc_tip' => __( 'When enabled, this will add addons below to all products.', 'woocommerce-jetpack' ),
399
+ 'id' => 'wcj_product_addons_all_products_enabled',
400
+ 'default' => 'no',
401
+ 'type' => 'checkbox',
402
+ ),
403
+ array(
404
+ 'title' => __( 'Product Addons Total Number', 'woocommerce-jetpack' ),
405
+ 'id' => 'wcj_product_addons_all_products_total_number',
406
+ 'default' => 1,
407
+ 'type' => 'custom_number',
408
+ 'desc' => apply_filters( 'get_wc_jetpack_plus_message', '', 'desc' ),
409
+ 'custom_attributes' => array_merge(
410
+ is_array( apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' ) ) ? apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' ) : array(),
411
+ array( 'step' => '1', 'min' => '0', )
412
+ ),
413
+ ),
414
+ ) );
415
+ $total_number = apply_filters( 'wcj_get_option_filter', 1, get_option( 'wcj_product_addons_all_products_total_number', 1 ) );
416
+ for ( $i = 1; $i <= $total_number; $i++ ) {
417
+ $settings = array_merge( $settings, array(
418
+ array(
419
+ 'title' => __( 'Product Addon', 'woocommerce-jetpack' ) . ' #' . $i,
420
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
421
+ 'id' => 'wcj_product_addons_all_products_enabled_' . $i,
422
+ 'default' => 'yes',
423
+ 'type' => 'checkbox',
424
+ ),
425
+ array(
426
+ 'desc' => __( 'Label', 'woocommerce-jetpack' ),
427
+ 'id' => 'wcj_product_addons_all_products_label_' . $i,
428
+ 'default' => '',
429
+ 'type' => 'text',
430
+ 'css' => 'width:300px;',
431
+ ),
432
+ array(
433
+ 'desc' => __( 'Price', 'woocommerce-jetpack' ),
434
+ 'id' => 'wcj_product_addons_all_products_price_' . $i,
435
+ 'default' => 0,
436
+ 'type' => 'number',
437
+ 'css' => 'width:300px;',
438
+ 'custom_attributes' => array( 'step' => '0.0001' ),
439
+ ),
440
+ ) );
441
+ }
442
+ $settings = array_merge( $settings, array(
443
+ array(
444
+ 'type' => 'sectionend',
445
+ 'id' => 'wcj_product_addons_all_products_options',
446
+ ),
447
+ ) );
448
+ $settings = array_merge( $settings, array(
449
+ array(
450
+ 'title' => __( 'Options', 'woocommerce-jetpack' ),
451
+ 'type' => 'title',
452
+ 'id' => 'wcj_product_addons_options',
453
+ ),
454
+ array(
455
+ 'title' => __( 'Enable AJAX on Single Product Page', 'woocommerce-jetpack' ),
456
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
457
+ 'id' => 'wcj_product_addons_ajax_enabled',
458
+ 'default' => 'no',
459
+ 'type' => 'checkbox',
460
+ ),
461
+ array(
462
+ 'type' => 'sectionend',
463
+ 'id' => 'wcj_product_addons_options',
464
+ ),
465
+ ) );
466
+ return $this->add_standard_settings( $settings );
467
+ }
468
+ }
469
+
470
+ endif;
471
+
472
+ return new WCJ_Product_Addons();
includes/class-wcj-product-bookings.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Product Bookings class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.5.0
9
  * @author Algoritmika Ltd.
10
  */
@@ -18,7 +18,7 @@ class WCJ_Product_Bookings extends WCJ_Module {
18
  /**
19
  * Constructor.
20
  *
21
- * @version 2.5.0
22
  * @since 2.5.0
23
  */
24
  function __construct() {
@@ -58,7 +58,9 @@ class WCJ_Product_Bookings extends WCJ_Module {
58
  add_filter( 'woocommerce_order_item_name', array( $this, 'add_info_to_order_item_name' ), PHP_INT_MAX, 2 );
59
  add_action( 'woocommerce_add_order_item_meta', array( $this, 'add_info_to_order_item_meta' ), PHP_INT_MAX, 3 );
60
  // Hide quantity
61
- add_filter( 'woocommerce_is_sold_individually', array( $this, 'sold_individually' ), PHP_INT_MAX, 2 );
 
 
62
  // Disable AJAX add to cart
63
  add_filter( 'woocommerce_product_supports', array( $this, 'disable_add_to_cart_ajax' ), PHP_INT_MAX, 3 );
64
  }
@@ -159,7 +161,7 @@ class WCJ_Product_Bookings extends WCJ_Module {
159
  * @version 2.5.0
160
  * @since 2.5.0
161
  */
162
- function add_info_to_order_item_meta( $item_id, $values, $cart_item_key ) {
163
  if ( isset( $values['wcj_bookings_price'] ) ) {
164
  wc_add_order_item_meta( $item_id, '_' . 'wcj_bookings_price', $values['wcj_bookings_price'] );
165
  wc_add_order_item_meta( $item_id, '_' . 'wcj_bookings_date_from', $values['wcj_bookings_date_from'] );
@@ -421,7 +423,7 @@ class WCJ_Product_Bookings extends WCJ_Module {
421
  /**
422
  * get_settings.
423
  *
424
- * @version 2.5.2
425
  * @since 2.5.0
426
  */
427
  function get_settings() {
@@ -484,6 +486,22 @@ class WCJ_Product_Bookings extends WCJ_Module {
484
  'type' => 'sectionend',
485
  'id' => 'wcj_product_bookings_labels_and_messages_options',
486
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
487
  );
488
  return $this->add_standard_settings( $settings, __( 'When enabled, module will add new "Booster: Bookings" meta box to each product\'s edit page.', 'woocommerce-jetpack' ) );
489
  }
4
  *
5
  * The WooCommerce Jetpack Product Bookings class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.5.0
9
  * @author Algoritmika Ltd.
10
  */
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 2.5.3
22
  * @since 2.5.0
23
  */
24
  function __construct() {
58
  add_filter( 'woocommerce_order_item_name', array( $this, 'add_info_to_order_item_name' ), PHP_INT_MAX, 2 );
59
  add_action( 'woocommerce_add_order_item_meta', array( $this, 'add_info_to_order_item_meta' ), PHP_INT_MAX, 3 );
60
  // Hide quantity
61
+ if ( 'yes' === get_option( 'wcj_product_bookings_hide_quantity', 'yes' ) ) {
62
+ add_filter( 'woocommerce_is_sold_individually', array( $this, 'sold_individually' ), PHP_INT_MAX, 2 );
63
+ }
64
  // Disable AJAX add to cart
65
  add_filter( 'woocommerce_product_supports', array( $this, 'disable_add_to_cart_ajax' ), PHP_INT_MAX, 3 );
66
  }
161
  * @version 2.5.0
162
  * @since 2.5.0
163
  */
164
+ function add_info_to_order_item_meta( $item_id, $values, $cart_item_key ) {
165
  if ( isset( $values['wcj_bookings_price'] ) ) {
166
  wc_add_order_item_meta( $item_id, '_' . 'wcj_bookings_price', $values['wcj_bookings_price'] );
167
  wc_add_order_item_meta( $item_id, '_' . 'wcj_bookings_date_from', $values['wcj_bookings_date_from'] );
423
  /**
424
  * get_settings.
425
  *
426
+ * @version 2.5.3
427
  * @since 2.5.0
428
  */
429
  function get_settings() {
486
  'type' => 'sectionend',
487
  'id' => 'wcj_product_bookings_labels_and_messages_options',
488
  ),
489
+ array(
490
+ 'title' => __( 'Options', 'woocommerce-jetpack' ),
491
+ 'type' => 'title',
492
+ 'id' => 'wcj_product_bookings_options',
493
+ ),
494
+ array(
495
+ 'title' => __( 'Hide Quantity Selector for Booking Products', 'woocommerce-jetpack' ),
496
+ 'desc' => __( 'Hide', 'woocommerce-jetpack' ),
497
+ 'id' => 'wcj_product_bookings_hide_quantity',
498
+ 'default' => 'yes',
499
+ 'type' => 'checkbox',
500
+ ),
501
+ array(
502
+ 'type' => 'sectionend',
503
+ 'id' => 'wcj_product_bookings_options',
504
+ ),
505
  );
506
  return $this->add_standard_settings( $settings, __( 'When enabled, module will add new "Booster: Bookings" meta box to each product\'s edit page.', 'woocommerce-jetpack' ) );
507
  }
includes/class-wcj-product-by-user.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Product by User class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.5.2
9
  * @author Algoritmika Ltd.
10
  */
@@ -18,17 +18,19 @@ class WCJ_Product_By_User extends WCJ_Module {
18
  /**
19
  * Constructor.
20
  *
21
- * @version 2.5.2
22
  * @since 2.5.2
23
  */
24
  public function __construct() {
25
 
26
  $this->id = 'product_by_user';
27
  $this->short_desc = __( 'Product by User', 'woocommerce-jetpack' );
28
- $this->desc = __( 'Let users to add new WooCommerce products from frontend.', 'woocommerce-jetpack' );
29
  $this->link = 'http://booster.io/features/woocommerce-product-by-user/';
30
  parent::__construct();
31
 
 
 
32
  if ( $this->is_enabled() ) {
33
  if ( 'yes' === get_option( 'wcj_product_by_user_add_to_my_account', 'yes' ) ) {
34
  add_filter( 'woocommerce_account_menu_items', array( $this, 'add_my_products_tab_my_account_page' ) );
@@ -125,34 +127,33 @@ class WCJ_Product_By_User extends WCJ_Module {
125
  }
126
 
127
  /**
128
- * get_user_roles.
129
  *
130
- * @version 2.5.2
131
- * @since 2.5.2
132
  */
133
- function get_user_roles() {
134
- global $wp_roles;
135
- $all_roles = ( isset( $wp_roles ) && is_object( $wp_roles ) ) ? $wp_roles->roles : array();
136
- $all_roles = apply_filters( 'editable_roles', $all_roles );
137
- $all_roles = array_merge( array(
138
- 'guest' => array(
139
- 'name' => __( 'Guest', 'woocommerce-jetpack' ),
140
- 'capabilities' => array(),
141
- ) ), $all_roles );
142
- $all_roles_options = array();
143
- foreach ( $all_roles as $_role_key => $_role ) {
144
- $all_roles_options[ $_role_key ] = $_role['name'];
145
- }
146
- return $all_roles_options;
147
  }
148
 
149
  /**
150
  * get_settings.
151
  *
152
- * @version 2.5.2
153
  * @since 2.5.2
154
  */
155
  function get_settings() {
 
 
 
 
 
 
 
 
 
 
 
156
 
157
  $fields = array(
158
  'desc' => __( 'Description', 'woocommerce-jetpack' ),
@@ -211,11 +212,13 @@ class WCJ_Product_By_User extends WCJ_Module {
211
  array(
212
  array(
213
  'title' => __( 'User Visibility', 'woocommerce-jetpack' ),
 
 
214
  'id' => 'wcj_product_by_user_user_visibility',
215
  'default' => array(),
216
  'type' => 'multiselect',
217
  'class' => 'chosen_select',
218
- 'options' => $this->get_user_roles(),
219
  ),
220
  array(
221
  'title' => __( 'Product Status', 'woocommerce-jetpack' ),
@@ -226,7 +229,7 @@ class WCJ_Product_By_User extends WCJ_Module {
226
  ),
227
  array(
228
  'title' => __( 'Add "My Products" Tab to User\'s My Account Page', 'woocommerce-jetpack' ),
229
- 'desc ' => __( 'Add', 'woocommerce-jetpack' ),
230
  'id' => 'wcj_product_by_user_add_to_my_account',
231
  'default' => 'yes',
232
  'type' => 'checkbox',
@@ -237,7 +240,7 @@ class WCJ_Product_By_User extends WCJ_Module {
237
  ),
238
  )
239
  );
240
- return $this->add_standard_settings( $settings, __( 'Use [wcj_product_add_new] shortcode.', 'woocommerce-jetpack' ) );
241
  }
242
  }
243
 
4
  *
5
  * The WooCommerce Jetpack Product by User class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.5.2
9
  * @author Algoritmika Ltd.
10
  */
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 2.5.3
22
  * @since 2.5.2
23
  */
24
  public function __construct() {
25
 
26
  $this->id = 'product_by_user';
27
  $this->short_desc = __( 'Product by User', 'woocommerce-jetpack' );
28
+ $this->desc = __( 'Let users add new WooCommerce products from frontend.', 'woocommerce-jetpack' );
29
  $this->link = 'http://booster.io/features/woocommerce-product-by-user/';
30
  parent::__construct();
31
 
32
+ add_action( 'init', array( $this, 'add_settings_hook' ) );
33
+
34
  if ( $this->is_enabled() ) {
35
  if ( 'yes' === get_option( 'wcj_product_by_user_add_to_my_account', 'yes' ) ) {
36
  add_filter( 'woocommerce_account_menu_items', array( $this, 'add_my_products_tab_my_account_page' ) );
127
  }
128
 
129
  /**
130
+ * add_settings_hook.
131
  *
132
+ * @version 2.5.3
133
+ * @since 2.5.3
134
  */
135
+ function add_settings_hook() {
136
+ add_filter( 'wcj_product_by_user_settings', array( $this, 'add_settings' ) );
 
 
 
 
 
 
 
 
 
 
 
 
137
  }
138
 
139
  /**
140
  * get_settings.
141
  *
142
+ * @version 2.5.3
143
  * @since 2.5.2
144
  */
145
  function get_settings() {
146
+ $settings = apply_filters( 'wcj_product_by_user_settings', array() );
147
+ return $this->add_standard_settings( $settings, __( 'Use [wcj_product_add_new] shortcode.', 'woocommerce-jetpack' ) );
148
+ }
149
+
150
+ /**
151
+ * add_settings.
152
+ *
153
+ * @version 2.5.3
154
+ * @since 2.5.3
155
+ */
156
+ function add_settings() {
157
 
158
  $fields = array(
159
  'desc' => __( 'Description', 'woocommerce-jetpack' ),
212
  array(
213
  array(
214
  'title' => __( 'User Visibility', 'woocommerce-jetpack' ),
215
+ 'desc' => sprintf( __( 'Custom roles can be added via "Add/Manage Custom Roles" tool in Booster\'s <a href="%s">General</a> module', 'woocommerce-jetpack' ),
216
+ admin_url( 'admin.php?page=wc-settings&tab=jetpack&wcj-cat=emails_and_misc&section=general' ) ),
217
  'id' => 'wcj_product_by_user_user_visibility',
218
  'default' => array(),
219
  'type' => 'multiselect',
220
  'class' => 'chosen_select',
221
+ 'options' => wcj_get_user_roles_options(),
222
  ),
223
  array(
224
  'title' => __( 'Product Status', 'woocommerce-jetpack' ),
229
  ),
230
  array(
231
  'title' => __( 'Add "My Products" Tab to User\'s My Account Page', 'woocommerce-jetpack' ),
232
+ 'desc' => __( 'Add', 'woocommerce-jetpack' ),
233
  'id' => 'wcj_product_by_user_add_to_my_account',
234
  'default' => 'yes',
235
  'type' => 'checkbox',
240
  ),
241
  )
242
  );
243
+ return $settings;
244
  }
245
  }
246
 
includes/class-wcj-product-custom-info.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Product Custom Info class.
6
  *
7
- * @version 2.5.0
8
  * @since 2.4.0
9
  * @author Algoritmika Ltd.
10
  */
@@ -18,12 +18,12 @@ class WCJ_Product_Custom_info extends WCJ_Module {
18
  /**
19
  * Constructor.
20
  *
21
- * @version 2.5.0
22
  */
23
  public function __construct() {
24
 
25
  $this->id = 'product_custom_info';
26
- $this->short_desc = __( 'Product Info V2', 'woocommerce-jetpack' );
27
  $this->desc = __( 'Add additional info to WooCommerce category and single product pages.', 'woocommerce-jetpack' );
28
  $this->link = 'http://booster.io/features/woocommerce-product-info/';
29
  parent::__construct();
4
  *
5
  * The WooCommerce Jetpack Product Custom Info class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.4.0
9
  * @author Algoritmika Ltd.
10
  */
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 2.5.3
22
  */
23
  public function __construct() {
24
 
25
  $this->id = 'product_custom_info';
26
+ $this->short_desc = __( 'Product Info', 'woocommerce-jetpack' );
27
  $this->desc = __( 'Add additional info to WooCommerce category and single product pages.', 'woocommerce-jetpack' );
28
  $this->link = 'http://booster.io/features/woocommerce-product-info/';
29
  parent::__construct();
includes/class-wcj-product-info.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Product Info class.
6
  *
7
- * @version 2.5.0
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -95,12 +95,12 @@ class WCJ_Product_Info extends WCJ_Module {
95
  /**
96
  * Constructor.
97
  *
98
- * @version 2.5.0
99
  */
100
  function __construct() {
101
 
102
  $this->id = 'product_info';
103
- $this->short_desc = __( 'Product Info', 'woocommerce-jetpack' );
104
  $this->desc = __( 'Add additional info to WooCommerce category and single product pages.', 'woocommerce-jetpack' );
105
  $this->link = 'http://booster.io/features/woocommerce-product-info/';
106
  parent::__construct();
4
  *
5
  * The WooCommerce Jetpack Product Info class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
95
  /**
96
  * Constructor.
97
  *
98
+ * @version 2.5.3
99
  */
100
  function __construct() {
101
 
102
  $this->id = 'product_info';
103
+ $this->short_desc = __( 'Product Info V1', 'woocommerce-jetpack' );
104
  $this->desc = __( 'Add additional info to WooCommerce category and single product pages.', 'woocommerce-jetpack' );
105
  $this->link = 'http://booster.io/features/woocommerce-product-info/';
106
  parent::__construct();
includes/class-wcj-product-listings.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Product Listings class.
6
  *
7
- * @version 2.4.8
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -17,28 +17,110 @@ class WCJ_Product_Listings extends WCJ_Module {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.4.8
 
21
  */
22
  public function __construct() {
23
  $this->id = 'product_listings';
24
  $this->short_desc = __( 'Product Listings', 'woocommerce-jetpack' );
25
- $this->desc = __( 'Change WooCommerce display options for shop and category pages: show/hide categories count, exclude categories, show/hide empty categories.', 'woocommerce-jetpack' );
26
  $this->link = 'http://booster.io/features/woocommerce-product-listings/';
27
  parent::__construct();
28
 
29
  if ( $this->is_enabled() ) {
 
30
  // Exclude and Hide Empty
31
  add_filter( 'woocommerce_product_subcategories_args', array( $this, 'filter_subcategories' ), 100 );
32
  add_filter( 'woocommerce_product_subcategories_hide_empty', array( $this, 'filter_subcategories_show_empty' ), 100 );
 
33
  // Hide Count
34
  if ( 'yes' === get_option( 'wcj_product_listings_hide_cats_count_on_shop' ) || 'yes' === get_option( 'wcj_product_listings_hide_cats_count_on_archive' ) ) {
35
  add_filter( 'woocommerce_subcategory_count_html', array( $this, 'remove_subcategory_count' ), 100 );
36
  }
 
 
 
 
 
 
 
 
 
 
37
  // Settings to "WooCommerce > Settings > Products > Product Listings"
38
  add_filter( 'woocommerce_product_settings', array( $this, 'add_fields_to_woocommerce_settings' ), 100 );
39
  }
40
  }
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  /**
43
  * remove_subcategory_count.
44
  */
@@ -58,10 +140,10 @@ class WCJ_Product_Listings extends WCJ_Module {
58
  public function filter_subcategories( $args ) {
59
  if ( is_shop() ) {
60
  $args['exclude'] = get_option( 'wcj_product_listings_exclude_cats_on_shop' );
61
- $args['hide_empty'] = ( 'yes' === get_option( 'wcj_product_listings_hide_empty_cats_on_shop' ) ) ? 1 : 0; // depreciated?
62
  } else {
63
  $args['exclude'] = get_option( 'wcj_product_listings_exclude_cats_on_archives' );
64
- $args['hide_empty'] = ( 'yes' === get_option( 'wcj_product_listings_hide_empty_cats_on_archives' ) ) ? 1 : 0; // depreciated?
65
  }
66
  return $args;
67
  }
@@ -186,7 +268,7 @@ class WCJ_Product_Listings extends WCJ_Module {
186
  /**
187
  * get_settings.
188
  *
189
- * @version 2.4.6
190
  */
191
  function get_settings() {
192
  $settings = array(
@@ -270,6 +352,64 @@ class WCJ_Product_Listings extends WCJ_Module {
270
  'type' => 'sectionend',
271
  'id' => 'wcj_product_listings_archive_pages_options',
272
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
  );
274
  return $this->add_standard_settings( $settings );
275
  }
4
  *
5
  * The WooCommerce Jetpack Product Listings class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 2.5.3
21
+ * @todo products per page - position priority for every hook; post or get.
22
  */
23
  public function __construct() {
24
  $this->id = 'product_listings';
25
  $this->short_desc = __( 'Product Listings', 'woocommerce-jetpack' );
26
+ $this->desc = __( 'Change WooCommerce display options for shop and category pages: show/hide categories count, exclude categories, show/hide empty categories. Add "products per page" selector.', 'woocommerce-jetpack' );
27
  $this->link = 'http://booster.io/features/woocommerce-product-listings/';
28
  parent::__construct();
29
 
30
  if ( $this->is_enabled() ) {
31
+
32
  // Exclude and Hide Empty
33
  add_filter( 'woocommerce_product_subcategories_args', array( $this, 'filter_subcategories' ), 100 );
34
  add_filter( 'woocommerce_product_subcategories_hide_empty', array( $this, 'filter_subcategories_show_empty' ), 100 );
35
+
36
  // Hide Count
37
  if ( 'yes' === get_option( 'wcj_product_listings_hide_cats_count_on_shop' ) || 'yes' === get_option( 'wcj_product_listings_hide_cats_count_on_archive' ) ) {
38
  add_filter( 'woocommerce_subcategory_count_html', array( $this, 'remove_subcategory_count' ), 100 );
39
  }
40
+
41
+ // Products per Page
42
+ if ( 'yes' === get_option( 'wcj_products_per_page_enabled', 'no' ) ) {
43
+ add_filter( 'loop_shop_per_page', array( $this, 'set_products_per_page_number' ), PHP_INT_MAX );
44
+ $position_hooks = get_option( 'wcj_products_per_page_position', array( 'woocommerce_before_shop_loop' ) );
45
+ foreach ( $position_hooks as $position_hook ) {
46
+ add_action( $position_hook, array( $this, 'add_products_per_page_form' ), get_option( 'wcj_products_per_page_position_priority', 40 ) );
47
+ }
48
+ }
49
+
50
  // Settings to "WooCommerce > Settings > Products > Product Listings"
51
  add_filter( 'woocommerce_product_settings', array( $this, 'add_fields_to_woocommerce_settings' ), 100 );
52
  }
53
  }
54
 
55
+ /**
56
+ * add_products_per_page_form.
57
+ *
58
+ * @version 2.5.3
59
+ * @since 2.5.3
60
+ */
61
+ function add_products_per_page_form() {
62
+
63
+ global $wp_query;
64
+
65
+ if ( isset( $_POST['wcj_products_per_page'] ) ) {
66
+ $products_per_page = $_POST['wcj_products_per_page'];
67
+ } elseif ( isset( $_COOKIE['wcj_products_per_page'] ) ) {
68
+ $products_per_page = $_COOKIE['wcj_products_per_page'];
69
+ } else {
70
+ $products_per_page = get_option( 'wcj_products_per_page_default', get_option( 'posts_per_page' ) ); // default
71
+ }
72
+
73
+ $paged = get_query_var( 'paged' );
74
+ if ( 0 == $paged ) {
75
+ $paged = 1;
76
+ }
77
+
78
+ $products_from = ( $paged - 1 ) * $products_per_page + 1;
79
+ $products_to = ( $paged - 1 ) * $products_per_page + $wp_query->post_count;
80
+ $products_total = $wp_query->found_posts;
81
+
82
+ $html = '';
83
+ $html .= '<div class="clearfix"></div>';
84
+ $html .= '<div>';
85
+ $html .= '<form action="' . remove_query_arg( 'paged' ) . '" method="POST">';
86
+ $the_text = get_option( 'wcj_products_per_page_text', __( 'Products <strong>%from% - %to%</strong> from <strong>%total%</strong>. Products on page %select_form%', 'woocommerce-jetpack' ) );
87
+ $select_form = '<select name="wcj_products_per_page" id="wcj_products_per_page" class="sortby rounded_corners_class" onchange="this.form.submit()">';
88
+ $html .= str_replace( array( '%from%', '%to%', '%total%', '%select_form%' ), array( $products_from, $products_to, $products_total, $select_form ), $the_text );
89
+ $products_per_page_select_options = apply_filters( 'wcj_get_option_filter', '10|10' . PHP_EOL . '25|25' . PHP_EOL . '50|50' . PHP_EOL . '100|100' . PHP_EOL . 'All|-1', get_option( 'wcj_products_per_page_select_options', '10|10' . PHP_EOL . '25|25' . PHP_EOL . '50|50' . PHP_EOL . '100|100' . PHP_EOL . 'All|-1' ) );
90
+ $products_per_page_select_options = explode( PHP_EOL, $products_per_page_select_options );
91
+ foreach ( $products_per_page_select_options as $products_per_page_select_option ) {
92
+ $the_option = explode( '|', $products_per_page_select_option );
93
+ if ( 2 === count( $the_option ) ) {
94
+ $sort_id = $the_option[1];
95
+ $sort_name = $the_option[0];
96
+ $html .= '<option value="' . $sort_id . '" ' . selected( $products_per_page, $sort_id, false ) . ' >' . $sort_name . '</option>';
97
+ }
98
+ }
99
+ $html .= '</select>';
100
+ $html .= '</form>';
101
+ $html .= '</div>';
102
+
103
+ echo $html;
104
+ }
105
+
106
+ /**
107
+ * set_products_per_page_number.
108
+ *
109
+ * @version 2.5.3
110
+ * @since 2.5.3
111
+ */
112
+ function set_products_per_page_number( $the_number ) {
113
+ if ( isset( $_POST['wcj_products_per_page'] ) ) {
114
+ $the_number = $_POST['wcj_products_per_page'];
115
+ setcookie( 'wcj_products_per_page', $the_number, ( time() + 1209600 ), '/', $_SERVER['SERVER_NAME'], false );
116
+ } elseif ( isset( $_COOKIE['wcj_products_per_page'] ) ) {
117
+ $the_number = $_COOKIE['wcj_products_per_page'];
118
+ } else {
119
+ $the_number = get_option( 'wcj_products_per_page_default', get_option( 'posts_per_page' ) );
120
+ }
121
+ return $the_number;
122
+ }
123
+
124
  /**
125
  * remove_subcategory_count.
126
  */
140
  public function filter_subcategories( $args ) {
141
  if ( is_shop() ) {
142
  $args['exclude'] = get_option( 'wcj_product_listings_exclude_cats_on_shop' );
143
+ $args['hide_empty'] = ( 'yes' === get_option( 'wcj_product_listings_hide_empty_cats_on_shop' ) ) ? 1 : 0; // depreciated?
144
  } else {
145
  $args['exclude'] = get_option( 'wcj_product_listings_exclude_cats_on_archives' );
146
+ $args['hide_empty'] = ( 'yes' === get_option( 'wcj_product_listings_hide_empty_cats_on_archives' ) ) ? 1 : 0; // depreciated?
147
  }
148
  return $args;
149
  }
268
  /**
269
  * get_settings.
270
  *
271
+ * @version 2.5.3
272
  */
273
  function get_settings() {
274
  $settings = array(
352
  'type' => 'sectionend',
353
  'id' => 'wcj_product_listings_archive_pages_options',
354
  ),
355
+ array(
356
+ 'title' => __( 'Products per Page Options', 'woocommerce-jetpack' ),
357
+ 'type' => 'title',
358
+ 'id' => 'wcj_products_per_page_options',
359
+ ),
360
+ array(
361
+ 'title' => __( 'Enable Products per Page', 'woocommerce-jetpack' ),
362
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
363
+ 'id' => 'wcj_products_per_page_enabled',
364
+ 'default' => 'no',
365
+ 'type' => 'checkbox',
366
+ ),
367
+ array(
368
+ 'title' => __( 'Select Options', 'woocommerce-jetpack' ),
369
+ 'desc' => __( 'Name|Number; one per line; -1 for all products', 'woocommerce-jetpack' ),
370
+ 'id' => 'wcj_products_per_page_select_options',
371
+ 'default' => '10|10' . PHP_EOL . '25|25' . PHP_EOL . '50|50' . PHP_EOL . '100|100' . PHP_EOL . 'All|-1',
372
+ 'type' => 'textarea',
373
+ 'css' => 'height:200px;',
374
+ 'custom_attributes' => apply_filters( 'get_wc_jetpack_plus_message', '', 'readonly' ),
375
+ 'desc_tip' => apply_filters( 'get_wc_jetpack_plus_message', '', 'desc_no_link' ),
376
+ ),
377
+ array(
378
+ 'title' => __( 'Default', 'woocommerce-jetpack' ),
379
+ 'id' => 'wcj_products_per_page_default',
380
+ 'default' => get_option( 'posts_per_page' ),
381
+ 'type' => 'number',
382
+ 'custom_attributes' => array( 'min' => -1 ),
383
+ ),
384
+ array(
385
+ 'title' => __( 'Position', 'woocommerce-jetpack' ),
386
+ 'id' => 'wcj_products_per_page_position',
387
+ 'default' => array( 'woocommerce_before_shop_loop' ),
388
+ 'type' => 'multiselect',
389
+ 'class' => 'chosen_select',
390
+ 'options' => array(
391
+ 'woocommerce_before_shop_loop' => __( 'Before shop loop', 'woocommerce-jetpack' ),
392
+ 'woocommerce_after_shop_loop' => __( 'After shop loop', 'woocommerce-jetpack' ),
393
+ ),
394
+ ),
395
+ array(
396
+ 'title' => __( 'Position Priority', 'woocommerce-jetpack' ),
397
+ 'id' => 'wcj_products_per_page_position_priority',
398
+ 'default' => 40,
399
+ 'type' => 'number',
400
+ 'custom_attributes' => array( 'min' => 0 ),
401
+ ),
402
+ array(
403
+ 'title' => __( 'Text', 'woocommerce-jetpack' ),
404
+ 'id' => 'wcj_products_per_page_text',
405
+ 'default' => __( 'Products <strong>%from% - %to%</strong> from <strong>%total%</strong>. Products on page %select_form%', 'woocommerce-jetpack' ),
406
+ 'type' => 'textarea',
407
+ 'css' => 'width:66%;min-width:300px;',
408
+ ),
409
+ array(
410
+ 'type' => 'sectionend',
411
+ 'id' => 'wcj_products_per_page_options',
412
+ ),
413
  );
414
  return $this->add_standard_settings( $settings );
415
  }
includes/class-wcj-reports.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Reports class.
6
  *
7
- * @version 2.5.0
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -232,7 +232,7 @@ class WCJ_Reports extends WCJ_Module {
232
  /**
233
  * Add reports to WooCommerce > Reports > Sales
234
  *
235
- * @version 2.4.7
236
  * @since 2.3.0
237
  */
238
  public function add_sales_reports( $reports ) {
@@ -245,7 +245,7 @@ class WCJ_Reports extends WCJ_Module {
245
  );
246
 
247
  $reports['orders']['reports']['booster_monthly_sales'] = array(
248
- 'title' => __( 'Booster: Monthly Sales', 'woocommerce-jetpack' ) . ' <sup>[' . __( 'Beta', 'woocommerce-jetpack' ) . ']</sup>',
249
  'description' => '',
250
  'hide_title' => false,
251
  'callback' => array( $this, 'get_report_monthly_sales' ),
4
  *
5
  * The WooCommerce Jetpack Reports class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
232
  /**
233
  * Add reports to WooCommerce > Reports > Sales
234
  *
235
+ * @version 2.5.3
236
  * @since 2.3.0
237
  */
238
  public function add_sales_reports( $reports ) {
245
  );
246
 
247
  $reports['orders']['reports']['booster_monthly_sales'] = array(
248
+ 'title' => __( 'Booster: Monthly Sales', 'woocommerce-jetpack' ),
249
  'description' => '',
250
  'hide_title' => false,
251
  'callback' => array( $this, 'get_report_monthly_sales' ),
includes/class-wcj-shipping.php CHANGED
@@ -4,8 +4,9 @@
4
  *
5
  * The WooCommerce Jetpack Shipping class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
 
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
@@ -17,7 +18,7 @@ class WCJ_Shipping extends WCJ_Module {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.5.0
21
  */
22
  function __construct() {
23
 
@@ -32,11 +33,16 @@ class WCJ_Shipping extends WCJ_Module {
32
 
33
  if ( $this->is_enabled() ) {
34
 
 
35
  include_once( 'shipping/class-wc-shipping-wcj-custom.php' );
36
 
37
- add_filter( 'woocommerce_package_rates', array( $this, 'hide_shipping_when_free_is_available' ), 10, 2 );
 
 
 
38
  add_filter( 'woocommerce_shipping_settings', array( $this, 'add_hide_shipping_if_free_available_fields' ), 100 );
39
 
 
40
  if ( 'yes' === get_option( 'wcj_shipping_left_to_free_info_enabled_cart', 'no' ) ) {
41
  add_action(
42
  get_option( 'wcj_shipping_left_to_free_info_position_cart', 'woocommerce_after_cart_totals' ),
@@ -104,35 +110,32 @@ class WCJ_Shipping extends WCJ_Module {
104
  /**
105
  * hide_shipping_when_free_is_available.
106
  *
107
- * @version 2.4.4
 
108
  */
109
  function hide_shipping_when_free_is_available( $rates, $package ) {
110
- // Only modify rates if free_shipping is present
111
- if ( isset( $rates['free_shipping'] ) ) {
112
- // Unset a single rate/method
113
- if ( 'yes' === get_option( 'wcj_shipping_hide_if_free_available_local_delivery' ) ) {
114
- unset( $rates['local_delivery'] );
115
- }
116
- if ( 'yes' === get_option( 'wcj_shipping_hide_if_free_available_all' ) ) {
117
- // Unset all methods except for free_shipping
118
- $free_shipping = $rates['free_shipping'];
119
- $rates = array();
120
- $rates['free_shipping'] = $free_shipping;
121
  }
122
  }
123
- return $rates;
124
  }
125
 
126
  /**
127
  * add_hide_shipping_if_free_available_fields.
128
  *
129
- * @version 2.4.4
130
  */
131
  function add_hide_shipping_if_free_available_fields( $settings ) {
132
  $updated_settings = array();
133
  foreach ( $settings as $section ) {
134
- if ( isset( $section['type'] ) && 'shipping_methods' === $section['type'] ) {
135
- $updated_settings[] = array(
 
136
  'title' => __( 'Booster: Hide shipping', 'woocommerce-jetpack' ),
137
  'desc' => __( 'Hide local delivery when free is available', 'woocommerce-jetpack' ),
138
  'desc_tip' => __( '', 'woocommerce-jetpack' ),
@@ -140,17 +143,16 @@ class WCJ_Shipping extends WCJ_Module {
140
  'default' => 'no',
141
  'type' => 'checkbox',
142
  'checkboxgroup' => 'start',
143
- );
144
  $updated_settings[] = array(
 
145
  'desc' => __( 'Hide all when free is available', 'woocommerce-jetpack' ),
146
- 'desc_tip' => __( '', 'woocommerce-jetpack' ),
147
  'id' => 'wcj_shipping_hide_if_free_available_all',
148
  'default' => 'no',
149
  'type' => 'checkbox',
150
- 'checkboxgroup' => 'end',
151
  );
152
  }
153
- $updated_settings[] = $section;
154
  }
155
  return $updated_settings;
156
  }
@@ -158,7 +160,7 @@ class WCJ_Shipping extends WCJ_Module {
158
  /**
159
  * get_settings.
160
  *
161
- * @version 2.4.8
162
  */
163
  function get_settings() {
164
  $wocommerce_shipping_settings_url = admin_url( 'admin.php?page=wc-settings&tab=shipping' );
@@ -201,25 +203,26 @@ class WCJ_Shipping extends WCJ_Module {
201
  ) );
202
  $settings = array_merge( $settings, array(
203
  array(
204
- 'title' => __( 'Hide if free is available', 'woocommerce-jetpack' ),
205
  'type' => 'title',
206
  'desc' => __( 'This section lets you hide other shipping options when free shipping is available on shop frontend.', 'woocommerce-jetpack' ),
207
  'id' => 'wcj_shipping_hide_if_free_available_options',
208
  ),
209
- array(
210
  'title' => __( 'Hide shipping', 'woocommerce-jetpack' ),
211
  'desc' => __( 'Hide local delivery when free is available', 'woocommerce-jetpack' ),
212
  'id' => 'wcj_shipping_hide_if_free_available_local_delivery',
213
  'default' => 'no',
214
  'type' => 'checkbox',
215
  'checkboxgroup' => 'start',
216
- ),
217
  array(
 
218
  'desc' => __( 'Hide all when free is available', 'woocommerce-jetpack' ),
219
  'id' => 'wcj_shipping_hide_if_free_available_all',
220
  'default' => 'no',
221
  'type' => 'checkbox',
222
- 'checkboxgroup' => 'end',
223
  ),
224
  array(
225
  'type' => 'sectionend',
4
  *
5
  * The WooCommerce Jetpack Shipping class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
+ * @todo Redo custom shipping methods according to new (since WC v2.6.0) shipping zones mechanism
10
  */
11
 
12
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 2.5.3
22
  */
23
  function __construct() {
24
 
33
 
34
  if ( $this->is_enabled() ) {
35
 
36
+ // Custom Shipping
37
  include_once( 'shipping/class-wc-shipping-wcj-custom.php' );
38
 
39
+ // Hide if free is available
40
+ if ( 'yes' === get_option( 'wcj_shipping_hide_if_free_available_all', 'no' ) ) {
41
+ add_filter( 'woocommerce_package_rates', array( $this, 'hide_shipping_when_free_is_available' ), 10, 2 );
42
+ }
43
  add_filter( 'woocommerce_shipping_settings', array( $this, 'add_hide_shipping_if_free_available_fields' ), 100 );
44
 
45
+ // Left to Free Shipping
46
  if ( 'yes' === get_option( 'wcj_shipping_left_to_free_info_enabled_cart', 'no' ) ) {
47
  add_action(
48
  get_option( 'wcj_shipping_left_to_free_info_position_cart', 'woocommerce_after_cart_totals' ),
110
  /**
111
  * hide_shipping_when_free_is_available.
112
  *
113
+ * @version 2.5.3
114
+ * @todo if ( 'yes' === get_option( 'wcj_shipping_hide_if_free_available_local_delivery' ) ) { unset( $rates['local_delivery'] ); }
115
  */
116
  function hide_shipping_when_free_is_available( $rates, $package ) {
117
+ $free_shipping_rates = array();
118
+ $is_free_shipping_available = false;
119
+ foreach ( $rates as $rate_key => $rate ) {
120
+ if ( false !== strpos( $rate_key, 'free_shipping' ) ) {
121
+ $is_free_shipping_available = true;
122
+ $free_shipping_rates[ $rate_key ] = $rate;
 
 
 
 
 
123
  }
124
  }
125
+ return ( $is_free_shipping_available ) ? $free_shipping_rates : $rates;
126
  }
127
 
128
  /**
129
  * add_hide_shipping_if_free_available_fields.
130
  *
131
+ * @version 2.5.3
132
  */
133
  function add_hide_shipping_if_free_available_fields( $settings ) {
134
  $updated_settings = array();
135
  foreach ( $settings as $section ) {
136
+ $updated_settings[] = $section;
137
+ if ( isset( $section['id'] ) && 'woocommerce_ship_to_destination' === $section['id'] ) {
138
+ /* $updated_settings[] = array(
139
  'title' => __( 'Booster: Hide shipping', 'woocommerce-jetpack' ),
140
  'desc' => __( 'Hide local delivery when free is available', 'woocommerce-jetpack' ),
141
  'desc_tip' => __( '', 'woocommerce-jetpack' ),
143
  'default' => 'no',
144
  'type' => 'checkbox',
145
  'checkboxgroup' => 'start',
146
+ ); */
147
  $updated_settings[] = array(
148
+ 'title' => __( 'Booster: Hide shipping', 'woocommerce-jetpack' ),
149
  'desc' => __( 'Hide all when free is available', 'woocommerce-jetpack' ),
 
150
  'id' => 'wcj_shipping_hide_if_free_available_all',
151
  'default' => 'no',
152
  'type' => 'checkbox',
153
+ /* 'checkboxgroup' => 'end', */
154
  );
155
  }
 
156
  }
157
  return $updated_settings;
158
  }
160
  /**
161
  * get_settings.
162
  *
163
+ * @version 2.5.3
164
  */
165
  function get_settings() {
166
  $wocommerce_shipping_settings_url = admin_url( 'admin.php?page=wc-settings&tab=shipping' );
203
  ) );
204
  $settings = array_merge( $settings, array(
205
  array(
206
+ 'title' => __( 'Hide if Free is Available', 'woocommerce-jetpack' ),
207
  'type' => 'title',
208
  'desc' => __( 'This section lets you hide other shipping options when free shipping is available on shop frontend.', 'woocommerce-jetpack' ),
209
  'id' => 'wcj_shipping_hide_if_free_available_options',
210
  ),
211
+ /* array(
212
  'title' => __( 'Hide shipping', 'woocommerce-jetpack' ),
213
  'desc' => __( 'Hide local delivery when free is available', 'woocommerce-jetpack' ),
214
  'id' => 'wcj_shipping_hide_if_free_available_local_delivery',
215
  'default' => 'no',
216
  'type' => 'checkbox',
217
  'checkboxgroup' => 'start',
218
+ ), */
219
  array(
220
+ 'title' => __( 'Hide shipping', 'woocommerce-jetpack' ),
221
  'desc' => __( 'Hide all when free is available', 'woocommerce-jetpack' ),
222
  'id' => 'wcj_shipping_hide_if_free_available_all',
223
  'default' => 'no',
224
  'type' => 'checkbox',
225
+ /* 'checkboxgroup' => 'end', */
226
  ),
227
  array(
228
  'type' => 'sectionend',
includes/class-wcj-sku.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack SKU class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
9
  * @todo add "random number" option
10
  */
@@ -18,7 +18,7 @@ class WCJ_SKU extends WCJ_Module {
18
  /**
19
  * Constructor.
20
  *
21
- * @version 2.4.8
22
  */
23
  function __construct() {
24
 
@@ -36,7 +36,12 @@ class WCJ_SKU extends WCJ_Module {
36
  ) );
37
 
38
  if ( $this->is_enabled() ) {
 
39
  add_action( 'wp_insert_post', array( $this, 'set_sku_for_new_product' ), PHP_INT_MAX, 3 );
 
 
 
 
40
  }
41
  }
42
 
@@ -242,7 +247,7 @@ class WCJ_SKU extends WCJ_Module {
242
  /**
243
  * get_settings.
244
  *
245
- * @version 2.5.2
246
  */
247
  function get_settings() {
248
  $settings = array(
@@ -352,6 +357,24 @@ class WCJ_SKU extends WCJ_Module {
352
  'id' => 'wcj_sku_categories_options',
353
  ),
354
  ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
355
  return $this->add_standard_settings(
356
  $settings,
357
  __( 'When enabled - all new products will be given (autogenerated) SKU.', 'woocommerce-jetpack' ) . '<br>' .
4
  *
5
  * The WooCommerce Jetpack SKU class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  * @todo add "random number" option
10
  */
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 2.5.3
22
  */
23
  function __construct() {
24
 
36
  ) );
37
 
38
  if ( $this->is_enabled() ) {
39
+
40
  add_action( 'wp_insert_post', array( $this, 'set_sku_for_new_product' ), PHP_INT_MAX, 3 );
41
+
42
+ if ( 'yes' === get_option( 'wcj_sku_allow_duplicates_enabled', 'no' ) ) {
43
+ add_filter( 'wc_product_has_unique_sku', '__return_false', PHP_INT_MAX );
44
+ }
45
  }
46
  }
47
 
247
  /**
248
  * get_settings.
249
  *
250
+ * @version 2.5.3
251
  */
252
  function get_settings() {
253
  $settings = array(
357
  'id' => 'wcj_sku_categories_options',
358
  ),
359
  ) );
360
+ $settings = array_merge( $settings, array(
361
+ array(
362
+ 'title' => __( 'More Options', 'woocommerce-jetpack' ),
363
+ 'type' => 'title',
364
+ 'id' => 'wcj_sku_more_options',
365
+ ),
366
+ array(
367
+ 'title' => __( 'Allow Duplicate SKUs', 'woocommerce-jetpack' ),
368
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
369
+ 'id' => 'wcj_sku_allow_duplicates_enabled',
370
+ 'default' => 'no',
371
+ 'type' => 'checkbox',
372
+ ),
373
+ array(
374
+ 'type' => 'sectionend',
375
+ 'id' => 'wcj_sku_more_options',
376
+ ),
377
+ ) );
378
  return $this->add_standard_settings(
379
  $settings,
380
  __( 'When enabled - all new products will be given (autogenerated) SKU.', 'woocommerce-jetpack' ) . '<br>' .
includes/classes/class-wcj-module.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Module class.
6
  *
7
- * @version 2.5.0
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
@@ -37,6 +37,62 @@ if ( ! class_exists( 'WCJ_Module' ) ) :
37
  add_action( 'init', array( $this, 'reset_settings' ), PHP_INT_MAX );
38
  }
39
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  /**
41
  * reset_settings.
42
  *
@@ -433,7 +489,7 @@ if ( ! class_exists( 'WCJ_Module' ) ) :
433
  * settings_section.
434
  * only for `module`
435
  *
436
- * @version 2.4.8
437
  */
438
  function add_enable_module_setting( $settings, $module_desc = '' ) {
439
  if ( 'module' != $this->type ) {
@@ -441,9 +497,9 @@ if ( ! class_exists( 'WCJ_Module' ) ) :
441
  }
442
  $the_link = '';
443
  if ( isset( $this->link ) && '' != $this->link ) {
444
- $the_link = ' <a class="button-primary"' .
445
  ' style="background: green; border-color: green; box-shadow: 0 1px 0 green; text-shadow: 0 -1px 1px #0a0,1px 0 1px #0a0,0 1px 1px #0a0,-1px 0 1px #0a0;"' .
446
- ' href="' . $this->link . '?utm_source=module_documentation&utm_medium=module_button&utm_campaign=booster_documentation" target="_blank">' . __( 'Documentation', 'woocommerce-jetpack' ) . '</a>';
447
  }
448
  $enable_module_setting = array(
449
  array(
4
  *
5
  * The WooCommerce Jetpack Module class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.2.0
9
  * @author Algoritmika Ltd.
10
  */
37
  add_action( 'init', array( $this, 'reset_settings' ), PHP_INT_MAX );
38
  }
39
 
40
+ /**
41
+ * save_meta_box_value.
42
+ *
43
+ * @version 2.5.3
44
+ * @since 2.5.3
45
+ */
46
+ function save_meta_box_value( $option_value, $option_name, $module_id ) {
47
+ if ( true === apply_filters( 'wcj_get_option_filter', false, true ) ) {
48
+ return $option_value;
49
+ }
50
+ if ( 'no' === $option_value ) {
51
+ return $option_value;
52
+ }
53
+ if ( $this->id === $module_id && $this->co === $option_name ) {
54
+ $args = array(
55
+ 'post_type' => 'product',
56
+ 'post_status' => 'any',
57
+ 'posts_per_page' => 3,
58
+ 'meta_key' => '_' . $this->co,
59
+ 'meta_value' => 'yes',
60
+ 'post__not_in' => array( get_the_ID() ),
61
+ );
62
+ $loop = new WP_Query( $args );
63
+ $c = $loop->found_posts + 1;
64
+ if ( $c >= 4 ) {
65
+ add_filter( 'redirect_post_location', array( $this, 'add_notice_query_var' ), 99 );
66
+ return 'no';
67
+ }
68
+ }
69
+ return $option_value;
70
+ }
71
+
72
+ /**
73
+ * add_notice_query_var.
74
+ *
75
+ * @version 2.5.3
76
+ * @since 2.5.3
77
+ */
78
+ function add_notice_query_var( $location ) {
79
+ remove_filter( 'redirect_post_location', array( $this, 'add_notice_query_var' ), 99 );
80
+ return add_query_arg( array( 'wcj_' . $this->id . '_admin_notice' => true ), $location );
81
+ }
82
+
83
+ /**
84
+ * admin_notices.
85
+ *
86
+ * @version 2.5.3
87
+ * @since 2.5.3
88
+ */
89
+ function admin_notices() {
90
+ if ( ! isset( $_GET[ 'wcj_' . $this->id . '_admin_notice' ] ) ) {
91
+ return;
92
+ }
93
+ echo '<div class="error"><p><div class="message">' . $this->get_the_notice() . '</div></p></div>';
94
+ }
95
+
96
  /**
97
  * reset_settings.
98
  *
489
  * settings_section.
490
  * only for `module`
491
  *
492
+ * @version 2.5.3
493
  */
494
  function add_enable_module_setting( $settings, $module_desc = '' ) {
495
  if ( 'module' != $this->type ) {
497
  }
498
  $the_link = '';
499
  if ( isset( $this->link ) && '' != $this->link ) {
500
+ $the_link = '<p><a class="button-primary"' .
501
  ' style="background: green; border-color: green; box-shadow: 0 1px 0 green; text-shadow: 0 -1px 1px #0a0,1px 0 1px #0a0,0 1px 1px #0a0,-1px 0 1px #0a0;"' .
502
+ ' href="' . $this->link . '?utm_source=module_documentation&utm_medium=module_button&utm_campaign=booster_documentation" target="_blank">' . __( 'Documentation', 'woocommerce-jetpack' ) . '</a></p>';
503
  }
504
  $enable_module_setting = array(
505
  array(
includes/css/wcj-admin.css ADDED
@@ -0,0 +1,10 @@
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * wcj-admin.
3
+ *
4
+ * @version 2.5.3
5
+ * @since 2.5.3
6
+ */
7
+
8
+ img.wcj-rocket-icon:hover {
9
+ box-shadow: 0 1px 0 #C43F15;
10
+ }
includes/emails/class-wc-email-wcj-custom.php CHANGED
@@ -11,7 +11,7 @@ if ( ! class_exists( 'WC_Email_WCJ_Custom' ) ) :
11
  *
12
  * An email sent to recipient list when selected triggers are called.
13
  *
14
- * @version 2.4.8
15
  * @since 2.3.9
16
  * @author Algoritmika Ltd.
17
  * @extends WC_Email
@@ -21,7 +21,7 @@ class WC_Email_WCJ_Custom extends WC_Email {
21
  /**
22
  * Constructor
23
  *
24
- * @version 2.4.8
25
  */
26
  function __construct( $id = 1 ) {
27
 
@@ -42,10 +42,10 @@ class WC_Email_WCJ_Custom extends WC_Email {
42
  $is_woocommerce_new_order_notification_added = false;
43
  foreach ( $trigger_hooks as $trigger_hook ) {
44
  if ( false !== strpos( $trigger_hook, 'woocommerce_new_order_notification' ) && false === $is_woocommerce_new_order_notification_added ) {
45
- add_action( 'woocommerce_new_order_notification', array( $this, 'trigger' ) );
46
  $is_woocommerce_new_order_notification_added = true;
47
  } else {
48
- add_action( $trigger_hook, array( $this, 'trigger' ) );
49
  }
50
  }
51
  }
@@ -80,12 +80,18 @@ class WC_Email_WCJ_Custom extends WC_Email {
80
  /**
81
  * Trigger.
82
  *
83
- * @version 2.4.5
 
84
  */
85
  function trigger( $order_id ) {
86
 
 
 
 
 
87
  if ( $order_id ) {
88
- $this->object = wc_get_order( $order_id );
 
89
 
90
  if ( $this->customer_email ) {
91
  $this->recipient = $this->object->billing_email;
@@ -96,13 +102,7 @@ class WC_Email_WCJ_Custom extends WC_Email {
96
 
97
  $this->replace['order-date'] = date_i18n( wc_date_format(), strtotime( $this->object->order_date ) );
98
  $this->replace['order-number'] = $this->object->get_order_number();
99
- }
100
-
101
- if ( ! $this->is_enabled() || ! $this->get_recipient() ) {
102
- return;
103
- }
104
 
105
- if ( $order_id ) {
106
  global $post;
107
  $order = wc_get_order( $order_id );
108
  if ( 'woocommerce_new_order_notification' === current_filter() ) {
@@ -125,7 +125,18 @@ class WC_Email_WCJ_Custom extends WC_Email {
125
  $post = $order->post;
126
  setup_postdata( $post );
127
  }
 
 
 
 
 
 
 
 
 
 
128
  $this->send( $this->get_recipient(), $this->get_subject(), do_shortcode( $this->get_content() ), $this->get_headers(), $this->get_attachments() );
 
129
  if ( $order_id ) {
130
  wp_reset_postdata();
131
  }
11
  *
12
  * An email sent to recipient list when selected triggers are called.
13
  *
14
+ * @version 2.5.3
15
  * @since 2.3.9
16
  * @author Algoritmika Ltd.
17
  * @extends WC_Email
21
  /**
22
  * Constructor
23
  *
24
+ * @version 2.5.3
25
  */
26
  function __construct( $id = 1 ) {
27
 
42
  $is_woocommerce_new_order_notification_added = false;
43
  foreach ( $trigger_hooks as $trigger_hook ) {
44
  if ( false !== strpos( $trigger_hook, 'woocommerce_new_order_notification' ) && false === $is_woocommerce_new_order_notification_added ) {
45
+ add_action( 'woocommerce_new_order_notification', array( $this, 'trigger' ), PHP_INT_MAX );
46
  $is_woocommerce_new_order_notification_added = true;
47
  } else {
48
+ add_action( $trigger_hook, array( $this, 'trigger' ), PHP_INT_MAX );
49
  }
50
  }
51
  }
80
  /**
81
  * Trigger.
82
  *
83
+ * @version 2.5.3
84
+ * @todo do_shortcode doesn't work for new order notifications
85
  */
86
  function trigger( $order_id ) {
87
 
88
+ if ( ! $this->is_enabled() /* || ! $this->get_recipient() */ ) {
89
+ return;
90
+ }
91
+
92
  if ( $order_id ) {
93
+
94
+ $this->object = wc_get_order( $order_id );
95
 
96
  if ( $this->customer_email ) {
97
  $this->recipient = $this->object->billing_email;
102
 
103
  $this->replace['order-date'] = date_i18n( wc_date_format(), strtotime( $this->object->order_date ) );
104
  $this->replace['order-number'] = $this->object->get_order_number();
 
 
 
 
 
105
 
 
106
  global $post;
107
  $order = wc_get_order( $order_id );
108
  if ( 'woocommerce_new_order_notification' === current_filter() ) {
125
  $post = $order->post;
126
  setup_postdata( $post );
127
  }
128
+
129
+ $this->recipient = do_shortcode( $this->recipient );
130
+
131
+ if ( ! $this->get_recipient() ) {
132
+ if ( $order_id ) {
133
+ wp_reset_postdata();
134
+ }
135
+ return;
136
+ }
137
+
138
  $this->send( $this->get_recipient(), $this->get_subject(), do_shortcode( $this->get_content() ), $this->get_headers(), $this->get_attachments() );
139
+
140
  if ( $order_id ) {
141
  wp_reset_postdata();
142
  }
includes/exchange-rates/class-wcj-exchange-rates-crons.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Exchange Rates Crons class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -23,7 +23,7 @@ class WCJ_Exchange_Rates_Crons {
23
 
24
  add_action( 'wp', array( $this, 'schedule_the_events' ) );
25
  $this->update_intervals = array(
26
- //'manual' => __( 'Enter Rates Manually', 'woocommerce-jetpack' ),
27
  'minutely' => __( 'Update Every Minute', 'woocommerce-jetpack' ),
28
  'hourly' => __( 'Update Hourly', 'woocommerce-jetpack' ),
29
  'twicedaily' => __( 'Update Twice Daily', 'woocommerce-jetpack' ),
@@ -111,7 +111,7 @@ class WCJ_Exchange_Rates_Crons {
111
  /**
112
  * On the scheduled action hook, run a function.
113
  *
114
- * @version 2.5.2
115
  */
116
  function update_the_exchange_rates( $interval ) {
117
 
@@ -190,8 +190,14 @@ class WCJ_Exchange_Rates_Crons {
190
  } else {
191
  $result_message = __( 'Cron job: exchange rates update failed', 'woocommerce-jetpack' );
192
  }
193
- if ( 'yes' === get_option( 'wcj_currency_exchange_logging_enabled', 'no' ) ) {
194
  wcj_log( $result_message . ': ' . $currency_from . $currency_to . ': ' . $the_rate . ': ' . 'update_the_exchange_rates: ' . $interval );
 
 
 
 
 
 
195
  }
196
  }
197
  }
4
  *
5
  * The WooCommerce Jetpack Exchange Rates Crons class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
23
 
24
  add_action( 'wp', array( $this, 'schedule_the_events' ) );
25
  $this->update_intervals = array(
26
+ // 'manual' => __( 'Enter Rates Manually', 'woocommerce-jetpack' ),
27
  'minutely' => __( 'Update Every Minute', 'woocommerce-jetpack' ),
28
  'hourly' => __( 'Update Hourly', 'woocommerce-jetpack' ),
29
  'twicedaily' => __( 'Update Twice Daily', 'woocommerce-jetpack' ),
111
  /**
112
  * On the scheduled action hook, run a function.
113
  *
114
+ * @version 2.5.3
115
  */
116
  function update_the_exchange_rates( $interval ) {
117
 
190
  } else {
191
  $result_message = __( 'Cron job: exchange rates update failed', 'woocommerce-jetpack' );
192
  }
193
+ /* if ( 'yes' === get_option( 'wcj_currency_exchange_logging_enabled', 'no' ) ) {
194
  wcj_log( $result_message . ': ' . $currency_from . $currency_to . ': ' . $the_rate . ': ' . 'update_the_exchange_rates: ' . $interval );
195
+ } */
196
+ }
197
+
198
+ if ( wcj_is_module_enabled( 'price_by_country' ) ) {
199
+ if ( 'yes' === get_option( 'wcj_price_by_country_price_filter_widget_support_enabled', 'no' ) ) {
200
+ wcj_update_products_price_by_country();
201
  }
202
  }
203
  }
includes/functions/wcj-functions.php CHANGED
@@ -4,10 +4,214 @@
4
  *
5
  * The WooCommerce Jetpack Functions.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
9
  */
10
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  if ( ! function_exists( 'wcj_add_files_upload_form_to_checkout_frontend' ) ) {
12
  /**
13
  * wcj_add_files_upload_form_to_checkout_frontend.
@@ -152,7 +356,7 @@ if ( ! function_exists( 'wcj_get_product_input_fields' ) ) {
152
  /*
153
  * wcj_get_left_to_free_shipping.
154
  *
155
- * @version 2.5.2
156
  * @since 2.4.4
157
  * @return string
158
  */
@@ -161,19 +365,50 @@ if ( ! function_exists( 'wcj_get_left_to_free_shipping' ) ) {
161
  if ( '' == $content ) {
162
  $content = __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' );
163
  }
164
- $free_shipping = new WC_Shipping_Free_Shipping();
165
- if ( in_array( $free_shipping->requires, array( 'min_amount', 'either', 'both' ) ) && isset( WC()->cart->cart_contents_total ) ) {
166
- if ( WC()->cart->prices_include_tax ) {
167
- $total = WC()->cart->cart_contents_total + array_sum( WC()->cart->taxes );
168
- } else {
169
- $total = WC()->cart->cart_contents_total;
170
  }
171
- if ( $total >= $free_shipping->min_amount ) {
172
- return do_shortcode( get_option( 'wcj_shipping_left_to_free_info_content_reached', __( 'You have Free delivery', 'woocommerce-jetpack' ) ) );
173
- } else {
174
- $content = str_replace( '%left_to_free%', wc_price( $free_shipping->min_amount - $total ), $content );
175
- $content = str_replace( '%free_shipping_min_amount%', wc_price( $free_shipping->min_amount ), $content );
176
- return $content;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
177
  }
178
  }
179
  }
@@ -425,6 +660,62 @@ if ( ! function_exists( 'is_shop_manager' ) ) {
425
  }
426
  }
427
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
428
  /**
429
  * wcj_is_user_role.
430
  *
4
  *
5
  * The WooCommerce Jetpack Functions.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
11
+ if ( ! function_exists( 'wcj_price_by_country' ) ) {
12
+ /**
13
+ * wcj_price_by_country.
14
+ *
15
+ * @version 2.5.3
16
+ * @since 2.5.3
17
+ */
18
+ function wcj_price_by_country( $price, $product, $group_id, $the_current_filter = '' ) {
19
+
20
+ $is_price_modified = false;
21
+
22
+ if ( 'yes' === get_option( 'wcj_price_by_country_local_enabled' ) ) {
23
+ // Per product
24
+ $meta_box_id = 'price_by_country';
25
+ $scope = 'local';
26
+
27
+ if ( is_numeric( $product ) ) {
28
+ $the_product_id = $product;
29
+ } else {
30
+ $the_product_id = ( isset( $product->variation_id ) ) ? $product->variation_id : $product->id;
31
+ }
32
+
33
+ $meta_id = '_' . 'wcj_' . $meta_box_id . '_make_empty_price_' . $scope . '_' . $group_id;
34
+ if ( 'on' === get_post_meta( $the_product_id, $meta_id, true ) ) {
35
+ return '';
36
+ }
37
+
38
+ $price_by_country = '';
39
+ if ( '' == $the_current_filter ) {
40
+ $the_current_filter = current_filter();
41
+ }
42
+ if ( 'woocommerce_get_price_including_tax' == $the_current_filter || 'woocommerce_get_price_excluding_tax' == $the_current_filter ) {
43
+ $_product = wc_get_product( $the_product_id );
44
+ $get_price_method = 'get_price_' . get_option( 'woocommerce_tax_display_shop' ) . 'uding_tax';
45
+ return $_product->$get_price_method();
46
+
47
+ } elseif ( 'woocommerce_get_price' == $the_current_filter || 'woocommerce_variation_prices_price' == $the_current_filter ) {
48
+
49
+ $regular_or_sale = '_regular_price_';
50
+ $meta_id = '_' . 'wcj_' . $meta_box_id . $regular_or_sale . $scope . '_' . $group_id;
51
+ $regular_price = get_post_meta( $the_product_id, $meta_id, true );
52
+
53
+ $regular_or_sale = '_sale_price_';
54
+ $meta_id = '_' . 'wcj_' . $meta_box_id . $regular_or_sale . $scope . '_' . $group_id;
55
+ $sale_price = get_post_meta( $the_product_id, $meta_id, true );
56
+
57
+ if ( ! empty( $sale_price ) && $sale_price < $regular_price ) {
58
+ $price_by_country = $sale_price;
59
+ } else {
60
+ $price_by_country = $regular_price;
61
+ }
62
+
63
+ }
64
+ elseif (
65
+ 'woocommerce_get_regular_price' == $the_current_filter ||
66
+ 'woocommerce_get_sale_price' == $the_current_filter ||
67
+ 'woocommerce_variation_prices_regular_price' == $the_current_filter ||
68
+ 'woocommerce_variation_prices_sale_price' == $the_current_filter
69
+ ) {
70
+ $regular_or_sale = (
71
+ 'woocommerce_get_regular_price' == $the_current_filter || 'woocommerce_variation_prices_regular_price' == $the_current_filter
72
+ ) ? '_regular_price_' : '_sale_price_';
73
+ $meta_id = '_' . 'wcj_' . $meta_box_id . $regular_or_sale . $scope . '_' . $group_id;
74
+ $price_by_country = get_post_meta( $the_product_id, $meta_id, true );
75
+ }
76
+
77
+ if ( '' != $price_by_country ) {
78
+ $modified_price = $price_by_country;
79
+ $is_price_modified = true;
80
+ }
81
+ }
82
+
83
+ if ( ! $is_price_modified ) {
84
+ if ( 'yes' === get_option( 'wcj_price_by_country_make_empty_price_group_' . $group_id, 1 ) || '' === $price ) {
85
+ return '';
86
+ }
87
+ }
88
+
89
+ if ( ! $is_price_modified ) {
90
+ // Globally
91
+ $country_exchange_rate = get_option( 'wcj_price_by_country_exchange_rate_group_' . $group_id, 1 );
92
+ if ( 1 != $country_exchange_rate ) {
93
+ $modified_price = $price * $country_exchange_rate;
94
+ $rounding = get_option( 'wcj_price_by_country_rounding', 'none' );
95
+ $precision = get_option( 'woocommerce_price_num_decimals', 2 );
96
+ switch ( $rounding ) {
97
+ case 'round':
98
+ $modified_price = round( $modified_price );
99
+ break;
100
+ case 'floor':
101
+ $modified_price = floor( $modified_price );
102
+ break;
103
+ case 'ceil':
104
+ $modified_price = ceil( $modified_price );
105
+ break;
106
+ default: // case 'none':
107
+ $modified_price = round( $modified_price, $precision ); // $modified_price
108
+ break;
109
+ }
110
+ $is_price_modified = true;
111
+ }
112
+ }
113
+
114
+ return ( $is_price_modified ) ? $modified_price : $price;
115
+ }
116
+ }
117
+
118
+ if ( ! function_exists( 'wcj_update_products_price_by_country_for_single_product' ) ) {
119
+ /**
120
+ * wcj_update_products_price_by_country_for_single_product.
121
+ *
122
+ * @version 2.5.3
123
+ * @since 2.5.3
124
+ */
125
+ function wcj_update_products_price_by_country_for_single_product( $product_id ) {
126
+ $_product = wc_get_product( $product_id );
127
+ if ( $_product->is_type( 'variable' ) ) {
128
+ $available_variations = $_product->get_available_variations();
129
+ for ( $i = 1; $i <= apply_filters( 'wcj_get_option_filter', 1, get_option( 'wcj_price_by_country_total_groups_number', 1 ) ); $i++ ) {
130
+ $min_variation_price = PHP_INT_MAX;
131
+ $max_variation_price = 0;
132
+ foreach ( $available_variations as $variation ) {
133
+ $variation_product_id = $variation['variation_id'];
134
+ $_old_variation_price = get_post_meta( $variation_product_id, '_price', true );
135
+ $price_by_country = wcj_price_by_country( $_old_variation_price, $variation_product_id, $i, 'woocommerce_get_price' );
136
+ update_post_meta( $variation_product_id, '_' . 'wcj_price_by_country_' . $i, $price_by_country );
137
+ if ( '' != $price_by_country && $price_by_country < $min_variation_price ) {
138
+ $min_variation_price = $price_by_country;
139
+ }
140
+ if ( $price_by_country > $max_variation_price ) {
141
+ $max_variation_price = $price_by_country;
142
+ }
143
+ }
144
+ delete_post_meta( $product_id, '_' . 'wcj_price_by_country_' . $i );
145
+ add_post_meta( $product_id, '_' . 'wcj_price_by_country_' . $i, $min_variation_price );
146
+ if ( $min_variation_price != $max_variation_price ) {
147
+ add_post_meta( $product_id, '_' . 'wcj_price_by_country_' . $i, $max_variation_price );
148
+ }
149
+ }
150
+ } else {
151
+ $_old_price = get_post_meta( $product_id, '_price', true );
152
+ for ( $i = 1; $i <= apply_filters( 'wcj_get_option_filter', 1, get_option( 'wcj_price_by_country_total_groups_number', 1 ) ); $i++ ) {
153
+ $price_by_country = wcj_price_by_country( $_old_price, $product_id, $i, 'woocommerce_get_price' );
154
+ update_post_meta( $product_id, '_' . 'wcj_price_by_country_' . $i, $price_by_country );
155
+ }
156
+ }
157
+ }
158
+ }
159
+
160
+ if ( ! function_exists( 'wcj_update_products_price_by_country' ) ) {
161
+ /**
162
+ * wcj_update_products_price_by_country - all products.
163
+ *
164
+ * @version 2.5.3
165
+ * @since 2.5.3
166
+ */
167
+ function wcj_update_products_price_by_country() {
168
+ $offset = 0;
169
+ $block_size = 96;
170
+ while( true ) {
171
+ $args = array(
172
+ 'post_type' => 'product',
173
+ 'post_status' => 'any',
174
+ 'posts_per_page' => $block_size,
175
+ 'offset' => $offset,
176
+ 'orderby' => 'title',
177
+ 'order' => 'ASC',
178
+ );
179
+ $loop = new WP_Query( $args );
180
+ if ( ! $loop->have_posts() ) break;
181
+ while ( $loop->have_posts() ) : $loop->the_post();
182
+ $product_id = $loop->post->ID;
183
+ wcj_update_products_price_by_country_for_single_product( $product_id );
184
+ endwhile;
185
+ $offset += $block_size;
186
+ }
187
+ wp_reset_postdata();
188
+ }
189
+ }
190
+
191
+ if ( ! function_exists( 'wcj_get_rocket_icon' ) ) {
192
+ /**
193
+ * wcj_get_rocket_icon.
194
+ *
195
+ * @version 2.5.3
196
+ * @since 2.5.3
197
+ */
198
+ function wcj_get_rocket_icon() {
199
+ return '<img class="wcj-rocket-icon" src="' . plugins_url() . '/' . 'woocommerce-jetpack' . '/assets/images/rocket-icon.png' . '" title="">';
200
+ }
201
+ }
202
+
203
+ if ( ! function_exists( 'wcj_get_5_rocket_image' ) ) {
204
+ /**
205
+ * wcj_get_5_rocket_image.
206
+ *
207
+ * @version 2.5.3
208
+ * @since 2.5.3
209
+ */
210
+ function wcj_get_5_rocket_image() {
211
+ return '<img class="wcj-rocket-icon" src="' . plugins_url() . '/' . 'woocommerce-jetpack' . '/assets/images/5-rockets.png' . '" title="">';
212
+ }
213
+ }
214
+
215
  if ( ! function_exists( 'wcj_add_files_upload_form_to_checkout_frontend' ) ) {
216
  /**
217
  * wcj_add_files_upload_form_to_checkout_frontend.
356
  /*
357
  * wcj_get_left_to_free_shipping.
358
  *
359
+ * @version 2.5.3
360
  * @since 2.4.4
361
  * @return string
362
  */
365
  if ( '' == $content ) {
366
  $content = __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' );
367
  }
368
+ $min_free_shipping_amount = 0;
369
+ $current_wc_version = get_option( 'woocommerce_version', null );
370
+ if ( version_compare( $current_wc_version, '2.6.0', '<' ) ) {
371
+ $free_shipping = new WC_Shipping_Free_Shipping();
372
+ if ( in_array( $free_shipping->requires, array( 'min_amount', 'either', 'both' ) ) ) {
373
+ $min_free_shipping_amount = $free_shipping->min_amount;
374
  }
375
+ } else {
376
+ $legacy_free_shipping = new WC_Shipping_Legacy_Free_Shipping();
377
+ if ( 'yes' === $legacy_free_shipping->enabled ) {
378
+ if ( in_array( $legacy_free_shipping->requires, array( 'min_amount', 'either', 'both' ) ) ) {
379
+ $min_free_shipping_amount = $legacy_free_shipping->min_amount;
380
+ }
381
+ }
382
+ if ( 0 == $min_free_shipping_amount ) {
383
+ if ( function_exists( 'WC' ) && ( $wc_shipping = WC()->shipping ) && ( $wc_cart = WC()->cart ) ) {
384
+ if ( $wc_shipping->enabled ) {
385
+ if ( $packages = $wc_cart->get_shipping_packages() ) {
386
+ $shipping_methods = $wc_shipping->load_shipping_methods( $packages[0] );
387
+ foreach ( $shipping_methods as $shipping_method ) {
388
+ if ( 'yes' === $shipping_method->enabled && 0 != $shipping_method->instance_id ) {
389
+ if ( 'WC_Shipping_Free_Shipping' === get_class( $shipping_method ) ) {
390
+ if ( in_array( $shipping_method->requires, array( 'min_amount', 'either', 'both' ) ) ) {
391
+ $min_free_shipping_amount = $shipping_method->min_amount;
392
+ break;
393
+ }
394
+ }
395
+ }
396
+ }
397
+ }
398
+ }
399
+ }
400
+ }
401
+ }
402
+ if ( 0 != $min_free_shipping_amount ) {
403
+ if ( isset( WC()->cart->cart_contents_total ) ) {
404
+ $total = ( WC()->cart->prices_include_tax ) ? WC()->cart->cart_contents_total + array_sum( WC()->cart->taxes ) : WC()->cart->cart_contents_total;
405
+ if ( $total >= $min_free_shipping_amount ) {
406
+ return do_shortcode( get_option( 'wcj_shipping_left_to_free_info_content_reached', __( 'You have Free delivery', 'woocommerce-jetpack' ) ) );
407
+ } else {
408
+ $content = str_replace( '%left_to_free%', wc_price( $min_free_shipping_amount - $total ), $content );
409
+ $content = str_replace( '%free_shipping_min_amount%', wc_price( $min_free_shipping_amount ), $content );
410
+ return $content;
411
+ }
412
  }
413
  }
414
  }
660
  }
661
  }
662
 
663
+ /**
664
+ * wcj_get_current_user_first_role.
665
+ *
666
+ * @version 2.5.3
667
+ * @since 2.5.3
668
+ */
669
+ if ( ! function_exists( 'wcj_get_current_user_first_role' ) ) {
670
+ function wcj_get_current_user_first_role() {
671
+ $current_user = wp_get_current_user();
672
+ return ( isset( $current_user->roles[0] ) && '' != $current_user->roles[0] ) ? $current_user->roles[0] : 'guest';
673
+ }
674
+ }
675
+
676
+ /**
677
+ * wcj_get_user_roles.
678
+ *
679
+ * @version 2.5.3
680
+ * @since 2.5.3
681
+ */
682
+ if ( ! function_exists( 'wcj_get_user_roles' ) ) {
683
+ function wcj_get_user_roles() {
684
+ global $wp_roles;
685
+ $all_roles = ( isset( $wp_roles ) && is_object( $wp_roles ) ) ? $wp_roles->roles : array();
686
+ $all_roles = apply_filters( 'editable_roles', $all_roles );
687
+ $all_roles = array_merge( array(
688
+ 'guest' => array(
689
+ 'name' => __( 'Guest', 'woocommerce-jetpack' ),
690
+ 'capabilities' => array(),
691
+ ) ), $all_roles );
692
+ return $all_roles;
693
+ }
694
+ }
695
+ /**
696
+ * wcj_get_user_roles_options.
697
+ *
698
+ * @version 2.5.3
699
+ * @since 2.5.3
700
+ */
701
+ if ( ! function_exists( 'wcj_get_user_roles_options' ) ) {
702
+ function wcj_get_user_roles_options() {
703
+ global $wp_roles;
704
+ $all_roles = ( isset( $wp_roles ) && is_object( $wp_roles ) ) ? $wp_roles->roles : array();
705
+ $all_roles = apply_filters( 'editable_roles', $all_roles );
706
+ $all_roles = array_merge( array(
707
+ 'guest' => array(
708
+ 'name' => __( 'Guest', 'woocommerce-jetpack' ),
709
+ 'capabilities' => array(),
710
+ ) ), $all_roles );
711
+ $all_roles_options = array();
712
+ foreach ( $all_roles as $_role_key => $_role ) {
713
+ $all_roles_options[ $_role_key ] = $_role['name'];
714
+ }
715
+ return $all_roles_options;
716
+ }
717
+ }
718
+
719
  /**
720
  * wcj_is_user_role.
721
  *
includes/input-fields/class-wcj-product-input-fields-abstract.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Product Input Fields abstract class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -285,9 +285,13 @@ class WCJ_Product_Input_Fields_Abstract {
285
  /**
286
  * output_custom_input_fields_in_admin_order.
287
  *
288
- * @version 2.4.6
289
  */
290
  function output_custom_input_fields_in_admin_order( $item_id, $item, $_product ) {
 
 
 
 
291
  echo '<table cellspacing="0" class="display_meta">';
292
  $total_number = apply_filters( 'wcj_get_option_filter', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $_product->id, 1 ) );
293
  for ( $i = 1; $i <= $total_number; $i++ ) {
4
  *
5
  * The WooCommerce Jetpack Product Input Fields abstract class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
285
  /**
286
  * output_custom_input_fields_in_admin_order.
287
  *
288
+ * @version 2.5.3
289
  */
290
  function output_custom_input_fields_in_admin_order( $item_id, $item, $_product ) {
291
+ if ( null === $_product ) {
292
+ // Shipping
293
+ return;
294
+ }
295
  echo '<table cellspacing="0" class="display_meta">';
296
  $total_number = apply_filters( 'wcj_get_option_filter', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $_product->id, 1 ) );
297
  for ( $i = 1; $i <= $total_number; $i++ ) {
includes/js/wcj-product-addons.js ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /**
2
+ * wcj-product-addons.
3
+ *
4
+ * version 2.5.3
5
+ * since 2.5.3
6
+ */
7
+
8
+ function change_price() {
9
+ var is_variation_ok = true;
10
+ if ( jQuery(".variations select").length ) {
11
+ if ( jQuery(".variations select").find(":selected").val() == '' ) {
12
+ is_variation_ok = false;
13
+ }
14
+ }
15
+ if ( is_variation_ok ) {
16
+ var product_id = jQuery("input[type='hidden'][name='variation_id']").val();
17
+ var is_variable;
18
+ if ( ! product_id ) {
19
+ is_variable = false;
20
+ product_id = ajax_object.product_id;
21
+ } else {
22
+ is_variable = true;
23
+ }
24
+ var data = {
25
+ 'action': 'product_addons_price_change',
26
+ 'product_id': product_id,
27
+ };
28
+ jQuery("input[name^='wcj_product_all_products_addons_']").each( function () {
29
+ if (jQuery(this).is(':checked')) {
30
+ data[jQuery(this).attr('name')] = '1';
31
+ }
32
+ });
33
+ jQuery("input[name^='wcj_product_per_product_addons_']").each( function () {
34
+ if (jQuery(this).is(':checked')) {
35
+ data[jQuery(this).attr('name')] = '1';
36
+ }
37
+ });
38
+ jQuery.post(ajax_object.ajax_url, data, function(response) {
39
+ if ( '' != response ) {
40
+ if ( ! is_variable ) {
41
+ jQuery("p[class='price']").html(response);
42
+ } else {
43
+ jQuery("span[class='price']").html(response);
44
+ }
45
+ }
46
+ });
47
+ }
48
+ }
49
+
50
+ jQuery(document).ready(function() {
51
+ change_price();
52
+ jQuery("input[name^='wcj_product_all_products_addons_']").each( function () {
53
+ jQuery(this).change( change_price );
54
+ });
55
+ jQuery("input[name^='wcj_product_per_product_addons_']").each( function () {
56
+ jQuery(this).change( change_price );
57
+ });
58
+ });
59
+
60
+ jQuery(document.body).on('change','.variations select',change_price);
61
+ jQuery(document.body).on('change','input[name="wcj_variations"]',change_price);
includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack PDF Invoices Report Tool class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.2.1
9
  * @author Algoritmika Ltd.
10
  */
@@ -195,7 +195,7 @@ class WCJ_PDF_Invoicing_Report_Tool {
195
  /**
196
  * Invoices Report function.
197
  *
198
- * @version 2.5.2
199
  */
200
  function get_invoices_report( $year, $month, $invoice_type_id ) {
201
 
@@ -213,6 +213,7 @@ class WCJ_PDF_Invoicing_Report_Tool {
213
  __( 'Order Taxes', 'woocommerce-jetpack' ),
214
  __( 'Order Total', 'woocommerce-jetpack' ),
215
  __( 'Order Currency', 'woocommerce-jetpack' ),
 
216
  );
217
 
218
  $total_sum = 0;
@@ -287,6 +288,7 @@ class WCJ_PDF_Invoicing_Report_Tool {
287
  $order_tax_html,
288
  sprintf( '%.2f', $order_total ),
289
  $the_order->get_order_currency(),
 
290
  //'<pre>' . print_r( get_post_meta( $order_id ), true ) . '</pre>',
291
  );
292
  }
4
  *
5
  * The WooCommerce Jetpack PDF Invoices Report Tool class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.2.1
9
  * @author Algoritmika Ltd.
10
  */
195
  /**
196
  * Invoices Report function.
197
  *
198
+ * @version 2.5.3
199
  */
200
  function get_invoices_report( $year, $month, $invoice_type_id ) {
201
 
213
  __( 'Order Taxes', 'woocommerce-jetpack' ),
214
  __( 'Order Total', 'woocommerce-jetpack' ),
215
  __( 'Order Currency', 'woocommerce-jetpack' ),
216
+ __( 'Refunds', 'woocommerce-jetpack' ),
217
  );
218
 
219
  $total_sum = 0;
288
  $order_tax_html,
289
  sprintf( '%.2f', $order_total ),
290
  $the_order->get_order_currency(),
291
+ $the_order->get_total_refunded(),
292
  //'<pre>' . print_r( get_post_meta( $order_id ), true ) . '</pre>',
293
  );
294
  }
includes/price-by-country/class-wcj-price-by-country-core.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Price by Country Core class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -16,16 +16,20 @@ class WCJ_Price_by_Country_Core {
16
 
17
  /**
18
  * Constructor.
 
 
19
  */
20
  public function __construct() {
21
  $this->customer_country_group_id = null;
 
 
22
  add_action( 'init', array( $this, 'add_hooks' ) );
23
  }
24
 
25
  /**
26
  * add_hooks.
27
  *
28
- * @version 2.5.0
29
  */
30
  function add_hooks() {
31
 
@@ -62,11 +66,47 @@ class WCJ_Price_by_Country_Core {
62
  add_filter( 'woocommerce_get_price_excluding_tax', array( $this, 'change_price_by_country_grouped' ), PHP_INT_MAX - 1, 3 );
63
 
64
  // Currency hooks
65
- add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol' ), PHP_INT_MAX - 1, 2 );
66
  add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX - 1, 1 );
67
 
68
  // Shipping
69
  add_filter( 'woocommerce_package_rates', array( $this, 'change_shipping_price_by_country' ), PHP_INT_MAX - 1, 2 );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
70
  }
71
 
72
  /**
@@ -261,107 +301,11 @@ class WCJ_Price_by_Country_Core {
261
  /**
262
  * change_price_by_country.
263
  *
264
- * @version 2.5.0
265
  */
266
  function change_price_by_country( $price, $product ) {
267
-
268
- if ( is_numeric( $product ) ) {
269
- $the_product_id = $product;
270
- } else {
271
- $the_product_id = ( isset( $product->variation_id ) ) ? $product->variation_id : $product->id;
272
- }
273
-
274
  if ( null != ( $group_id = $this->get_customer_country_group_id() ) ) {
275
-
276
- $is_price_modified = false;
277
-
278
- if ( 'yes' === get_option( 'wcj_price_by_country_local_enabled' ) ) {
279
- // Per product
280
- $meta_box_id = 'price_by_country';
281
- $scope = 'local';
282
-
283
- $meta_id = '_' . 'wcj_' . $meta_box_id . '_make_empty_price_' . $scope . '_' . $group_id;
284
- if ( 'on' === get_post_meta( $the_product_id, $meta_id, true ) ) {
285
- return '';
286
- }
287
-
288
- $price_by_country = '';
289
- $the_current_filter = current_filter();
290
- if ( 'woocommerce_get_price_including_tax' == $the_current_filter || 'woocommerce_get_price_excluding_tax' == $the_current_filter ) {
291
- $_product = wc_get_product( $the_product_id );
292
- $get_price_method = 'get_price_' . get_option( 'woocommerce_tax_display_shop' ) . 'uding_tax';
293
- return $_product->$get_price_method();
294
-
295
- } elseif ( 'woocommerce_get_price' == $the_current_filter || 'woocommerce_variation_prices_price' == $the_current_filter ) {
296
-
297
- $regular_or_sale = '_regular_price_';
298
- $meta_id = '_' . 'wcj_' . $meta_box_id . $regular_or_sale . $scope . '_' . $group_id;
299
- $regular_price = get_post_meta( $the_product_id, $meta_id, true );
300
-
301
- $regular_or_sale = '_sale_price_';
302
- $meta_id = '_' . 'wcj_' . $meta_box_id . $regular_or_sale . $scope . '_' . $group_id;
303
- $sale_price = get_post_meta( $the_product_id, $meta_id, true );
304
-
305
- if ( ! empty( $sale_price ) && $sale_price < $regular_price ) {
306
- $price_by_country = $sale_price;
307
- } else {
308
- $price_by_country = $regular_price;
309
- }
310
-
311
- }
312
- elseif (
313
- 'woocommerce_get_regular_price' == $the_current_filter ||
314
- 'woocommerce_get_sale_price' == $the_current_filter ||
315
- 'woocommerce_variation_prices_regular_price' == $the_current_filter ||
316
- 'woocommerce_variation_prices_sale_price' == $the_current_filter
317
- ) {
318
- $regular_or_sale = (
319
- 'woocommerce_get_regular_price' == $the_current_filter || 'woocommerce_variation_prices_regular_price' == $the_current_filter
320
- ) ? '_regular_price_' : '_sale_price_';
321
- $meta_id = '_' . 'wcj_' . $meta_box_id . $regular_or_sale . $scope . '_' . $group_id;
322
- $price_by_country = get_post_meta( $the_product_id, $meta_id, true );
323
- }
324
-
325
- if ( '' != $price_by_country ) {
326
- $modified_price = $price_by_country;
327
- $is_price_modified = true;
328
- }
329
- }
330
-
331
- if ( ! $is_price_modified ) {
332
- if ( 'yes' === get_option( 'wcj_price_by_country_make_empty_price_group_' . $group_id, 1 ) || '' === $price ) {
333
- return '';
334
- }
335
- }
336
-
337
- if ( ! $is_price_modified ) {
338
- // Globally
339
- $country_exchange_rate = get_option( 'wcj_price_by_country_exchange_rate_group_' . $group_id, 1 );
340
- if ( 1 != $country_exchange_rate ) {
341
- $modified_price = $price * $country_exchange_rate;
342
- $rounding = get_option( 'wcj_price_by_country_rounding', 'none' );
343
- $precision = get_option( 'woocommerce_price_num_decimals', 2 );
344
- switch ( $rounding ) {
345
- case 'round':
346
- $modified_price = round( $modified_price );
347
- break;
348
- case 'floor':
349
- $modified_price = floor( $modified_price );
350
- break;
351
- case 'ceil':
352
- $modified_price = ceil( $modified_price );
353
- break;
354
- default: // case 'none':
355
- $modified_price = round( $modified_price, $precision ); // $modified_price
356
- break;
357
- }
358
- $is_price_modified = true;
359
- }
360
- }
361
-
362
- if ( $is_price_modified ) {
363
- return $modified_price;
364
- }
365
  }
366
  // No changes
367
  return $price;
4
  *
5
  * The WooCommerce Jetpack Price by Country Core class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
16
 
17
  /**
18
  * Constructor.
19
+ *
20
+ * @version 2.5.3
21
  */
22
  public function __construct() {
23
  $this->customer_country_group_id = null;
24
+ add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol' ), PHP_INT_MAX - 1, 2 ); // so early because of price filter widget
25
+ // $this->add_hooks();
26
  add_action( 'init', array( $this, 'add_hooks' ) );
27
  }
28
 
29
  /**
30
  * add_hooks.
31
  *
32
+ * @version 2.5.3
33
  */
34
  function add_hooks() {
35
 
66
  add_filter( 'woocommerce_get_price_excluding_tax', array( $this, 'change_price_by_country_grouped' ), PHP_INT_MAX - 1, 3 );
67
 
68
  // Currency hooks
69
+ // add_filter( 'woocommerce_currency_symbol', array( $this, 'change_currency_symbol' ), PHP_INT_MAX - 1, 2 );
70
  add_filter( 'woocommerce_currency', array( $this, 'change_currency_code' ), PHP_INT_MAX - 1, 1 );
71
 
72
  // Shipping
73
  add_filter( 'woocommerce_package_rates', array( $this, 'change_shipping_price_by_country' ), PHP_INT_MAX - 1, 2 );
74
+
75
+ // Price Filter Widget
76
+ if ( 'yes' === get_option( 'wcj_price_by_country_price_filter_widget_support_enabled', 'no' ) ) {
77
+ add_filter( 'woocommerce_price_filter_meta_keys', array( $this, 'price_filter_meta_keys' ), PHP_INT_MAX, 1 );
78
+ add_filter( 'woocommerce_product_query_meta_query', array( $this, 'price_filter_meta_query' ), PHP_INT_MAX, 2 );
79
+ }
80
+ }
81
+
82
+ /**
83
+ * price_filter_meta_query.
84
+ *
85
+ * @version 2.5.3
86
+ * @since 2.5.3
87
+ */
88
+ function price_filter_meta_query( $meta_query, $_wc_query ) {
89
+ foreach ( $meta_query as $_key => $_query ) {
90
+ if ( isset( $_query['price_filter'] ) && true === $_query['price_filter'] && isset( $_query['key'] ) ) {
91
+ if ( null != ( $group_id = $this->get_customer_country_group_id() ) ) {
92
+ $meta_query[ $_key ]['key'] = '_' . 'wcj_price_by_country_' . $group_id;
93
+ }
94
+ }
95
+ }
96
+ return $meta_query;
97
+ }
98
+
99
+ /**
100
+ * price_filter_meta_keys.
101
+ *
102
+ * @version 2.5.3
103
+ * @since 2.5.3
104
+ */
105
+ function price_filter_meta_keys( $keys ) {
106
+ if ( null != ( $group_id = $this->get_customer_country_group_id() ) ) {
107
+ $keys = array( '_' . 'wcj_price_by_country_' . $group_id );
108
+ }
109
+ return $keys;
110
  }
111
 
112
  /**
301
  /**
302
  * change_price_by_country.
303
  *
304
+ * @version 2.5.3
305
  */
306
  function change_price_by_country( $price, $product ) {
 
 
 
 
 
 
 
307
  if ( null != ( $group_id = $this->get_customer_country_group_id() ) ) {
308
+ return wcj_price_by_country( $price, $product, $group_id );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
309
  }
310
  // No changes
311
  return $price;
includes/reports/wcj-class-reports-monthly-sales.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Mothly Sales Reports class.
6
  *
7
- * @version 2.4.8
8
  * @since 2.4.7
9
  * @author Algoritmika Ltd.
10
  */
@@ -28,99 +28,149 @@ class WCJ_Reports_Monthly_Sales {
28
  /**
29
  * get_report.
30
  *
31
- * @version 2.4.7
32
  * @since 2.4.7
33
  */
34
  public function get_report() {
35
  $html = '';
36
  $this->year = isset( $_GET['year'] ) ? $_GET['year'] : date( 'Y' );
 
 
 
 
37
  $html .= $this->get_monthly_sales_report();
38
  return $html;
39
  }
40
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  /*
42
  * get_exchange_rate_average.
43
  *
44
- * @version 2.4.8
45
  * @since 2.4.7
 
46
  */
47
  function get_exchange_rate_average( $currency_from, $currency_to, $start_date, $end_date ) {
 
48
  if ( $currency_from == $currency_to ) {
49
  return 1.0;
50
  }
 
 
 
 
 
 
 
 
 
 
 
51
  if ( 'USD' != $currency_from ) {
52
  // USD/$currency_from
53
- $url = 'https://query.yahooapis.com/v1/public/yql?q=select%20Close%20from%20yahoo.finance.historicaldata%20where%20symbol%20%3D%20%22'
54
- . $currency_from . '%3DX%22%20and%20startDate%20%3D%20%22'
55
- . $start_date . '%22%20and%20endDate%20%3D%20%22'
56
- . $end_date. '%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=';
57
- ob_start();
58
- $max_execution_time = ini_get( 'max_execution_time' );
59
- set_time_limit( 5 );
60
- $exchange_rate = json_decode( file_get_contents( $url ) );
61
- set_time_limit( $max_execution_time );
62
- ob_end_clean();
63
- if ( ! isset( $exchange_rate->query->results->quote ) || count( $exchange_rate->query->results->quote ) < 1 ) {
64
  return false;
65
  }
66
- $average_currency_from = 0;
67
- foreach ( $exchange_rate->query->results->quote as $quote ) {
68
- $average_currency_from += $quote->Close;
69
- }
70
- $average_currency_from = $average_currency_from / count( $exchange_rate->query->results->quote );
71
  } else {
72
  $average_currency_from = 1.0;
73
  }
74
  if ( 'USD' != $currency_to ) {
75
  // USD/$currency_to
76
- $url = 'https://query.yahooapis.com/v1/public/yql?q=select%20Close%20from%20yahoo.finance.historicaldata%20where%20symbol%20%3D%20%22'
77
- . $currency_to . '%3DX%22%20and%20startDate%20%3D%20%22'
78
- . $start_date . '%22%20and%20endDate%20%3D%20%22'
79
- . $end_date. '%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=';
80
- ob_start();
81
- $max_execution_time = ini_get( 'max_execution_time' );
82
- set_time_limit( 5 );
83
- $exchange_rate = json_decode( file_get_contents( $url ) );
84
- set_time_limit( $max_execution_time );
85
- ob_end_clean();
86
- if ( ! isset( $exchange_rate->query->results->quote ) || count( $exchange_rate->query->results->quote ) < 1 ) {
87
  return false;
88
  }
89
- $average_currency_to = 0;
90
- foreach ( $exchange_rate->query->results->quote as $quote ) {
91
- $average_currency_to += $quote->Close;
92
- }
93
- $average_currency_to = $average_currency_to / count( $exchange_rate->query->results->quote );
94
  } else {
95
  $average_currency_to = 1.0;
96
  }
97
- return $average_currency_to / $average_currency_from;
 
 
 
 
 
98
  }
99
 
100
  /*
101
  * get_monthly_sales_report.
102
  *
103
- * @version 2.4.8
104
  * @since 2.4.7
 
105
  */
106
  function get_monthly_sales_report() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  $block_size = 96;
108
  $table_data = array();
109
- $months_array = array( '' );
110
- $total_orders_array = array( __( 'Total Orders', 'woocommerce-jetpack' ) );
111
- $total_orders_sum_array = array(
112
- __( 'Total Sum', 'woocommerce-jetpack' ) . '<br>' .
113
- __( 'Total Sum (excl. TAX)', 'woocommerce-jetpack' ) . '<br>' .
114
- __( 'Average / Day (excl. TAX)', 'woocommerce-jetpack' )
115
- );
116
- $order_currencies_array = array(); // TODO
117
- $report_currency = ( isset( $_GET['currency'] ) && 'merge' != $_GET['currency'] ) ? $_GET['currency'] : get_woocommerce_currency();
118
  for ( $i = 1; $i <= 12; $i++ ) {
119
  $current_months_averages = array();
120
  $total_orders = 0;
121
  $total_orders_sum = 0;
122
  $total_orders_sum_excl_tax = 0;
123
  $offset = 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
124
  while( true ) {
125
  $args_orders = array(
126
  'post_type' => 'shop_order',
@@ -129,11 +179,18 @@ class WCJ_Reports_Monthly_Sales {
129
  'orderby' => 'date',
130
  'order' => 'DESC',
131
  'offset' => $offset,
132
- 'date_query' => array(
133
- array(
134
  'year' => $this->year,
135
  'month' => $i,
 
136
  ),
 
 
 
 
 
 
137
  ),
138
  );
139
  $loop_orders = new WP_Query( $args_orders );
@@ -150,55 +207,100 @@ class WCJ_Reports_Monthly_Sales {
150
  $order_total = $order->get_total();
151
  $order_total_excl_tax = $order->get_total() - $order->get_total_tax();
152
  if ( ! isset( $current_months_averages[ $order_currency ][ $report_currency ] ) ) {
153
- $start_date = $this->year . '-' . sprintf( '%02d', $i ) . '-'. '01';
154
  $end_date = date( 'Y-m-t', strtotime( $start_date ) );
155
- $current_months_averages[ $order_currency ][ $report_currency ] = $this->get_exchange_rate_average(
156
- $order_currency,
157
- $report_currency,
158
- $start_date,
159
- $end_date
160
- );
161
- // TODO: take not monthly average, but "Close" of closest day
 
 
 
 
162
  }
163
  $total_orders_sum += $order_total * $current_months_averages[ $order_currency ][ $report_currency ];
164
  $total_orders_sum_excl_tax += $order_total_excl_tax * $current_months_averages[ $order_currency ][ $report_currency ];
165
  endwhile;
166
  $offset += $block_size;
167
  }
168
- $months_array[] = date_i18n( 'F', mktime( 0, 0, 0, $i, 10 ) )/* . '[' . $start_date . ' ~ ' . $end_date . ']' */;
169
- $total_orders_array[] = $total_orders;
170
 
171
- $total_orders_result_html = $report_currency . ' ' . number_format( $total_orders_sum, 2, '.', ',' );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
172
  //if ( $total_orders_sum != $total_orders_sum_excl_tax) {
173
- $total_orders_result_html .= '<br>' . $report_currency . ' ' . number_format( $total_orders_sum_excl_tax, 2, '.', ',' );
 
 
174
  //}
175
- $day_for_average = ( $i == date( 'm' ) ) ? date( 'd' ) : date( 'd', strtotime( $end_date ) );
 
 
 
176
  $average_result = $total_orders_sum_excl_tax / $day_for_average;
177
- $total_orders_result_html .= '<br>' . $report_currency . ' ' . number_format( $average_result, 2, '.', ',' );
178
- if ( 0 != $average_result ) {
179
- $total_orders_result_html .= ' (' . $day_for_average . 'd.)';
180
- }
181
- /* $total_orders_result_html .= '<br>' . $report_currency . ' ' . number_format( $total_orders_sum_excl_tax * 0.965, 2, '.', ',' ); // TODO !!!;
182
- $total_orders_result_html .= '<br>' . $report_currency . ' ' . number_format( $total_orders_sum_excl_tax * 0.965 * 0.80, 2, '.', ',' ); // TODO !!!; */
183
- // if ( isset( $_GET['show_rates'] ) ) { // TODO
184
  ksort( $current_months_averages, true );
185
- // $total_orders_result_html .= '<pre style="font-size:8px;">' . print_r( $current_months_averages, true ) . '</pre>';
186
- $total_orders_result_html .= '<pre style="font-size:x-small;">';
187
  foreach ( $current_months_averages as $currency_from => $currencies_to ) {
188
  foreach ( $currencies_to as $currency_to => $rate ) {
189
- $total_orders_result_html .= $currency_from . $currency_to . '~' . number_format( $rate, 4 ) . '<br>';
 
 
190
  }
191
  }
192
- $total_orders_result_html .= '</pre>';
193
  // }
194
- $total_orders_sum_array[] = $total_orders_result_html;
195
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
196
  $table_data[] = $months_array;
 
197
  $table_data[] = $total_orders_array;
 
198
  $table_data[] = $total_orders_sum_array;
 
 
 
 
199
  /* foreach ( $order_currencies_array as $order_currency => $total_currency_orders ) {
200
  $table_data[] = array( $order_currency . ' (' . $total_currency_orders . ')' );
201
  } */
 
 
 
 
202
  $html = '';
203
  $menu = '';
204
  $menu .= '<ul class="subsubsub">';
@@ -208,25 +310,23 @@ class WCJ_Reports_Monthly_Sales {
208
  $menu .= '<br class="clear">';
209
  $html .= $menu;
210
  $html .= '<h4>' . __( 'Report currency', 'woocommerce-jetpack' ) . ': ' . $report_currency . '</h4>';
 
 
 
 
211
  $html .= wcj_get_table_html( $table_data, array(
212
  'table_class' => 'widefat striped',
213
  'table_heading_type' => 'horizontal',
214
- 'columns_styles' => array(
215
- 'width:16%;',
216
- 'width:7%;',
217
- 'width:7%;',
218
- 'width:7%;',
219
- 'width:7%;',
220
- 'width:7%;',
221
- 'width:7%;',
222
- 'width:7%;',
223
- 'width:7%;',
224
- 'width:7%;',
225
- 'width:7%;',
226
- 'width:7%;',
227
- 'width:7%;',
228
  ),
229
  ) );
 
 
 
 
230
  return $html;
231
  }
232
  }
4
  *
5
  * The WooCommerce Jetpack Mothly Sales Reports class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.4.7
9
  * @author Algoritmika Ltd.
10
  */
28
  /**
29
  * get_report.
30
  *
31
+ * @version 2.5.3
32
  * @since 2.4.7
33
  */
34
  public function get_report() {
35
  $html = '';
36
  $this->year = isset( $_GET['year'] ) ? $_GET['year'] : date( 'Y' );
37
+ if ( isset( $_POST['wcj_reset_currency_rates'] ) ) {
38
+ delete_option( 'wcj_reports_currency_rates' );
39
+ $html .= '<p>' . __( 'Currency rates deleted.', 'woocommerce-jetpack' ) . '</p>';
40
+ }
41
  $html .= $this->get_monthly_sales_report();
42
  return $html;
43
  }
44
 
45
+ /*
46
+ * get_exchange_rate_average_USD.
47
+ *
48
+ * @version 2.5.3
49
+ * @since 2.5.3
50
+ */
51
+ function get_exchange_rate_average_USD( $currency, $start_date, $end_date ) {
52
+ $url = 'https://query.yahooapis.com/v1/public/yql?q=select%20Close%20from%20yahoo.finance.historicaldata%20where%20symbol%20%3D%20%22'
53
+ . $currency . '%3DX%22%20and%20startDate%20%3D%20%22'
54
+ . $start_date . '%22%20and%20endDate%20%3D%20%22'
55
+ . $end_date. '%22&format=json&diagnostics=true&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback=';
56
+ ob_start();
57
+ $max_execution_time = ini_get( 'max_execution_time' );
58
+ set_time_limit( 5 );
59
+ $exchange_rate = json_decode( file_get_contents( $url ) );
60
+ set_time_limit( $max_execution_time );
61
+ ob_end_clean();
62
+ if ( ! isset( $exchange_rate->query->results->quote ) || count( $exchange_rate->query->results->quote ) < 1 ) {
63
+ return false;
64
+ }
65
+ $average_currency = 0;
66
+ foreach ( $exchange_rate->query->results->quote as $quote ) {
67
+ $average_currency += $quote->Close;
68
+ }
69
+ $average_currency = $average_currency / count( $exchange_rate->query->results->quote );
70
+ if ( 0 == $average_currency ) {
71
+ return false;
72
+ }
73
+ return $average_currency;
74
+ }
75
+
76
  /*
77
  * get_exchange_rate_average.
78
  *
79
+ * @version 2.5.3
80
  * @since 2.4.7
81
+ * @todo current month rate - save only once a day (now saving every time)
82
  */
83
  function get_exchange_rate_average( $currency_from, $currency_to, $start_date, $end_date ) {
84
+ // Same currency
85
  if ( $currency_from == $currency_to ) {
86
  return 1.0;
87
  }
88
+ // Saved values
89
+ $saved_rates = get_option( 'wcj_reports_currency_rates', array() );
90
+ $is_current_month = ( date( 'Y-m' ) == date( 'Y-m', strtotime( $start_date ) ) ) ? true : false;
91
+ if ( ! $is_current_month ) {
92
+ if ( ! empty( $saved_rates ) ) {
93
+ if ( isset( $saved_rates[ $currency_from ][ $currency_to ][ $start_date ][ $end_date ] ) ) {
94
+ return $saved_rates[ $currency_from ][ $currency_to ][ $start_date ][ $end_date ];
95
+ }
96
+ }
97
+ }
98
+ // Get exchange rate
99
  if ( 'USD' != $currency_from ) {
100
  // USD/$currency_from
101
+ $average_currency_from = $this->get_exchange_rate_average_USD( $currency_from, $start_date, $end_date );
102
+ if ( false === $average_currency_from ) {
 
 
 
 
 
 
 
 
 
103
  return false;
104
  }
 
 
 
 
 
105
  } else {
106
  $average_currency_from = 1.0;
107
  }
108
  if ( 'USD' != $currency_to ) {
109
  // USD/$currency_to
110
+ $average_currency_to = $this->get_exchange_rate_average_USD( $currency_to, $start_date, $end_date );
111
+ if ( false === $average_currency_to ) {
 
 
 
 
 
 
 
 
 
112
  return false;
113
  }
 
 
 
 
 
114
  } else {
115
  $average_currency_to = 1.0;
116
  }
117
+ $the_rate = $average_currency_to / $average_currency_from;
118
+ if ( ! $is_current_month ) {
119
+ $saved_rates[ $currency_from ][ $currency_to ][ $start_date ][ $end_date ] = $the_rate;
120
+ update_option( 'wcj_reports_currency_rates', $saved_rates );
121
+ }
122
+ return $the_rate;
123
  }
124
 
125
  /*
126
  * get_monthly_sales_report.
127
  *
128
+ * @version 2.5.3
129
  * @since 2.4.7
130
+ * @todo take not monthly average, but "Close" of closest day; forecast for current month; $order_currencies_array;
131
  */
132
  function get_monthly_sales_report() {
133
+
134
+ $execution_time_start = microtime( true );
135
+
136
+ $months_array = array( '' );
137
+ $months_days_array = array( __( 'Days', 'woocommerce-jetpack' ) );
138
+ $total_orders_array = array( __( 'Total Orders', 'woocommerce-jetpack' ) );
139
+ $total_orders_average_array = array( __( 'Orders Average / Day', 'woocommerce-jetpack' ) );
140
+ $total_orders_sum_array = array( __( 'Total Sum', 'woocommerce-jetpack' ) );
141
+ $total_orders_sum_excl_tax_array = array( __( 'Total Sum (excl. TAX)', 'woocommerce-jetpack' ) );
142
+ $total_orders_sum_average_order_array = array( __( 'Average / Order (excl. TAX)', 'woocommerce-jetpack' ) );
143
+ $total_orders_sum_average_array = array( __( 'Average / Day (excl. TAX)', 'woocommerce-jetpack' ) );
144
+ $currency_rates_array = array( __( 'Currency Rates', 'woocommerce-jetpack' ) );
145
+
146
+ $total_months_days = 0;
147
+ $total_orders_total = 0;
148
+ $total_orders_sum_total = 0;
149
+ $total_orders_sum_excl_tax_total = 0;
150
+
151
+ $order_currencies_array = array();
152
+ $report_currency = ( isset( $_GET['currency'] ) && 'merge' != $_GET['currency'] ) ? $_GET['currency'] : get_woocommerce_currency();
153
  $block_size = 96;
154
  $table_data = array();
 
 
 
 
 
 
 
 
 
155
  for ( $i = 1; $i <= 12; $i++ ) {
156
  $current_months_averages = array();
157
  $total_orders = 0;
158
  $total_orders_sum = 0;
159
  $total_orders_sum_excl_tax = 0;
160
  $offset = 0;
161
+ $day_for_average = ( $i == date( 'm' ) && $this->year == date( 'Y' ) ) ? date( 'd' ) - 1 : date( 't', strtotime( $this->year . '-' . sprintf( '%02d', $i ) . '-' . '01' ) );
162
+ if ( 0 == $day_for_average ) {
163
+ $months_array[] = date_i18n( 'F', mktime( 0, 0, 0, $i, 1, $this->year ) );
164
+ $months_days_array[] = '-';
165
+ $total_orders_array[] = '-';
166
+ $total_orders_average_array[] = '-';
167
+ $total_orders_sum_array[] = '-';
168
+ $total_orders_sum_excl_tax_array[] = '-';
169
+ $total_orders_sum_average_order_array[] = '-';
170
+ $total_orders_sum_average_array[] = '-';
171
+ $currency_rates_array[] = '';
172
+ continue;
173
+ }
174
  while( true ) {
175
  $args_orders = array(
176
  'post_type' => 'shop_order',
179
  'orderby' => 'date',
180
  'order' => 'DESC',
181
  'offset' => $offset,
182
+ 'date_query' => array(
183
+ 'after' => array(
184
  'year' => $this->year,
185
  'month' => $i,
186
+ 'day' => 1,
187
  ),
188
+ 'before' => array(
189
+ 'year' => $this->year,
190
+ 'month' => $i,
191
+ 'day' => $day_for_average,
192
+ ),
193
+ 'inclusive' => true,
194
  ),
195
  );
196
  $loop_orders = new WP_Query( $args_orders );
207
  $order_total = $order->get_total();
208
  $order_total_excl_tax = $order->get_total() - $order->get_total_tax();
209
  if ( ! isset( $current_months_averages[ $order_currency ][ $report_currency ] ) ) {
210
+ $start_date = $this->year . '-' . sprintf( '%02d', $i ) . '-' . '01';
211
  $end_date = date( 'Y-m-t', strtotime( $start_date ) );
212
+ $the_rate = $this->get_exchange_rate_average( $order_currency, $report_currency, $start_date, $end_date );
213
+ if ( false === $the_rate ) {
214
+ // Try previous month
215
+ $start_date_prev_month = date( 'Y-m-d', strtotime( 'first day of last month', strtotime( $start_date ) ) );
216
+ $end_date_prev_month = date( 'Y-m-t', strtotime( $start_date_prev_month ) );
217
+ $the_rate = $this->get_exchange_rate_average( $order_currency, $report_currency, $start_date_prev_month, $end_date_prev_month );
218
+ if ( false === $the_rate ) {
219
+ return '<p>' . sprintf( __( 'Error getting currency rate for %s', 'woocommerce-jetpack' ), $order_currency . $report_currency ) . '</p>';
220
+ }
221
+ }
222
+ $current_months_averages[ $order_currency ][ $report_currency ] = $the_rate;
223
  }
224
  $total_orders_sum += $order_total * $current_months_averages[ $order_currency ][ $report_currency ];
225
  $total_orders_sum_excl_tax += $order_total_excl_tax * $current_months_averages[ $order_currency ][ $report_currency ];
226
  endwhile;
227
  $offset += $block_size;
228
  }
 
 
229
 
230
+ // Month Name
231
+ $months_array[] = date_i18n( 'F', mktime( 0, 0, 0, $i, 1, $this->year ) ) /* . '[' . $start_date . ' ~ ' . $end_date . ']' */;
232
+ // Month Days
233
+ $months_days_array[] = ( date( 'm' ) >= $i || $this->year != date( 'Y' ) ? $day_for_average : '-' );
234
+ $total_months_days += ( date( 'm' ) >= $i || $this->year != date( 'Y' ) ? $day_for_average : 0 );
235
+
236
+ // Sales
237
+ $total_orders_array[] = ( $total_orders > 0 ? $total_orders : '-' );
238
+ $total_orders_total += $total_orders;
239
+ // Sales Average
240
+ $average_sales_result = $total_orders / $day_for_average;
241
+ $total_orders_average_array[] = ( $average_sales_result > 0 ? number_format( $average_sales_result, 2, '.', ',' ) : '-' );
242
+
243
+ // Sum
244
+ $total_orders_sum_array[] = ( $total_orders_sum > 0 ? $report_currency . ' ' . number_format( $total_orders_sum, 2, '.', ',' ) : '-' );
245
+ $total_orders_sum_total += $total_orders_sum;
246
+ // Sum excl. Tax
247
  //if ( $total_orders_sum != $total_orders_sum_excl_tax) {
248
+ $total_orders_sum_excl_tax_array[] = ( $total_orders_sum_excl_tax > 0 ?
249
+ $report_currency . ' ' . number_format( $total_orders_sum_excl_tax, 2, '.', ',' ) : '-' );
250
+ $total_orders_sum_excl_tax_total += $total_orders_sum_excl_tax;
251
  //}
252
+ // Order Average
253
+ $total_orders_sum_average_order_array[] = ( $total_orders_sum_excl_tax > 0 && $total_orders > 0 ?
254
+ $report_currency . ' ' . number_format( $total_orders_sum_excl_tax / $total_orders, 2, '.', ',' ) : '-' );
255
+ // Sum Average
256
  $average_result = $total_orders_sum_excl_tax / $day_for_average;
257
+ $total_orders_sum_average_array[] = ( $average_result > 0 ? $report_currency . ' ' . number_format( $average_result, 2, '.', ',' ) : '-' );
258
+
259
+ // Currency Rates
260
+ // if ( isset( $_GET['show_rates'] ) ) {
 
 
 
261
  ksort( $current_months_averages, true );
262
+ // $currency_rates_html = '<pre style="font-size:8px;">' . print_r( $current_months_averages, true ) . '</pre>';
263
+ $currency_rates_html = '<pre style="font-size:x-small;">';
264
  foreach ( $current_months_averages as $currency_from => $currencies_to ) {
265
  foreach ( $currencies_to as $currency_to => $rate ) {
266
+ if ( $currency_from != $currency_to ) {
267
+ $currency_rates_html .= $currency_from . $currency_to . '~' . number_format( $rate, 4 ) . '<br>';
268
+ }
269
  }
270
  }
271
+ $currency_rates_html .= '</pre>';
272
  // }
273
+ $currency_rates_array[] = $currency_rates_html;
274
  }
275
+
276
+ // Totals
277
+ $months_array[] = __( 'Totals', 'woocommerce-jetpack' );
278
+ $months_days_array[] = $total_months_days;
279
+ $total_orders_array[] = $total_orders_total;
280
+ $total_orders_average_array[] = ( $total_months_days > 0 ? number_format( ( $total_orders_total / $total_months_days ), 2, '.', ',' ) : '-' );
281
+ $total_orders_sum_array[] = $report_currency . ' ' . number_format( $total_orders_sum_total, 2, '.', ',' );
282
+ $total_orders_sum_excl_tax_array[] = $report_currency . ' ' . number_format( $total_orders_sum_excl_tax_total, 2, '.', ',' );
283
+ $total_orders_sum_average_order_array[] = ( $total_orders_total > 0 ? $report_currency . ' ' . number_format( ( $total_orders_sum_excl_tax_total / $total_orders_total ), 2, '.', ',' ) : '-' );
284
+ $total_orders_sum_average_array[] = ( $total_months_days > 0 ? $report_currency . ' ' . number_format( ( $total_orders_sum_excl_tax_total / $total_months_days ), 2, '.', ',' ) : '-' );
285
+ $currency_rates_array[] = '';
286
+
287
+ // Table
288
  $table_data[] = $months_array;
289
+ $table_data[] = $months_days_array;
290
  $table_data[] = $total_orders_array;
291
+ $table_data[] = $total_orders_average_array;
292
  $table_data[] = $total_orders_sum_array;
293
+ $table_data[] = $total_orders_sum_excl_tax_array;
294
+ $table_data[] = $total_orders_sum_average_order_array;
295
+ $table_data[] = $total_orders_sum_average_array;
296
+ $table_data[] = $currency_rates_array;
297
  /* foreach ( $order_currencies_array as $order_currency => $total_currency_orders ) {
298
  $table_data[] = array( $order_currency . ' (' . $total_currency_orders . ')' );
299
  } */
300
+
301
+ $execution_time_end = microtime( true );
302
+
303
+ // HTML
304
  $html = '';
305
  $menu = '';
306
  $menu .= '<ul class="subsubsub">';
310
  $menu .= '<br class="clear">';
311
  $html .= $menu;
312
  $html .= '<h4>' . __( 'Report currency', 'woocommerce-jetpack' ) . ': ' . $report_currency . '</h4>';
313
+ $months_styles = array();
314
+ for ( $i = 1; $i <= 12; $i++ ) {
315
+ $months_styles[] = 'width:6%;';
316
+ }
317
  $html .= wcj_get_table_html( $table_data, array(
318
  'table_class' => 'widefat striped',
319
  'table_heading_type' => 'horizontal',
320
+ 'columns_styles' => array_merge(
321
+ array( 'width:16%;' ),
322
+ $months_styles,
323
+ array( 'width:12%;font-weight:bold;' )
 
 
 
 
 
 
 
 
 
 
324
  ),
325
  ) );
326
+ $html .= '<p style="font-size:x-small;"><em>' . sprintf( __( 'Report generated in: %s s', 'woocommerce-jetpack' ),
327
+ number_format( ( $execution_time_end - $execution_time_start ), 2, '.', ',' ) ) . '</em></p>';
328
+ $html .= '<form method="post" action="">' . '<input name="wcj_reset_currency_rates" type="submit" class="button button-primary" value="' . __( 'Reset Currency Rates', 'woocommerce-jetpack' ) . '">' . '</form>';
329
+ // $html .= '<pre>' . print_r( get_option( 'wcj_reports_currency_rates' ), true ) . '</pre>';
330
  return $html;
331
  }
332
  }
includes/shipping/class-wc-shipping-wcj-custom.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Custom Shipping class.
6
  *
7
- * @version 2.5.2
8
  * @since 2.4.8
9
  * @author Algoritmika Ltd.
10
  */
@@ -156,12 +156,12 @@ if ( ! function_exists( 'init_wc_shipping_wcj_custom_class' ) ) {
156
  /**
157
  * calculate_shipping function.
158
  *
159
- * @version 2.5.2
160
  * @access public
161
  * @param mixed $package
162
  * @return void
163
  */
164
- function calculate_shipping( $package ) {
165
  switch ( $this->type ) {
166
  case 'by_total_cart_quantity':
167
  $cart_quantity = 0;
4
  *
5
  * The WooCommerce Jetpack Custom Shipping class.
6
  *
7
+ * @version 2.5.3
8
  * @since 2.4.8
9
  * @author Algoritmika Ltd.
10
  */
156
  /**
157
  * calculate_shipping function.
158
  *
159
+ * @version 2.5.3
160
  * @access public
161
  * @param mixed $package
162
  * @return void
163
  */
164
+ function calculate_shipping( $package = array() ) {
165
  switch ( $this->type ) {
166
  case 'by_total_cart_quantity':
167
  $cart_quantity = 0;
includes/shortcodes/class-wcj-orders-shortcodes.php CHANGED
@@ -4,7 +4,7 @@
4
  *
5
  * The WooCommerce Jetpack Orders Shortcodes class.
6
  *
7
- * @version 2.5.2
8
  * @author Algoritmika Ltd.
9
  */
10
 
@@ -17,7 +17,7 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
17
  /**
18
  * Constructor.
19
  *
20
- * @version 2.4.8
21
  */
22
  public function __construct() {
23
 
@@ -36,12 +36,14 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
36
  'wcj_order_custom_field',
37
  'wcj_order_custom_meta_field',
38
  'wcj_order_meta',
 
39
 
40
  'wcj_order_subtotal',
41
  'wcj_order_subtotal_plus_shipping',
42
  'wcj_order_total_discount',
43
  // 'wcj_order_cart_discount',
44
  'wcj_order_shipping_tax',
 
45
  'wcj_order_total_tax',
46
  'wcj_order_total_tax_percent',
47
  'wcj_order_total',
@@ -49,6 +51,7 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
49
  'wcj_order_total_in_words',
50
  'wcj_order_total_excl_tax',
51
  'wcj_order_shipping_price',
 
52
 
53
  'wcj_order_total_fees',
54
  'wcj_order_total_fees_incl_tax',
@@ -283,6 +286,29 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
283
  return $this->the_order->billing_phone;
284
  }
285
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  /**
287
  * wcj_order_meta.
288
  *
@@ -444,6 +470,35 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
444
  return number_format( $order_total_tax_percent, $atts['precision'] );
445
  }
446
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
447
  /**
448
  * wcj_order_total_tax.
449
  */
4
  *
5
  * The WooCommerce Jetpack Orders Shortcodes class.
6
  *
7
+ * @version 2.5.3
8
  * @author Algoritmika Ltd.
9
  */
10
 
17
  /**
18
  * Constructor.
19
  *
20
+ * @version 2.5.3
21
  */
22
  public function __construct() {
23
 
36
  'wcj_order_custom_field',
37
  'wcj_order_custom_meta_field',
38
  'wcj_order_meta',
39
+ 'wcj_order_items_meta',
40
 
41
  'wcj_order_subtotal',
42
  'wcj_order_subtotal_plus_shipping',
43
  'wcj_order_total_discount',
44
  // 'wcj_order_cart_discount',
45
  'wcj_order_shipping_tax',
46
+ 'wcj_order_taxes_html',
47
  'wcj_order_total_tax',
48
  'wcj_order_total_tax_percent',
49
  'wcj_order_total',
51
  'wcj_order_total_in_words',
52
  'wcj_order_total_excl_tax',
53
  'wcj_order_shipping_price',
54
+ 'wcj_order_total_refunded',
55
 
56
  'wcj_order_total_fees',
57
  'wcj_order_total_fees_incl_tax',
286
  return $this->the_order->billing_phone;
287
  }
288
 
289
+ /**
290
+ * wcj_order_items_meta.
291
+ *
292
+ * @version 2.5.3
293
+ * @since 2.5.3
294
+ */
295
+ function wcj_order_items_meta( $atts ) {
296
+ $items_metas = array();
297
+ $the_items = $this->the_order->get_items();
298
+ foreach ( $the_items as $item_id => $item ) {
299
+ $the_meta = $this->the_order->get_item_meta( $item_id, $atts['meta_key'], true );
300
+ if ( '' != $the_meta ) {
301
+ $items_metas[] = $the_meta;
302
+ }
303
+ /* foreach ( $item as $key => $value ) {
304
+ if ( $atts['meta_key'] === $key ) {
305
+ $items_metas[] = $value;
306
+ }
307
+ } */
308
+ }
309
+ return ( ! empty( $items_metas ) ) ? implode( ', ', $items_metas ) : '';
310
+ }
311
+
312
  /**
313
  * wcj_order_meta.
314
  *
470
  return number_format( $order_total_tax_percent, $atts['precision'] );
471
  }
472
 
473
+ /**
474
+ * wcj_order_total_refunded.
475
+ *
476
+ * @version 2.5.3
477
+ * @since 2.5.3
478
+ */
479
+ function wcj_order_total_refunded( $atts ) {
480
+ return $this->wcj_price_shortcode( $this->the_order->get_total_refunded(), $atts );
481
+ }
482
+
483
+ /**
484
+ * wcj_order_taxes_html.
485
+ *
486
+ * @version 2.5.3
487
+ * @since 2.5.3
488
+ */
489
+ function wcj_order_taxes_html( $atts ) {
490
+ $order_taxes = $this->the_order->get_taxes();
491
+ $taxes_html = '';
492
+ foreach ( $order_taxes as $order_tax ) {
493
+ $taxes_html .= ( isset( $order_tax['label'] ) ) ? $order_tax['label'] . ': ' : '';
494
+ $amount = 0;
495
+ $amount += ( isset( $order_tax['tax_amount'] ) ) ? $order_tax['tax_amount'] : 0;
496
+ $amount += ( isset( $order_tax['shipping_tax_amount'] ) ) ? $order_tax['shipping_tax_amount'] : 0;
497
+ $taxes_html .= $this->wcj_price_shortcode( $amount, $atts ) . '<br>';
498
+ }
499
+ return $taxes_html;
500
+ }
501
+
502
  /**
503
  * wcj_order_total_tax.
504
  */
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: algoritmika,anbinder
3
  Tags: woocommerce,booster for woocommerce,woocommerce jetpack,custom price labels,call for price,currency symbol,remove sorting,remove old product slugs,add to cart text,order number,sequential order numbering,email pdf invoice,pdf invoice,pdf invoices,already in cart,empty cart,redirect to checkout,minimum order amount,customize checkout fields,checkout fields,email,customize product tabs,product tabs,related products number,empty cart,redirect add to cart,redirect to checkout,product already in cart,custom payment gateway,payment gateway icon,auto-complete all orders,custom order statuses,custom order status,remove text from price,custom css,hide categories count,hide subcategories count,hide category count,hide subcategory count,display total sales,custom product tabs,remove product tab,payment gateway fee,vat,gateway by country,price by country,currency switcher
4
  Requires at least: 4.1
5
  Tested up to: 4.5
6
- Stable tag: 2.5.2
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -42,15 +42,16 @@ Booster for WooCommerce is a WordPress plugin that supercharges your site with a
42
 
43
  * *Bookings* - Add bookings products to WooCommerce.
44
  * *Crowdfunding* - Add crowdfunding products to WooCommerce.
45
- * *Product Add to Cart* - Set any local url to redirect to on WooCommerce Add to Cart. Automatically add to cart on product visit. Display radio buttons instead of drop box for variable products.
 
46
  * *Product Cost Price* - Save WooCommerce product purchase costs data for admin reports.
47
  * *Product Images* - Customize WooCommerce products images, thumbnails and sale flashes.
48
  * *Product Info* - Add additional info to WooCommerce category and single product pages.
49
  * *Product Input Fields* - WooCommerce product input fields.
50
- * *Product Listings* - Change WooCommerce display options for shop and category pages: show/hide categories count, exclude categories, show/hide empty categories.
51
  * *Product Tabs* - Add custom product tabs - globally or per product. Customize or completely remove WooCommerce default product tabs.
52
  * *Product by Country* - Display WooCommerce products by customers country.
53
- * *Product by User* - Let users to add new WooCommerce products from frontend.
54
  * *Related Products* - Change displayed WooCommerce related products number, columns, order, relate by tag and/or category, or hide related products completely.
55
  * *SKU* - Generate WooCommerce SKUs automatically.
56
  * *Sorting* - Add more WooCommerce sorting options or remove all sorting including default.
@@ -73,6 +74,7 @@ Booster for WooCommerce is a WordPress plugin that supercharges your site with a
73
  * *Gateways Icons* - Change or completely remove icons (images) for any (default or custom) WooCommerce payment gateway.
74
  * *Gateways Min/Max* - Add min/max amounts for WooCommerce payment gateways to show up.
75
  * *Gateways by Country or State* - Set countries or states to include/exclude for WooCommerce payment gateways to show up.
 
76
  * *Gateways per Product or Category* - Show WooCommerce gateway only if there is selected product or product category in cart.
77
 
78
  **Shipping & Orders**
@@ -80,7 +82,7 @@ Booster for WooCommerce is a WordPress plugin that supercharges your site with a
80
  * *Address Formats* - Set address format in WooCommerce orders on per country basis. Force base country display.
81
  * *Order Custom Statuses* - Custom statuses for WooCommerce orders.
82
  * *Order Numbers* - WooCommerce sequential order numbering, custom order number prefix, suffix and number width.
83
- * *Orders* - Minimum WooCommerce order amount; orders auto-complete; custom admin order list columns.
84
  * *Shipping* - Add multiple custom shipping methods to WooCommerce. Hide WooCommerce shipping when free is available. Display "left to free shipping" info.
85
  * *Shipping Calculator* - Customize WooCommerce shipping calculator on cart page.
86
 
@@ -94,7 +96,7 @@ Booster for WooCommerce is a WordPress plugin that supercharges your site with a
94
  * *Booster WPML* - Booster for WooCommerce basic WPML support.
95
  * *EU VAT Number* - Collect and validate EU VAT numbers on WooCommerce checkout. Automatically disable VAT for valid numbers. Add all EU countries VAT standard rates to WooCommerce.
96
  * *Emails* - Add custom emails. Add another email recipient(s) to all WooCommerce emails.
97
- * *General* - Separate custom CSS for front and back end. Shortcodes in Wordpress text widgets.
98
  * *Old Slugs* - Remove old WooCommerce products slugs.
99
  * *Reports* - WooCommerce stock, sales, customers etc. reports.
100
 
@@ -124,6 +126,39 @@ To unlock all Booster for WooCommerce features, please install additional [Boost
124
 
125
  == Changelog ==
126
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  = 2.5.2 - 21/06/2016 =
128
  * Dev - "Manage Settings" functionality added.
129
  * Dev - `wcj_add_files_upload_form_to_checkout_frontend` function added.
3
  Tags: woocommerce,booster for woocommerce,woocommerce jetpack,custom price labels,call for price,currency symbol,remove sorting,remove old product slugs,add to cart text,order number,sequential order numbering,email pdf invoice,pdf invoice,pdf invoices,already in cart,empty cart,redirect to checkout,minimum order amount,customize checkout fields,checkout fields,email,customize product tabs,product tabs,related products number,empty cart,redirect add to cart,redirect to checkout,product already in cart,custom payment gateway,payment gateway icon,auto-complete all orders,custom order statuses,custom order status,remove text from price,custom css,hide categories count,hide subcategories count,hide category count,hide subcategory count,display total sales,custom product tabs,remove product tab,payment gateway fee,vat,gateway by country,price by country,currency switcher
4
  Requires at least: 4.1
5
  Tested up to: 4.5
6
+ Stable tag: 2.5.3
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
42
 
43
  * *Bookings* - Add bookings products to WooCommerce.
44
  * *Crowdfunding* - Add crowdfunding products to WooCommerce.
45
+ * *Product Add to Cart* - Set any local url to redirect to on WooCommerce Add to Cart. Automatically add to cart on product visit. Display radio buttons instead of drop box for variable products. Disable quantity input. Disable add to cart button on per product basis. Open external products on add to cart in new window.
46
+ * *Product Addons* - Add (paid/free/discount) addons to WooCommerce products.
47
  * *Product Cost Price* - Save WooCommerce product purchase costs data for admin reports.
48
  * *Product Images* - Customize WooCommerce products images, thumbnails and sale flashes.
49
  * *Product Info* - Add additional info to WooCommerce category and single product pages.
50
  * *Product Input Fields* - WooCommerce product input fields.
51
+ * *Product Listings* - Change WooCommerce display options for shop and category pages: show/hide categories count, exclude categories, show/hide empty categories. Add "products per page" selector.
52
  * *Product Tabs* - Add custom product tabs - globally or per product. Customize or completely remove WooCommerce default product tabs.
53
  * *Product by Country* - Display WooCommerce products by customers country.
54
+ * *Product by User* - Let users add new WooCommerce products from frontend.
55
  * *Related Products* - Change displayed WooCommerce related products number, columns, order, relate by tag and/or category, or hide related products completely.
56
  * *SKU* - Generate WooCommerce SKUs automatically.
57
  * *Sorting* - Add more WooCommerce sorting options or remove all sorting including default.
74
  * *Gateways Icons* - Change or completely remove icons (images) for any (default or custom) WooCommerce payment gateway.
75
  * *Gateways Min/Max* - Add min/max amounts for WooCommerce payment gateways to show up.
76
  * *Gateways by Country or State* - Set countries or states to include/exclude for WooCommerce payment gateways to show up.
77
+ * *Gateways by User Role* - Set user roles to include/exclude for WooCommerce payment gateways to show up.
78
  * *Gateways per Product or Category* - Show WooCommerce gateway only if there is selected product or product category in cart.
79
 
80
  **Shipping & Orders**
82
  * *Address Formats* - Set address format in WooCommerce orders on per country basis. Force base country display.
83
  * *Order Custom Statuses* - Custom statuses for WooCommerce orders.
84
  * *Order Numbers* - WooCommerce sequential order numbering, custom order number prefix, suffix and number width.
85
+ * *Orders* - Minimum WooCommerce order amount (optionally by user role); orders auto-complete; custom admin order list columns.
86
  * *Shipping* - Add multiple custom shipping methods to WooCommerce. Hide WooCommerce shipping when free is available. Display "left to free shipping" info.
87
  * *Shipping Calculator* - Customize WooCommerce shipping calculator on cart page.
88
 
96
  * *Booster WPML* - Booster for WooCommerce basic WPML support.
97
  * *EU VAT Number* - Collect and validate EU VAT numbers on WooCommerce checkout. Automatically disable VAT for valid numbers. Add all EU countries VAT standard rates to WooCommerce.
98
  * *Emails* - Add custom emails. Add another email recipient(s) to all WooCommerce emails.
99
+ * *General* - Separate custom CSS for front and back end. Shortcodes in Wordpress text widgets. Export tools. Custom roles tool.
100
  * *Old Slugs* - Remove old WooCommerce products slugs.
101
  * *Reports* - WooCommerce stock, sales, customers etc. reports.
102
 
126
 
127
  == Changelog ==
128
 
129
+ = 2.5.3 - 04/07/2016 =
130
+ * Dev - Shortcodes - Orders - `[wcj_order_total_refunded]` shortcode added.
131
+ * Dev - Shortcodes - Orders - `[wcj_order_taxes_html]` shortcode added.
132
+ * Dev - Shortcodes - Orders - `[wcj_order_items_meta]` shortcode added.
133
+ * Dev - PRICES & CURRENCIES - Currency Exchange Rates - "Logging" option removed.
134
+ * Fix - PRICES & CURRENCIES - Prices and Currencies by Country - Price Filter widget fixed. `add_hooks()` function moved from `init` hook to constructor.
135
+ * Dev - PRICES & CURRENCIES - Price by User Role - Class functions replaced with global functions.
136
+ * Dev - PRODUCTS - Bookings - "Hide Quantity Selector" option added.
137
+ * Dev - PRODUCTS - Product Add to Cart - "Open External Products on Add to Cart in New Window" option added.
138
+ * Dev - PRODUCTS - Product Addons - Initial module release.
139
+ * Fix - PRODUCTS - Product by User - Settings moved to `init` hook. This caused "wp-admin show white screen and no errors" on some servers (or "Fatal error: Call to undefined function wp_get_current_user() in ..." message if debug enabled).
140
+ * Dev - PRODUCTS - Product by User - Class functions replaced with global functions.
141
+ * Dev - PRODUCTS - Product Listings - "Products per Page" options added.
142
+ * Fix - PRODUCTS - Product Input Fields - `output_custom_input_fields_in_admin_order()` for shipping bug fixed.
143
+ * Dev - PRODUCTS - SKU - "Allow Duplicate SKUs" option added.
144
+ * Dev - PAYMENT GATEWAYS - Gateways by User Role - Initial module release.
145
+ * Dev - SHIPPING & ORDERS - Orders - "Custom Columns" options added.
146
+ * Dev - SHIPPING & ORDERS - Orders - Settings moved to `init` hook.
147
+ * Dev - SHIPPING & ORDERS - Orders - Order Minimum Amount - "By user role" options added. All order minimum amount hooks moved to `init` action.
148
+ * Fix - SHIPPING & ORDERS - Shipping - Hide if free is available - Fixed to work with WooCommerce since version 2.6.0. "Hide local delivery when free is available" option removed.
149
+ * Fix - SHIPPING & ORDERS - Shipping - Left to Free Shipping - Fixed to work with WooCommerce since version 2.6.0.
150
+ * Dev - PDF INVOICING & PACKING SLIPS - Invoices Report - Added "Refunds" column to the table.
151
+ * Dev - EMAILS & MISC. - Emails - Custom Emails - `do_shortcode` added to custom email recipient.
152
+ * Dev - EMAILS & MISC. - General - "Export Products" tool added.
153
+ * Dev - EMAILS & MISC. - General - "Add/Manage Custom Roles" tool moved from "Price by User Role" module.
154
+ * Dev - EMAILS & MISC. - Reports - Monthly Sales - Major code refactoring. New data added.
155
+ * Tweak - Rating message added.
156
+ * Tweak - Module's documentation button on new line.
157
+ * Tweak - Depreciated module message updated.
158
+ * Tweak - PRODUCTS - Product Add to Cart - Module description updated.
159
+ * Tweak - PRODUCTS - Product by User - Module and admin settings descriptions updated.
160
+ * Tweak - PRODUCTS - Product Info - Moved to EMAILS & MISC. Renamed to "Product Info V1". "Product Info V2" renamed to "Product Info".
161
+
162
  = 2.5.2 - 21/06/2016 =
163
  * Dev - "Manage Settings" functionality added.
164
  * Dev - `wcj_add_files_upload_form_to_checkout_frontend` function added.
woocommerce-jetpack.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: http://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
- Version: 2.5.2
7
  Author: Algoritmika Ltd
8
  Author URI: http://www.algoritmika.com
9
  Text Domain: woocommerce-jetpack
@@ -28,7 +28,7 @@ if ( ! class_exists( 'WC_Jetpack' ) ) :
28
  * Main WC_Jetpack Class
29
  *
30
  * @class WC_Jetpack
31
- * @version 2.5.2
32
  */
33
 
34
  final class WC_Jetpack {
@@ -39,7 +39,7 @@ final class WC_Jetpack {
39
  * @var string
40
  * @since 2.4.7
41
  */
42
- public $version = '2.5.2';
43
 
44
  /**
45
  * @var WC_Jetpack The single instance of the class
@@ -78,7 +78,7 @@ final class WC_Jetpack {
78
  /**
79
  * WC_Jetpack Constructor.
80
  *
81
- * @version 2.5.2
82
  * @access public
83
  */
84
  public function __construct() {
@@ -98,12 +98,13 @@ final class WC_Jetpack {
98
  add_filter( 'get_wc_jetpack_plus_message', array( $this, 'get_wcj_plus_message' ), 100, 2 );
99
  add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'action_links' ) );
100
  add_action( 'admin_menu', array( $this, 'jetpack_menu' ), 100 );
101
- // add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 2 );
102
  // add_action( 'admin_notices', array( $this, 'name_changed_notice' ) );
103
  }
104
 
105
  // Scripts
106
  if ( is_admin() ) {
 
107
  if (
108
  'yes' === get_option( 'wcj_purchase_data_enabled' ) ||
109
  'yes' === get_option( 'wcj_pdf_invoicing_enabled' ) ||
@@ -131,6 +132,16 @@ final class WC_Jetpack {
131
  do_action( 'wcj_loaded' );
132
  }
133
 
 
 
 
 
 
 
 
 
 
 
134
  /**
135
  * manage_options.
136
  *
@@ -299,15 +310,26 @@ final class WC_Jetpack {
299
 
300
  /**
301
  * admin_footer_text
 
 
302
  */
303
- /* public function admin_footer_text( $footer_text ) {
304
  if ( isset( $_GET['page'] ) ) {
305
  if ( 'wcj-tools' === $_GET['page'] || ( 'wc-settings' === $_GET['page'] && isset( $_GET['tab'] ) && 'jetpack' === $_GET['tab'] ) ) {
306
- return sprintf( __( 'If you like <strong>WooCommerce Jetpack</strong> please leave us a <a href="%1$s" target="_blank">&#9733;&#9733;&#9733;&#9733;&#9733;</a> rating on <a href="%1$s" target="_blank">WordPress.org</a>. We will be grateful for any help!', 'woocommerce-jetpack' ), 'https://wordpress.org/support/view/plugin-reviews/woocommerce-jetpack?filter=5#postform' );
 
 
 
 
 
 
 
 
 
307
  }
308
  }
309
  return $footer_text;
310
- } */
311
 
312
  /**
313
  * Add menu item
@@ -459,7 +481,7 @@ final class WC_Jetpack {
459
  /**
460
  * Include modules and submodules
461
  *
462
- * @version 2.5.2
463
  */
464
  function include_modules() {
465
  $modules_files = array(
@@ -478,6 +500,7 @@ final class WC_Jetpack {
478
  'includes/class-wcj-purchase-data.php',
479
  'includes/class-wcj-product-bookings.php',
480
  'includes/class-wcj-crowdfunding.php',
 
481
  'includes/class-wcj-wholesale-price.php',
482
  'includes/class-wcj-product-open-pricing.php',
483
  'includes/class-wcj-price-by-user-role.php',
@@ -501,6 +524,7 @@ final class WC_Jetpack {
501
  'includes/class-wcj-payment-gateways-currency.php',
502
  'includes/class-wcj-payment-gateways-min-max.php',
503
  'includes/class-wcj-payment-gateways-by-country.php',
 
504
  'includes/class-wcj-shipping.php',
505
  'includes/class-wcj-shipping-calculator.php',
506
  'includes/class-wcj-address-formats.php',
@@ -640,7 +664,7 @@ final class WC_Jetpack {
640
  /**
641
  * manage_options_export.
642
  *
643
- * @version 2.5.2
644
  * @since 2.5.2
645
  */
646
  function manage_options_export() {
@@ -669,7 +693,6 @@ final class WC_Jetpack {
669
  header( "Content-Description: File Transfer" );
670
  header( "Content-Length: " . strlen( $export_settings ) );
671
  echo $export_settings;
672
- wcj_log( $export_counter );
673
  die();
674
  }
675
 
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: http://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
+ Version: 2.5.3
7
  Author: Algoritmika Ltd
8
  Author URI: http://www.algoritmika.com
9
  Text Domain: woocommerce-jetpack
28
  * Main WC_Jetpack Class
29
  *
30
  * @class WC_Jetpack
31
+ * @version 2.5.3
32
  */
33
 
34
  final class WC_Jetpack {
39
  * @var string
40
  * @since 2.4.7
41
  */
42
+ public $version = '2.5.3';
43
 
44
  /**
45
  * @var WC_Jetpack The single instance of the class
78
  /**
79
  * WC_Jetpack Constructor.
80
  *
81
+ * @version 2.5.3
82
  * @access public
83
  */
84
  public function __construct() {
98
  add_filter( 'get_wc_jetpack_plus_message', array( $this, 'get_wcj_plus_message' ), 100, 2 );
99
  add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'action_links' ) );
100
  add_action( 'admin_menu', array( $this, 'jetpack_menu' ), 100 );
101
+ add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 2 );
102
  // add_action( 'admin_notices', array( $this, 'name_changed_notice' ) );
103
  }
104
 
105
  // Scripts
106
  if ( is_admin() ) {
107
+ add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_wcj_backend_scripts' ) );
108
  if (
109
  'yes' === get_option( 'wcj_purchase_data_enabled' ) ||
110
  'yes' === get_option( 'wcj_pdf_invoicing_enabled' ) ||
132
  do_action( 'wcj_loaded' );
133
  }
134
 
135
+ /**
136
+ * enqueue_wcj_backend_scripts.
137
+ *
138
+ * @version 2.5.3
139
+ * @since 2.5.3
140
+ */
141
+ function enqueue_wcj_backend_scripts() {
142
+ wp_enqueue_style( 'wcj-admin', wcj_plugin_url() . '/includes/css/wcj-admin.css' );
143
+ }
144
+
145
  /**
146
  * manage_options.
147
  *
310
 
311
  /**
312
  * admin_footer_text
313
+ *
314
+ * @version 2.5.3
315
  */
316
+ function admin_footer_text( $footer_text ) {
317
  if ( isset( $_GET['page'] ) ) {
318
  if ( 'wcj-tools' === $_GET['page'] || ( 'wc-settings' === $_GET['page'] && isset( $_GET['tab'] ) && 'jetpack' === $_GET['tab'] ) ) {
319
+ /* $rocket_icons = '';
320
+ for ( $i = 0; $i < 5; $i++ ) {
321
+ $rocket_icons .= wcj_get_rocket_icon();
322
+ } */
323
+ $rocket_icons = wcj_get_5_rocket_image();
324
+ $rating_link = '<a href="https://wordpress.org/support/view/plugin-reviews/woocommerce-jetpack?filter=5#postform" target="_blank">' . $rocket_icons . '</a>';
325
+ return sprintf(
326
+ __( 'If you like <strong>Booster for WooCommerce</strong> please leave us a %s rating. Thank you, we couldn\'t have done it without you!', 'woocommerce-jetpack' ),
327
+ $rating_link
328
+ );
329
  }
330
  }
331
  return $footer_text;
332
+ }
333
 
334
  /**
335
  * Add menu item
481
  /**
482
  * Include modules and submodules
483
  *
484
+ * @version 2.5.3
485
  */
486
  function include_modules() {
487
  $modules_files = array(
500
  'includes/class-wcj-purchase-data.php',
501
  'includes/class-wcj-product-bookings.php',
502
  'includes/class-wcj-crowdfunding.php',
503
+ 'includes/class-wcj-product-addons.php',
504
  'includes/class-wcj-wholesale-price.php',
505
  'includes/class-wcj-product-open-pricing.php',
506
  'includes/class-wcj-price-by-user-role.php',
524
  'includes/class-wcj-payment-gateways-currency.php',
525
  'includes/class-wcj-payment-gateways-min-max.php',
526
  'includes/class-wcj-payment-gateways-by-country.php',
527
+ 'includes/class-wcj-payment-gateways-by-user-role.php',
528
  'includes/class-wcj-shipping.php',
529
  'includes/class-wcj-shipping-calculator.php',
530
  'includes/class-wcj-address-formats.php',
664
  /**
665
  * manage_options_export.
666
  *
667
+ * @version 2.5.3
668
  * @since 2.5.2
669
  */
670
  function manage_options_export() {
693
  header( "Content-Description: File Transfer" );
694
  header( "Content-Length: " . strlen( $export_settings ) );
695
  echo $export_settings;
 
696
  die();
697
  }
698