Booster for WooCommerce - Version 3.5.0

Version Description

  • 04/04/2018 =
  • Dev - PRICES & CURRENCIES - Currency Exchange Rates - Exchange Rates Server - "Bank of England (BOE)" server added.
  • Dev - PRICES & CURRENCIES - Currency Exchange Rates - Exchange Rates Server - "Google" server added.
  • Dev - PRICES & CURRENCIES - Currency Exchange Rates - Exchange Rates Server - ECB option set as fallback; marked as "recommended".
  • Fix - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - Missing options (rounding) added to variation prices hash and hash array restructured.
  • Fix - PRICES & CURRENCIES - Multicurrency Product Base Price - Missing options (rounding etc.) added to variation prices hash and hash array restructured.
  • Dev - PRICES & CURRENCIES - Multicurrency Product Base Price - Minor code refactoring.
  • Dev - PRICES & CURRENCIES - Price Formats - wc_get_price_decimals filter added.
  • Dev - PRICES & CURRENCIES - Price by User Role - "Price by User Role by Products Tags" section added.
  • Dev - PRICES & CURRENCIES - Prices and Currencies by Country - "Booster - Selector" (country) widget now overrides "Booster - Country Switcher" widget (in case if both widgets are enabled).
  • Dev - PRODUCTS - Product Input Fields - Local input fields are saved as array now in product's meta.
  • Dev - PRODUCTS - Product Listings - Shop Page Display Options - "Exclude Categories Products" option added.
  • Dev - PRODUCTS - Product Visibility by Country - Modify Query - "Widgets" option added.
  • Dev - PRODUCTS - SKU - Autogenerate SKUs tool - Optional "Min ID" and "Max ID" options added (to generate SKUs only for selected products).
  • Dev - PRODUCTS - SKU - {product_slug}, {parent_product_slug}, {variation_attributes}, {parent_sku} replaced values added.
  • Dev - PRODUCTS - Stock - Now shortcodes are processed in all "HTML" options.
  • Dev - PAYMENT GATEWAYS - Gateways by Country, State or Postcode - General Options - "Detect Country by" (billing / shipping / by IP) and "Detect State by" (billing / shipping) options added.
  • Dev - PAYMENT GATEWAYS - Gateways by Shipping - "Use Shipping Instances" option added.
  • Dev - PAYMENT GATEWAYS - Gateways by Shipping - Code refactoring (wcj_get_shipping_methods()).
  • Fix - SHIPPING & ORDERS - Left to Free Shipping - Calculating cart total exactly as in WC_Shipping_Free_Shipping class.
  • Dev - SHIPPING & ORDERS - Left to Free Shipping - Admin settings - Descriptions updated.
  • Dev - SHIPPING & ORDERS - Left to Free Shipping - %cart_total% replaced value added.
  • Dev - SHIPPING & ORDERS - Maximum Products per User - Initial module release.
  • Dev - SHIPPING & ORDERS - Order Numbers - "Enable Editable Order Number Meta Box" option added.
  • Dev - SHIPPING & ORDERS - Order Numbers - "Minimal Order ID" option added.
  • Dev - SHIPPING & ORDERS - Order Numbers - %order_items_skus% replaced value added.
  • Dev - SHIPPING & ORDERS - Shipping Descriptions - "Description Position" option added.
  • Dev - SHIPPING & ORDERS - Shipping Methods by Min/Max Order Amount - "Use Shipping Instances" option added.
  • Dev - SHIPPING & ORDERS - Shipping Methods by Products - "Products" section - "Add Products Variations" option added.
  • Dev - SHIPPING & ORDERS - Shipping Time - Initial module release.
  • Dev - SHIPPING & ORDERS - WCJ_Module_Shipping_By_Condition (Shipping Methods by Products / Users) - "Use Shipping Instances" option added.
  • Fix - PDF INVOICING & PACKING SLIPS - Advanced - Temp Directory - Option now used in "Invoices Report" tool and in orders "Bulk Actions".
  • Dev - PDF INVOICING & PACKING SLIPS - Advanced - General Display Options - Meta Box - Editable invoice numbers added.
  • Fix - PDF INVOICING & PACKING SLIPS - Invoices Report Tool - "Download all monthly documents PDFs in single ZIP file" - check_user_roles() fixed.
  • Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - "Merge (Print)" bulk action added.
  • Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - Code refactoring.
  • Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - Download - Code refactoring (wcj_send_file() function added).
  • Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - Download - Site URL and min/max orders IDs added to zip filename.
  • Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - Download - ZIPARCHIVE::OVERWRITE added when creating zip file.
  • Dev - EMAILS & MISC. - Admin Tools - Show Variable Product Pricing Table - Displaying all variations (instead of only available variations).
  • Dev - EMAILS & MISC. - Email Options - Email Forwarding - "Orders Emails: Enable for Statuses" option added.
  • Dev - Shortcodes - General - [wcj_cart_total] - multiply_by attribute added.
  • Dev - Shortcodes - General - [wcj_shipping_time_table] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_customer_data] shortcode added.
  • Dev - Shortcodes - Orders - [wcj_order_items] - Special _sku value added for the field attribute.
  • Dev - Shortcodes - Orders - [wcj_order_notes] - limit attribute added.
  • Dev - Shortcodes - Products - [wcj_product_price] - multiply_by_attribute attribute added.
  • Dev - Shortcodes - Products - [wcj_product_shipping_time_table] shortcode added.
  • Dev - Shortcodes - multiply common attribute added.
  • Dev - Shortcodes - site_visibility common attribute - front_page option added.
  • Dev - Functions - Debug - error_reporting( E_ALL ) moved to wcj-loader.php.
  • Dev - Functions - Debug - wcj_log() - $do_var_dump param added.
  • Dev - Functions - Price and Currency - wcj_get_currency_exchange_rate_product_base_currency() - Minor code refactoring.
  • Dev - Functions - Products - wcj_get_products() - Product's ID info added.
  • Dev - Functions - Products - wcj_product_has_terms() - Function now also accepts product id as param.
  • Dev - Functions - Shipping - wcj-functions-shipping.php added.
  • Fix - Classes - WCJ_Invoice - get_file_name() - Empty file name fallback fixed.
  • Dev - Classes - Shortcodes - Minor code refactoring.
  • Dev - Classes - WCJ_PDF_Invoice - Minor code refactoring.
  • Dev - Manage Settings - "Use List Instead of Comma Separated Text for Products Categories/Tags in Settings" options added (Supported modules: Product Info).
Download this release

Release Info

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

Code changes from version 3.4.5 to 3.5.0

Files changed (121) hide show
  1. includes/admin/class-wc-settings-jetpack.php +22 -4
  2. includes/admin/wcj-modules-cats.php +3 -1
  3. includes/class-wcj-admin-tools.php +1 -0
  4. includes/class-wcj-email-options.php +38 -11
  5. includes/class-wcj-max-products-per-user.php +282 -0
  6. includes/class-wcj-multicurrency-product-base-price.php +8 -26
  7. includes/class-wcj-multicurrency.php +9 -8
  8. includes/class-wcj-order-numbers.php +32 -5
  9. includes/class-wcj-order-quantities.php +3 -3
  10. includes/class-wcj-payment-gateways-by-country.php +10 -5
  11. includes/class-wcj-payment-gateways-by-shipping.php +28 -8
  12. includes/class-wcj-pdf-invoicing.php +112 -55
  13. includes/class-wcj-price-by-user-role.php +33 -4
  14. includes/class-wcj-price-formats.php +37 -3
  15. includes/class-wcj-product-addons.php +1 -1
  16. includes/class-wcj-product-by-country.php +30 -2
  17. includes/class-wcj-product-custom-info.php +6 -6
  18. includes/class-wcj-product-listings.php +23 -2
  19. includes/class-wcj-shipping-by-order-amount.php +8 -5
  20. includes/class-wcj-shipping-by-products.php +35 -9
  21. includes/class-wcj-shipping-description.php +18 -8
  22. includes/class-wcj-shipping-time.php +38 -0
  23. includes/class-wcj-sku.php +47 -13
  24. includes/class-wcj-stock.php +18 -19
  25. includes/classes/class-wcj-invoice.php +8 -5
  26. includes/classes/class-wcj-module-shipping-by-condition.php +12 -5
  27. includes/classes/class-wcj-pdf-invoice.php +32 -34
  28. includes/classes/class-wcj-shortcodes.php +19 -7
  29. includes/core/wcj-functions.php +2 -1
  30. includes/core/wcj-loader.php +6 -1
  31. includes/core/wcj-modules.php +3 -1
  32. includes/functions/wcj-functions-admin.php +15 -7
  33. includes/functions/wcj-functions-country.php +1 -0
  34. includes/functions/wcj-functions-currencies.php +1 -0
  35. includes/functions/wcj-functions-debug.php +8 -9
  36. includes/functions/wcj-functions-exchange-rates.php +129 -11
  37. includes/functions/wcj-functions-general.php +70 -95
  38. includes/functions/wcj-functions-invoicing.php +13 -1
  39. includes/functions/wcj-functions-price-currency.php +4 -6
  40. includes/functions/wcj-functions-products.php +8 -7
  41. includes/functions/wcj-functions-reports.php +1 -0
  42. includes/functions/wcj-functions-shipping.php +278 -0
  43. includes/functions/wcj-functions-users.php +16 -1
  44. includes/input-fields/class-wcj-product-input-fields-core.php +72 -31
  45. includes/lib/FPDI/LICENSE.txt +21 -0
  46. includes/lib/FPDI/README.md +141 -0
  47. includes/lib/FPDI/composer.json +48 -0
  48. includes/lib/FPDI/src/FpdfTpl.php +428 -0
  49. includes/lib/FPDI/src/Fpdi.php +147 -0
  50. includes/lib/FPDI/src/FpdiException.php +20 -0
  51. includes/lib/FPDI/src/FpdiTrait.php +523 -0
  52. includes/lib/FPDI/src/PdfParser/CrossReference/AbstractReader.php +86 -0
  53. includes/lib/FPDI/src/PdfParser/CrossReference/CrossReference.php +295 -0
  54. includes/lib/FPDI/src/PdfParser/CrossReference/CrossReferenceException.php +81 -0
  55. includes/lib/FPDI/src/PdfParser/CrossReference/FixedReader.php +193 -0
  56. includes/lib/FPDI/src/PdfParser/CrossReference/LineReader.php +173 -0
  57. includes/lib/FPDI/src/PdfParser/CrossReference/ReaderInterface.php +36 -0
  58. includes/lib/FPDI/src/PdfParser/Filter/Ascii85.php +105 -0
  59. includes/lib/FPDI/src/PdfParser/Filter/Ascii85Exception.php +29 -0
  60. includes/lib/FPDI/src/PdfParser/Filter/AsciiHex.php +49 -0
  61. includes/lib/FPDI/src/PdfParser/Filter/FilterException.php +25 -0
  62. includes/lib/FPDI/src/PdfParser/Filter/FilterInterface.php +27 -0
  63. includes/lib/FPDI/src/PdfParser/Filter/Flate.php +69 -0
  64. includes/lib/FPDI/src/PdfParser/Filter/FlateException.php +29 -0
  65. includes/lib/FPDI/src/PdfParser/Filter/Lzw.php +190 -0
  66. includes/lib/FPDI/src/PdfParser/Filter/LzwException.php +24 -0
  67. includes/lib/FPDI/src/PdfParser/PdfParser.php +305 -0
  68. includes/lib/FPDI/src/PdfParser/PdfParserException.php +51 -0
  69. includes/lib/FPDI/src/PdfParser/StreamReader.php +461 -0
  70. includes/lib/FPDI/src/PdfParser/Tokenizer.php +162 -0
  71. includes/lib/FPDI/src/PdfParser/Type/PdfArray.php +85 -0
  72. includes/lib/FPDI/src/PdfParser/Type/PdfBoolean.php +43 -0
  73. includes/lib/FPDI/src/PdfParser/Type/PdfDictionary.php +133 -0
  74. includes/lib/FPDI/src/PdfParser/Type/PdfHexString.php +82 -0
  75. includes/lib/FPDI/src/PdfParser/Type/PdfIndirectObject.php +103 -0
  76. includes/lib/FPDI/src/PdfParser/Type/PdfIndirectObjectReference.php +53 -0
  77. includes/lib/FPDI/src/PdfParser/Type/PdfName.php +82 -0
  78. includes/lib/FPDI/src/PdfParser/Type/PdfNull.php +21 -0
  79. includes/lib/FPDI/src/PdfParser/Type/PdfNumeric.php +44 -0
  80. includes/lib/FPDI/src/PdfParser/Type/PdfStream.php +275 -0
  81. includes/lib/FPDI/src/PdfParser/Type/PdfString.php +172 -0
  82. includes/lib/FPDI/src/PdfParser/Type/PdfToken.php +44 -0
  83. includes/lib/FPDI/src/PdfParser/Type/PdfType.php +76 -0
  84. includes/lib/FPDI/src/PdfParser/Type/PdfTypeException.php +26 -0
  85. includes/lib/FPDI/src/PdfReader/DataStructure/Rectangle.php +169 -0
  86. includes/lib/FPDI/src/PdfReader/Page.php +251 -0
  87. includes/lib/FPDI/src/PdfReader/PageBoundaries.php +96 -0
  88. includes/lib/FPDI/src/PdfReader/PdfReader.php +207 -0
  89. includes/lib/FPDI/src/PdfReader/PdfReaderException.php +36 -0
  90. includes/lib/FPDI/src/TcpdfFpdi.php +262 -0
  91. includes/lib/FPDI/src/autoload.php +21 -0
  92. includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php +5 -5
  93. includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php +16 -4
  94. includes/price-by-country/class-wcj-price-by-country-core.php +5 -2
  95. includes/settings/meta-box/wcj-settings-meta-box-admin-tools.php +3 -2
  96. includes/settings/meta-box/wcj-settings-meta-box-max-products-per-user.php +21 -0
  97. includes/settings/meta-box/wcj-settings-meta-box-order-numbers.php +20 -0
  98. includes/settings/meta-box/wcj-settings-meta-box-pdf-invoicing.php +33 -0
  99. includes/settings/wcj-settings-left-to-free-shipping.php +5 -12
  100. includes/settings/wcj-settings-max-products-per-user.php +89 -0
  101. includes/settings/wcj-settings-order-numbers.php +19 -1
  102. includes/settings/wcj-settings-payment-gateways-by-country.php +24 -4
  103. includes/settings/wcj-settings-payment-gateways-by-shipping.php +25 -9
  104. includes/settings/wcj-settings-pdf-invoicing-advanced.php +8 -2
  105. includes/settings/wcj-settings-price-by-user-role.php +64 -46
  106. includes/settings/wcj-settings-price-formats.php +2 -2
  107. includes/settings/wcj-settings-product-by-country.php +8 -1
  108. includes/settings/wcj-settings-product-custom-info.php +42 -38
  109. includes/settings/wcj-settings-product-listings.php +11 -1
  110. includes/settings/wcj-settings-shipping-by-condition.php +29 -6
  111. includes/settings/wcj-settings-shipping-by-order-amount.php +27 -6
  112. includes/settings/wcj-settings-shipping-description.php +16 -2
  113. includes/settings/wcj-settings-shipping-time.php +83 -0
  114. includes/settings/wcj-settings-sku.php +13 -2
  115. includes/settings/wcj-settings-stock.php +4 -1
  116. includes/shortcodes/class-wcj-shortcodes-general.php +25 -4
  117. includes/shortcodes/class-wcj-shortcodes-orders.php +32 -14
  118. includes/shortcodes/class-wcj-shortcodes-products.php +34 -3
  119. langs/woocommerce-jetpack.pot +1563 -1049
  120. readme.txt +64 -1
  121. woocommerce-jetpack.php +2 -2
includes/admin/class-wc-settings-jetpack.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings
4
  *
5
- * @version 3.4.0
6
  * @since 1.0.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -167,7 +167,7 @@ class WC_Settings_Jetpack extends WC_Settings_Page {
167
  /**
168
  * Output the settings.
169
  *
170
- * @version 3.0.0
171
  * @todo (maybe) admin_notices
172
  */
173
  function output() {
@@ -208,7 +208,7 @@ class WC_Settings_Jetpack extends WC_Settings_Page {
208
  echo '</div>';
209
  }
210
 
211
- if ( 'yes' === get_option( 'wcj_admin_tools_enabled' ) && 'yes' === get_option( 'wcj_debuging_enabled', 'no' ) ) {
212
  // Breadcrumbs
213
  $breadcrumbs_html = '';
214
  $breadcrumbs_html .= '<p>';
@@ -445,7 +445,7 @@ class WC_Settings_Jetpack extends WC_Settings_Page {
445
  /**
446
  * get_manager_settings.
447
  *
448
- * @version 3.2.4
449
  * @since 2.6.0
450
  * @return array
451
  */
@@ -472,6 +472,24 @@ class WC_Settings_Jetpack extends WC_Settings_Page {
472
  'id' => 'wcj_list_for_products',
473
  'default' => 'yes',
474
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
475
  );
476
  }
477
 
2
  /**
3
  * Booster for WooCommerce - Settings
4
  *
5
+ * @version 3.5.0
6
  * @since 1.0.0
7
  * @author Algoritmika Ltd.
8
  */
167
  /**
168
  * Output the settings.
169
  *
170
+ * @version 3.5.0
171
  * @todo (maybe) admin_notices
172
  */
173
  function output() {
208
  echo '</div>';
209
  }
210
 
211
+ if ( 'yes' === get_option( 'wcj_admin_tools_enabled', 'no' ) && 'yes' === get_option( 'wcj_debuging_enabled', 'no' ) ) {
212
  // Breadcrumbs
213
  $breadcrumbs_html = '';
214
  $breadcrumbs_html .= '<p>';
445
  /**
446
  * get_manager_settings.
447
  *
448
+ * @version 3.5.0
449
  * @since 2.6.0
450
  * @return array
451
  */
472
  'id' => 'wcj_list_for_products',
473
  'default' => 'yes',
474
  ),
475
+ array(
476
+ 'title' => __( 'Use List Instead of Comma Separated Text for Products Categories in Settings', 'woocommerce-jetpack' ),
477
+ 'type' => 'checkbox',
478
+ 'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
479
+ __( 'Product Info', 'woocommerce-jetpack' ),
480
+ ) ) ),
481
+ 'id' => 'wcj_list_for_products_cats',
482
+ 'default' => 'yes',
483
+ ),
484
+ array(
485
+ 'title' => __( 'Use List Instead of Comma Separated Text for Products Tags in Settings', 'woocommerce-jetpack' ),
486
+ 'type' => 'checkbox',
487
+ 'desc' => sprintf( __( 'Supported modules: %s.', 'woocommerce-jetpack' ), implode( ', ', array(
488
+ __( 'Product Info', 'woocommerce-jetpack' ),
489
+ ) ) ),
490
+ 'id' => 'wcj_list_for_products_tags',
491
+ 'default' => 'yes',
492
+ ),
493
  );
494
  }
495
 
includes/admin/wcj-modules-cats.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Modules Array
4
  *
5
- * @version 3.4.0
6
  * @since 2.2.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) split "Shipping & Orders", "Cart & Checkout", "Products", "Prices & Currencies" etc.
@@ -133,6 +133,7 @@ return apply_filters( 'wcj_modules', array(
133
  'shipping_options',
134
  'shipping_icons',
135
  'shipping_description',
 
136
  'left_to_free_shipping',
137
  'shipping_calculator',
138
  'shipping_by_user_role',
@@ -145,6 +146,7 @@ return apply_filters( 'wcj_modules', array(
145
  'order_numbers',
146
  'order_custom_statuses',
147
  'order_quantities',
 
148
  ),
149
  ),
150
 
2
  /**
3
  * Booster for WooCommerce - Modules Array
4
  *
5
+ * @version 3.5.0
6
  * @since 2.2.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) split "Shipping & Orders", "Cart & Checkout", "Products", "Prices & Currencies" etc.
133
  'shipping_options',
134
  'shipping_icons',
135
  'shipping_description',
136
+ 'shipping_time',
137
  'left_to_free_shipping',
138
  'shipping_calculator',
139
  'shipping_by_user_role',
146
  'order_numbers',
147
  'order_custom_statuses',
148
  'order_quantities',
149
+ 'max_products_per_user',
150
  ),
151
  ),
152
 
includes/class-wcj-admin-tools.php CHANGED
@@ -16,6 +16,7 @@ class WCJ_Admin_Tools extends WCJ_Module {
16
  * Constructor.
17
  *
18
  * @version 3.3.0
 
19
  */
20
  function __construct() {
21
 
16
  * Constructor.
17
  *
18
  * @version 3.3.0
19
+ * @todo (maybe) add editable (product and order) metas
20
  */
21
  function __construct() {
22
 
includes/class-wcj-email-options.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Email Options
4
  *
5
- * @version 2.9.1
6
  * @since 2.9.1
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Email_Options extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.9.1
20
  * @since 2.9.1
21
  * @todo meta customizer - check "gravity-forms-emails-woocommerce" plugin
22
  */
@@ -31,10 +31,10 @@ class WCJ_Email_Options extends WCJ_Module {
31
  if ( $this->is_enabled() ) {
32
  // Email Forwarding
33
  if ( '' != get_option( 'wcj_emails_bcc_email', '' ) ) {
34
- add_filter( 'woocommerce_email_headers', array( $this, 'add_bcc_email' ) );
35
  }
36
  if ( '' != get_option( 'wcj_emails_cc_email', '' ) ) {
37
- add_filter( 'woocommerce_email_headers', array( $this, 'add_cc_email' ) );
38
  }
39
  // Product Info
40
  if ( 'yes' === get_option( 'wcj_product_info_in_email_order_item_name_enabled', 'no' ) ) {
@@ -62,28 +62,44 @@ class WCJ_Email_Options extends WCJ_Module {
62
  return $item_name;
63
  }
64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  /**
66
  * Add another email recipient to all WooCommerce emails.
67
  *
68
- * @version 2.9.1
69
  */
70
- function add_bcc_email( $email_headers ) {
71
- return $email_headers . "Bcc: " . get_option( 'wcj_emails_bcc_email', '' ) . "\r\n";
72
  }
73
 
74
  /**
75
  * Add another email recipient to all WooCommerce emails.
76
  *
77
- * @version 2.9.1
78
  */
79
- function add_cc_email( $email_headers ) {
80
- return $email_headers . "Cc: " . get_option( 'wcj_emails_cc_email', '' ) . "\r\n";
81
  }
82
 
83
  /**
84
  * get_emails_forwarding_settings.
85
  *
86
- * @version 2.3.9
87
  * @since 2.3.9
88
  */
89
  function get_emails_forwarding_settings( $extended_title = false ) {
@@ -110,6 +126,17 @@ class WCJ_Email_Options extends WCJ_Module {
110
  'default' => '',
111
  'type' => 'text',
112
  ),
 
 
 
 
 
 
 
 
 
 
 
113
  array(
114
  'type' => 'sectionend',
115
  'id' => 'wcj_emails_forwarding_options',
2
  /**
3
  * Booster for WooCommerce - Module - Email Options
4
  *
5
+ * @version 3.5.0
6
  * @since 2.9.1
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.5.0
20
  * @since 2.9.1
21
  * @todo meta customizer - check "gravity-forms-emails-woocommerce" plugin
22
  */
31
  if ( $this->is_enabled() ) {
32
  // Email Forwarding
33
  if ( '' != get_option( 'wcj_emails_bcc_email', '' ) ) {
34
+ add_filter( 'woocommerce_email_headers', array( $this, 'add_bcc_email' ), PHP_INT_MAX, 3 );
35
  }
36
  if ( '' != get_option( 'wcj_emails_cc_email', '' ) ) {
37
+ add_filter( 'woocommerce_email_headers', array( $this, 'add_cc_email' ), PHP_INT_MAX, 3 );
38
  }
39
  // Product Info
40
  if ( 'yes' === get_option( 'wcj_product_info_in_email_order_item_name_enabled', 'no' ) ) {
62
  return $item_name;
63
  }
64
 
65
+ /**
66
+ * maybe_check_order_status.
67
+ *
68
+ * @version 3.5.0
69
+ * @since 3.5.0
70
+ */
71
+ function maybe_check_order_status( $_object ) {
72
+ $enable_order_statuses = apply_filters( 'booster_option', '', get_option( 'wcj_emails_forwarding_enable_order_status', '' ) );
73
+ if ( ! empty( $enable_order_statuses ) && isset( $_object ) && is_object( $_object ) && 'WC_Order' === get_class( $_object ) ) {
74
+ if ( ! in_array( $_object->get_status(), $enable_order_statuses ) ) {
75
+ return false;
76
+ }
77
+ }
78
+ return true;
79
+ }
80
+
81
  /**
82
  * Add another email recipient to all WooCommerce emails.
83
  *
84
+ * @version 3.5.0
85
  */
86
+ function add_bcc_email( $email_headers, $id, $_object ) {
87
+ return ( $this->maybe_check_order_status( $_object ) ? $email_headers . "Bcc: " . get_option( 'wcj_emails_bcc_email', '' ) . "\r\n" : $email_headers );
88
  }
89
 
90
  /**
91
  * Add another email recipient to all WooCommerce emails.
92
  *
93
+ * @version 3.5.0
94
  */
95
+ function add_cc_email( $email_headers, $id, $_object ) {
96
+ return ( $this->maybe_check_order_status( $_object ) ? $email_headers . "Cc: " . get_option( 'wcj_emails_cc_email', '' ) . "\r\n" : $email_headers );
97
  }
98
 
99
  /**
100
  * get_emails_forwarding_settings.
101
  *
102
+ * @version 3.5.0
103
  * @since 2.3.9
104
  */
105
  function get_emails_forwarding_settings( $extended_title = false ) {
126
  'default' => '',
127
  'type' => 'text',
128
  ),
129
+ array(
130
+ 'title' => __( 'Orders Emails: Enable for Statuses', 'woocommerce-jetpack' ),
131
+ 'desc' => apply_filters( 'booster_message', '', 'desc' ),
132
+ 'desc_tip' => __( 'If you want to forward emails for certain orders only, set order statuses here. Leave blank to send for all orders statuses.', 'woocommerce-jetpack' ),
133
+ 'id' => 'wcj_emails_forwarding_enable_order_status',
134
+ 'default' => '',
135
+ 'type' => 'multiselect',
136
+ 'class' => 'chosen_select',
137
+ 'options' => wcj_get_order_statuses(),
138
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
139
+ ),
140
  array(
141
  'type' => 'sectionend',
142
  'id' => 'wcj_emails_forwarding_options',
includes/class-wcj-max-products-per-user.php ADDED
@@ -0,0 +1,282 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Max Products per User
4
+ *
5
+ * @version 3.5.0
6
+ * @since 3.5.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ if ( ! class_exists( 'WCJ_Max_products_Per_User' ) ) :
13
+
14
+ class WCJ_Max_products_Per_User extends WCJ_Module {
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 3.5.0
20
+ * @since 3.5.0
21
+ * @todo (maybe) JS
22
+ * @todo (maybe) zero quantity for "Guest"
23
+ * @todo (maybe) editable sales date (i.e. change "Qty Bought" for product for user)
24
+ */
25
+ function __construct() {
26
+
27
+ $this->id = 'max_products_per_user';
28
+ $this->short_desc = __( 'Maximum Products per User', 'woocommerce-jetpack' );
29
+ $this->desc = __( 'Limit number of items your WooCommerce customers (logged) can buy.', 'woocommerce-jetpack' );
30
+ $this->extra_desc = __( 'Please note, that there is no maximum quantity set for not-logged (i.e. guest) users. Product quantities are updated, when order status is changed to completed.', 'woocommerce-jetpack' );
31
+ $this->link_slug = 'woocommerce-maximum-products-per-user';
32
+ parent::__construct();
33
+
34
+ if ( $this->is_enabled() ) {
35
+ if ( 'yes' === get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) || 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
36
+ add_action( 'woocommerce_checkout_process', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
37
+ add_action( 'woocommerce_before_cart', array( $this, 'check_cart_quantities' ), PHP_INT_MAX );
38
+ if ( 'yes' === get_option( 'wcj_max_products_per_user_stop_from_seeing_checkout', 'no' ) ) {
39
+ add_action( 'wp', array( $this, 'stop_from_seeing_checkout' ), PHP_INT_MAX );
40
+ }
41
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) ) {
42
+ add_action( 'add_meta_boxes', array( $this, 'add_meta_box' ) );
43
+ add_action( 'save_post_product', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
44
+ }
45
+ }
46
+ add_action( 'woocommerce_order_status_completed', array( $this, 'save_quantities' ), PHP_INT_MAX );
47
+ add_action( 'add_meta_boxes', array( $this, 'add_report_meta_box' ) );
48
+ add_action( 'admin_init', array( $this, 'calculate_data' ) );
49
+ add_action( 'admin_notices', array( $this, 'calculate_data_notice' ) );
50
+ }
51
+ }
52
+
53
+ /**
54
+ * calculate_data_notice.
55
+ *
56
+ * @version 3.5.0
57
+ * @since 3.5.0
58
+ */
59
+ function calculate_data_notice() {
60
+ if ( isset( $_GET['wcj_max_products_per_user_calculate_data_finished'] ) ) {
61
+ $class = 'notice notice-info';
62
+ $message = __( 'Data re-calculated.', 'woocommerce-jetpack' ) . ' ' .
63
+ sprintf( __( '%s order(s) processed.', 'woocommerce-jetpack' ), $_GET['wcj_max_products_per_user_calculate_data_finished'] );
64
+ printf( '<div class="%1$s"><p>%2$s</p></div>', esc_attr( $class ), esc_html( $message ) );
65
+ }
66
+ }
67
+
68
+ /**
69
+ * calculate_data.
70
+ *
71
+ * @version 3.5.0
72
+ * @since 3.5.0
73
+ * @todo reset `wcj_max_products_per_user_report` and `wcj_max_products_per_user_saved` meta
74
+ */
75
+ function calculate_data() {
76
+ if ( isset( $_GET['wcj_max_products_per_user_calculate_data'] ) ) {
77
+ $offset = 0;
78
+ $block_size = 512;
79
+ $total_orders = 0;
80
+ while( true ) {
81
+ $args = array(
82
+ 'post_type' => 'shop_order',
83
+ 'post_status' => 'wc-completed',
84
+ 'posts_per_page' => $block_size,
85
+ 'orderby' => 'ID',
86
+ 'order' => 'DESC',
87
+ 'offset' => $offset,
88
+ 'fields' => 'ids',
89
+ );
90
+ $loop = new WP_Query( $args );
91
+ if ( ! $loop->have_posts() ) {
92
+ break;
93
+ }
94
+ foreach ( $loop->posts as $_order_id ) {
95
+ $this->save_quantities( $_order_id );
96
+ $total_orders++;
97
+ }
98
+ $offset += $block_size;
99
+ }
100
+ wp_safe_redirect( add_query_arg( 'wcj_max_products_per_user_calculate_data_finished', $total_orders,
101
+ remove_query_arg( 'wcj_max_products_per_user_calculate_data' ) ) );
102
+ exit;
103
+ }
104
+ }
105
+
106
+ /**
107
+ * add_report_meta_box.
108
+ *
109
+ * @version 3.5.0
110
+ * @since 3.5.0
111
+ */
112
+ function add_report_meta_box() {
113
+ add_meta_box(
114
+ 'wc-jetpack-' . $this->id . '-report',
115
+ __( 'Booster', 'woocommerce-jetpack' ) . ': ' . __( 'Maximum Products per User: Sales Data', 'woocommerce-jetpack' ),
116
+ array( $this, 'create_report_meta_box' ),
117
+ 'product',
118
+ 'normal',
119
+ 'high'
120
+ );
121
+ }
122
+
123
+ /**
124
+ * create_report_meta_box.
125
+ *
126
+ * @version 3.5.0
127
+ * @since 3.5.0
128
+ */
129
+ function create_report_meta_box() {
130
+ if ( $users_quantities = get_post_meta( get_the_ID(), '_' . 'wcj_max_products_per_user_report', true ) ) {
131
+ $table_data = array();
132
+ $table_data[] = array( __( 'User ID', 'woocommerce-jetpack' ), __( 'User Name', 'woocommerce-jetpack' ), __( 'Qty Bought', 'woocommerce-jetpack' ) );
133
+ foreach ( $users_quantities as $user_id => $qty_bought ) {
134
+ if ( 0 == $user_id ) {
135
+ $user = __( 'Guest', 'woocommerce-jetpack' );
136
+ } else {
137
+ $user = get_user_by( 'id', $user_id );
138
+ $user = ( isset( $user->data->user_nicename ) ? $user->data->user_nicename : '-' );
139
+ }
140
+ $table_data[] = array( $user_id, $user, $qty_bought );
141
+ }
142
+ echo wcj_get_table_html( $table_data, array( 'table_class' => 'widefat striped', 'table_heading_type' => 'horizontal' ) );
143
+ } else {
144
+ echo '<em>' . __( 'No data yet.', 'woocommerce-jetpack' ) . '</em>';
145
+ }
146
+ }
147
+
148
+ /**
149
+ * save_quantities.
150
+ *
151
+ * @version 3.5.0
152
+ * @since 3.5.0
153
+ * @todo (maybe) customizable `save_quantities` trigger
154
+ */
155
+ function save_quantities( $order_id ) {
156
+ if ( $order = wc_get_order( $order_id ) ) {
157
+ if ( 'yes' !== get_post_meta( $order_id, '_' . 'wcj_max_products_per_user_saved', true ) ) {
158
+ if ( sizeof( $order->get_items() ) > 0 ) {
159
+ $user_id = ( WCJ_IS_WC_VERSION_BELOW_3 ? $order->customer_user : $order->get_customer_id() );
160
+ foreach ( $order->get_items() as $item ) {
161
+ if ( $item->is_type( 'line_item' ) && ( $product = $item->get_product() ) ) {
162
+ $product_id = wcj_get_product_id_or_variation_parent_id( $product );
163
+ $product_qty = $item->get_quantity();
164
+ if ( '' == ( $users_quantities = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', true ) ) ) {
165
+ $users_quantities = array();
166
+ }
167
+ if ( isset( $users_quantities[ $user_id ] ) ) {
168
+ $product_qty += $users_quantities[ $user_id ];
169
+ }
170
+ $users_quantities[ $user_id ] = $product_qty;
171
+ update_post_meta( $product_id, '_' . 'wcj_max_products_per_user_report', $users_quantities );
172
+ }
173
+ }
174
+ }
175
+ update_post_meta( $order_id, '_' . 'wcj_max_products_per_user_saved', 'yes' );
176
+ }
177
+ }
178
+ }
179
+
180
+ /**
181
+ * get_max_qty.
182
+ *
183
+ * @version 3.5.0
184
+ * @since 3.5.0
185
+ * @todo (maybe) local - add "enabled/disabled" option
186
+ * @todo (maybe) global - apply only to selected products (i.e. include/exclude products, cats, tags)
187
+ * @todo (maybe) per user and/or per user role (both global and local)
188
+ */
189
+ function get_max_qty( $product_id ) {
190
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_max_products_per_user_local_enabled', 'no' ) ) && 0 != ( $qty = get_post_meta( $product_id, '_' . 'wcj_max_products_per_user_qty', true ) ) ) {
191
+ return $qty;
192
+ } elseif ( 'yes' === get_option( 'wcj_max_products_per_user_global_enabled', 'no' ) ) {
193
+ return get_option( 'wcj_max_products_per_user_global_max_qty', 1 );
194
+ } else {
195
+ return 0;
196
+ }
197
+ }
198
+
199
+ /**
200
+ * stop_from_seeing_checkout.
201
+ *
202
+ * @version 3.5.0
203
+ * @since 3.5.0
204
+ */
205
+ function stop_from_seeing_checkout() {
206
+ if ( ! function_exists( 'is_checkout' ) || ! is_checkout() ) {
207
+ return;
208
+ }
209
+ if ( ! $this->check_quantities( false ) ) {
210
+ wp_safe_redirect( wc_get_cart_url() );
211
+ exit;
212
+ }
213
+ }
214
+
215
+ /**
216
+ * check_cart_quantities.
217
+ *
218
+ * @version 3.5.0
219
+ * @since 3.5.0
220
+ */
221
+ function check_cart_quantities() {
222
+ $this->check_quantities();
223
+ }
224
+
225
+ /**
226
+ * check_quantities.
227
+ *
228
+ * @version 3.5.0
229
+ * @since 3.5.0
230
+ */
231
+ function check_quantities( $add_notices = true ) {
232
+ $result = true;
233
+ if ( ! isset( WC()->cart ) ) {
234
+ return $result;
235
+ }
236
+ if ( 0 == ( $current_user_id = wcj_get_current_user_id() ) ) {
237
+ return $result;
238
+ }
239
+ $cart_item_quantities = WC()->cart->get_cart_item_quantities();
240
+ if ( empty( $cart_item_quantities ) || ! is_array( $cart_item_quantities ) ) {
241
+ return $result;
242
+ }
243
+ $is_cart = ( function_exists( 'is_cart' ) && is_cart() );
244
+ foreach ( $cart_item_quantities as $_product_id => $cart_item_quantity ) {
245
+ if ( 0 == ( $max_qty = $this->get_max_qty( $_product_id ) ) ) {
246
+ continue;
247
+ }
248
+ $user_already_bought = 0;
249
+ if ( ( $users_quantities = get_post_meta( $_product_id, '_' . 'wcj_max_products_per_user_report', true ) ) && isset( $users_quantities[ $current_user_id ] ) ) {
250
+ $user_already_bought = $users_quantities[ $current_user_id ];
251
+ }
252
+ if ( ( $user_already_bought + $cart_item_quantity ) > $max_qty ) {
253
+ if ( $add_notices ) {
254
+ $result = false;
255
+ $product = wc_get_product( $_product_id );
256
+ $replaced_values = array(
257
+ '%max_qty%' => $max_qty,
258
+ '%product_title%' => $product->get_title(),
259
+ '%qty_already_bought%' => $user_already_bought,
260
+ '%remaining_qty%' => max( ( $max_qty - $user_already_bought ), 0 ),
261
+ );
262
+ $message = get_option( 'wcj_max_products_per_user_message',
263
+ __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' ) );
264
+ $message = str_replace( array_keys( $replaced_values ), $replaced_values, $message );
265
+ if ( $is_cart ) {
266
+ wc_print_notice( $message, 'notice' );
267
+ } else {
268
+ wc_add_notice( $message, 'error' );
269
+ }
270
+ } else {
271
+ return false;
272
+ }
273
+ }
274
+ }
275
+ return $result;
276
+ }
277
+
278
+ }
279
+
280
+ endif;
281
+
282
+ return new WCJ_Max_products_Per_User();
includes/class-wcj-multicurrency-product-base-price.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Multicurrency Product Base Price
4
  *
5
- * @version 2.8.0
6
  * @since 2.4.8
7
  * @author Algoritmika Ltd.
8
  */
@@ -44,26 +44,6 @@ class WCJ_Multicurrency_Base_Price extends WCJ_Module {
44
  }
45
  }
46
 
47
- /**
48
- * get_currency_exchange_rate.
49
- *
50
- * @version 2.5.6
51
- */
52
- function get_currency_exchange_rate( $currency_code ) {
53
- /*
54
- $currency_exchange_rate = 1;
55
- $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_multicurrency_base_price_total_number', 1 ) );
56
- for ( $i = 1; $i <= $total_number; $i++ ) {
57
- if ( $currency_code === get_option( 'wcj_multicurrency_base_price_currency_' . $i ) ) {
58
- $currency_exchange_rate = get_option( 'wcj_multicurrency_base_price_exchange_rate_' . $i );
59
- break;
60
- }
61
- }
62
- return $currency_exchange_rate;
63
- */
64
- return wcj_get_currency_exchange_rate_product_base_currency( $currency_code );
65
- }
66
-
67
  /**
68
  * change_price_grouped.
69
  *
@@ -96,14 +76,16 @@ class WCJ_Multicurrency_Base_Price extends WCJ_Module {
96
  /**
97
  * get_variation_prices_hash.
98
  *
99
- * @version 2.7.0
100
  */
101
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
102
  $multicurrency_base_price_currency = get_post_meta( wcj_get_product_id_or_variation_parent_id( $_product, true ), '_' . 'wcj_multicurrency_base_price_currency', true );
103
- $currency_exchange_rate = $this->get_currency_exchange_rate( $multicurrency_base_price_currency );
104
- $price_hash['wcj_base_currency'] = array(
105
- $multicurrency_base_price_currency,
106
- $currency_exchange_rate,
 
 
107
  );
108
  return $price_hash;
109
  }
2
  /**
3
  * Booster for WooCommerce - Module - Multicurrency Product Base Price
4
  *
5
+ * @version 3.5.0
6
  * @since 2.4.8
7
  * @author Algoritmika Ltd.
8
  */
44
  }
45
  }
46
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  /**
48
  * change_price_grouped.
49
  *
76
  /**
77
  * get_variation_prices_hash.
78
  *
79
+ * @version 3.5.0
80
  */
81
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
82
  $multicurrency_base_price_currency = get_post_meta( wcj_get_product_id_or_variation_parent_id( $_product, true ), '_' . 'wcj_multicurrency_base_price_currency', true );
83
+ $price_hash['wcj_multicurrency_base_price'] = array(
84
+ 'currency' => $multicurrency_base_price_currency,
85
+ 'exchange_rate' => wcj_get_currency_exchange_rate_product_base_currency( $multicurrency_base_price_currency ),
86
+ 'rounding' => get_option( 'wcj_multicurrency_base_price_round_enabled', 'no' ),
87
+ 'rounding_precision' => get_option( 'wcj_multicurrency_base_price_round_precision', get_option( 'woocommerce_price_num_decimals' ) ),
88
+ 'save_prices' => get_option( 'wcj_multicurrency_base_price_save_prices', 'no' ),
89
  );
90
  return $price_hash;
91
  }
includes/class-wcj-multicurrency.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Multicurrency (Currency Switcher)
4
  *
5
- * @version 3.4.5
6
  * @since 2.4.3
7
  * @author Algoritmika Ltd.
8
  */
@@ -172,15 +172,16 @@ class WCJ_Multicurrency extends WCJ_Module {
172
  /**
173
  * get_variation_prices_hash.
174
  *
175
- * @version 2.5.0
176
  */
177
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
178
  $currency_code = $this->get_current_currency_code();
179
- $currency_exchange_rate = $this->get_currency_exchange_rate( $currency_code );
180
- $price_hash['wcj_multicurrency_data'] = array(
181
- $currency_code,
182
- $currency_exchange_rate,
183
- get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ),
 
184
  );
185
  return $price_hash;
186
  }
@@ -326,7 +327,7 @@ class WCJ_Multicurrency extends WCJ_Module {
326
  if ( $this->do_revert() ) {
327
  return $package_rates;
328
  }
329
- $currency_exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() );
330
  return wcj_change_price_shipping_package_rates( $package_rates, $currency_exchange_rate );
331
  }
332
 
2
  /**
3
  * Booster for WooCommerce - Module - Multicurrency (Currency Switcher)
4
  *
5
+ * @version 3.5.0
6
  * @since 2.4.3
7
  * @author Algoritmika Ltd.
8
  */
172
  /**
173
  * get_variation_prices_hash.
174
  *
175
+ * @version 3.5.0
176
  */
177
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
178
  $currency_code = $this->get_current_currency_code();
179
+ $price_hash['wcj_multicurrency'] = array(
180
+ 'currency' => $currency_code,
181
+ 'exchange_rate' => $this->get_currency_exchange_rate( $currency_code ),
182
+ 'per_product' => get_option( 'wcj_multicurrency_per_product_enabled', 'yes' ),
183
+ 'rounding' => get_option( 'wcj_multicurrency_rounding', 'no_round' ),
184
+ 'rounding_precision' => get_option( 'wcj_multicurrency_rounding_precision', absint( get_option( 'woocommerce_price_num_decimals', 2 ) ) ),
185
  );
186
  return $price_hash;
187
  }
327
  if ( $this->do_revert() ) {
328
  return $package_rates;
329
  }
330
+ $currency_exchange_rate = $this->get_currency_exchange_rate( $this->get_current_currency_code() );
331
  return wcj_change_price_shipping_package_rates( $package_rates, $currency_exchange_rate );
332
  }
333
 
includes/class-wcj-order-numbers.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Order Numbers
4
  *
5
- * @version 3.4.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,8 +15,7 @@ class WCJ_Order_Numbers extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 3.2.3
19
- * @todo (maybe) add option (order meta box) to set number directly
20
  * @todo (maybe) rename "Orders Renumerate" to "Renumerate orders"
21
  * @todo (maybe) use `woocommerce_new_order` hook instead of `wp_insert_post`
22
  */
@@ -50,6 +49,27 @@ class WCJ_Order_Numbers extends WCJ_Module {
50
  foreach ( $woocommerce_subscriptions_types as $woocommerce_subscriptions_type ) {
51
  add_filter( 'wcs_' . $woocommerce_subscriptions_type . '_meta', array( $this, 'woocommerce_subscriptions_remove_meta_copy' ), PHP_INT_MAX, 3 );
52
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
  }
54
  }
55
 
@@ -143,7 +163,7 @@ class WCJ_Order_Numbers extends WCJ_Module {
143
  /**
144
  * Display order number.
145
  *
146
- * @version 2.7.0
147
  */
148
  function display_order_number( $order_number, $order ) {
149
  $order_id = wcj_get_order_id( $order );
@@ -162,6 +182,9 @@ class WCJ_Order_Numbers extends WCJ_Module {
162
  date_i18n( get_option( 'wcj_order_number_date_suffix', '' ), $order_timestamp )
163
  )
164
  );
 
 
 
165
  return $order_number;
166
  }
167
 
@@ -253,13 +276,17 @@ class WCJ_Order_Numbers extends WCJ_Module {
253
  /**
254
  * Add/update order_number meta to order.
255
  *
256
- * @version 3.4.0
 
257
  */
258
  function add_order_number_meta( $order_id, $do_overwrite ) {
259
  if ( 'shop_order' !== get_post_type( $order_id ) || 'auto-draft' === get_post_status( $order_id ) ) {
260
  return;
261
  }
262
  if ( true === $do_overwrite || 0 == get_post_meta( $order_id, '_wcj_order_number', true ) ) {
 
 
 
263
  if ( 'yes' === get_option( 'wcj_order_number_sequential_enabled', 'yes' ) && 'yes' === get_option( 'wcj_order_number_use_mysql_transaction_enabled', 'yes' ) ) {
264
  global $wpdb;
265
  $wpdb->query( 'START TRANSACTION' );
2
  /**
3
  * Booster for WooCommerce - Module - Order Numbers
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.5.0
 
19
  * @todo (maybe) rename "Orders Renumerate" to "Renumerate orders"
20
  * @todo (maybe) use `woocommerce_new_order` hook instead of `wp_insert_post`
21
  */
49
  foreach ( $woocommerce_subscriptions_types as $woocommerce_subscriptions_type ) {
50
  add_filter( 'wcs_' . $woocommerce_subscriptions_type . '_meta', array( $this, 'woocommerce_subscriptions_remove_meta_copy' ), PHP_INT_MAX, 3 );
51
  }
52
+ // Editable order number
53
+ if ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_order_number_editable_order_number_meta_box_enabled', 'no' ) ) ) {
54
+ $this->meta_box_screen = 'shop_order';
55
+ $this->meta_box_context = 'side';
56
+ $this->meta_box_priority = 'high';
57
+ add_action( 'add_meta_boxes', array( $this, 'maybe_add_meta_box' ), PHP_INT_MAX, 2 );
58
+ add_action( 'save_post_shop_order', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
59
+ }
60
+ }
61
+ }
62
+
63
+ /**
64
+ * maybe_add_meta_box.
65
+ *
66
+ * @version 3.5.0
67
+ * @since 3.5.0
68
+ * @todo re-think if setting number for yet not-numbered order should be allowed (i.e. do not check for `( '' !== get_post_meta( $post->ID, '_wcj_order_number', true ) )`)
69
+ */
70
+ function maybe_add_meta_box( $post_type, $post ) {
71
+ if ( '' !== get_post_meta( $post->ID, '_wcj_order_number', true ) ) {
72
+ parent::add_meta_box();
73
  }
74
  }
75
 
163
  /**
164
  * Display order number.
165
  *
166
+ * @version 3.5.0
167
  */
168
  function display_order_number( $order_number, $order ) {
169
  $order_id = wcj_get_order_id( $order );
182
  date_i18n( get_option( 'wcj_order_number_date_suffix', '' ), $order_timestamp )
183
  )
184
  );
185
+ if ( false !== strpos( $order_number, '%order_items_skus%' ) ) {
186
+ $order_number = str_replace( '%order_items_skus%', do_shortcode( '[wcj_order_items order_id="' . $order_id . '" field="_sku" sep="-"]' ), $order_number );
187
+ }
188
  return $order_number;
189
  }
190
 
276
  /**
277
  * Add/update order_number meta to order.
278
  *
279
+ * @version 3.5.0
280
+ * @todo (maybe) save order ID instead of `$current_order_number = ''` (if `'no' === get_option( 'wcj_order_number_sequential_enabled', 'yes' )`)
281
  */
282
  function add_order_number_meta( $order_id, $do_overwrite ) {
283
  if ( 'shop_order' !== get_post_type( $order_id ) || 'auto-draft' === get_post_status( $order_id ) ) {
284
  return;
285
  }
286
  if ( true === $do_overwrite || 0 == get_post_meta( $order_id, '_wcj_order_number', true ) ) {
287
+ if ( $order_id < get_option( 'wcj_order_numbers_min_order_id', 0 ) ) {
288
+ return;
289
+ }
290
  if ( 'yes' === get_option( 'wcj_order_number_sequential_enabled', 'yes' ) && 'yes' === get_option( 'wcj_order_number_use_mysql_transaction_enabled', 'yes' ) ) {
291
  global $wpdb;
292
  $wpdb->query( 'START TRANSACTION' );
includes/class-wcj-order-quantities.php CHANGED
@@ -47,12 +47,12 @@ class WCJ_Order_Quantities extends WCJ_Module {
47
  }
48
  add_filter( 'woocommerce_available_variation', array( $this, 'set_quantity_input_min_max_variation' ), PHP_INT_MAX, 3 );
49
  if ( 'yes' === get_option( 'wcj_order_quantities_min_section_enabled', 'no' ) ) {
50
- add_filter( 'woocommerce_quantity_input_min', array( $this, 'set_quantity_input_min' ), PHP_INT_MAX, 2 );
51
  }
52
  if ( 'yes' === get_option( 'wcj_order_quantities_max_section_enabled', 'no' ) ) {
53
- add_filter( 'woocommerce_quantity_input_max', array( $this, 'set_quantity_input_max' ), PHP_INT_MAX, 2 );
54
  }
55
- add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_script' ) );
56
  }
57
  }
58
  }
47
  }
48
  add_filter( 'woocommerce_available_variation', array( $this, 'set_quantity_input_min_max_variation' ), PHP_INT_MAX, 3 );
49
  if ( 'yes' === get_option( 'wcj_order_quantities_min_section_enabled', 'no' ) ) {
50
+ add_filter( 'woocommerce_quantity_input_min', array( $this, 'set_quantity_input_min' ), PHP_INT_MAX, 2 );
51
  }
52
  if ( 'yes' === get_option( 'wcj_order_quantities_max_section_enabled', 'no' ) ) {
53
+ add_filter( 'woocommerce_quantity_input_max', array( $this, 'set_quantity_input_max' ), PHP_INT_MAX, 2 );
54
  }
55
+ add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_script' ) );
56
  }
57
  }
58
  }
includes/class-wcj-payment-gateways-by-country.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Payment Gateways by Country
4
  *
5
- * @version 3.4.0
6
  * @since 2.4.1
7
  * @author Algoritmika Ltd.
8
  */
@@ -34,15 +34,21 @@ class WCJ_Payment_Gateways_By_Country extends WCJ_Module {
34
  /**
35
  * get_location.
36
  *
37
- * @version 3.4.0
38
  * @since 3.4.0
 
39
  */
40
  function get_location( $type ) {
41
  switch ( $type ) {
42
  case 'country':
43
- return ( isset( WC()->customer ) ? wcj_customer_get_country() : '' );
 
 
 
44
  case 'state':
45
- return ( isset( WC()->customer ) ? ( WCJ_IS_WC_VERSION_BELOW_3 ? WC()->customer->get_state() : WC()->customer->get_billing_state() ) : '' );
 
 
46
  case 'postcode':
47
  $postcode = '';
48
  if ( isset( $_REQUEST['postcode'] ) && 'billing' === get_option( 'wcj_gateways_by_location_postcodes_type', 'billing' ) ) {
@@ -96,7 +102,6 @@ class WCJ_Payment_Gateways_By_Country extends WCJ_Module {
96
  * @todo (maybe) code refactoring
97
  * @todo (maybe) add more locations options (e.g. "... by city")
98
  * @todo (maybe) add option to detect customer's country and state by current `$_REQUEST` (as it is now done with postcodes)
99
- * @todo (maybe) add option to detect customer's country by IP (instead of `wcj_customer_get_country()`); probably won't work with states though...
100
  */
101
  function available_payment_gateways( $_available_gateways ) {
102
  $customer_country = $this->get_location( 'country' );
2
  /**
3
  * Booster for WooCommerce - Module - Payment Gateways by Country
4
  *
5
+ * @version 3.5.0
6
  * @since 2.4.1
7
  * @author Algoritmika Ltd.
8
  */
34
  /**
35
  * get_location.
36
  *
37
+ * @version 3.5.0
38
  * @since 3.4.0
39
+ * @todo on `WCJ_IS_WC_VERSION_BELOW_3` recheck if `get_shipping_country()` and `get_shipping_state()` work correctly
40
  */
41
  function get_location( $type ) {
42
  switch ( $type ) {
43
  case 'country':
44
+ $country_type = get_option( 'wcj_gateways_by_location_country_type', 'billing' );
45
+ return ( 'by_ip' === $country_type ?
46
+ wcj_get_country_by_ip() :
47
+ ( isset( WC()->customer ) ? ( 'billing' === $country_type ? wcj_customer_get_country() : WC()->customer->get_shipping_country() ) : '' ) );
48
  case 'state':
49
+ return ( isset( WC()->customer ) ?
50
+ ( 'billing' === get_option( 'wcj_gateways_by_location_state_type', 'billing' ) ? wcj_customer_get_country_state() : WC()->customer->get_shipping_state() ) :
51
+ '' );
52
  case 'postcode':
53
  $postcode = '';
54
  if ( isset( $_REQUEST['postcode'] ) && 'billing' === get_option( 'wcj_gateways_by_location_postcodes_type', 'billing' ) ) {
102
  * @todo (maybe) code refactoring
103
  * @todo (maybe) add more locations options (e.g. "... by city")
104
  * @todo (maybe) add option to detect customer's country and state by current `$_REQUEST` (as it is now done with postcodes)
 
105
  */
106
  function available_payment_gateways( $_available_gateways ) {
107
  $customer_country = $this->get_location( 'country' );
includes/class-wcj-payment-gateways-by-shipping.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Payment Gateways by Shipping
4
  *
5
- * @version 2.8.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,8 +16,9 @@ class WCJ_Payment_Gateways_By_Shipping extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 2.8.0
20
  * @since 2.7.0
 
21
  */
22
  function __construct() {
23
 
@@ -28,6 +29,7 @@ class WCJ_Payment_Gateways_By_Shipping extends WCJ_Module {
28
  parent::__construct();
29
 
30
  if ( $this->is_enabled() ) {
 
31
  add_filter( 'woocommerce_available_payment_gateways', array( $this, 'available_payment_gateways' ), PHP_INT_MAX, 1 );
32
  }
33
  }
@@ -35,7 +37,7 @@ class WCJ_Payment_Gateways_By_Shipping extends WCJ_Module {
35
  /**
36
  * check_if_enabled_for_methods.
37
  *
38
- * @version 2.7.0
39
  * @since 2.7.0
40
  * @see `is_available()` function in WooCommerce `WC_Gateway_COD` class
41
  * @todo (maybe) virtual orders (`enable_for_virtual`)
@@ -104,10 +106,26 @@ class WCJ_Payment_Gateways_By_Shipping extends WCJ_Module {
104
 
105
  $found = false;
106
 
 
 
 
 
 
 
 
 
 
 
 
107
  foreach ( $enable_for_methods as $method_id ) {
108
- if ( strpos( $check_method, $method_id ) === 0 ) {
109
- $found = true;
110
- break;
 
 
 
 
 
111
  }
112
  }
113
 
@@ -122,12 +140,14 @@ class WCJ_Payment_Gateways_By_Shipping extends WCJ_Module {
122
  /**
123
  * available_payment_gateways.
124
  *
125
- * @version 2.7.0
126
  * @since 2.7.0
127
  */
128
  function available_payment_gateways( $_available_gateways ) {
129
  foreach ( $_available_gateways as $key => $gateway ) {
130
- $enable_for_methods = get_option( 'wcj_gateways_by_shipping_enable_' . $key, '' );
 
 
131
  if ( ! empty( $enable_for_methods ) && ! $this->check_if_enabled_for_methods( $key, $enable_for_methods ) ) {
132
  unset( $_available_gateways[ $key ] );
133
  continue;
2
  /**
3
  * Booster for WooCommerce - Module - Payment Gateways by Shipping
4
  *
5
+ * @version 3.5.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.5.0
20
  * @since 2.7.0
21
+ * @todo re-check in which more modules `use_shipping_instance` can be used
22
  */
23
  function __construct() {
24
 
29
  parent::__construct();
30
 
31
  if ( $this->is_enabled() ) {
32
+ $this->use_shipping_instance = ( 'yes' === get_option( 'wcj_payment_gateways_by_shipping_use_shipping_instance', 'no' ) );
33
  add_filter( 'woocommerce_available_payment_gateways', array( $this, 'available_payment_gateways' ), PHP_INT_MAX, 1 );
34
  }
35
  }
37
  /**
38
  * check_if_enabled_for_methods.
39
  *
40
+ * @version 3.5.0
41
  * @since 2.7.0
42
  * @see `is_available()` function in WooCommerce `WC_Gateway_COD` class
43
  * @todo (maybe) virtual orders (`enable_for_virtual`)
106
 
107
  $found = false;
108
 
109
+ // Shipping method instance
110
+ if ( $this->use_shipping_instance ) {
111
+ $check_method = explode( ':', $check_method, 2 );
112
+ if ( ! isset( $check_method[1] ) || ! is_numeric( $check_method[1] ) ) {
113
+ return false;
114
+ } else {
115
+ $check_method = $check_method[1];
116
+ }
117
+ }
118
+
119
+ // Final check
120
  foreach ( $enable_for_methods as $method_id ) {
121
+ if ( $this->use_shipping_instance ) {
122
+ if ( $check_method == $method_id ) {
123
+ return true;
124
+ }
125
+ } else {
126
+ if ( strpos( $check_method, $method_id ) === 0 ) {
127
+ return true;
128
+ }
129
  }
130
  }
131
 
140
  /**
141
  * available_payment_gateways.
142
  *
143
+ * @version 3.5.0
144
  * @since 2.7.0
145
  */
146
  function available_payment_gateways( $_available_gateways ) {
147
  foreach ( $_available_gateways as $key => $gateway ) {
148
+ $enable_for_methods = ( $this->use_shipping_instance ?
149
+ get_option( 'wcj_gateways_by_shipping_enable_instance_' . $key, '' ) :
150
+ get_option( 'wcj_gateways_by_shipping_enable_' . $key, '' ) );
151
  if ( ! empty( $enable_for_methods ) && ! $this->check_if_enabled_for_methods( $key, $enable_for_methods ) ) {
152
  unset( $_available_gateways[ $key ] );
153
  continue;
includes/class-wcj-pdf-invoicing.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - PDF Invoicing
4
  *
5
- * @version 3.4.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,7 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 3.2.0
19
  */
20
  function __construct() {
21
 
@@ -64,6 +64,12 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
64
  }
65
  }
66
  }
 
 
 
 
 
 
67
  }
68
  }
69
 
@@ -72,33 +78,38 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
72
  *
73
  * Using Javascript until WordPress core fixes: http://core.trac.wordpress.org/ticket/16031
74
  *
75
- * @todo add "print" action
76
  * @see https://www.skyverge.com/blog/add-custom-bulk-action/
77
- * @version 2.5.7
78
  * @since 2.5.7
 
79
  */
80
  function bulk_actions_pdfs_admin_footer() {
81
  global $post_type;
82
  if ( 'shop_order' == $post_type ) {
83
- ?><script type="text/javascript"><?php
84
  $invoice_types = wcj_get_enabled_invoice_types();
85
- foreach ( $invoice_types as $invoice_type ) {
86
- $key = $invoice_type['id'];
87
- $title = $invoice_type['title'];
88
- ?>jQuery(function() {
89
- jQuery('<option>').val('generate_<?php echo $key; ?>').text('<?php echo __( 'Generate', 'woocommerce-jetpack' ) . ' ' . $title; ?>').appendTo('select[name="action"]');
90
- jQuery('<option>').val('generate_<?php echo $key; ?>').text('<?php echo __( 'Generate', 'woocommerce-jetpack' ) . ' ' . $title; ?>').appendTo('select[name="action2"]');
91
- });<?php
92
- }
93
- foreach ( $invoice_types as $invoice_type ) {
94
- $key = $invoice_type['id'];
95
- $title = $invoice_type['title'];
96
- ?>jQuery(function() {
97
- jQuery('<option>').val('download_<?php echo $key; ?>').text('<?php echo __( 'Download', 'woocommerce-jetpack' ) . ' ' . $title; ?>').appendTo('select[name="action"]');
98
- jQuery('<option>').val('download_<?php echo $key; ?>').text('<?php echo __( 'Download', 'woocommerce-jetpack' ) . ' ' . $title; ?>').appendTo('select[name="action2"]');
99
- });<?php
 
 
 
 
 
100
  }
101
- ?></script><?php
 
102
  }
103
  }
104
 
@@ -136,8 +147,10 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
136
  /**
137
  * bulk_actions_pdfs.
138
  *
139
- * @version 3.1.0
140
  * @since 2.5.7
 
 
141
  */
142
  function bulk_actions_pdfs() {
143
 
@@ -145,24 +158,21 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
145
  $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
146
  $action = $wp_list_table->current_action();
147
 
148
- // TODO: Security check
149
- // check_admin_referer( 'bulk-posts' );
150
-
151
  // Validate the action
152
  $action_exploded = explode( '_', $action, 2 );
153
- if ( empty( $action_exploded ) || ! is_array( $action_exploded ) || 2 !== count( $action_exploded ) || ! in_array( $action_exploded[0], array( 'generate', 'download' ) ) ) {
 
 
 
154
  return;
155
  }
 
156
  // Perform the action
157
  $post_ids = $_GET['post'];
158
  $the_action = $action_exploded[0];
159
  $the_type = $action_exploded[1];
160
  switch( $the_action ) {
161
  case 'generate':
162
- // TODO: Validate user permissions/capabilities
163
- // if ( ! current_user_can( $post_type_object->cap->export_post, $post_id ) ) {
164
- // wp_die( __( 'You are not allowed to export this post.' ) );
165
- // }
166
  $generated = 0;
167
  foreach( $post_ids as $post_id ) {
168
  if ( $this->create_document( $post_id, $the_type ) ) {
@@ -184,6 +194,7 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
184
  break;
185
  case 'download':
186
  if ( '' != ( $result = $this->get_invoices_zip( $the_type, $post_ids ) ) ) {
 
187
  $sendback = add_query_arg(
188
  array(
189
  'post_type' => 'shop_order',
@@ -194,6 +205,27 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
194
  );
195
  }
196
  break;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  default:
198
  return;
199
  }
@@ -203,11 +235,50 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
203
  exit();
204
  }
205
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  /**
207
  * get_invoices_zip.
208
  *
209
- * @version 3.1.0
210
  * @since 2.5.7
 
 
211
  */
212
  function get_invoices_zip( $invoice_type_id, $post_ids ) {
213
  if ( ! class_exists( 'ZipArchive' ) ) {
@@ -215,12 +286,15 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
215
  }
216
  // Creating Zip
217
  $zip = new ZipArchive();
218
- $zip_file_name = $invoice_type_id . '.zip';
219
- $zip_file_path = sys_get_temp_dir() . '/' . $zip_file_name;
 
 
 
220
  if ( file_exists( $zip_file_path ) ) {
221
- unlink ( $zip_file_path );
222
  }
223
- if ( $zip->open( $zip_file_path, ZipArchive::CREATE ) !== TRUE ) {
224
  return 'ziparchive_error';
225
  }
226
  foreach( $post_ids as $post_id ) {
@@ -232,23 +306,7 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
232
  }
233
  $zip->close();
234
  // Sending Zip
235
- header( "Content-Type: application/octet-stream" );
236
- header( "Content-Disposition: attachment; filename=" . urlencode( $zip_file_name ) );
237
- header( "Content-Type: application/octet-stream" );
238
- header( "Content-Type: application/download" );
239
- header( "Content-Description: File Transfer" );
240
- header( "Content-Length: " . filesize( $zip_file_path ) );
241
- flush(); // this doesn't really matter.
242
- if ( false !== ( $fp = fopen( $zip_file_path, "r" ) ) ) {
243
- while ( ! feof( $fp ) ) {
244
- echo fread( $fp, 65536 );
245
- flush(); // this is essential for large downloads
246
- }
247
- fclose( $fp );
248
- exit();
249
- } else {
250
- die( __( 'Unexpected error', 'woocommerce-jetpack' ) );
251
- }
252
  return '';
253
  }
254
 
@@ -382,14 +440,13 @@ class WCJ_PDF_Invoicing extends WCJ_Module {
382
  * @version 2.9.0
383
  */
384
  function generate_pdf_on_init() {
385
-
386
  // Check if all is OK
387
  if ( true !== $this->get_invoice || 0 == $this->order_id || ! is_user_logged_in() || ! $this->check_user_roles() ) {
388
  return;
389
  }
390
-
391
  $the_invoice = wcj_get_pdf_invoice( $this->order_id, $this->invoice_type_id );
392
- $dest = ( true === $this->save_as_pdf ) ? 'D' : 'I';
393
  $the_invoice->get_pdf( $dest );
394
  die();
395
  }
2
  /**
3
  * Booster for WooCommerce - Module - PDF Invoicing
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.5.0
19
  */
20
  function __construct() {
21
 
64
  }
65
  }
66
  }
67
+
68
+ // Editable numbers in meta box
69
+ if ( 'yes' === get_option( 'wcj_invoicing_add_order_meta_box_numbering', 'yes' ) ) {
70
+ add_action( 'save_post_shop_order', array( $this, 'save_meta_box' ), PHP_INT_MAX, 2 );
71
+ }
72
+
73
  }
74
  }
75
 
78
  *
79
  * Using Javascript until WordPress core fixes: http://core.trac.wordpress.org/ticket/16031
80
  *
 
81
  * @see https://www.skyverge.com/blog/add-custom-bulk-action/
82
+ * @version 3.5.0
83
  * @since 2.5.7
84
+ * @todo add bulk actions in a correct way for newer WP
85
  */
86
  function bulk_actions_pdfs_admin_footer() {
87
  global $post_type;
88
  if ( 'shop_order' == $post_type ) {
 
89
  $invoice_types = wcj_get_enabled_invoice_types();
90
+ $actions = array(
91
+ 'generate' => __( 'Generate', 'woocommerce-jetpack' ),
92
+ 'download' => __( 'Download (Zip)', 'woocommerce-jetpack' ),
93
+ 'merge' => __( 'Merge (Print)', 'woocommerce-jetpack' ),
94
+ );
95
+ $html = '';
96
+ $html .= '<script type="text/javascript">';
97
+ foreach ( $actions as $action_id => $action_title ) {
98
+ foreach ( $invoice_types as $invoice_type ) {
99
+ $key = $invoice_type['id'];
100
+ $title = $invoice_type['title'];
101
+ $html .= 'jQuery(function() { ';
102
+ foreach ( array( 'action', 'action2' ) as $action ) {
103
+ $html .= 'jQuery(\'<option>\').' .
104
+ 'val(\''. $action_id . '_' . $key . '\').' .
105
+ 'text(\'' . $action_title . ' ' . $title . '\').' .
106
+ 'appendTo(\'select[name="' . $action . '"]\'); ';
107
+ }
108
+ $html .= '}); ';
109
+ }
110
  }
111
+ $html .= '</script>';
112
+ echo $html;
113
  }
114
  }
115
 
147
  /**
148
  * bulk_actions_pdfs.
149
  *
150
+ * @version 3.5.0
151
  * @since 2.5.7
152
+ * @todo on `generate` (and maybe other actions) validate user permissions/capabilities - `if ( ! current_user_can( $post_type_object->cap->export_post, $post_id ) ) { wp_die( __( 'You are not allowed to export this post.' ) ); }`
153
+ * @todo add security check - `check_admin_referer( 'bulk-posts' )`
154
  */
155
  function bulk_actions_pdfs() {
156
 
158
  $wp_list_table = _get_list_table( 'WP_Posts_List_Table' );
159
  $action = $wp_list_table->current_action();
160
 
 
 
 
161
  // Validate the action
162
  $action_exploded = explode( '_', $action, 2 );
163
+ if (
164
+ ! isset( $_GET['post'] ) || empty( $action_exploded ) || ! is_array( $action_exploded ) || 2 !== count( $action_exploded ) ||
165
+ ! in_array( $action_exploded[0], array( 'generate', 'download', 'merge' ) )
166
+ ) {
167
  return;
168
  }
169
+
170
  // Perform the action
171
  $post_ids = $_GET['post'];
172
  $the_action = $action_exploded[0];
173
  $the_type = $action_exploded[1];
174
  switch( $the_action ) {
175
  case 'generate':
 
 
 
 
176
  $generated = 0;
177
  foreach( $post_ids as $post_id ) {
178
  if ( $this->create_document( $post_id, $the_type ) ) {
194
  break;
195
  case 'download':
196
  if ( '' != ( $result = $this->get_invoices_zip( $the_type, $post_ids ) ) ) {
197
+ // Build the redirect url
198
  $sendback = add_query_arg(
199
  array(
200
  'post_type' => 'shop_order',
205
  );
206
  }
207
  break;
208
+ case 'merge':
209
+ $merge_ids = array();
210
+ foreach( $post_ids as $post_id ) {
211
+ if ( wcj_is_invoice_created( $post_id, $the_type ) ) {
212
+ $merge_ids[] = $post_id;
213
+ }
214
+ }
215
+ if ( ! empty( $merge_ids ) ) {
216
+ if ( '' != ( $result = $this->merge_pdfs( $the_type, $merge_ids ) ) ) {
217
+ // Build the redirect url
218
+ $sendback = add_query_arg(
219
+ array(
220
+ 'post_type' => 'shop_order',
221
+ 'post_status' => $_GET['post_status'],
222
+ 'wcj_notice' => $result,
223
+ ),
224
+ $sendback
225
+ );
226
+ }
227
+ }
228
+ break;
229
  default:
230
  return;
231
  }
235
  exit();
236
  }
237
 
238
+ /**
239
+ * merge_pdfs.
240
+ *
241
+ * @version 3.5.0
242
+ * @since 3.5.0
243
+ * @see https://www.setasign.com/products/fpdi/demos/concatenate-fake/
244
+ * @todo add errors notices
245
+ * @todo rethink filename (i.e. 'docs.pdf')
246
+ * @todo (maybe) always save/download instead of display on output
247
+ */
248
+ function merge_pdfs( $invoice_type_id, $post_ids ) {
249
+ $files = array();
250
+ foreach( $post_ids as $post_id ) {
251
+ $the_invoice = wcj_get_pdf_invoice( $post_id, $invoice_type_id );
252
+ $files[] = $the_invoice->get_pdf( 'F' );
253
+ }
254
+ if ( empty( $files ) ) {
255
+ return 'merge_pdfs_no_files';
256
+ }
257
+ require_once( wcj_plugin_path() . '/includes/lib/FPDI/src/autoload.php' );
258
+ $fpdi_pdf = new \setasign\Fpdi\TcpdfFpdi();
259
+ $fpdi_pdf->SetTitle( 'docs.pdf' );
260
+ $fpdi_pdf->setPrintHeader( false );
261
+ $fpdi_pdf->setPrintFooter( false );
262
+ foreach( $files as $file ) {
263
+ $page_count = $fpdi_pdf->setSourceFile( $file );
264
+ for ( $page_nr = 1; $page_nr <= $page_count; $page_nr++ ) {
265
+ $page_id = $fpdi_pdf->ImportPage( $page_nr );
266
+ $s = $fpdi_pdf->getTemplatesize( $page_id );
267
+ $fpdi_pdf->AddPage( $s['orientation'], $s );
268
+ $fpdi_pdf->useImportedPage( $page_id );
269
+ }
270
+ }
271
+ $fpdi_pdf->Output( 'docs.pdf', ( 'yes' === get_option( 'wcj_invoicing_' . $invoice_type_id . '_save_as_enabled', 'no' ) ? 'D' : 'I' ) );
272
+ die();
273
+ }
274
+
275
  /**
276
  * get_invoices_zip.
277
  *
278
+ * @version 3.5.0
279
  * @since 2.5.7
280
+ * @todo (maybe) add timestamp to filename
281
+ * @todo add `ZipArchive` fallback
282
  */
283
  function get_invoices_zip( $invoice_type_id, $post_ids ) {
284
  if ( ! class_exists( 'ZipArchive' ) ) {
286
  }
287
  // Creating Zip
288
  $zip = new ZipArchive();
289
+ $zip_file_name = $invoice_type_id . '-' .
290
+ sanitize_title( str_replace( array( 'http://', 'https://' ), '', site_url() ) ) . '-' .
291
+ min( $post_ids ) . '-' . max( $post_ids ) .
292
+ '.zip';
293
+ $zip_file_path = wcj_get_invoicing_temp_dir() . '/' . $zip_file_name;
294
  if ( file_exists( $zip_file_path ) ) {
295
+ @unlink( $zip_file_path );
296
  }
297
+ if ( $zip->open( $zip_file_path, ZipArchive::CREATE | ZIPARCHIVE::OVERWRITE ) !== TRUE ) {
298
  return 'ziparchive_error';
299
  }
300
  foreach( $post_ids as $post_id ) {
306
  }
307
  $zip->close();
308
  // Sending Zip
309
+ wcj_send_file( $zip_file_name, $zip_file_path, 'zip', true );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
310
  return '';
311
  }
312
 
440
  * @version 2.9.0
441
  */
442
  function generate_pdf_on_init() {
 
443
  // Check if all is OK
444
  if ( true !== $this->get_invoice || 0 == $this->order_id || ! is_user_logged_in() || ! $this->check_user_roles() ) {
445
  return;
446
  }
447
+ // Get PDF
448
  $the_invoice = wcj_get_pdf_invoice( $this->order_id, $this->invoice_type_id );
449
+ $dest = ( true === $this->save_as_pdf ? 'D' : 'I' );
450
  $the_invoice->get_pdf( $dest );
451
  die();
452
  }
includes/class-wcj-price-by-user-role.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Price by User Role
4
  *
5
- * @version 3.2.2
6
  * @since 2.5.0
7
  * @author Algoritmika Ltd.
8
  * @todo Fix "Make Empty Price" option for variable products
@@ -159,8 +159,9 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
159
  /**
160
  * change_price.
161
  *
162
- * @version 3.2.2
163
  * @since 2.5.0
 
164
  */
165
  function change_price( $price, $_product ) {
166
 
@@ -257,6 +258,25 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
257
  }
258
  }
259
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
260
  // Global
261
  if ( 'yes' === get_option( 'wcj_price_by_user_role_empty_price_' . $current_user_role, 'no' ) ) {
262
  return '';
@@ -272,13 +292,15 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
272
  /**
273
  * get_variation_prices_hash.
274
  *
275
- * @version 3.2.0
276
  * @since 2.5.0
277
  * @todo only hash categories that is relevant to the product
 
278
  */
279
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
280
- $user_role = wcj_get_current_user_first_role();
281
  $categories = apply_filters( 'booster_option', '', get_option( 'wcj_price_by_user_role_categories', '' ) );
 
282
  $price_hash['wcj_user_role'] = array(
283
  $user_role,
284
  get_option( 'wcj_price_by_user_role_' . $user_role, 1 ),
@@ -288,6 +310,7 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
288
  get_option( 'wcj_price_by_user_role_disable_for_products_on_sale', 'no' ),
289
  $this->disable_for_regular_price,
290
  $categories,
 
291
  );
292
  if ( ! empty( $categories ) ) {
293
  foreach ( $categories as $category ) {
@@ -295,6 +318,12 @@ class WCJ_Price_By_User_Role extends WCJ_Module {
295
  $price_hash['wcj_user_role'][] = get_option( 'wcj_price_by_user_role_cat_' . $category . '_' . $user_role, 1 );
296
  }
297
  }
 
 
 
 
 
 
298
  return $price_hash;
299
  }
300
 
2
  /**
3
  * Booster for WooCommerce - Module - Price by User Role
4
  *
5
+ * @version 3.5.0
6
  * @since 2.5.0
7
  * @author Algoritmika Ltd.
8
  * @todo Fix "Make Empty Price" option for variable products
159
  /**
160
  * change_price.
161
  *
162
+ * @version 3.5.0
163
  * @since 2.5.0
164
+ * @todo (maybe) code refactoring (cats/tags)
165
  */
166
  function change_price( $price, $_product ) {
167
 
258
  }
259
  }
260
 
261
+ // By tag
262
+ $tags = apply_filters( 'booster_option', '', get_option( 'wcj_price_by_user_role_tags', '' ) );
263
+ if ( ! empty( $tags ) ) {
264
+ $product_tags = get_the_terms( wcj_get_product_id_or_variation_parent_id( $_product ), 'product_tag' );
265
+ if ( ! empty( $product_tags ) ) {
266
+ foreach ( $product_tags as $product_tag ) {
267
+ foreach ( $tags as $tag ) {
268
+ if ( $product_tag->term_id == $tag ) {
269
+ if ( 'yes' === get_option( 'wcj_price_by_user_role_tag_empty_price_' . $tag . '_' . $current_user_role, 'no' ) ) {
270
+ return '';
271
+ }
272
+ $koef_tag = get_option( 'wcj_price_by_user_role_tag_' . $tag . '_' . $current_user_role, 1 );
273
+ return ( '' === $price ) ? $price : $price * $koef_tag;
274
+ }
275
+ }
276
+ }
277
+ }
278
+ }
279
+
280
  // Global
281
  if ( 'yes' === get_option( 'wcj_price_by_user_role_empty_price_' . $current_user_role, 'no' ) ) {
282
  return '';
292
  /**
293
  * get_variation_prices_hash.
294
  *
295
+ * @version 3.5.0
296
  * @since 2.5.0
297
  * @todo only hash categories that is relevant to the product
298
+ * @todo (maybe) code refactoring (cats/tags)
299
  */
300
  function get_variation_prices_hash( $price_hash, $_product, $display ) {
301
+ $user_role = wcj_get_current_user_first_role();
302
  $categories = apply_filters( 'booster_option', '', get_option( 'wcj_price_by_user_role_categories', '' ) );
303
+ $tags = apply_filters( 'booster_option', '', get_option( 'wcj_price_by_user_role_tags', '' ) );
304
  $price_hash['wcj_user_role'] = array(
305
  $user_role,
306
  get_option( 'wcj_price_by_user_role_' . $user_role, 1 ),
310
  get_option( 'wcj_price_by_user_role_disable_for_products_on_sale', 'no' ),
311
  $this->disable_for_regular_price,
312
  $categories,
313
+ $tags,
314
  );
315
  if ( ! empty( $categories ) ) {
316
  foreach ( $categories as $category ) {
318
  $price_hash['wcj_user_role'][] = get_option( 'wcj_price_by_user_role_cat_' . $category . '_' . $user_role, 1 );
319
  }
320
  }
321
+ if ( ! empty( $tags ) ) {
322
+ foreach ( $tags as $tag ) {
323
+ $price_hash['wcj_user_role'][] = get_option( 'wcj_price_by_user_role_tag_empty_price_' . $tag . '_' . $user_role, 'no' );
324
+ $price_hash['wcj_user_role'][] = get_option( 'wcj_price_by_user_role_tag_' . $tag . '_' . $user_role, 1 );
325
+ }
326
+ }
327
  return $price_hash;
328
  }
329
 
includes/class-wcj-price-formats.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Price Formats
4
  *
5
- * @version 3.2.4
6
  * @since 2.5.2
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Price_Formats extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 3.1.3
20
  * @since 2.5.2
21
  */
22
  function __construct() {
@@ -34,11 +34,45 @@ class WCJ_Price_Formats extends WCJ_Module {
34
  }
35
  // Price Formats by Currency (or WPML)
36
  if ( 'yes' === get_option( 'wcj_price_formats_by_currency_enabled', 'yes' ) ) {
37
- add_filter( 'wc_price_args', array( $this, 'price_format' ), PHP_INT_MAX );
 
38
  }
39
  }
40
  }
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
  /**
43
  * price_format.
44
  *
2
  /**
3
  * Booster for WooCommerce - Module - Price Formats
4
  *
5
+ * @version 3.5.0
6
  * @since 2.5.2
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.5.0
20
  * @since 2.5.2
21
  */
22
  function __construct() {
34
  }
35
  // Price Formats by Currency (or WPML)
36
  if ( 'yes' === get_option( 'wcj_price_formats_by_currency_enabled', 'yes' ) ) {
37
+ add_filter( 'wc_price_args', array( $this, 'price_format' ), PHP_INT_MAX );
38
+ add_action( 'init', array( $this, 'add_hooks' ), PHP_INT_MAX );
39
  }
40
  }
41
  }
42
 
43
+ /**
44
+ * add_hooks.
45
+ *
46
+ * @version 3.5.0
47
+ * @since 3.5.0
48
+ */
49
+ function add_hooks() {
50
+ add_filter( 'wc_get_price_decimals', array( $this, 'price_decimals' ), PHP_INT_MAX );
51
+ }
52
+
53
+ /**
54
+ * price_decimals.
55
+ *
56
+ * @version 3.5.0
57
+ * @since 3.5.0
58
+ * @todo code refactoring
59
+ */
60
+ function price_decimals( $price_decimals_num ) {
61
+ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_price_formats_total_number', 1 ) ); $i++ ) {
62
+ if ( get_woocommerce_currency() === get_option( 'wcj_price_formats_currency_' . $i ) ) {
63
+ if ( defined( 'ICL_LANGUAGE_CODE' ) && '' != ( $wpml_language = get_option( 'wcj_price_formats_wpml_language_' . $i, '' ) ) ) {
64
+ $wpml_language = explode( ',', trim( str_replace( ' ', '', $wpml_language ), ',' ) );
65
+ if ( ! in_array( ICL_LANGUAGE_CODE, $wpml_language ) ) {
66
+ continue;
67
+ }
68
+ }
69
+ $price_decimals_num = get_option( 'wcj_price_formats_number_of_decimals_' . $i );
70
+ break;
71
+ }
72
+ }
73
+ return $price_decimals_num;
74
+ }
75
+
76
  /**
77
  * price_format.
78
  *
includes/class-wcj-product-addons.php CHANGED
@@ -355,7 +355,7 @@ class WCJ_Product_Addons extends WCJ_Module {
355
  *
356
  * @version 3.4.0
357
  * @since 3.4.0
358
- * @todo this is only a temporary solution: must replace `$item->legacy_values` (check "Bookings" module)
359
  */
360
  function add_info_to_order_item_meta_wc3( $item_id, $item, $order_id ) {
361
  if ( is_a( $item, 'WC_Order_Item_Product' ) ) {
355
  *
356
  * @version 3.4.0
357
  * @since 3.4.0
358
+ * @todo this is only a temporary solution: must replace `$item->legacy_values` (check "Bookings" module - `woocommerce_checkout_create_order_line_item` hook)
359
  */
360
  function add_info_to_order_item_meta_wc3( $item_id, $item, $order_id ) {
361
  if ( is_a( $item, 'WC_Order_Item_Product' ) ) {
includes/class-wcj-product-by-country.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Product Visibility by Country
4
  *
5
- * @version 3.2.4
6
  * @since 2.5.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,8 +16,9 @@ class WCJ_Product_By_Country extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 3.1.0
20
  * @since 2.5.0
 
21
  */
22
  function __construct() {
23
 
@@ -42,6 +43,9 @@ class WCJ_Product_By_Country extends WCJ_Module {
42
  }
43
  if ( 'yes' === get_option( 'wcj_product_by_country_query', 'no' ) ) {
44
  add_action( 'pre_get_posts', array( $this, 'product_by_country_pre_get_posts' ) );
 
 
 
45
  }
46
  if ( 'manual' === apply_filters( 'booster_option', 'by_ip', get_option( 'wcj_product_by_country_selection_method', 'by_ip' ) ) ) {
47
  add_action( 'init', array( $this, 'save_country_in_session' ), PHP_INT_MAX ) ;
@@ -96,6 +100,30 @@ class WCJ_Product_By_Country extends WCJ_Module {
96
  }
97
  }
98
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  /**
100
  * product_by_country_pre_get_posts.
101
  *
2
  /**
3
  * Booster for WooCommerce - Module - Product Visibility by Country
4
  *
5
+ * @version 3.5.0
6
  * @since 2.5.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.5.0
20
  * @since 2.5.0
21
+ * @todo ! add `wcj_product_by_country_query_widgets` option to all "Product Visibility ..." modules
22
  */
23
  function __construct() {
24
 
43
  }
44
  if ( 'yes' === get_option( 'wcj_product_by_country_query', 'no' ) ) {
45
  add_action( 'pre_get_posts', array( $this, 'product_by_country_pre_get_posts' ) );
46
+ if ( 'yes' === get_option( 'wcj_product_by_country_query_widgets', 'no' ) ) {
47
+ add_filter( 'woocommerce_products_widget_query_args', array( $this, 'products_widget_query' ), PHP_INT_MAX );
48
+ }
49
  }
50
  if ( 'manual' === apply_filters( 'booster_option', 'by_ip', get_option( 'wcj_product_by_country_selection_method', 'by_ip' ) ) ) {
51
  add_action( 'init', array( $this, 'save_country_in_session' ), PHP_INT_MAX ) ;
100
  }
101
  }
102
 
103
+ /**
104
+ * products_widget_query.
105
+ *
106
+ * @version 3.5.0
107
+ * @since 3.5.0
108
+ */
109
+ function products_widget_query( $query_args ) {
110
+ remove_action( 'pre_get_posts', array( $this, 'product_by_country_pre_get_posts' ) );
111
+ $country = $this->get_country();
112
+ $post__not_in = ( isset( $query_args['post__not_in'] ) ? $query_args['post__not_in'] : array() );
113
+ $args = $query_args;
114
+ $args['fields'] = 'ids';
115
+ $args['posts_per_page'] = -1;
116
+ $loop = new WP_Query( $args );
117
+ foreach ( $loop->posts as $product_id ) {
118
+ if ( ! $this->is_product_visible_in_country( $product_id, $country ) ) {
119
+ $post__not_in[] = $product_id;
120
+ }
121
+ }
122
+ $query_args['post__not_in'] = $post__not_in;
123
+ add_action( 'pre_get_posts', array( $this, 'product_by_country_pre_get_posts' ) );
124
+ return $query_args;
125
+ }
126
+
127
  /**
128
  * product_by_country_pre_get_posts.
129
  *
includes/class-wcj-product-custom-info.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Product Info
4
  *
5
- * @version 2.9.1
6
  * @since 2.4.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -71,14 +71,14 @@ class WCJ_Product_Custom_info extends WCJ_Module {
71
  /**
72
  * check_included_and_excluded.
73
  *
74
- * @version 2.9.1
75
  * @since 2.9.0
76
  */
77
  function check_included_and_excluded( $product_id, $single_or_archive, $i ) {
78
- $product_cats_to_include = get_option( 'wcj_product_custom_info_product_cats_to_include_' . $single_or_archive . '_' . $i );
79
- $product_cats_to_exclude = get_option( 'wcj_product_custom_info_product_cats_to_exclude_' . $single_or_archive . '_' . $i );
80
- $product_tags_to_include = get_option( 'wcj_product_custom_info_product_tags_to_include_' . $single_or_archive . '_' . $i );
81
- $product_tags_to_exclude = get_option( 'wcj_product_custom_info_product_tags_to_exclude_' . $single_or_archive . '_' . $i );
82
  $products_to_exclude = wcj_maybe_convert_string_to_array( get_option( 'wcj_product_custom_info_products_to_exclude_' . $single_or_archive . '_' . $i ) );
83
  $products_to_include = wcj_maybe_convert_string_to_array( get_option( 'wcj_product_custom_info_products_to_include_' . $single_or_archive . '_' . $i ) );
84
  return (
2
  /**
3
  * Booster for WooCommerce - Module - Product Info
4
  *
5
+ * @version 3.5.0
6
  * @since 2.4.0
7
  * @author Algoritmika Ltd.
8
  */
71
  /**
72
  * check_included_and_excluded.
73
  *
74
+ * @version 3.5.0
75
  * @since 2.9.0
76
  */
77
  function check_included_and_excluded( $product_id, $single_or_archive, $i ) {
78
+ $product_cats_to_include = wcj_maybe_convert_string_to_array( get_option( 'wcj_product_custom_info_product_cats_to_include_' . $single_or_archive . '_' . $i ) );
79
+ $product_cats_to_exclude = wcj_maybe_convert_string_to_array( get_option( 'wcj_product_custom_info_product_cats_to_exclude_' . $single_or_archive . '_' . $i ) );
80
+ $product_tags_to_include = wcj_maybe_convert_string_to_array( get_option( 'wcj_product_custom_info_product_tags_to_include_' . $single_or_archive . '_' . $i ) );
81
+ $product_tags_to_exclude = wcj_maybe_convert_string_to_array( get_option( 'wcj_product_custom_info_product_tags_to_exclude_' . $single_or_archive . '_' . $i ) );
82
  $products_to_exclude = wcj_maybe_convert_string_to_array( get_option( 'wcj_product_custom_info_products_to_exclude_' . $single_or_archive . '_' . $i ) );
83
  $products_to_include = wcj_maybe_convert_string_to_array( get_option( 'wcj_product_custom_info_products_to_include_' . $single_or_archive . '_' . $i ) );
84
  return (
includes/class-wcj-product-listings.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Product Listings
4
  *
5
- * @version 3.2.4
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,12 @@ class WCJ_Product_Listings extends WCJ_Module {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 3.2.4
 
 
 
 
 
19
  */
20
  function __construct() {
21
  $this->id = 'product_listings';
@@ -40,9 +45,25 @@ class WCJ_Product_Listings extends WCJ_Module {
40
  add_filter( 'woocommerce_product_is_visible', array( $this, 'product_visibility_by_price' ), PHP_INT_MAX, 2 );
41
  }
42
 
 
 
 
 
 
 
43
  }
44
  }
45
 
 
 
 
 
 
 
 
 
 
 
46
  /**
47
  * product_visibility_by_price.
48
  *
2
  /**
3
  * Booster for WooCommerce - Module - Product Listings
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.5.0
19
+ * @todo more descriptions in settings (i.e. Storefront etc.)
20
+ * @todo add deprecated options (which were moved to Storefront)
21
+ * @todo add options to enable/disable each section
22
+ * @todo add "Exclude Categories Products" to "Category Display Options" also
23
+ * @todo add "Exclude Products" and "Exclude Tags Products"
24
  */
25
  function __construct() {
26
  $this->id = 'product_listings';
45
  add_filter( 'woocommerce_product_is_visible', array( $this, 'product_visibility_by_price' ), PHP_INT_MAX, 2 );
46
  }
47
 
48
+ // Product visibility by category
49
+ $this->cats_products_to_hide_on_shop = get_option( 'wcj_product_listings_exclude_cats_products_on_shop', '' );
50
+ if ( ! empty( $this->cats_products_to_hide_on_shop ) ) {
51
+ add_filter( 'woocommerce_product_is_visible', array( $this, 'product_visibility_by_category' ), PHP_INT_MAX, 2 );
52
+ }
53
+
54
  }
55
  }
56
 
57
+ /**
58
+ * product_visibility_by_category.
59
+ *
60
+ * @version 3.5.0
61
+ * @since 3.5.0
62
+ */
63
+ function product_visibility_by_category( $visible, $product_id ) {
64
+ return ( ! isset( $_GET['s'] ) && is_shop() && wcj_is_product_term( $product_id, $this->cats_products_to_hide_on_shop, 'product_cat' ) ? false : $visible );
65
+ }
66
+
67
  /**
68
  * product_visibility_by_price.
69
  *
includes/class-wcj-shipping-by-order-amount.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Shipping Methods by Min/Max Order Amount
4
  *
5
- * @version 3.2.1
6
  * @since 3.2.1
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Shipping_By_Order_Amount extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 3.2.1
20
  * @since 3.2.1
21
  * @todo (maybe) add customer messages on cart and checkout pages (if some shipping method is not available)
22
  */
@@ -29,6 +29,7 @@ class WCJ_Shipping_By_Order_Amount extends WCJ_Module {
29
  parent::__construct();
30
 
31
  if ( $this->is_enabled() ) {
 
32
  add_filter( 'woocommerce_package_rates', array( $this, 'available_shipping_methods' ), PHP_INT_MAX, 2 );
33
  }
34
  }
@@ -36,7 +37,7 @@ class WCJ_Shipping_By_Order_Amount extends WCJ_Module {
36
  /**
37
  * available_shipping_methods.
38
  *
39
- * @version 3.2.1
40
  * @since 3.2.1
41
  * @todo apply_filters( 'booster_option' )
42
  * @todo (maybe) add option to include or exclude taxes when calculating cart total
@@ -47,8 +48,10 @@ class WCJ_Shipping_By_Order_Amount extends WCJ_Module {
47
  }
48
  $total_in_cart = WC()->cart->cart_contents_total;
49
  foreach ( $rates as $rate_key => $rate ) {
50
- $min = get_option( 'wcj_shipping_by_order_amount_min_' . $rate->method_id, 0 );
51
- $max = get_option( 'wcj_shipping_by_order_amount_max_' . $rate->method_id, 0 );
 
 
52
  if ( 0 != $min && $total_in_cart < $min ) {
53
  unset( $rates[ $rate_key ] );
54
  } elseif ( 0 != $max && $total_in_cart > $max ) {
2
  /**
3
  * Booster for WooCommerce - Module - Shipping Methods by Min/Max Order Amount
4
  *
5
+ * @version 3.5.0
6
  * @since 3.2.1
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.5.0
20
  * @since 3.2.1
21
  * @todo (maybe) add customer messages on cart and checkout pages (if some shipping method is not available)
22
  */
29
  parent::__construct();
30
 
31
  if ( $this->is_enabled() ) {
32
+ $this->use_shipping_instances = ( 'yes' === get_option( 'wcj_shipping_by_order_amount_use_shipping_instance', 'no' ) );
33
  add_filter( 'woocommerce_package_rates', array( $this, 'available_shipping_methods' ), PHP_INT_MAX, 2 );
34
  }
35
  }
37
  /**
38
  * available_shipping_methods.
39
  *
40
+ * @version 3.5.0
41
  * @since 3.2.1
42
  * @todo apply_filters( 'booster_option' )
43
  * @todo (maybe) add option to include or exclude taxes when calculating cart total
48
  }
49
  $total_in_cart = WC()->cart->cart_contents_total;
50
  foreach ( $rates as $rate_key => $rate ) {
51
+ $min = ( $this->use_shipping_instances ?
52
+ get_option( 'wcj_shipping_by_order_amount_min_instance_' . $rate->instance_id, 0 ) : get_option( 'wcj_shipping_by_order_amount_min_' . $rate->method_id, 0 ) );
53
+ $max = ( $this->use_shipping_instances ?
54
+ get_option( 'wcj_shipping_by_order_amount_max_instance_' . $rate->instance_id, 0 ) : get_option( 'wcj_shipping_by_order_amount_max_' . $rate->method_id, 0 ) );
55
  if ( 0 != $min && $total_in_cart < $min ) {
56
  unset( $rates[ $rate_key ] );
57
  } elseif ( 0 != $max && $total_in_cart > $max ) {
includes/class-wcj-shipping-by-products.php CHANGED
@@ -1,8 +1,8 @@
1
  <?php
2
  /**
3
- * Booster for WooCommerce - Module - Shipping by Products
4
  *
5
- * @version 3.2.1
6
  * @since 3.2.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -48,20 +48,34 @@ class WCJ_Shipping_By_Products extends WCJ_Module_Shipping_By_Condition {
48
  /**
49
  * check.
50
  *
51
- * @version 3.2.1
52
  * @since 3.2.0
 
53
  */
54
  function check( $options_id, $products_or_cats_or_tags, $include_or_exclude ) {
55
  if ( ! isset( WC()->cart ) || WC()->cart->is_empty() ) {
56
  return true;
57
  }
 
 
 
 
 
 
 
 
 
 
 
 
58
  $validate_all_for_include = ( 'include' === $include_or_exclude && 'yes' === get_option( 'wcj_shipping_by_' . $options_id . '_validate_all_enabled', 'no' ) );
59
  foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
60
  switch( $options_id ) {
61
  case 'products':
62
- if ( $validate_all_for_include && ! in_array( $values['product_id'], $products_or_cats_or_tags ) ) {
 
63
  return false;
64
- } elseif ( ! $validate_all_for_include && in_array( $values['product_id'], $products_or_cats_or_tags ) ) {
65
  return true;
66
  }
67
  break;
@@ -91,13 +105,13 @@ class WCJ_Shipping_By_Products extends WCJ_Module_Shipping_By_Condition {
91
  /**
92
  * get_condition_options.
93
  *
94
- * @version 3.2.0
95
  * @since 3.2.0
96
  */
97
  function get_condition_options( $options_id ) {
98
  switch( $options_id ) {
99
  case 'products':
100
- return wcj_get_products();
101
  case 'product_cats':
102
  return wcj_get_terms( 'product_cat' );
103
  case 'product_tags':
@@ -108,11 +122,11 @@ class WCJ_Shipping_By_Products extends WCJ_Module_Shipping_By_Condition {
108
  /**
109
  * get_additional_section_settings.
110
  *
111
- * @version 3.2.1
112
  * @since 3.2.1
113
  */
114
  function get_additional_section_settings( $options_id ) {
115
- return array(
116
  array(
117
  'title' => __( '"Include" Options', 'woocommerce-jetpack' ),
118
  'desc_tip' => __( 'Enable this checkbox if you want all products in cart to be valid (instead of at least one).', 'woocommerce-jetpack' ),
@@ -122,6 +136,18 @@ class WCJ_Shipping_By_Products extends WCJ_Module_Shipping_By_Condition {
122
  'default' => 'no',
123
  ),
124
  );
 
 
 
 
 
 
 
 
 
 
 
 
125
  }
126
 
127
  }
1
  <?php
2
  /**
3
+ * Booster for WooCommerce - Module - Shipping Methods by Products
4
  *
5
+ * @version 3.5.0
6
  * @since 3.2.0
7
  * @author Algoritmika Ltd.
8
  */
48
  /**
49
  * check.
50
  *
51
+ * @version 3.5.0
52
  * @since 3.2.0
53
+ * @todo (maybe) if needed, prepare `$products_variations` earlier (and only once)
54
  */
55
  function check( $options_id, $products_or_cats_or_tags, $include_or_exclude ) {
56
  if ( ! isset( WC()->cart ) || WC()->cart->is_empty() ) {
57
  return true;
58
  }
59
+ if ( 'products' === $options_id && ( $do_add_variations = ( 'yes' === get_option( 'wcj_shipping_by_' . $options_id . '_add_variations_enabled', 'no' ) ) ) ) {
60
+ $products_variations = array();
61
+ foreach ( $products_or_cats_or_tags as $_product_id ) {
62
+ $_product = wc_get_product( $_product_id );
63
+ if ( $_product->is_type( 'variable' ) ) {
64
+ $products_variations = array_merge( $products_variations, $_product->get_children() );
65
+ } else {
66
+ $products_variations[] = $_product_id;
67
+ }
68
+ }
69
+ $products_or_cats_or_tags = array_unique( $products_variations );
70
+ }
71
  $validate_all_for_include = ( 'include' === $include_or_exclude && 'yes' === get_option( 'wcj_shipping_by_' . $options_id . '_validate_all_enabled', 'no' ) );
72
  foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
73
  switch( $options_id ) {
74
  case 'products':
75
+ $_product_id = ( $do_add_variations && 0 != $values['variation_id'] ? $values['variation_id'] : $values['product_id'] );
76
+ if ( $validate_all_for_include && ! in_array( $_product_id, $products_or_cats_or_tags ) ) {
77
  return false;
78
+ } elseif ( ! $validate_all_for_include && in_array( $_product_id, $products_or_cats_or_tags ) ) {
79
  return true;
80
  }
81
  break;
105
  /**
106
  * get_condition_options.
107
  *
108
+ * @version 3.5.0
109
  * @since 3.2.0
110
  */
111
  function get_condition_options( $options_id ) {
112
  switch( $options_id ) {
113
  case 'products':
114
+ return ( 'yes' === get_option( 'wcj_shipping_by_' . $options_id . '_add_variations_enabled', 'no' ) ? wcj_get_products( array(), 'any', 256, true ) : wcj_get_products() );
115
  case 'product_cats':
116
  return wcj_get_terms( 'product_cat' );
117
  case 'product_tags':
122
  /**
123
  * get_additional_section_settings.
124
  *
125
+ * @version 3.5.0
126
  * @since 3.2.1
127
  */
128
  function get_additional_section_settings( $options_id ) {
129
+ $return = array(
130
  array(
131
  'title' => __( '"Include" Options', 'woocommerce-jetpack' ),
132
  'desc_tip' => __( 'Enable this checkbox if you want all products in cart to be valid (instead of at least one).', 'woocommerce-jetpack' ),
136
  'default' => 'no',
137
  ),
138
  );
139
+ if ( 'products' === $options_id ) {
140
+ $return[] = array(
141
+ 'title' => __( 'Add Products Variations', 'woocommerce-jetpack' ),
142
+ 'desc_tip' => __( 'Enable this checkbox if you want to add products variations to the products list.', 'woocommerce-jetpack' ) . ' ' .
143
+ __( 'Save changes after enabling this option.', 'woocommerce-jetpack' ),
144
+ 'desc' => __( 'Add', 'woocommerce-jetpack' ),
145
+ 'id' => 'wcj_shipping_by_' . $options_id . '_add_variations_enabled',
146
+ 'type' => 'checkbox',
147
+ 'default' => 'no',
148
+ );
149
+ }
150
+ return $return;
151
  }
152
 
153
  }
includes/class-wcj-shipping-description.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Shipping Descriptions
4
  *
5
- * @version 3.4.1
6
  * @since 3.4.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -16,7 +16,7 @@ class WCJ_Shipping_Descriptions extends WCJ_Module {
16
  /**
17
  * Constructor.
18
  *
19
- * @version 3.4.1
20
  * @since 3.4.0
21
  */
22
  function __construct() {
@@ -28,6 +28,8 @@ class WCJ_Shipping_Descriptions extends WCJ_Module {
28
  parent::__construct();
29
 
30
  if ( $this->is_enabled() ) {
 
 
31
  add_filter( 'woocommerce_cart_shipping_method_full_label', array( $this, 'shipping_description' ), PHP_INT_MAX, 2 );
32
  }
33
  }
@@ -35,21 +37,29 @@ class WCJ_Shipping_Descriptions extends WCJ_Module {
35
  /**
36
  * shipping_description.
37
  *
38
- * @version 2.6.0
39
  * @since 2.5.6
 
40
  */
41
  function shipping_description( $label, $method ) {
42
- $shipping_descriptions_visibility = apply_filters( 'booster_option', 'both', get_option( 'wcj_shipping_descriptions_visibility', 'both' ) );
43
- if ( 'checkout_only' === $shipping_descriptions_visibility && is_cart() ) {
44
  return $label;
45
  }
46
- if ( 'cart_only' === $shipping_descriptions_visibility && is_checkout() ) {
47
  return $label;
48
  }
49
  if ( '' != ( $desc = get_option( 'wcj_shipping_description_' . $method->method_id, '' ) ) ) {
50
- $label .= $desc;
 
 
 
 
 
 
 
 
 
51
  }
52
- return $label;
53
  }
54
 
55
  }
2
  /**
3
  * Booster for WooCommerce - Module - Shipping Descriptions
4
  *
5
+ * @version 3.5.0
6
  * @since 3.4.0
7
  * @author Algoritmika Ltd.
8
  */
16
  /**
17
  * Constructor.
18
  *
19
+ * @version 3.5.0
20
  * @since 3.4.0
21
  */
22
  function __construct() {
28
  parent::__construct();
29
 
30
  if ( $this->is_enabled() ) {
31
+ $this->shipping_descriptions_visibility = apply_filters( 'booster_option', 'both', get_option( 'wcj_shipping_descriptions_visibility', 'both' ) );
32
+ $this->shipping_descriptions_position = apply_filters( 'booster_option', 'after', get_option( 'wcj_shipping_descriptions_position', 'after' ) );
33
  add_filter( 'woocommerce_cart_shipping_method_full_label', array( $this, 'shipping_description' ), PHP_INT_MAX, 2 );
34
  }
35
  }
37
  /**
38
  * shipping_description.
39
  *
40
+ * @version 3.5.0
41
  * @since 2.5.6
42
+ * @todo `shipping_descriptions_position` on per method basis
43
  */
44
  function shipping_description( $label, $method ) {
45
+ if ( 'checkout_only' === $this->shipping_descriptions_visibility && is_cart() ) {
 
46
  return $label;
47
  }
48
+ if ( 'cart_only' === $this->shipping_descriptions_visibility && is_checkout() ) {
49
  return $label;
50
  }
51
  if ( '' != ( $desc = get_option( 'wcj_shipping_description_' . $method->method_id, '' ) ) ) {
52
+ switch ( $this->shipping_descriptions_position ) {
53
+ case 'before':
54
+ return $desc . $label;
55
+ case 'instead':
56
+ return $desc;
57
+ default: // 'after'
58
+ return $label . $desc;
59
+ }
60
+ } else {
61
+ return $label;
62
  }
 
63
  }
64
 
65
  }
includes/class-wcj-shipping-time.php ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Module - Shipping Time
4
+ *
5
+ * @version 3.5.0
6
+ * @since 3.5.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ if ( ! class_exists( 'WCJ_Shipping_Time' ) ) :
13
+
14
+ class WCJ_Shipping_Time extends WCJ_Module {
15
+
16
+ /**
17
+ * Constructor.
18
+ *
19
+ * @version 3.5.0
20
+ * @since 3.5.0
21
+ */
22
+ function __construct() {
23
+
24
+ $this->id = 'shipping_time';
25
+ $this->short_desc = __( 'Shipping Time', 'woocommerce-jetpack' );
26
+ $this->extra_desc = sprintf( __( 'After you set estimated shipping time here, you can display it on frontend with %s shortcodes.', 'woocommerce-jetpack' ),
27
+ '<code>[wcj_shipping_time_table]</code>, <code>[wcj_product_shipping_time_table]</code>' );
28
+ $this->desc = __( 'Add delivery time estimation to WooCommerce shipping methods.', 'woocommerce-jetpack' );
29
+ $this->link_slug = 'woocommerce-shipping-time';
30
+ parent::__construct();
31
+
32
+ }
33
+
34
+ }
35
+
36
+ endif;
37
+
38
+ return new WCJ_Shipping_Time();
includes/class-wcj-sku.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - SKU
4
  *
5
- * @version 3.4.1
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -227,13 +227,16 @@ class WCJ_SKU extends WCJ_Module {
227
  /**
228
  * set_sku.
229
  *
230
- * @version 2.9.0
231
  */
232
  function set_sku( $product_id, $sku_number, $variation_suffix, $is_preview, $parent_product_id, $_product ) {
233
 
 
 
234
  $old_sku = $_product->get_sku();
235
  $do_generate_new_sku = ( 'no' === get_option( 'wcj_sku_generate_only_for_empty_sku', 'no' ) || '' === $old_sku );
236
 
 
237
  $category_prefix = '';
238
  $category_suffix = '';
239
  $product_cat = '';
@@ -247,17 +250,32 @@ class WCJ_SKU extends WCJ_Module {
247
  }
248
  }
249
 
 
 
 
 
 
 
 
 
 
 
 
250
  $format_template = get_option( 'wcj_sku_template',
251
  '{category_prefix}{prefix}{sku_number}{suffix}{category_suffix}{variation_suffix}' );
252
  $replace_values = array(
253
- '{category_prefix}' => apply_filters( 'booster_option', '', $category_prefix ),
254
- // '{tag_prefix}' => $tag_prefix,
255
- '{prefix}' => get_option( 'wcj_sku_prefix', '' ),
256
- '{sku_number}' => sprintf( '%0' . get_option( 'wcj_sku_minimum_number_length', 0 ) . 's', $sku_number ),
257
- '{suffix}' => get_option( 'wcj_sku_suffix', '' ),
258
- // '{tag_suffix}' => $tag_suffix,
259
- '{category_suffix}' => $category_suffix,
260
- '{variation_suffix}' => $variation_suffix,
 
 
 
 
261
  );
262
  $the_sku = ( $do_generate_new_sku ) ? str_replace( array_keys( $replace_values ), array_values( $replace_values ), $format_template ) : $old_sku;
263
 
@@ -317,12 +335,14 @@ class WCJ_SKU extends WCJ_Module {
317
  /**
318
  * set_all_products_skus.
319
  *
320
- * @version 2.9.0
321
  */
322
  function set_all_products_skus( $is_preview ) {
323
  $this->maybe_get_sequential_counters();
324
- $limit = 512;
325
  $offset = 0;
 
 
326
  while ( true ) {
327
  $posts = new WP_Query( array(
328
  'posts_per_page' => $limit,
@@ -337,6 +357,9 @@ class WCJ_SKU extends WCJ_Module {
337
  break;
338
  }
339
  foreach ( $posts->posts as $post_id ) {
 
 
 
340
  $this->set_sku_with_variable( $post_id, $is_preview );
341
  }
342
  $offset += $limit;
@@ -380,7 +403,7 @@ class WCJ_SKU extends WCJ_Module {
380
  /**
381
  * create_sku_tool
382
  *
383
- * @version 2.9.0
384
  */
385
  function create_sku_tool() {
386
  $result_message = '';
@@ -410,9 +433,20 @@ class WCJ_SKU extends WCJ_Module {
410
  $html .= $result_message;
411
  }
412
  $html .= '<form method="post" action="">';
 
413
  $html .= '<input class="button-primary" type="submit" name="preview_sku" id="preview_sku" value="' . __( 'Preview SKUs', 'woocommerce-jetpack' ) . '">';
414
  $html .= ' ';
415
  $html .= '<input class="button-primary" type="submit" name="set_sku" id="set_sku" value="' . __( 'Set SKUs', 'woocommerce-jetpack' ) . '">';
 
 
 
 
 
 
 
 
 
 
416
  $html .= '</form>';
417
  if ( $is_preview ) {
418
  $html .= $preview_html;
2
  /**
3
  * Booster for WooCommerce - Module - SKU
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
227
  /**
228
  * set_sku.
229
  *
230
+ * @version 3.5.0
231
  */
232
  function set_sku( $product_id, $sku_number, $variation_suffix, $is_preview, $parent_product_id, $_product ) {
233
 
234
+ $parent_product = wc_get_product( $parent_product_id );
235
+
236
  $old_sku = $_product->get_sku();
237
  $do_generate_new_sku = ( 'no' === get_option( 'wcj_sku_generate_only_for_empty_sku', 'no' ) || '' === $old_sku );
238
 
239
+ // {category_prefix} & {category_suffix}
240
  $category_prefix = '';
241
  $category_suffix = '';
242
  $product_cat = '';
250
  }
251
  }
252
 
253
+ // {variation_attributes}
254
+ $variation_attributes = '';
255
+ if ( 'WC_Product_Variation' === get_class( $_product ) ) {
256
+ $attr_slugs = array();
257
+ foreach ( $_product->get_variation_attributes() as $attr_key => $attr_slug ) {
258
+ $attr_slugs[] = $attr_slug;
259
+ }
260
+ $sep = get_option( 'wcj_sku_variations_product_slug_sep', '-' );
261
+ $variation_attributes = implode( $sep, $attr_slugs );
262
+ }
263
+
264
  $format_template = get_option( 'wcj_sku_template',
265
  '{category_prefix}{prefix}{sku_number}{suffix}{category_suffix}{variation_suffix}' );
266
  $replace_values = array(
267
+ '{parent_sku}' => $parent_product->get_sku(),
268
+ '{product_slug}' => $_product->get_slug(),
269
+ '{parent_product_slug}' => $parent_product->get_slug(),
270
+ '{variation_attributes}' => $variation_attributes,
271
+ '{category_prefix}' => apply_filters( 'booster_option', '', $category_prefix ),
272
+ // '{tag_prefix}' => $tag_prefix,
273
+ '{prefix}' => get_option( 'wcj_sku_prefix', '' ),
274
+ '{sku_number}' => sprintf( '%0' . get_option( 'wcj_sku_minimum_number_length', 0 ) . 's', $sku_number ),
275
+ '{suffix}' => get_option( 'wcj_sku_suffix', '' ),
276
+ // '{tag_suffix}' => $tag_suffix,
277
+ '{category_suffix}' => $category_suffix,
278
+ '{variation_suffix}' => $variation_suffix,
279
  );
280
  $the_sku = ( $do_generate_new_sku ) ? str_replace( array_keys( $replace_values ), array_values( $replace_values ), $format_template ) : $old_sku;
281
 
335
  /**
336
  * set_all_products_skus.
337
  *
338
+ * @version 3.5.0
339
  */
340
  function set_all_products_skus( $is_preview ) {
341
  $this->maybe_get_sequential_counters();
342
+ $limit = 512;
343
  $offset = 0;
344
+ $start_id = ( isset( $_POST['wcj_sku_start_id'] ) && 0 != $_POST['wcj_sku_start_id'] ? $_POST['wcj_sku_start_id'] : 0 );
345
+ $end_id = ( isset( $_POST['wcj_sku_end_id'] ) && 0 != $_POST['wcj_sku_end_id'] ? $_POST['wcj_sku_end_id'] : PHP_INT_MAX );
346
  while ( true ) {
347
  $posts = new WP_Query( array(
348
  'posts_per_page' => $limit,
357
  break;
358
  }
359
  foreach ( $posts->posts as $post_id ) {
360
+ if ( $post_id < $start_id || $post_id > $end_id ) {
361
+ continue;
362
+ }
363
  $this->set_sku_with_variable( $post_id, $is_preview );
364
  }
365
  $offset += $limit;
403
  /**
404
  * create_sku_tool
405
  *
406
+ * @version 3.5.0
407
  */
408
  function create_sku_tool() {
409
  $result_message = '';
433
  $html .= $result_message;
434
  }
435
  $html .= '<form method="post" action="">';
436
+ $html .= '<p>';
437
  $html .= '<input class="button-primary" type="submit" name="preview_sku" id="preview_sku" value="' . __( 'Preview SKUs', 'woocommerce-jetpack' ) . '">';
438
  $html .= ' ';
439
  $html .= '<input class="button-primary" type="submit" name="set_sku" id="set_sku" value="' . __( 'Set SKUs', 'woocommerce-jetpack' ) . '">';
440
+ $html .= '</p>';
441
+ $html .= '<p>';
442
+ $html .= '<em>' . __( 'You can optionally limit affected products by main product\'s ID (set option to zero to ignore):', 'woocommerce-jetpack' ) . '</em>';
443
+ $html .= '<br>';
444
+ $html .= '<label for="wcj_sku_start_id">' . __( 'Min ID', 'woocommerce-jetpack' ) . ': ' . '</label>';
445
+ $html .= '<input type="number" name="wcj_sku_start_id" id="wcj_sku_start_id" min="0" value="' . ( isset( $_POST['wcj_sku_start_id'] ) ? $_POST['wcj_sku_start_id'] : 0 ) . '">';
446
+ $html .= ' ';
447
+ $html .= '<label for="wcj_sku_end_id">' . __( 'Max ID', 'woocommerce-jetpack' ) . ': ' . '</label>';
448
+ $html .= '<input type="number" name="wcj_sku_end_id" id="wcj_sku_end_id" min="0" value="' . ( isset( $_POST['wcj_sku_end_id'] ) ? $_POST['wcj_sku_end_id'] : 0 ) . '">';
449
+ $html .= '</p>';
450
  $html .= '</form>';
451
  if ( $is_preview ) {
452
  $html .= $preview_html;
includes/class-wcj-stock.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Stock
4
  *
5
- * @version 3.4.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -18,8 +18,7 @@ class WCJ_Stock extends WCJ_Module {
18
  *
19
  * @version 3.4.0
20
  * @since 2.8.0
21
- * @todo custom stock html
22
- * @todo (maybe) "woocommerce-products-stock" or "woocommerce-product-stock"
23
  */
24
  function __construct() {
25
 
@@ -66,8 +65,8 @@ class WCJ_Stock extends WCJ_Module {
66
  /**
67
  * custom_stock_html_below_wc_3.
68
  *
69
- * @version 3.4.0
70
- * @version 3.4.0
71
  */
72
  function custom_stock_html_below_wc_3( $html, $availability_availability, $product ) {
73
  $availability = $product->get_availability();
@@ -75,15 +74,15 @@ class WCJ_Stock extends WCJ_Module {
75
  '%class%' => ( ! empty( $availability['class'] ) ? $availability['class'] : '' ),
76
  '%availability%' => $availability_availability,
77
  );
78
- return str_replace( array_keys( $replacements ), $replacements, apply_filters( 'booster_option', '<p class="stock %class%">%availability%</p>',
79
- get_option( 'wcj_stock_custom_stock_html', '<p class="stock %class%">%availability%</p>' ) ) );
80
  }
81
 
82
  /**
83
  * custom_stock_html.
84
  *
85
- * @version 3.4.0
86
- * @version 3.4.0
87
  */
88
  function custom_stock_html( $html, $product ) {
89
  $availability = $product->get_availability();
@@ -91,15 +90,15 @@ class WCJ_Stock extends WCJ_Module {
91
  '%class%' => ( ! empty( $availability['class'] ) ? $availability['class'] : '' ),
92
  '%availability%' => ( ! empty( $availability['availability'] ) ? $availability['availability'] : '' ),
93
  );
94
- return str_replace( array_keys( $replacements ), $replacements, apply_filters( 'booster_option', '<p class="stock %class%">%availability%</p>',
95
- get_option( 'wcj_stock_custom_stock_html', '<p class="stock %class%">%availability%</p>' ) ) );
96
  }
97
 
98
  /**
99
  * custom_in_stock_class.
100
  *
101
  * @version 3.4.0
102
- * @version 3.4.0
103
  */
104
  function custom_in_stock_class( $class, $_product ) {
105
  if ( $_product->is_in_stock() ) {
@@ -111,12 +110,12 @@ class WCJ_Stock extends WCJ_Module {
111
  /**
112
  * custom_in_stock.
113
  *
114
- * @version 3.4.0
115
- * @version 3.4.0
116
  */
117
  function custom_in_stock( $availability, $_product ) {
118
  if ( $_product->is_in_stock() ) {
119
- return get_option( 'wcj_stock_custom_in_stock', '' );
120
  }
121
  return $availability;
122
  }
@@ -125,7 +124,7 @@ class WCJ_Stock extends WCJ_Module {
125
  * custom_out_of_stock_class.
126
  *
127
  * @version 2.8.0
128
- * @version 2.8.0
129
  */
130
  function custom_out_of_stock_class( $class, $_product ) {
131
  if ( ! $_product->is_in_stock() ) {
@@ -137,13 +136,13 @@ class WCJ_Stock extends WCJ_Module {
137
  /**
138
  * custom_out_of_stock.
139
  *
140
- * @version 2.8.0
141
- * @version 2.8.0
142
  * @todo html tags in < WC3
143
  */
144
  function custom_out_of_stock( $availability, $_product ) {
145
  if ( ! $_product->is_in_stock() ) {
146
- return get_option( 'wcj_stock_custom_out_of_stock', '' );
147
  }
148
  return $availability;
149
  }
2
  /**
3
  * Booster for WooCommerce - Module - Stock
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
18
  *
19
  * @version 3.4.0
20
  * @since 2.8.0
21
+ * @todo (maybe) change `link_slug` to "woocommerce-products-stock" or "woocommerce-product-stock"
 
22
  */
23
  function __construct() {
24
 
65
  /**
66
  * custom_stock_html_below_wc_3.
67
  *
68
+ * @version 3.5.0
69
+ * @since 3.4.0
70
  */
71
  function custom_stock_html_below_wc_3( $html, $availability_availability, $product ) {
72
  $availability = $product->get_availability();
74
  '%class%' => ( ! empty( $availability['class'] ) ? $availability['class'] : '' ),
75
  '%availability%' => $availability_availability,
76
  );
77
+ return do_shortcode( str_replace( array_keys( $replacements ), $replacements, apply_filters( 'booster_option', '<p class="stock %class%">%availability%</p>',
78
+ get_option( 'wcj_stock_custom_stock_html', '<p class="stock %class%">%availability%</p>' ) ) ) );
79
  }
80
 
81
  /**
82
  * custom_stock_html.
83
  *
84
+ * @version 3.5.0
85
+ * @since 3.4.0
86
  */
87
  function custom_stock_html( $html, $product ) {
88
  $availability = $product->get_availability();
90
  '%class%' => ( ! empty( $availability['class'] ) ? $availability['class'] : '' ),
91
  '%availability%' => ( ! empty( $availability['availability'] ) ? $availability['availability'] : '' ),
92
  );
93
+ return do_shortcode( str_replace( array_keys( $replacements ), $replacements, apply_filters( 'booster_option', '<p class="stock %class%">%availability%</p>',
94
+ get_option( 'wcj_stock_custom_stock_html', '<p class="stock %class%">%availability%</p>' ) ) ) );
95
  }
96
 
97
  /**
98
  * custom_in_stock_class.
99
  *
100
  * @version 3.4.0
101
+ * @since 3.4.0
102
  */
103
  function custom_in_stock_class( $class, $_product ) {
104
  if ( $_product->is_in_stock() ) {
110
  /**
111
  * custom_in_stock.
112
  *
113
+ * @version 3.5.0
114
+ * @since 3.4.0
115
  */
116
  function custom_in_stock( $availability, $_product ) {
117
  if ( $_product->is_in_stock() ) {
118
+ return do_shortcode( get_option( 'wcj_stock_custom_in_stock', '' ) );
119
  }
120
  return $availability;
121
  }
124
  * custom_out_of_stock_class.
125
  *
126
  * @version 2.8.0
127
+ * @since 2.8.0
128
  */
129
  function custom_out_of_stock_class( $class, $_product ) {
130
  if ( ! $_product->is_in_stock() ) {
136
  /**
137
  * custom_out_of_stock.
138
  *
139
+ * @version 3.5.0
140
+ * @since 2.8.0
141
  * @todo html tags in < WC3
142
  */
143
  function custom_out_of_stock( $availability, $_product ) {
144
  if ( ! $_product->is_in_stock() ) {
145
+ return do_shortcode( get_option( 'wcj_stock_custom_out_of_stock', '' ) );
146
  }
147
  return $availability;
148
  }
includes/classes/class-wcj-invoice.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce Invoice
4
  *
5
- * @version 3.2.2
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -73,12 +73,15 @@ class WCJ_Invoice {
73
 
74
  /**
75
  * get_file_name.
 
 
76
  */
77
  function get_file_name() {
78
- $the_file_name = do_shortcode( get_option( 'wcj_invoicing_' . $this->invoice_type . '_file_name', 'invoice-' . $this->order_id ) . '.pdf' );
79
- if ( '' == $the_file_name ) $the_file_name = 'invoice';
80
- $the_file_name = sanitize_file_name( $the_file_name );
81
- return apply_filters( 'wcj_get_' . $this->invoice_type . '_file_name', $the_file_name, $this->order_id );
 
82
  }
83
 
84
  /**
2
  /**
3
  * Booster for WooCommerce Invoice
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
73
 
74
  /**
75
  * get_file_name.
76
+ *
77
+ * @version 3.5.0
78
  */
79
  function get_file_name() {
80
+ $_file_name = sanitize_file_name( do_shortcode( get_option( 'wcj_invoicing_' . $this->invoice_type . '_file_name', '' ) ) );
81
+ if ( '' === $_file_name ) {
82
+ $_file_name = $this->invoice_type . '-' . $this->order_id;
83
+ }
84
+ return apply_filters( 'wcj_get_' . $this->invoice_type . '_file_name', $_file_name . '.pdf', $this->order_id );
85
  }
86
 
87
  /**
includes/classes/class-wcj-module-shipping-by-condition.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Module - Shipping by Condition
4
  *
5
- * @version 3.2.4
6
  * @since 3.2.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) `abstract class WCJ_Module_Shipping_By_Condition`
@@ -18,12 +18,13 @@ class WCJ_Module_Shipping_By_Condition extends WCJ_Module {
18
  /**
19
  * Constructor.
20
  *
21
- * @version 3.2.4
22
  * @since 3.2.0
23
  */
24
  function __construct( $type = 'module' ) {
25
  parent::__construct( $type );
26
  if ( $this->is_enabled() ) {
 
27
  add_filter( 'woocommerce_package_rates', array( $this, 'available_shipping_methods' ), wcj_get_woocommerce_package_rates_module_filter_priority( $this->id ) , 2 );
28
  }
29
  }
@@ -31,7 +32,7 @@ class WCJ_Module_Shipping_By_Condition extends WCJ_Module {
31
  /**
32
  * available_shipping_methods.
33
  *
34
- * @version 3.2.1
35
  * @since 3.2.0
36
  * @todo apply_filters( 'booster_option' )
37
  */
@@ -41,12 +42,18 @@ class WCJ_Module_Shipping_By_Condition extends WCJ_Module {
41
  if ( 'no' === get_option( 'wcj_shipping_by_' . $options_id . '_section_enabled', 'yes' ) ) {
42
  continue;
43
  }
44
- $include = get_option( 'wcj_shipping_' . $options_id . '_include_' . $rate->method_id, '' );
 
 
 
45
  if ( ! empty( $include ) && ! $this->check( $options_id, $include, 'include' ) ) {
46
  unset( $rates[ $rate_key ] );
47
  break;
48
  }
49
- $exclude = get_option( 'wcj_shipping_' . $options_id . '_exclude_' . $rate->method_id, '' );
 
 
 
50
  if ( ! empty( $exclude ) && $this->check( $options_id, $exclude , 'exclude' ) ) {
51
  unset( $rates[ $rate_key ] );
52
  break;
2
  /**
3
  * Booster for WooCommerce - Module - Shipping by Condition
4
  *
5
+ * @version 3.5.0
6
  * @since 3.2.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) `abstract class WCJ_Module_Shipping_By_Condition`
18
  /**
19
  * Constructor.
20
  *
21
+ * @version 3.5.0
22
  * @since 3.2.0
23
  */
24
  function __construct( $type = 'module' ) {
25
  parent::__construct( $type );
26
  if ( $this->is_enabled() ) {
27
+ $this->use_shipping_instances = ( 'yes' === get_option( 'wcj_' . $this->id . '_use_shipping_instance', 'no' ) );
28
  add_filter( 'woocommerce_package_rates', array( $this, 'available_shipping_methods' ), wcj_get_woocommerce_package_rates_module_filter_priority( $this->id ) , 2 );
29
  }
30
  }
32
  /**
33
  * available_shipping_methods.
34
  *
35
+ * @version 3.5.0
36
  * @since 3.2.0
37
  * @todo apply_filters( 'booster_option' )
38
  */
42
  if ( 'no' === get_option( 'wcj_shipping_by_' . $options_id . '_section_enabled', 'yes' ) ) {
43
  continue;
44
  }
45
+ $include = ( $this->use_shipping_instances ?
46
+ get_option( 'wcj_shipping_' . $options_id . '_include_' . 'instance_' . $rate->instance_id, '' ) :
47
+ get_option( 'wcj_shipping_' . $options_id . '_include_' . $rate->method_id, '' )
48
+ );
49
  if ( ! empty( $include ) && ! $this->check( $options_id, $include, 'include' ) ) {
50
  unset( $rates[ $rate_key ] );
51
  break;
52
  }
53
+ $exclude = ( $this->use_shipping_instances ?
54
+ get_option( 'wcj_shipping_' . $options_id . '_exclude_' . 'instance_' . $rate->instance_id, '' ) :
55
+ get_option( 'wcj_shipping_' . $options_id . '_exclude_' . $rate->method_id, '' )
56
+ );
57
  if ( ! empty( $exclude ) && $this->check( $options_id, $exclude , 'exclude' ) ) {
58
  unset( $rates[ $rate_key ] );
59
  break;
includes/classes/class-wcj-pdf-invoice.php CHANGED
@@ -2,9 +2,8 @@
2
  /**
3
  * Booster for WooCommerce PDF Invoice
4
  *
5
- * @version 3.4.3
6
  * @author Algoritmika Ltd.
7
- * @todo clean up
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
@@ -25,6 +24,8 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
25
  *
26
  * @version 3.4.3
27
  * @todo check `addTTFfont()`
 
 
28
  */
29
  function prepare_pdf() {
30
 
@@ -55,7 +56,7 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
55
 
56
  // Set document information
57
  $pdf->SetCreator( PDF_CREATOR );
58
- // $pdf->SetAuthor( 'Algoritmika Ltd.' );
59
  $invoice_title = $invoice_type;
60
  $invoice_types = /* ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ) ? wcj_get_enabled_invoice_types() : */ wcj_get_invoice_types();
61
  foreach ( $invoice_types as $invoice_type_data ) {
@@ -104,8 +105,8 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
104
  $tcpdf_font = wcj_get_tcpdf_font( $invoice_type );
105
 
106
  // Set Header and Footer fonts
107
- $pdf->setHeaderFont( Array( /* PDF_FONT_NAME_MAIN */ $tcpdf_font, '', PDF_FONT_SIZE_MAIN ) );
108
- $pdf->setFooterFont( Array( /* PDF_FONT_NAME_DATA */ $tcpdf_font, '', PDF_FONT_SIZE_DATA ) );
109
 
110
  // Set default monospaced font
111
  $pdf->SetDefaultMonospacedFont( PDF_FONT_MONOSPACED );
@@ -120,7 +121,7 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
120
  $pdf->SetFooterMargin( get_option( 'wcj_invoicing_' . $invoice_type . '_margin_footer', 10 ) );
121
 
122
  // Set auto page breaks
123
- $pdf->SetAutoPageBreak( TRUE, get_option( 'wcj_invoicing_' . $invoice_type . '_margin_bottom', 0 ) );
124
 
125
  // Set image scale factor
126
  $pdf->setImageScale( PDF_IMAGE_SCALE_RATIO );
@@ -157,16 +158,18 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
157
  }
158
 
159
  /**
160
- * get_pdf.
 
 
161
  *
162
- * @version 3.2.4
 
163
  * @todo pass other params (billing_country, payment_method) as global (same as user_id) instead of $_GET
 
164
  */
165
- function get_pdf( $dest ) {
166
-
167
- // Get invoice content HTML
168
- $_GET['order_id'] = $this->order_id;
169
- $the_order = wc_get_order( $this->order_id );
170
  if ( ! isset( $_GET['billing_country'] ) ) {
171
  $_GET['billing_country'] = ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_order->billing_country : $the_order->get_billing_country() );
172
  }
@@ -179,39 +182,37 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
179
  }
180
  $html = do_shortcode( get_option( 'wcj_invoicing_' . $this->invoice_type . '_template',
181
  WCJ()->modules['pdf_invoicing_templates']->get_default_template( $this->invoice_type ) ) );
182
- $html = force_balance_tags( $html );
 
 
 
 
 
 
 
 
 
 
183
  $styling = '<style>' . get_option( 'wcj_invoicing_' . $this->invoice_type . '_css',
184
  WCJ()->modules['pdf_invoicing_styling']->get_default_css_template( $this->invoice_type ) ) . '</style>';
185
-
186
  $pdf = $this->prepare_pdf();
187
- // Print text using writeHTMLCell()
188
  $pdf->writeHTMLCell( 0, 0, '', '', $styling . $html, 0, 1, 0, true, '', true );
189
-
190
- // Close and output PDF document
191
  $result_pdf = $pdf->Output( '', 'S' );
192
- $file_name = $this->get_file_name();
193
-
194
- $tmp_dir = get_option( 'wcj_invoicing_general_tmp_dir', '' );
195
- if ( '' === $tmp_dir ) {
196
- $tmp_dir = sys_get_temp_dir();
197
- }
198
-
199
  if ( 'F' === $dest ) {
200
- $file_path = $tmp_dir . '/' . $file_name;
201
  if ( ! file_put_contents( $file_path, $result_pdf ) ) {
202
  return null;
203
  }
204
  return $file_path;
205
- }
206
- elseif ( 'D' === $dest || 'I' === $dest ) {
207
  if ( 'D' === $dest ) {
208
  header( "Content-Type: application/octet-stream" );
209
  header( "Content-Disposition: attachment; filename=" . urlencode( $file_name ) );
210
  header( "Content-Type: application/octet-stream" );
211
  header( "Content-Type: application/download" );
212
  header( "Content-Description: File Transfer" );
213
- }
214
- elseif ( 'I' === $dest ) {
215
  header( "Content-type: application/pdf" );
216
  header( "Content-Disposition: inline; filename=" . urlencode( $file_name ) );
217
  }
@@ -219,15 +220,12 @@ class WCJ_PDF_Invoice extends WCJ_Invoice {
219
  header( "Content-Length: " . strlen( $result_pdf ) );
220
  echo $result_pdf;
221
  } else {
222
-
223
- $file_path = $tmp_dir . '/' . $file_name;
224
  if ( ! file_put_contents( $file_path, $result_pdf ) ) {
225
  return null;
226
  }
227
-
228
  header( "Content-Length: " . filesize( $file_path ) );
229
  flush(); // this doesn't really matter.
230
-
231
  if ( false !== ( $fp = fopen( $file_path, "r" ) ) ) {
232
  while ( ! feof( $fp ) ) {
233
  echo fread( $fp, 65536 );
2
  /**
3
  * Booster for WooCommerce PDF Invoice
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
 
7
  */
8
 
9
  if ( ! defined( 'ABSPATH' ) ) exit;
24
  *
25
  * @version 3.4.3
26
  * @todo check `addTTFfont()`
27
+ * @todo clean up
28
+ * @todo (maybe) option to set different font in footer (and maybe also header)
29
  */
30
  function prepare_pdf() {
31
 
56
 
57
  // Set document information
58
  $pdf->SetCreator( PDF_CREATOR );
59
+ // $pdf->SetAuthor( 'Booster for WooCommerce' );
60
  $invoice_title = $invoice_type;
61
  $invoice_types = /* ( 'yes' === get_option( 'wcj_invoicing_hide_disabled_docs_settings', 'no' ) ) ? wcj_get_enabled_invoice_types() : */ wcj_get_invoice_types();
62
  foreach ( $invoice_types as $invoice_type_data ) {
105
  $tcpdf_font = wcj_get_tcpdf_font( $invoice_type );
106
 
107
  // Set Header and Footer fonts
108
+ $pdf->setHeaderFont( array( /* PDF_FONT_NAME_MAIN */ $tcpdf_font, '', PDF_FONT_SIZE_MAIN ) );
109
+ $pdf->setFooterFont( array( /* PDF_FONT_NAME_DATA */ $tcpdf_font, '', PDF_FONT_SIZE_DATA ) );
110
 
111
  // Set default monospaced font
112
  $pdf->SetDefaultMonospacedFont( PDF_FONT_MONOSPACED );
121
  $pdf->SetFooterMargin( get_option( 'wcj_invoicing_' . $invoice_type . '_margin_footer', 10 ) );
122
 
123
  // Set auto page breaks
124
+ $pdf->SetAutoPageBreak( true, get_option( 'wcj_invoicing_' . $invoice_type . '_margin_bottom', 0 ) );
125
 
126
  // Set image scale factor
127
  $pdf->setImageScale( PDF_IMAGE_SCALE_RATIO );
158
  }
159
 
160
  /**
161
+ * get_html.
162
+ *
163
+ * Gets invoice content HTML.
164
  *
165
+ * @version 3.5.0
166
+ * @since 3.5.0
167
  * @todo pass other params (billing_country, payment_method) as global (same as user_id) instead of $_GET
168
+ * @todo `force_balance_tags()` - there are some bugs and performance issues, see http://wordpress.stackexchange.com/questions/89121/why-doesnt-default-wordpress-page-view-use-force-balance-tags
169
  */
170
+ function get_html( $order_id ) {
171
+ $_GET['order_id'] = $order_id;
172
+ $the_order = wc_get_order( $order_id );
 
 
173
  if ( ! isset( $_GET['billing_country'] ) ) {
174
  $_GET['billing_country'] = ( WCJ_IS_WC_VERSION_BELOW_3 ? $the_order->billing_country : $the_order->get_billing_country() );
175
  }
182
  }
183
  $html = do_shortcode( get_option( 'wcj_invoicing_' . $this->invoice_type . '_template',
184
  WCJ()->modules['pdf_invoicing_templates']->get_default_template( $this->invoice_type ) ) );
185
+ return force_balance_tags( $html );
186
+ }
187
+
188
+ /**
189
+ * get_pdf.
190
+ *
191
+ * @version 3.5.0
192
+ * @todo (maybe) `die()` on success
193
+ */
194
+ function get_pdf( $dest ) {
195
+ $html = $this->get_html( $this->order_id );
196
  $styling = '<style>' . get_option( 'wcj_invoicing_' . $this->invoice_type . '_css',
197
  WCJ()->modules['pdf_invoicing_styling']->get_default_css_template( $this->invoice_type ) ) . '</style>';
 
198
  $pdf = $this->prepare_pdf();
 
199
  $pdf->writeHTMLCell( 0, 0, '', '', $styling . $html, 0, 1, 0, true, '', true );
 
 
200
  $result_pdf = $pdf->Output( '', 'S' );
201
+ $file_name = $this->get_file_name();
 
 
 
 
 
 
202
  if ( 'F' === $dest ) {
203
+ $file_path = wcj_get_invoicing_temp_dir() . '/' . $file_name;
204
  if ( ! file_put_contents( $file_path, $result_pdf ) ) {
205
  return null;
206
  }
207
  return $file_path;
208
+ } elseif ( 'D' === $dest || 'I' === $dest ) {
 
209
  if ( 'D' === $dest ) {
210
  header( "Content-Type: application/octet-stream" );
211
  header( "Content-Disposition: attachment; filename=" . urlencode( $file_name ) );
212
  header( "Content-Type: application/octet-stream" );
213
  header( "Content-Type: application/download" );
214
  header( "Content-Description: File Transfer" );
215
+ } elseif ( 'I' === $dest ) {
 
216
  header( "Content-type: application/pdf" );
217
  header( "Content-Disposition: inline; filename=" . urlencode( $file_name ) );
218
  }
220
  header( "Content-Length: " . strlen( $result_pdf ) );
221
  echo $result_pdf;
222
  } else {
223
+ $file_path = wcj_get_invoicing_temp_dir() . '/' . $file_name;
 
224
  if ( ! file_put_contents( $file_path, $result_pdf ) ) {
225
  return null;
226
  }
 
227
  header( "Content-Length: " . filesize( $file_path ) );
228
  flush(); // this doesn't really matter.
 
229
  if ( false !== ( $fp = fopen( $file_path, "r" ) ) ) {
230
  while ( ! feof( $fp ) ) {
231
  echo fread( $fp, 65536 );
includes/classes/class-wcj-shortcodes.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes
4
  *
5
- * @version 3.1.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -57,9 +57,10 @@ class WCJ_Shortcodes {
57
  /**
58
  * wcj_shortcode.
59
  *
60
- * @version 3.1.0
61
  * @todo `time` - weekly, e.g. 8:00-19:59;8:00-19:59;8:00-19:59;8:00-19:59;8:00-9:59,12:00-17:59;-;-;
62
  * @todo (maybe) - `return $atts['on_empty'];` everywhere instead of `return '';`
 
63
  */
64
  function wcj_shortcode( $atts, $content, $shortcode ) {
65
 
@@ -94,6 +95,7 @@ class WCJ_Shortcodes {
94
  'on_empty' => '',
95
  'on_zero' => 0,
96
  'time' => '',
 
97
  );
98
  $atts = array_merge( $global_defaults, $atts );
99
 
@@ -157,9 +159,10 @@ class WCJ_Shortcodes {
157
  // Check if site visibility is ok
158
  if ( '' != $atts['site_visibility'] ) {
159
  if (
160
- ( 'single' === $atts['site_visibility'] && ! is_single() ) ||
161
- ( 'page' === $atts['site_visibility'] && ! is_page() ) ||
162
- ( 'archive' === $atts['site_visibility'] && ! is_archive() )
 
163
  ) {
164
  return '';
165
  }
@@ -174,8 +177,14 @@ class WCJ_Shortcodes {
174
  }
175
 
176
  // Check if language is ok
177
- if ( 'wcj_wpml' === $shortcode || 'wcj_wpml_translate' === $shortcode ) $atts['wpml_language'] = isset( $atts['lang'] ) ? $atts['lang'] : '';
178
- if ( 'wcj_wpml' === $shortcode || 'wcj_wpml_translate' === $shortcode ) $atts['wpml_not_language'] = isset( $atts['not_lang'] ) ? $atts['not_lang'] : '';
 
 
 
 
 
 
179
  if ( '' != $atts['wpml_language'] ) {
180
  if ( ! defined( 'ICL_LANGUAGE_CODE' ) ) {
181
  return '';
@@ -254,6 +263,9 @@ class WCJ_Shortcodes {
254
  if ( 'yes' === $atts['strip_tags'] ) {
255
  $result = strip_tags( $result );
256
  }
 
 
 
257
  return $atts['before'] . apply_filters( 'wcj_shortcode_result', $result, $atts, $content, $shortcode ) . $atts['after'];
258
  }
259
  return $atts['on_empty'];
2
  /**
3
  * Booster for WooCommerce - Shortcodes
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
57
  /**
58
  * wcj_shortcode.
59
  *
60
+ * @version 3.5.0
61
  * @todo `time` - weekly, e.g. 8:00-19:59;8:00-19:59;8:00-19:59;8:00-19:59;8:00-9:59,12:00-17:59;-;-;
62
  * @todo (maybe) - `return $atts['on_empty'];` everywhere instead of `return '';`
63
+ * @todo (maybe) - add `$atts['function']` and `$atts['function_args']` - if set, will be run on shortcode's result
64
  */
65
  function wcj_shortcode( $atts, $content, $shortcode ) {
66
 
95
  'on_empty' => '',
96
  'on_zero' => 0,
97
  'time' => '',
98
+ 'multiply' => 1,
99
  );
100
  $atts = array_merge( $global_defaults, $atts );
101
 
159
  // Check if site visibility is ok
160
  if ( '' != $atts['site_visibility'] ) {
161
  if (
162
+ ( 'single' === $atts['site_visibility'] && ! is_single() ) ||
163
+ ( 'page' === $atts['site_visibility'] && ! is_page() ) ||
164
+ ( 'archive' === $atts['site_visibility'] && ! is_archive() ) ||
165
+ ( 'front_page' === $atts['site_visibility'] && ! is_front_page() )
166
  ) {
167
  return '';
168
  }
177
  }
178
 
179
  // Check if language is ok
180
+ if ( 'wcj_wpml' === $shortcode || 'wcj_wpml_translate' === $shortcode ) {
181
+ if ( isset( $atts['lang'] ) ) {
182
+ $atts['wpml_language'] = $atts['lang'];
183
+ }
184
+ if ( isset( $atts['not_lang'] ) ) {
185
+ $atts['wpml_not_language'] = $atts['not_lang'];
186
+ }
187
+ }
188
  if ( '' != $atts['wpml_language'] ) {
189
  if ( ! defined( 'ICL_LANGUAGE_CODE' ) ) {
190
  return '';
263
  if ( 'yes' === $atts['strip_tags'] ) {
264
  $result = strip_tags( $result );
265
  }
266
+ if ( 1 != $atts['multiply'] ) {
267
+ $result = $result * $atts['multiply'];
268
+ }
269
  return $atts['before'] . apply_filters( 'wcj_shortcode_result', $result, $atts, $content, $shortcode ) . $atts['after'];
270
  }
271
  return $atts['on_empty'];
includes/core/wcj-functions.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions
4
  *
5
- * @version 3.3.0
6
  * @since 3.2.4
7
  * @author Algoritmika Ltd.
8
  */
@@ -14,6 +14,7 @@ $wcj_function_files = array(
14
  'wcj-functions-debug.php',
15
  'wcj-functions-admin.php',
16
  'wcj-functions-general.php',
 
17
  'wcj-functions-date-time.php',
18
  'wcj-functions-crons.php',
19
  'wcj-functions-products.php',
2
  /**
3
  * Booster for WooCommerce - Functions
4
  *
5
+ * @version 3.5.0
6
  * @since 3.2.4
7
  * @author Algoritmika Ltd.
8
  */
14
  'wcj-functions-debug.php',
15
  'wcj-functions-admin.php',
16
  'wcj-functions-general.php',
17
+ 'wcj-functions-shipping.php',
18
  'wcj-functions-date-time.php',
19
  'wcj-functions-crons.php',
20
  'wcj-functions-products.php',
includes/core/wcj-loader.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Core - Loader
4
  *
5
- * @version 3.3.0
6
  * @since 3.2.4
7
  * @author Algoritmika Ltd.
8
  */
@@ -11,6 +11,11 @@ if ( ! defined( 'ABSPATH' ) ) {
11
  exit;
12
  }
13
 
 
 
 
 
 
14
  if ( ! defined( 'WCJ_PLUGIN_PATH' ) ) {
15
  /**
16
  * WCJ_PLUGIN_PATH.
2
  /**
3
  * Booster for WooCommerce - Core - Loader
4
  *
5
+ * @version 3.5.0
6
  * @since 3.2.4
7
  * @author Algoritmika Ltd.
8
  */
11
  exit;
12
  }
13
 
14
+ // Debug Mode
15
+ if ( 'yes' === get_option( 'wcj_admin_tools_enabled', 'no' ) && 'yes' === get_option( 'wcj_debuging_enabled', 'no' ) ) {
16
+ error_reporting( E_ALL );
17
+ }
18
+
19
  if ( ! defined( 'WCJ_PLUGIN_PATH' ) ) {
20
  /**
21
  * WCJ_PLUGIN_PATH.
includes/core/wcj-modules.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Modules
4
  *
5
- * @version 3.4.0
6
  * @since 3.2.4
7
  * @author Algoritmika Ltd.
8
  */
@@ -73,6 +73,7 @@ $wcj_module_files = array(
73
  'class-wcj-shipping-options.php',
74
  'class-wcj-shipping-icons.php',
75
  'class-wcj-shipping-description.php',
 
76
  'class-wcj-left-to-free-shipping.php',
77
  'class-wcj-shipping-calculator.php',
78
  'class-wcj-shipping-by-user-role.php',
@@ -85,6 +86,7 @@ $wcj_module_files = array(
85
  'class-wcj-order-numbers.php',
86
  'class-wcj-order-custom-statuses.php',
87
  'class-wcj-order-quantities.php',
 
88
  'class-wcj-pdf-invoicing.php',
89
  'class-wcj-emails.php',
90
  'class-wcj-email-options.php',
2
  /**
3
  * Booster for WooCommerce - Modules
4
  *
5
+ * @version 3.5.0
6
  * @since 3.2.4
7
  * @author Algoritmika Ltd.
8
  */
73
  'class-wcj-shipping-options.php',
74
  'class-wcj-shipping-icons.php',
75
  'class-wcj-shipping-description.php',
76
+ 'class-wcj-shipping-time.php',
77
  'class-wcj-left-to-free-shipping.php',
78
  'class-wcj-shipping-calculator.php',
79
  'class-wcj-shipping-by-user-role.php',
86
  'class-wcj-order-numbers.php',
87
  'class-wcj-order-custom-statuses.php',
88
  'class-wcj-order-quantities.php',
89
+ 'class-wcj-max-products-per-user.php',
90
  'class-wcj-pdf-invoicing.php',
91
  'class-wcj-emails.php',
92
  'class-wcj-email-options.php',
includes/functions/wcj-functions-admin.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Admin
4
  *
5
- * @version 3.3.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -49,21 +49,29 @@ if ( ! function_exists( 'wcj_get_product_ids_for_meta_box_options' ) ) {
49
  /**
50
  * wcj_get_product_ids_for_meta_box_options.
51
  *
52
- * @version 3.3.0
53
  * @since 3.3.0
54
  * @todo use this function where needed
55
  */
56
- function wcj_get_product_ids_for_meta_box_options( $main_product_id ) {
57
  $_product = wc_get_product( $main_product_id );
58
  if ( ! $_product ) {
59
  return array();
60
  }
61
  $products = array();
62
  if ( $_product->is_type( 'variable' ) ) {
63
- $available_variations = $_product->get_available_variations();
64
- foreach ( $available_variations as $variation ) {
65
- $variation_product = wc_get_product( $variation['variation_id'] );
66
- $products[ $variation['variation_id'] ] = ' (' . wcj_get_product_formatted_variation( $variation_product, true ) . ')';
 
 
 
 
 
 
 
 
67
  }
68
  } else {
69
  $products[ $main_product_id ] = '';
2
  /**
3
  * Booster for WooCommerce - Functions - Admin
4
  *
5
+ * @version 3.5.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
49
  /**
50
  * wcj_get_product_ids_for_meta_box_options.
51
  *
52
+ * @version 3.5.0
53
  * @since 3.3.0
54
  * @todo use this function where needed
55
  */
56
+ function wcj_get_product_ids_for_meta_box_options( $main_product_id, $do_get_all_variations = false ) {
57
  $_product = wc_get_product( $main_product_id );
58
  if ( ! $_product ) {
59
  return array();
60
  }
61
  $products = array();
62
  if ( $_product->is_type( 'variable' ) ) {
63
+ if ( $do_get_all_variations ) {
64
+ $all_variations = $_product->get_children();
65
+ foreach ( $all_variations as $variation_id ) {
66
+ $variation_product = wc_get_product( $variation_id );
67
+ $products[ $variation_id ] = ' (' . wcj_get_product_formatted_variation( $variation_product, true ) . ')';
68
+ }
69
+ } else {
70
+ $available_variations = $_product->get_available_variations();
71
+ foreach ( $available_variations as $variation ) {
72
+ $variation_product = wc_get_product( $variation['variation_id'] );
73
+ $products[ $variation['variation_id'] ] = ' (' . wcj_get_product_formatted_variation( $variation_product, true ) . ')';
74
+ }
75
  }
76
  } else {
77
  $products[ $main_product_id ] = '';
includes/functions/wcj-functions-country.php CHANGED
@@ -44,6 +44,7 @@ if ( ! function_exists( 'wcj_get_customer_country' ) ) {
44
  *
45
  * @version 2.9.0
46
  * @return string
 
47
  */
48
  function wcj_get_customer_country( $user_id ) {
49
  $user_meta = get_user_meta( $user_id );
44
  *
45
  * @version 2.9.0
46
  * @return string
47
+ * @todo re-check: there is also `wcj_customer_get_country()`
48
  */
49
  function wcj_get_customer_country( $user_id ) {
50
  $user_meta = get_user_meta( $user_id );
includes/functions/wcj-functions-currencies.php CHANGED
@@ -11,6 +11,7 @@ if ( ! function_exists( 'wcj_get_currencies_array' ) ) {
11
  * wcj_get_currencies_array.
12
  *
13
  * @version 3.3.0
 
14
  */
15
  function wcj_get_currencies_array() {
16
  return array(
11
  * wcj_get_currencies_array.
12
  *
13
  * @version 3.3.0
14
+ * @todo clean up / rewrite
15
  */
16
  function wcj_get_currencies_array() {
17
  return array(
includes/functions/wcj-functions-debug.php CHANGED
@@ -2,28 +2,27 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Debug
4
  *
5
- * @version 3.3.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
9
  if ( ! defined( 'ABSPATH' ) ) exit;
10
 
11
- // Debug Mode
12
- if ( wcj_is_module_enabled( 'admin_tools' ) && 'yes' === get_option( 'wcj_debuging_enabled', 'no' ) ) {
13
- error_reporting( E_ALL );
14
- }
15
-
16
  if ( ! function_exists( 'wcj_log' ) ) {
17
  /**
18
  * wcj_log.
19
  *
20
- * @version 3.3.0
21
  */
22
- function wcj_log( $message = '' ) {
23
  if ( ! wcj_is_module_enabled( 'admin_tools' ) || ( 'no' === get_option( 'wcj_logging_enabled', 'no' ) && 'no' === get_option( 'wcj_wc_logging_enabled', 'no' ) ) ) {
24
  return;
25
  }
26
- if ( is_array( $message ) || is_object( $message ) ) {
 
 
 
 
27
  $message = print_r( $message, true );
28
  }
29
  if ( 'yes' === get_option( 'wcj_logging_enabled', 'no' ) ) {
2
  /**
3
  * Booster for WooCommerce - Functions - Debug
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
9
  if ( ! defined( 'ABSPATH' ) ) exit;
10
 
 
 
 
 
 
11
  if ( ! function_exists( 'wcj_log' ) ) {
12
  /**
13
  * wcj_log.
14
  *
15
+ * @version 3.5.0
16
  */
17
+ function wcj_log( $message = '', $do_var_dump = false ) {
18
  if ( ! wcj_is_module_enabled( 'admin_tools' ) || ( 'no' === get_option( 'wcj_logging_enabled', 'no' ) && 'no' === get_option( 'wcj_wc_logging_enabled', 'no' ) ) ) {
19
  return;
20
  }
21
+ if ( $do_var_dump ) {
22
+ ob_start();
23
+ var_dump( $message );
24
+ $message = ob_get_clean();
25
+ } elseif ( is_array( $message ) || is_object( $message ) ) {
26
  $message = print_r( $message, true );
27
  }
28
  if ( 'yes' === get_option( 'wcj_logging_enabled', 'no' ) ) {
includes/functions/wcj-functions-exchange-rates.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Exchange Rates
4
  *
5
- * @version 3.4.5
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -61,17 +61,19 @@ if ( ! function_exists( 'wcj_get_currency_exchange_rate_servers' ) ) {
61
  /**
62
  * wcj_get_currency_exchange_rate_servers.
63
  *
64
- * @version 3.2.4
65
  * @since 2.6.0
66
  */
67
  function wcj_get_currency_exchange_rate_servers() {
68
  return array(
69
  'yahoo' => __( 'Yahoo', 'woocommerce-jetpack' ),
70
- 'ecb' => __( 'European Central Bank (ECB)', 'woocommerce-jetpack' ),
71
  'tcmb' => __( 'TCMB', 'woocommerce-jetpack' ),
72
  'fixer' => __( 'Fixer.io', 'woocommerce-jetpack' ),
73
  'coinbase' => __( 'Coinbase', 'woocommerce-jetpack' ),
74
  'coinmarketcap' => __( 'CoinMarketCap', 'woocommerce-jetpack' ),
 
 
75
  );
76
  }
77
  }
@@ -125,7 +127,7 @@ if ( ! function_exists( 'wcj_get_exchange_rate' ) ) {
125
  /*
126
  * wcj_get_exchange_rate.
127
  *
128
- * @version 3.2.4
129
  * @since 2.6.0
130
  */
131
  function wcj_get_exchange_rate( $currency_from, $currency_to ) {
@@ -139,8 +141,8 @@ if ( ! function_exists( 'wcj_get_exchange_rate' ) ) {
139
  case 'tcmb':
140
  $return = wcj_tcmb_get_exchange_rate( $currency_from, $currency_to );
141
  break;
142
- case 'ecb':
143
- $return = wcj_ecb_get_exchange_rate( $currency_from, $currency_to );
144
  break;
145
  case 'fixer':
146
  $return = wcj_fixer_io_get_exchange_rate( $currency_from, $currency_to );
@@ -151,8 +153,14 @@ if ( ! function_exists( 'wcj_get_exchange_rate' ) ) {
151
  case 'coinmarketcap':
152
  $return = wcj_coinmarketcap_get_exchange_rate( $currency_from, $currency_to );
153
  break;
154
- default: // 'yahoo'
155
- $return = wcj_yahoo_get_exchange_rate( $currency_from, $currency_to );
 
 
 
 
 
 
156
  break;
157
  }
158
  return ( 'yes' === $calculate_by_invert ) ? round( ( 1 / $return ), 6 ) : $return;
@@ -163,11 +171,11 @@ if ( ! function_exists( 'wcj_get_currency_exchange_rates_url_response' ) ) {
163
  /*
164
  * wcj_get_currency_exchange_rates_url_response.
165
  *
166
- * @version 3.2.4
167
  * @since 3.2.4
168
  * @todo use where needed
169
  */
170
- function wcj_get_currency_exchange_rates_url_response( $url ) {
171
  $response = '';
172
  if ( 'no' === get_option( 'wcj_currency_exchange_rates_always_curl', 'no' ) && ini_get( 'allow_url_fopen' ) ) {
173
  $response = file_get_contents( $url );
@@ -178,7 +186,117 @@ if ( ! function_exists( 'wcj_get_currency_exchange_rates_url_response' ) ) {
178
  $response = curl_exec( $curl );
179
  curl_close( $curl );
180
  }
181
- return ( '' != $response ? json_decode( $response ) : false );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
182
  }
183
  }
184
 
2
  /**
3
  * Booster for WooCommerce - Functions - Exchange Rates
4
  *
5
+ * @version 3.5.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
61
  /**
62
  * wcj_get_currency_exchange_rate_servers.
63
  *
64
+ * @version 3.5.0
65
  * @since 2.6.0
66
  */
67
  function wcj_get_currency_exchange_rate_servers() {
68
  return array(
69
  'yahoo' => __( 'Yahoo', 'woocommerce-jetpack' ),
70
+ 'ecb' => __( 'European Central Bank (ECB)', 'woocommerce-jetpack' ) . ' [' . __( 'recommended', 'woocommerce-jetpack' ) . ']',
71
  'tcmb' => __( 'TCMB', 'woocommerce-jetpack' ),
72
  'fixer' => __( 'Fixer.io', 'woocommerce-jetpack' ),
73
  'coinbase' => __( 'Coinbase', 'woocommerce-jetpack' ),
74
  'coinmarketcap' => __( 'CoinMarketCap', 'woocommerce-jetpack' ),
75
+ 'google' => __( 'Google', 'woocommerce-jetpack' ),
76
+ 'boe' => __( 'Bank of England (BOE)', 'woocommerce-jetpack' ),
77
  );
78
  }
79
  }
127
  /*
128
  * wcj_get_exchange_rate.
129
  *
130
+ * @version 3.5.0
131
  * @since 2.6.0
132
  */
133
  function wcj_get_exchange_rate( $currency_from, $currency_to ) {
141
  case 'tcmb':
142
  $return = wcj_tcmb_get_exchange_rate( $currency_from, $currency_to );
143
  break;
144
+ case 'yahoo':
145
+ $return = wcj_yahoo_get_exchange_rate( $currency_from, $currency_to );
146
  break;
147
  case 'fixer':
148
  $return = wcj_fixer_io_get_exchange_rate( $currency_from, $currency_to );
153
  case 'coinmarketcap':
154
  $return = wcj_coinmarketcap_get_exchange_rate( $currency_from, $currency_to );
155
  break;
156
+ case 'google':
157
+ $return = wcj_google_get_exchange_rate( $currency_from, $currency_to );
158
+ break;
159
+ case 'boe':
160
+ $return = wcj_boe_get_exchange_rate( $currency_from, $currency_to );
161
+ break;
162
+ default: // 'ecb'
163
+ $return = wcj_ecb_get_exchange_rate( $currency_from, $currency_to );
164
  break;
165
  }
166
  return ( 'yes' === $calculate_by_invert ) ? round( ( 1 / $return ), 6 ) : $return;
171
  /*
172
  * wcj_get_currency_exchange_rates_url_response.
173
  *
174
+ * @version 3.5.0
175
  * @since 3.2.4
176
  * @todo use where needed
177
  */
178
+ function wcj_get_currency_exchange_rates_url_response( $url, $do_json_decode = true ) {
179
  $response = '';
180
  if ( 'no' === get_option( 'wcj_currency_exchange_rates_always_curl', 'no' ) && ini_get( 'allow_url_fopen' ) ) {
181
  $response = file_get_contents( $url );
186
  $response = curl_exec( $curl );
187
  curl_close( $curl );
188
  }
189
+ return ( '' != $response ? ( $do_json_decode ? json_decode( $response ) : $response ) : false );
190
+ }
191
+ }
192
+
193
+ if ( ! function_exists( 'wcj_boe_get_exchange_rate_gbp' ) ) {
194
+ /*
195
+ * wcj_boe_get_exchange_rate_gbp.
196
+ *
197
+ * @version 3.5.0
198
+ * @since 3.5.0
199
+ */
200
+ function wcj_boe_get_exchange_rate_gbp( $currency_to ) {
201
+ if ( 'GBP' == $currency_to ) {
202
+ return 1;
203
+ }
204
+ $final_rate = false;
205
+ $currency_codes = array(
206
+ 'AUD' => 'EC3', // Australian Dollar
207
+ 'CAD' => 'ECL', // Canadian Dollar
208
+ 'CNY' => 'INB', // Chinese Yuan
209
+ 'CZK' => 'DS7', // Czech Koruna
210
+ 'DKK' => 'ECH', // Danish Krone
211
+ 'EUR' => 'C8J', // Euro
212
+ 'HKD' => 'ECN', // Hong Kong Dollar
213
+ 'HUF' => '5LA', // Hungarian Forint
214
+ 'INR' => 'INE', // Indian Rupee
215
+ 'ILS' => 'IN7', // Israeli Shekel
216
+ 'JPY' => 'C8N', // Japanese Yen
217
+ 'MYR' => 'IN8', // Malaysian ringgit
218
+ 'NZD' => 'ECO', // New Zealand Dollar
219
+ 'NOK' => 'EC6', // Norwegian Krone
220
+ 'PLN' => '5OW', // Polish Zloty
221
+ 'RUB' => 'IN9', // Russian Ruble
222
+ 'SAR' => 'ECZ', // Saudi Riyal
223
+ 'SGD' => 'ECQ', // Singapore Dollar
224
+ 'ZAR' => 'ECE', // South African Rand
225
+ 'KRW' => 'INC', // South Korean Won
226
+ 'SEK' => 'ECC', // Swedish Krona
227
+ 'CHF' => 'ECU', // Swiss Franc
228
+ 'TWD' => 'ECD', // Taiwan Dollar
229
+ 'THB' => 'INA', // Thai Baht
230
+ 'TRY' => 'IND', // Turkish Lira
231
+ 'USD' => 'C8P', // US Dollar
232
+ );
233
+ if ( isset( $currency_codes[ $currency_to ] ) && function_exists( 'simplexml_load_file' ) ) {
234
+ for ( $i = 1; $i <= 7; $i++ ) {
235
+ $date = time() - $i*24*60*60;
236
+ $date_from_d = date( 'd', $date );
237
+ $date_from_m = date( 'M', $date );
238
+ $date_from_y = date( 'Y', $date );
239
+ $date_to_d = date( 'd', $date );
240
+ $date_to_m = date( 'M', $date );
241
+ $date_to_y = date( 'Y', $date );
242
+ $date_url = '&FD=' . $date_from_d . '&FM=' . $date_from_m . '&FY=' . $date_from_y . '&TD=' . $date_to_d . '&TM=' . $date_to_m . '&TY=' . $date_to_y;
243
+ $url = 'http://www.bankofengland.co.uk/boeapps/iadb/fromshowcolumns.asp?Travel=NIxRSxSUx&FromSeries=1&ToSeries=50&DAT=RNG' . $date_url .
244
+ '&VFD=Y&xml.x=23&xml.y=18&CSVF=TT&C=' . $currency_codes[ $currency_to ] . '&Filter=N';
245
+ $xml = simplexml_load_file( $url );
246
+ $json_string = json_encode( $xml );
247
+ $result_array = json_decode( $json_string, true );
248
+ if ( isset( $result_array['Cube']['Cube'] ) ) {
249
+ $last_element_index = count( $result_array['Cube']['Cube'] ) - 1;
250
+ if ( isset( $result_array['Cube']['Cube'][ $last_element_index ]['@attributes']['OBS_VALUE'] ) ) {
251
+ return $result_array['Cube']['Cube'][ $last_element_index ]['@attributes']['OBS_VALUE'];
252
+ }
253
+ }
254
+ }
255
+ }
256
+ return $final_rate;
257
+ }
258
+ }
259
+
260
+ if ( ! function_exists( 'wcj_boe_get_exchange_rate' ) ) {
261
+ /*
262
+ * wcj_boe_get_exchange_rate.
263
+ *
264
+ * @version 3.5.0
265
+ * @since 3.5.0
266
+ */
267
+ function wcj_boe_get_exchange_rate( $currency_from, $currency_to ) {
268
+ if (
269
+ false != ( $gbp_currency_from = wcj_boe_get_exchange_rate_gbp( $currency_from ) ) &&
270
+ false != ( $gbp_currency_to = wcj_boe_get_exchange_rate_gbp( $currency_to ) )
271
+ ) {
272
+ return round( $gbp_currency_to / $gbp_currency_from, 6 );
273
+ }
274
+ return false;
275
+ }
276
+ }
277
+
278
+ if ( ! function_exists( 'wcj_google_get_exchange_rate' ) ) {
279
+ /*
280
+ * wcj_google_get_exchange_rate.
281
+ *
282
+ * @version 3.5.0
283
+ * @since 3.5.0
284
+ * @see https://gist.github.com/daveismyname/8067095
285
+ */
286
+ function wcj_google_get_exchange_rate( $currency_from, $currency_to ) {
287
+ $amount = 1;
288
+ $url = 'https://finance.google.com/finance/converter?a=' . $amount . '&from=' . $currency_from . '&to=' . $currency_to;
289
+ if ( false != ( $response = wcj_get_currency_exchange_rates_url_response( $url, false ) ) ) {
290
+ preg_match( "/<span class=bld>(.*)<\/span>/", $response, $converted );
291
+ if ( isset( $converted[1] ) ) {
292
+ if ( $converted = preg_replace( "/[^0-9.]/", "", $converted[1] ) ) {
293
+ if ( $return = round( $converted, 6 ) ) {
294
+ return $return;
295
+ }
296
+ }
297
+ }
298
+ }
299
+ return false;
300
  }
301
  }
302
 
includes/functions/wcj-functions-general.php CHANGED
@@ -1,14 +1,68 @@
1
  <?php
2
  /**
3
- * Booster for WooCommerce - Functions
4
  *
5
- * @version 3.4.0
6
  * @author Algoritmika Ltd.
7
  * @todo add `wcj_add_actions()` and `wcj_add_filters()`
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  if ( ! function_exists( 'wcj_handle_replacements' ) ) {
13
  /**
14
  * wcj_handle_replacements.
@@ -151,27 +205,6 @@ if ( ! function_exists( 'wcj_barcode' ) ) {
151
  }
152
  }
153
 
154
- if ( ! function_exists( 'wcj_get_woocommerce_package_rates_module_filter_priority' ) ) {
155
- /**
156
- * wcj_get_woocommerce_package_rates_module_filter_priority.
157
- *
158
- * @version 3.2.4
159
- * @since 3.2.4
160
- * @todo add `shipping_by_order_amount` module
161
- */
162
- function wcj_get_woocommerce_package_rates_module_filter_priority( $module_id ) {
163
- $modules_priorities = array(
164
- 'shipping_options_hide_free_shipping' => PHP_INT_MAX,
165
- 'shipping_by_products' => PHP_INT_MAX - 100,
166
- 'shipping_by_user_role' => PHP_INT_MAX - 100,
167
- );
168
- return ( 0 != ( $priority = get_option( 'wcj_' . $module_id . '_filter_priority', 0 ) ) ?
169
- $priority :
170
- ( isset( $modules_priorities[ $module_id ] ) ? $modules_priorities[ $module_id ] : PHP_INT_MAX )
171
- );
172
- }
173
- }
174
-
175
  if ( ! function_exists( 'wcj_session_maybe_start' ) ) {
176
  /**
177
  * wcj_session_maybe_start.
@@ -328,12 +361,26 @@ if ( ! function_exists( 'wcj_customer_get_country' ) ) {
328
  *
329
  * @version 2.8.0
330
  * @since 2.8.0
 
331
  */
332
  function wcj_customer_get_country() {
333
  return ( WCJ_IS_WC_VERSION_BELOW_3 ? WC()->customer->get_country() : WC()->customer->get_billing_country() );
334
  }
335
  }
336
 
 
 
 
 
 
 
 
 
 
 
 
 
 
337
  if ( ! function_exists( 'wcj_is_bot' ) ) {
338
  /**
339
  * wcj_is_bot.
@@ -490,78 +537,6 @@ if ( ! function_exists( 'wcj_maybe_unserialize_and_implode' ) ) {
490
  }
491
  }
492
 
493
- if ( ! function_exists( 'wcj_get_left_to_free_shipping' ) ) {
494
- /*
495
- * wcj_get_left_to_free_shipping.
496
- *
497
- * @version 3.4.0
498
- * @since 2.4.4
499
- * @return string
500
- */
501
- function wcj_get_left_to_free_shipping( $content, $multiply_by = 1 ) {
502
- if ( function_exists( 'WC' ) && ( WC()->shipping ) && ( $packages = WC()->shipping->get_packages() ) ) {
503
- foreach ( $packages as $i => $package ) {
504
- $available_shipping_methods = $package['rates'];
505
- foreach ( $available_shipping_methods as $available_shipping_method ) {
506
- $method_id = ( WCJ_IS_WC_VERSION_BELOW_3_2_0 ? $available_shipping_method->method_id : $available_shipping_method->get_method_id() );
507
- if ( 'free_shipping' === $method_id ) {
508
- return do_shortcode( get_option( 'wcj_shipping_left_to_free_info_content_reached', __( 'You have Free delivery', 'woocommerce-jetpack' ) ) );
509
- }
510
- }
511
- }
512
- }
513
- if ( '' == $content ) {
514
- $content = __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' );
515
- }
516
- $min_free_shipping_amount = 0;
517
- if ( version_compare( WCJ_WC_VERSION, '2.6.0', '<' ) ) {
518
- $free_shipping = new WC_Shipping_Free_Shipping();
519
- if ( in_array( $free_shipping->requires, array( 'min_amount', 'either', 'both' ) ) ) {
520
- $min_free_shipping_amount = $free_shipping->min_amount;
521
- }
522
- } else {
523
- $legacy_free_shipping = new WC_Shipping_Legacy_Free_Shipping();
524
- if ( 'yes' === $legacy_free_shipping->enabled ) {
525
- if ( in_array( $legacy_free_shipping->requires, array( 'min_amount', 'either', 'both' ) ) ) {
526
- $min_free_shipping_amount = $legacy_free_shipping->min_amount;
527
- }
528
- }
529
- if ( 0 == $min_free_shipping_amount ) {
530
- if ( function_exists( 'WC' ) && ( $wc_shipping = WC()->shipping ) && ( $wc_cart = WC()->cart ) ) {
531
- if ( $wc_shipping->enabled ) {
532
- if ( $packages = $wc_cart->get_shipping_packages() ) {
533
- $shipping_methods = $wc_shipping->load_shipping_methods( $packages[0] );
534
- foreach ( $shipping_methods as $shipping_method ) {
535
- if ( 'yes' === $shipping_method->enabled && 0 != $shipping_method->instance_id ) {
536
- if ( 'WC_Shipping_Free_Shipping' === get_class( $shipping_method ) ) {
537
- if ( in_array( $shipping_method->requires, array( 'min_amount', 'either', 'both' ) ) ) {
538
- $min_free_shipping_amount = $shipping_method->min_amount;
539
- break;
540
- }
541
- }
542
- }
543
- }
544
- }
545
- }
546
- }
547
- }
548
- }
549
- if ( 0 != $min_free_shipping_amount ) {
550
- if ( isset( WC()->cart->cart_contents_total ) ) {
551
- $cart_taxes = ( WCJ_IS_WC_VERSION_BELOW_3_2_0 ? WC()->cart->taxes : WC()->cart->get_cart_contents_taxes() );
552
- $total = ( WC()->cart->prices_include_tax ) ? WC()->cart->cart_contents_total + array_sum( $cart_taxes ) : WC()->cart->cart_contents_total;
553
- if ( $total >= $min_free_shipping_amount ) {
554
- return do_shortcode( get_option( 'wcj_shipping_left_to_free_info_content_reached', __( 'You have Free delivery', 'woocommerce-jetpack' ) ) );
555
- } else {
556
- $content = str_replace( '%left_to_free%', wc_price( ( $min_free_shipping_amount - $total ) * $multiply_by ), $content );
557
- $content = str_replace( '%free_shipping_min_amount%', wc_price( ( $min_free_shipping_amount ) * $multiply_by ), $content );
558
- return $content;
559
- }
560
- }
561
- }
562
- }
563
- }
564
-
565
  if ( ! function_exists( 'wcj_get_cart_filters' ) ) {
566
  /*
567
  * wcj_get_cart_filters()
1
  <?php
2
  /**
3
+ * Booster for WooCommerce - Functions - General
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  * @todo add `wcj_add_actions()` and `wcj_add_filters()`
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
+ if ( ! function_exists( 'wcj_send_file' ) ) {
13
+ /**
14
+ * wcj_send_file.
15
+ *
16
+ * @version 3.5.0
17
+ * @since 3.5.0
18
+ * @todo use where needed
19
+ * @todo add more cases for `$file_type`
20
+ */
21
+ function wcj_send_file( $file_name, $file_path, $file_type, $do_cleanup = true ) {
22
+ switch ( $file_type ) {
23
+ default: // 'zip'
24
+ header( "Content-Type: application/octet-stream" );
25
+ header( "Content-Disposition: attachment; filename=" . urlencode( $file_name ) );
26
+ header( "Content-Type: application/octet-stream" );
27
+ header( "Content-Type: application/download" );
28
+ header( "Content-Description: File Transfer" );
29
+ header( "Content-Length: " . filesize( $file_path ) );
30
+ break;
31
+ }
32
+ flush(); // this doesn't really matter.
33
+ if ( false !== ( $fp = fopen( $file_path, "r" ) ) ) {
34
+ while ( ! feof( $fp ) ) {
35
+ echo fread( $fp, 65536 );
36
+ flush(); // this is essential for large downloads
37
+ }
38
+ fclose( $fp );
39
+ if ( $do_cleanup ) {
40
+ @unlink( $file_path );
41
+ }
42
+ exit();
43
+ } else {
44
+ die( __( 'Unexpected error', 'woocommerce-jetpack' ) );
45
+ }
46
+ }
47
+ }
48
+
49
+ if ( ! function_exists( 'wcj_parse_number' ) ) {
50
+ /**
51
+ * wcj_parse_number.
52
+ *
53
+ * @version 3.5.0
54
+ * @since 3.5.0
55
+ * @todo maybe there is a better way (e.g. `numfmt_parse()`)
56
+ */
57
+ function wcj_parse_number( $number_string ) {
58
+ if ( false !== strpos( $number_string, '.' ) ) {
59
+ return str_replace( ',', '', $number_string );
60
+ } else {
61
+ return str_replace( ',', '.', $number_string );
62
+ }
63
+ }
64
+ }
65
+
66
  if ( ! function_exists( 'wcj_handle_replacements' ) ) {
67
  /**
68
  * wcj_handle_replacements.
205
  }
206
  }
207
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
208
  if ( ! function_exists( 'wcj_session_maybe_start' ) ) {
209
  /**
210
  * wcj_session_maybe_start.
361
  *
362
  * @version 2.8.0
363
  * @since 2.8.0
364
+ * @todo (maybe) move to `wcj-functions-users.php`
365
  */
366
  function wcj_customer_get_country() {
367
  return ( WCJ_IS_WC_VERSION_BELOW_3 ? WC()->customer->get_country() : WC()->customer->get_billing_country() );
368
  }
369
  }
370
 
371
+ if ( ! function_exists( 'wcj_customer_get_country_state' ) ) {
372
+ /**
373
+ * wcj_customer_get_country_state.
374
+ *
375
+ * @version 3.5.0
376
+ * @since 3.5.0
377
+ * @todo (maybe) move to `wcj-functions-users.php`
378
+ */
379
+ function wcj_customer_get_country_state() {
380
+ return ( WCJ_IS_WC_VERSION_BELOW_3 ? WC()->customer->get_state() : WC()->customer->get_billing_state() );
381
+ }
382
+ }
383
+
384
  if ( ! function_exists( 'wcj_is_bot' ) ) {
385
  /**
386
  * wcj_is_bot.
537
  }
538
  }
539
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
540
  if ( ! function_exists( 'wcj_get_cart_filters' ) ) {
541
  /*
542
  * wcj_get_cart_filters()
includes/functions/wcj-functions-invoicing.php CHANGED
@@ -2,10 +2,22 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Invoicing
4
  *
5
- * @version 3.4.3
6
  * @author Algoritmika Ltd.
7
  */
8
 
 
 
 
 
 
 
 
 
 
 
 
 
9
  if ( ! function_exists( 'wcj_get_invoicing_current_image_path_desc' ) ) {
10
  /**
11
  * wcj_get_invoicing_current_image_path_desc.
2
  /**
3
  * Booster for WooCommerce - Functions - Invoicing
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
9
+ if ( ! function_exists( 'wcj_get_invoicing_temp_dir' ) ) {
10
+ /**
11
+ * wcj_get_invoicing_temp_dir.
12
+ *
13
+ * @version 3.5.0
14
+ * @since 3.5.0
15
+ */
16
+ function wcj_get_invoicing_temp_dir() {
17
+ return ( '' === ( $tmp_dir = get_option( 'wcj_invoicing_general_tmp_dir', '' ) ) ? sys_get_temp_dir() : $tmp_dir );
18
+ }
19
+ }
20
+
21
  if ( ! function_exists( 'wcj_get_invoicing_current_image_path_desc' ) ) {
22
  /**
23
  * wcj_get_invoicing_current_image_path_desc.
includes/functions/wcj-functions-price-currency.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Price and Currency
4
  *
5
- * @version 3.4.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -141,19 +141,17 @@ if ( ! function_exists( 'wcj_get_currency_exchange_rate_product_base_currency' )
141
  /**
142
  * wcj_get_currency_exchange_rate_product_base_currency.
143
  *
144
- * @version 2.5.6
145
  * @since 2.5.6
146
  */
147
  function wcj_get_currency_exchange_rate_product_base_currency( $currency_code ) {
148
- $currency_exchange_rate = 1;
149
  $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_multicurrency_base_price_total_number', 1 ) );
150
  for ( $i = 1; $i <= $total_number; $i++ ) {
151
  if ( $currency_code === get_option( 'wcj_multicurrency_base_price_currency_' . $i ) ) {
152
- $currency_exchange_rate = get_option( 'wcj_multicurrency_base_price_exchange_rate_' . $i );
153
- break;
154
  }
155
  }
156
- return $currency_exchange_rate;
157
  }
158
  }
159
 
2
  /**
3
  * Booster for WooCommerce - Functions - Price and Currency
4
  *
5
+ * @version 3.5.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
141
  /**
142
  * wcj_get_currency_exchange_rate_product_base_currency.
143
  *
144
+ * @version 3.5.0
145
  * @since 2.5.6
146
  */
147
  function wcj_get_currency_exchange_rate_product_base_currency( $currency_code ) {
 
148
  $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_multicurrency_base_price_total_number', 1 ) );
149
  for ( $i = 1; $i <= $total_number; $i++ ) {
150
  if ( $currency_code === get_option( 'wcj_multicurrency_base_price_currency_' . $i ) ) {
151
+ return get_option( 'wcj_multicurrency_base_price_exchange_rate_' . $i );
 
152
  }
153
  }
154
+ return 1; // fallback
155
  }
156
  }
157
 
includes/functions/wcj-functions-products.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Products
4
  *
5
- * @version 3.4.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -294,7 +294,7 @@ if ( ! function_exists( 'wcj_get_products' ) ) {
294
  /**
295
  * wcj_get_products.
296
  *
297
- * @version 2.8.0
298
  */
299
  function wcj_get_products( $products = array(), $post_status = 'any', $block_size = 256, $add_variations = false ) {
300
  $offset = 0;
@@ -313,12 +313,12 @@ if ( ! function_exists( 'wcj_get_products' ) ) {
313
  break;
314
  }
315
  foreach ( $loop->posts as $post_id ) {
316
- $products[ $post_id ] = get_the_title( $post_id );
317
  if ( $add_variations ) {
318
  $_product = wc_get_product( $post_id );
319
  if ( $_product->is_type( 'variable' ) ) {
320
  foreach ( $_product->get_children() as $child_id ) {
321
- $products[ $child_id ] = get_the_title( $child_id );
322
  }
323
  }
324
  }
@@ -333,8 +333,8 @@ if ( ! function_exists( 'wcj_product_has_terms' ) ) {
333
  /**
334
  * wcj_product_has_terms.
335
  *
336
- * @version 2.8.2
337
- * @version 2.8.2
338
  */
339
  function wcj_product_has_terms( $_product, $_values, $_term ) {
340
  if ( is_string( $_values ) ) {
@@ -343,7 +343,8 @@ if ( ! function_exists( 'wcj_product_has_terms' ) ) {
343
  if ( empty( $_values ) ) {
344
  return false;
345
  }
346
- $product_categories = get_the_terms( wcj_get_product_id_or_variation_parent_id( $_product ), $_term );
 
347
  if ( empty( $product_categories ) ) {
348
  return false;
349
  }
2
  /**
3
  * Booster for WooCommerce - Functions - Products
4
  *
5
+ * @version 3.5.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
294
  /**
295
  * wcj_get_products.
296
  *
297
+ * @version 3.5.0
298
  */
299
  function wcj_get_products( $products = array(), $post_status = 'any', $block_size = 256, $add_variations = false ) {
300
  $offset = 0;
313
  break;
314
  }
315
  foreach ( $loop->posts as $post_id ) {
316
+ $products[ $post_id ] = get_the_title( $post_id ) . ' (ID:' . $post_id . ')';
317
  if ( $add_variations ) {
318
  $_product = wc_get_product( $post_id );
319
  if ( $_product->is_type( 'variable' ) ) {
320
  foreach ( $_product->get_children() as $child_id ) {
321
+ $products[ $child_id ] = get_the_title( $child_id ) . ' (ID:' . $child_id . ')';
322
  }
323
  }
324
  }
333
  /**
334
  * wcj_product_has_terms.
335
  *
336
+ * @version 3.5.0
337
+ * @since 2.8.2
338
  */
339
  function wcj_product_has_terms( $_product, $_values, $_term ) {
340
  if ( is_string( $_values ) ) {
343
  if ( empty( $_values ) ) {
344
  return false;
345
  }
346
+ $product_id = ( is_numeric( $_product ) && $_product > 0 ? $_product : wcj_get_product_id_or_variation_parent_id( $_product ) );
347
+ $product_categories = get_the_terms( $product_id, $_term );
348
  if ( empty( $product_categories ) ) {
349
  return false;
350
  }
includes/functions/wcj-functions-reports.php CHANGED
@@ -74,6 +74,7 @@ if ( ! function_exists( 'wcj_get_reports_custom_ranges' ) ) {
74
  *
75
  * @version 3.2.4
76
  * @since 2.9.0
 
77
  */
78
  function wcj_get_reports_custom_ranges() {
79
  $current_time = (int) current_time( 'timestamp' );
74
  *
75
  * @version 3.2.4
76
  * @since 2.9.0
77
+ * @todo fix `-1 month` - sometimes it produces the wrong result (e.g. on current date = "2018.03.30")
78
  */
79
  function wcj_get_reports_custom_ranges() {
80
  $current_time = (int) current_time( 'timestamp' );
includes/functions/wcj-functions-shipping.php ADDED
@@ -0,0 +1,278 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Functions - Shipping
4
+ *
5
+ * @version 3.5.0
6
+ * @since 3.5.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit;
11
+
12
+ if ( ! function_exists( 'wcj_get_shipping_time_table' ) ) {
13
+ /**
14
+ * wcj_get_shipping_time_table.
15
+ *
16
+ * @version 3.5.0
17
+ * @since 3.5.0
18
+ * @todo customizable `$method_title` format
19
+ * @todo predefined `$matching_zone_id` (i.e. `$atts['shipping_zone_id']`)
20
+ * @todo all zones (i.e. no `$matching_zone_id`)
21
+ * @todo customizable final message
22
+ * @todo check for "Shipping Time" module to be enabled
23
+ * @todo time in hours (i.e. not days)
24
+ * @todo check for `WC()` etc. to exist
25
+ */
26
+ function wcj_get_shipping_time_table( $do_use_shipping_instances, $option_id_shipping_class ) {
27
+ $shipping_methods = ( $do_use_shipping_instances ? wcj_get_shipping_methods_instances( true ) : WC()->shipping()->load_shipping_methods() );
28
+ $matching_zone_id = wcj_get_customer_shipping_matching_zone_id();
29
+ $table_data = array();
30
+ foreach ( $shipping_methods as $method ) {
31
+ if ( $do_use_shipping_instances && $method['zone_id'] != $matching_zone_id ) {
32
+ continue;
33
+ }
34
+ $option_id_shipping_method = ( $do_use_shipping_instances ? 'instance_' . $method['shipping_method_instance_id'] : $method->id );
35
+ $option_id = 'wcj_shipping_time_' . $option_id_shipping_method . $option_id_shipping_class;
36
+ if ( '' !== ( $time = get_option( $option_id, '' ) ) ) {
37
+ $method_title = ( $do_use_shipping_instances ? $method['zone_name'] . ': ' . $method['shipping_method_title']: $method->get_method_title() );
38
+ $table_data[] = array( $method_title, sprintf( __( '%s day(s)' ), $time ) );
39
+ }
40
+ }
41
+ return ( empty( $table_data ) ? '' : wcj_get_table_html( $table_data, array( 'table_heading_type' => 'vertical' ) ) );
42
+ }
43
+ }
44
+
45
+ if ( ! function_exists( 'wcj_get_customer_shipping_matching_zone_id' ) ) {
46
+ /**
47
+ * wcj_get_customer_shipping_matching_zone_id.
48
+ *
49
+ * @version 3.5.0
50
+ * @since 3.5.0
51
+ * @todo (maybe) move to `wcj-functions-users.php`
52
+ * @todo (maybe) add `wcj_get_customer_shipping_destination()` function
53
+ */
54
+ function wcj_get_customer_shipping_matching_zone_id() {
55
+ $package = false;
56
+ if ( is_user_logged_in() ) {
57
+ $current_user = wp_get_current_user();
58
+ if ( '' != ( $meta = get_user_meta( $current_user->ID, 'shipping_country', true ) ) ) {
59
+ $package['destination']['country'] = $meta;
60
+ $package['destination']['state'] = get_user_meta( $current_user->ID, 'shipping_state', true );
61
+ $package['destination']['postcode'] = '';
62
+ }
63
+ }
64
+ if ( false === $package ) {
65
+ $package['destination'] = wc_get_customer_default_location();
66
+ $package['destination']['postcode'] = '';
67
+ }
68
+ $data_store = WC_Data_Store::load( 'shipping-zone' );
69
+ return $data_store->get_zone_id_from_package( $package );
70
+ }
71
+ }
72
+
73
+ if ( ! function_exists( 'wcj_get_product_shipping_class_term_id' ) ) {
74
+ /**
75
+ * wcj_get_product_shipping_class_term_id.
76
+ *
77
+ * @version 3.5.0
78
+ * @since 3.5.0
79
+ * @todo (maybe) move to `wcj-functions-products.php`
80
+ */
81
+ function wcj_get_product_shipping_class_term_id( $_product ) {
82
+ $product_shipping_class = $_product->get_shipping_class();
83
+ if ( '' != $product_shipping_class ) {
84
+ foreach ( WC()->shipping->get_shipping_classes() as $shipping_class ) {
85
+ if ( $product_shipping_class === $shipping_class->slug ) {
86
+ return $shipping_class->term_id;
87
+ }
88
+ }
89
+ }
90
+ return 0;
91
+ }
92
+ }
93
+
94
+ if ( ! function_exists( 'wcj_get_shipping_classes' ) ) {
95
+ /**
96
+ * wcj_get_shipping_classes.
97
+ *
98
+ * @version 3.5.0
99
+ * @since 3.5.0
100
+ */
101
+ function wcj_get_shipping_classes( $include_empty_shipping_class = true ) {
102
+ $shipping_classes = WC()->shipping->get_shipping_classes();
103
+ $shipping_classes_data = array();
104
+ foreach ( $shipping_classes as $shipping_class ) {
105
+ $shipping_classes_data[ $shipping_class->term_id ] = $shipping_class->name;
106
+ }
107
+ if ( $include_empty_shipping_class ) {
108
+ $shipping_classes_data[0] = __( 'No shipping class', 'woocommerce' );
109
+ }
110
+ return $shipping_classes_data;
111
+ }
112
+ }
113
+
114
+ if ( ! function_exists( 'wcj_get_shipping_methods' ) ) {
115
+ /**
116
+ * wcj_get_shipping_methods.
117
+ *
118
+ * @version 3.5.0
119
+ * @since 3.5.0
120
+ */
121
+ function wcj_get_shipping_methods() {
122
+ $shipping_methods = array();
123
+ foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
124
+ $shipping_methods[ $method->id ] = $method->get_method_title();
125
+ }
126
+ return $shipping_methods;
127
+ }
128
+ }
129
+
130
+ if ( ! function_exists( 'wcj_get_shipping_zones' ) ) {
131
+ /**
132
+ * wcj_get_shipping_zones.
133
+ *
134
+ * @version 3.5.0
135
+ * @since 3.5.0
136
+ */
137
+ function wcj_get_shipping_zones( $include_empty_zone = true ) {
138
+ $zones = WC_Shipping_Zones::get_zones();
139
+ if ( $include_empty_zone ) {
140
+ $zone = new WC_Shipping_Zone( 0 );
141
+ $zones[ $zone->get_id() ] = $zone->get_data();
142
+ $zones[ $zone->get_id() ]['zone_id'] = $zone->get_id();
143
+ $zones[ $zone->get_id() ]['formatted_zone_location'] = $zone->get_formatted_location();
144
+ $zones[ $zone->get_id() ]['shipping_methods'] = $zone->get_shipping_methods();
145
+ }
146
+ return $zones;
147
+ }
148
+ }
149
+
150
+ if ( ! function_exists( 'wcj_get_shipping_methods_instances' ) ) {
151
+ /**
152
+ * wcj_get_shipping_methods_instances.
153
+ *
154
+ * @version 3.5.0
155
+ * @since 3.5.0
156
+ */
157
+ function wcj_get_shipping_methods_instances( $full_data = false ) {
158
+ $shipping_methods = array();
159
+ foreach ( wcj_get_shipping_zones() as $zone_id => $zone_data ) {
160
+ foreach ( $zone_data['shipping_methods'] as $shipping_method ) {
161
+ if ( $full_data ) {
162
+ $shipping_methods[ $shipping_method->instance_id ] = array(
163
+ 'zone_id' => $zone_id,
164
+ 'zone_name' => $zone_data['zone_name'],
165
+ 'formatted_zone_location' => $zone_data['formatted_zone_location'],
166
+ 'shipping_method_title' => $shipping_method->title,
167
+ 'shipping_method_id' => $shipping_method->id,
168
+ 'shipping_method_instance_id' => $shipping_method->instance_id,
169
+ );
170
+ } else {
171
+ $shipping_methods[ $shipping_method->instance_id ] = $zone_data['zone_name'] . ': ' . $shipping_method->title;
172
+ }
173
+ }
174
+ }
175
+ return $shipping_methods;
176
+ }
177
+ }
178
+
179
+ if ( ! function_exists( 'wcj_get_woocommerce_package_rates_module_filter_priority' ) ) {
180
+ /**
181
+ * wcj_get_woocommerce_package_rates_module_filter_priority.
182
+ *
183
+ * @version 3.2.4
184
+ * @since 3.2.4
185
+ * @todo add `shipping_by_order_amount` module
186
+ */
187
+ function wcj_get_woocommerce_package_rates_module_filter_priority( $module_id ) {
188
+ $modules_priorities = array(
189
+ 'shipping_options_hide_free_shipping' => PHP_INT_MAX,
190
+ 'shipping_by_products' => PHP_INT_MAX - 100,
191
+ 'shipping_by_user_role' => PHP_INT_MAX - 100,
192
+ );
193
+ return ( 0 != ( $priority = get_option( 'wcj_' . $module_id . '_filter_priority', 0 ) ) ?
194
+ $priority :
195
+ ( isset( $modules_priorities[ $module_id ] ) ? $modules_priorities[ $module_id ] : PHP_INT_MAX )
196
+ );
197
+ }
198
+ }
199
+
200
+ if ( ! function_exists( 'wcj_get_left_to_free_shipping' ) ) {
201
+ /*
202
+ * wcj_get_left_to_free_shipping.
203
+ *
204
+ * @version 3.5.0
205
+ * @since 2.4.4
206
+ * @return string
207
+ */
208
+ function wcj_get_left_to_free_shipping( $content, $multiply_by = 1 ) {
209
+ // "You have Free delivery"
210
+ if ( function_exists( 'WC' ) && ( WC()->shipping ) && ( $packages = WC()->shipping->get_packages() ) ) {
211
+ foreach ( $packages as $i => $package ) {
212
+ $available_shipping_methods = $package['rates'];
213
+ foreach ( $available_shipping_methods as $available_shipping_method ) {
214
+ $method_id = ( WCJ_IS_WC_VERSION_BELOW_3_2_0 ? $available_shipping_method->method_id : $available_shipping_method->get_method_id() );
215
+ if ( 'free_shipping' === $method_id ) {
216
+ return do_shortcode( get_option( 'wcj_shipping_left_to_free_info_content_reached', __( 'You have Free delivery', 'woocommerce-jetpack' ) ) );
217
+ }
218
+ }
219
+ }
220
+ }
221
+ // Getting `$min_free_shipping_amount`
222
+ $min_free_shipping_amount = 0;
223
+ if ( version_compare( WCJ_WC_VERSION, '2.6.0', '<' ) ) {
224
+ $free_shipping = new WC_Shipping_Free_Shipping();
225
+ if ( in_array( $free_shipping->requires, array( 'min_amount', 'either', 'both' ) ) ) {
226
+ $min_free_shipping_amount = $free_shipping->min_amount;
227
+ }
228
+ } else {
229
+ $legacy_free_shipping = new WC_Shipping_Legacy_Free_Shipping();
230
+ if ( 'yes' === $legacy_free_shipping->enabled ) {
231
+ if ( in_array( $legacy_free_shipping->requires, array( 'min_amount', 'either', 'both' ) ) ) {
232
+ $min_free_shipping_amount = $legacy_free_shipping->min_amount;
233
+ }
234
+ }
235
+ if ( 0 == $min_free_shipping_amount ) {
236
+ if ( function_exists( 'WC' ) && ( $wc_shipping = WC()->shipping ) && ( $wc_cart = WC()->cart ) ) {
237
+ if ( $wc_shipping->enabled ) {
238
+ if ( $packages = $wc_cart->get_shipping_packages() ) {
239
+ $shipping_methods = $wc_shipping->load_shipping_methods( $packages[0] );
240
+ foreach ( $shipping_methods as $shipping_method ) {
241
+ if ( 'yes' === $shipping_method->enabled && 0 != $shipping_method->instance_id ) {
242
+ if ( 'WC_Shipping_Free_Shipping' === get_class( $shipping_method ) ) {
243
+ if ( in_array( $shipping_method->requires, array( 'min_amount', 'either', 'both' ) ) ) {
244
+ $min_free_shipping_amount = $shipping_method->min_amount;
245
+ break;
246
+ }
247
+ }
248
+ }
249
+ }
250
+ }
251
+ }
252
+ }
253
+ }
254
+ }
255
+ // Outputting "left to free shipping"
256
+ if ( 0 != $min_free_shipping_amount ) {
257
+ if ( isset( WC()->cart ) ) {
258
+ // Getting cart total
259
+ $total = WC()->cart->get_displayed_subtotal();
260
+ if ( WC()->cart->display_prices_including_tax() ) {
261
+ $total = round( $total - ( WC()->cart->get_discount_total() + WC()->cart->get_discount_tax() ), wc_get_price_decimals() );
262
+ } else {
263
+ $total = round( $total - WC()->cart->get_discount_total(), wc_get_price_decimals() );
264
+ }
265
+ // Final message
266
+ if ( $total >= $min_free_shipping_amount ) {
267
+ return do_shortcode( get_option( 'wcj_shipping_left_to_free_info_content_reached', __( 'You have Free delivery', 'woocommerce-jetpack' ) ) );
268
+ } else {
269
+ return wcj_handle_replacements( array(
270
+ '%left_to_free%' => wc_price( ( $min_free_shipping_amount - $total ) * $multiply_by ),
271
+ '%free_shipping_min_amount%' => wc_price( ( $min_free_shipping_amount ) * $multiply_by ),
272
+ '%cart_total%' => wc_price( ( $total ) * $multiply_by ),
273
+ ), ( '' == $content ? __( '%left_to_free% left to free shipping', 'woocommerce-jetpack' ) : $content ) );
274
+ }
275
+ }
276
+ }
277
+ }
278
+ }
includes/functions/wcj-functions-users.php CHANGED
@@ -2,13 +2,28 @@
2
  /**
3
  * Booster for WooCommerce - Functions - Users
4
  *
5
- * @version 3.4.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
12
  if ( ! function_exists( 'wcj_get_users_as_options' ) ) {
13
  /**
14
  * wcj_get_users_as_options.
2
  /**
3
  * Booster for WooCommerce - Functions - Users
4
  *
5
+ * @version 3.5.0
6
  * @since 2.7.0
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit;
11
 
12
+ if ( ! function_exists( 'wcj_get_current_user_id' ) ) {
13
+ /**
14
+ * wcj_get_current_user_id.
15
+ *
16
+ * @version 3.5.0
17
+ * @since 3.5.0
18
+ */
19
+ function wcj_get_current_user_id() {
20
+ if ( ! function_exists( 'get_current_user_id' ) ) {
21
+ require_once( ABSPATH . 'wp-includes/pluggable.php' );
22
+ }
23
+ return get_current_user_id();
24
+ }
25
+ }
26
+
27
  if ( ! function_exists( 'wcj_get_users_as_options' ) ) {
28
  /**
29
  * wcj_get_users_as_options.
includes/input-fields/class-wcj-product-input-fields-core.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Product Input Fields - Core
4
  *
5
- * @version 3.4.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -19,7 +19,7 @@ class WCJ_Product_Input_Fields_Core {
19
  * Constructor.
20
  *
21
  * @version 3.4.0
22
- * @todo save all info in product meta
23
  */
24
  function __construct( $scope ) {
25
  $this->scope = $scope;
@@ -70,33 +70,32 @@ class WCJ_Product_Input_Fields_Core {
70
  /**
71
  * Save product input fields on Product Edit.
72
  *
73
- * @version 2.2.9
74
  */
75
  function save_local_product_input_fields_on_product_edit( $post_id, $post ) {
76
-
77
  // Check that we are saving with input fields displayed.
78
- if ( ! isset( $_POST['woojetpack_product_input_fields_save_post'] ) )
79
  return;
80
-
81
- // Save enabled, required, title etc.
82
- $default_total_input_fields = apply_filters( 'booster_option', 1, get_option( 'wcj_product_input_fields_local_total_number_default', 1 ) );
83
- $total_input_fields_before_saving = get_post_meta( $post_id, '_' . 'wcj_product_input_fields_local_total_number', true );
84
  $total_input_fields_before_saving = ( '' != $total_input_fields_before_saving ) ? $total_input_fields_before_saving : $default_total_input_fields;
85
- $options = $this->get_options();
 
 
 
86
  for ( $i = 1; $i <= $total_input_fields_before_saving; $i++ ) {
87
  foreach ( $options as $option ) {
 
88
  if ( isset( $_POST[ $option['id'] . $i ] ) ) {
89
- update_post_meta( $post_id, '_' . $option['id'] . $i, $_POST[ $option['id'] . $i ] );
90
  } elseif ( 'checkbox' === $option['type'] ) {
91
- update_post_meta( $post_id, '_' . $option['id'] . $i, 'off' );
92
  }
93
  }
94
  }
95
-
96
- // Save total product input fields number
97
- $option_name = 'wcj_product_input_fields_local_total_number';
98
- $total_input_fields = isset( $_POST[ $option_name ] ) ? $_POST[ $option_name ] : $default_total_input_fields;
99
- update_post_meta( $post_id, '_' . $option_name, $_POST[ $option_name ] );
100
  }
101
 
102
  /**
@@ -118,8 +117,8 @@ class WCJ_Product_Input_Fields_Core {
118
  /**
119
  * create_local_product_input_fields_meta_box.
120
  *
121
- * @version 3.1.0
122
- * @todo output options via standard "meta-box" mechanism
123
  */
124
  function create_local_product_input_fields_meta_box() {
125
 
@@ -130,10 +129,12 @@ class WCJ_Product_Input_Fields_Core {
130
 
131
  // Get total number
132
  $current_post_id = get_the_ID();
 
133
  $option_name = 'wcj_' . $meta_box_id . '_local_total_number';
134
  // If none total number set - check for the default
135
- if ( ! ( $total_number = apply_filters( 'booster_option', 1, get_post_meta( $current_post_id, '_' . $option_name, true ) ) ) )
136
  $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_' . $meta_box_id . '_local_total_number_default', 1 ) );
 
137
 
138
  // Start html
139
  $html = '';
@@ -162,12 +163,8 @@ class WCJ_Product_Input_Fields_Core {
162
  $html .= '<hr>';
163
  $html .= '<h3>' . __( 'Product Input Field', 'woocommerce-jetpack' ) . ' #' . $i . '</h3>';
164
  foreach ( $options as $option ) {
165
- $option_id = $option['id'] . $i;
166
- $option_value = get_post_meta( $current_post_id, '_' . $option_id, true );
167
-
168
- if ( ! metadata_exists( 'post', $current_post_id, '_' . $option_id ) ) {
169
- $option_value = $option['default'];
170
- }
171
 
172
  if ( 'checkbox' === $option['type'] )
173
  $is_checked = checked( $option_value, 'on', false );
@@ -286,7 +283,7 @@ class WCJ_Product_Input_Fields_Core {
286
  /**
287
  * hide_custom_input_fields_default_output_in_admin_order.
288
  *
289
- * @todo Get actual (max) number of fields in case of local scope.
290
  */
291
  function hide_custom_input_fields_default_output_in_admin_order( $hidden_metas ) {
292
  $total_number = 0;
@@ -345,10 +342,19 @@ class WCJ_Product_Input_Fields_Core {
345
  /**
346
  * get_value.
347
  *
348
- * @version 3.1.0
349
  */
350
  function get_value( $option_name, $product_id, $default ) {
351
- return ( 'global' === $this->scope ? get_option( $option_name, $default ) : get_post_meta( $product_id, '_' . $option_name, true ) );
 
 
 
 
 
 
 
 
 
352
  }
353
 
354
  /**
@@ -412,10 +418,44 @@ class WCJ_Product_Input_Fields_Core {
412
  return $passed;
413
  }
414
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
415
  /**
416
  * add_product_input_fields_to_frontend.
417
  *
418
- * @version 3.4.0
419
  * @todo `$set_value` - add "default" option for all other types except checkbox
420
  * @todo `$set_value` - 'file' type
421
  * @todo add `required` attributes
@@ -426,6 +466,7 @@ class WCJ_Product_Input_Fields_Core {
426
  return;
427
  }
428
  $_product_id = wcj_get_product_id_or_variation_parent_id( $product );
 
429
  $fields = array();
430
  $total_number = apply_filters( 'booster_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $_product_id, 1 ) );
431
  for ( $i = 1; $i <= $total_number; $i++ ) {
@@ -771,7 +812,7 @@ class WCJ_Product_Input_Fields_Core {
771
  *
772
  * @version 3.4.0
773
  * @since 3.4.0
774
- * @todo this is only a temporary solution: must replace `$item->legacy_values` (check "Bookings" module)
775
  */
776
  function add_product_input_fields_to_order_item_meta_wc3( $item_id, $item, $order_id ) {
777
  if ( is_a( $item, 'WC_Order_Item_Product' ) ) {
2
  /**
3
  * Booster for WooCommerce - Product Input Fields - Core
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
19
  * Constructor.
20
  *
21
  * @version 3.4.0
22
+ * @todo save all info (e.g. label etc.) in order meta
23
  */
24
  function __construct( $scope ) {
25
  $this->scope = $scope;
70
  /**
71
  * Save product input fields on Product Edit.
72
  *
73
+ * @version 3.5.0
74
  */
75
  function save_local_product_input_fields_on_product_edit( $post_id, $post ) {
 
76
  // Check that we are saving with input fields displayed.
77
+ if ( ! isset( $_POST['woojetpack_product_input_fields_save_post'] ) ) {
78
  return;
79
+ }
80
+ // Save values
81
+ $default_total_input_fields = apply_filters( 'booster_option', 1, get_option( 'wcj_product_input_fields_local_total_number_default', 1 ) );
82
+ $total_input_fields_before_saving = apply_filters( 'booster_option', 1, $this->get_value( 'wcj_product_input_fields_local_total_number', $post_id, 1 ) );
83
  $total_input_fields_before_saving = ( '' != $total_input_fields_before_saving ) ? $total_input_fields_before_saving : $default_total_input_fields;
84
+ $options = $this->get_options();
85
+ $values = array();
86
+ $values['local_total_number'] = isset( $_POST['wcj_product_input_fields_local_total_number'] ) ?
87
+ $_POST['wcj_product_input_fields_local_total_number'] : $default_total_input_fields;
88
  for ( $i = 1; $i <= $total_input_fields_before_saving; $i++ ) {
89
  foreach ( $options as $option ) {
90
+ $option_name = str_replace( 'wcj_product_input_fields_', '', $option['id'] . $i );
91
  if ( isset( $_POST[ $option['id'] . $i ] ) ) {
92
+ $values[ $option_name ] = $_POST[ $option['id'] . $i ];
93
  } elseif ( 'checkbox' === $option['type'] ) {
94
+ $values[ $option_name ] = 'off';
95
  }
96
  }
97
  }
98
+ update_post_meta( $post_id, '_wcj_product_input_fields', $values );
 
 
 
 
99
  }
100
 
101
  /**
117
  /**
118
  * create_local_product_input_fields_meta_box.
119
  *
120
+ * @version 3.5.0
121
+ * @todo output options via standard "meta-box" mechanism (and make "serialized" meta box type)
122
  */
123
  function create_local_product_input_fields_meta_box() {
124
 
129
 
130
  // Get total number
131
  $current_post_id = get_the_ID();
132
+ $this->maybe_update_local_input_fields( $current_post_id );
133
  $option_name = 'wcj_' . $meta_box_id . '_local_total_number';
134
  // If none total number set - check for the default
135
+ if ( ! ( $total_number = apply_filters( 'booster_option', 1, $this->get_value( 'wcj_product_input_fields_local_total_number', $current_post_id, 1 ) ) ) ) {
136
  $total_number = apply_filters( 'booster_option', 1, get_option( 'wcj_' . $meta_box_id . '_local_total_number_default', 1 ) );
137
+ }
138
 
139
  // Start html
140
  $html = '';
163
  $html .= '<hr>';
164
  $html .= '<h3>' . __( 'Product Input Field', 'woocommerce-jetpack' ) . ' #' . $i . '</h3>';
165
  foreach ( $options as $option ) {
166
+ $option_id = $option['id'] . $i;
167
+ $option_value = $this->get_value( $option_id, $current_post_id, $option['default'] );
 
 
 
 
168
 
169
  if ( 'checkbox' === $option['type'] )
170
  $is_checked = checked( $option_value, 'on', false );
283
  /**
284
  * hide_custom_input_fields_default_output_in_admin_order.
285
  *
286
+ * @todo get actual (max) number of fields in case of local scope
287
  */
288
  function hide_custom_input_fields_default_output_in_admin_order( $hidden_metas ) {
289
  $total_number = 0;
342
  /**
343
  * get_value.
344
  *
345
+ * @version 3.5.0
346
  */
347
  function get_value( $option_name, $product_id, $default ) {
348
+ if ( 'global' === $this->scope ) {
349
+ return get_option( $option_name, $default );
350
+ } else { // local
351
+ if ( '' != ( $options = get_post_meta( $product_id, '_' . 'wcj_product_input_fields', true ) ) ) {
352
+ $option_name = str_replace( 'wcj_product_input_fields_', '', $option_name );
353
+ return ( isset( $options[ $option_name ] ) ? $options[ $option_name ] : $default );
354
+ } else { // Booster version < 3.5.0
355
+ return get_post_meta( $product_id, '_' . $option_name, true );
356
+ }
357
+ }
358
  }
359
 
360
  /**
418
  return $passed;
419
  }
420
 
421
+ /**
422
+ * maybe_update_local_input_fields.
423
+ *
424
+ * @version 3.5.0
425
+ * @since 3.5.0
426
+ * @todo (maybe) if `$total_number` is not set - use `$default_total_input_fields` instead
427
+ */
428
+ function maybe_update_local_input_fields( $_product_id ) {
429
+ if ( 'local' != $this->scope ) {
430
+ return;
431
+ }
432
+ if ( '' != get_post_meta( $_product_id, '_' . 'wcj_product_input_fields', true ) ) {
433
+ return;
434
+ }
435
+ $values = array();
436
+ $options = $this->get_options();
437
+ $total_number = apply_filters( 'booster_option', 1, get_post_meta( $_product_id, '_' . 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', true ) );
438
+ $values[ $this->scope . '_total_number' ] = $total_number;
439
+ delete_post_meta( $_product_id, '_' . 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number' );
440
+ for ( $i = 1; $i <= $total_number; $i++ ) {
441
+ foreach ( $options as $option ) {
442
+ $option_id = $option['id'] . $i;
443
+ if ( metadata_exists( 'post', $_product_id, '_' . $option_id ) ) {
444
+ $option_value = get_post_meta( $_product_id, '_' . $option_id, true );
445
+ delete_post_meta( $_product_id, '_' . $option_id );
446
+ } else {
447
+ $option_value = $option['default'];
448
+ }
449
+ $values[ str_replace( 'wcj_product_input_fields_', '', $option_id ) ] = $option_value;
450
+ }
451
+ }
452
+ update_post_meta( $_product_id, '_wcj_product_input_fields', $values );
453
+ }
454
+
455
  /**
456
  * add_product_input_fields_to_frontend.
457
  *
458
+ * @version 3.5.0
459
  * @todo `$set_value` - add "default" option for all other types except checkbox
460
  * @todo `$set_value` - 'file' type
461
  * @todo add `required` attributes
466
  return;
467
  }
468
  $_product_id = wcj_get_product_id_or_variation_parent_id( $product );
469
+ $this->maybe_update_local_input_fields( $_product_id );
470
  $fields = array();
471
  $total_number = apply_filters( 'booster_option', 1, $this->get_value( 'wcj_' . 'product_input_fields' . '_' . $this->scope . '_total_number', $_product_id, 1 ) );
472
  for ( $i = 1; $i <= $total_number; $i++ ) {
812
  *
813
  * @version 3.4.0
814
  * @since 3.4.0
815
+ * @todo this is only a temporary solution: must replace `$item->legacy_values` (check "Bookings" module - `woocommerce_checkout_create_order_line_item` hook)
816
  */
817
  function add_product_input_fields_to_order_item_meta_wc3( $item_id, $item, $order_id ) {
818
  if ( is_a( $item, 'WC_Order_Item_Product' ) ) {
includes/lib/FPDI/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Setasign - Jan Slabon, https://www.setasign.com
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
includes/lib/FPDI/README.md ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FPDI - Free PDF Document Importer
2
+ =================================
3
+
4
+ [![Latest Stable Version](https://poser.pugx.org/setasign/fpdi/v/stable.svg)](https://packagist.org/packages/setasign/fpdi)
5
+ [![Total Downloads](https://poser.pugx.org/setasign/fpdi/downloads.svg)](https://packagist.org/packages/setasign/fpdi)
6
+ [![Latest Unstable Version](https://poser.pugx.org/setasign/fpdi/v/unstable.svg)](https://packagist.org/packages/setasign/fpdi)
7
+ [![License](https://poser.pugx.org/setasign/fpdi/license.svg)](https://packagist.org/packages/setasign/fpdi)
8
+ [![Build Status](https://travis-ci.org/Setasign/FPDI.svg?branch=development)](https://travis-ci.org/Setasign/FPDI)
9
+
10
+ :heavy_exclamation_mark: This document refers to FPDI 2. Version 1 is deprecated and development is discontinued. :heavy_exclamation_mark:
11
+
12
+ FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF
13
+ documents and use them as templates in [FPDF](http://www.fpdf.org), which was developed by Olivier Plathey. Apart
14
+ from a copy of [FPDF](http://www.fpdf.org), FPDI does not require any special PHP extensions.
15
+
16
+ FPDI can also be used as an extension for [TCPDF](https://github.com/tecnickcom/TCPDF), too.
17
+
18
+ ## Installation with [Composer](https://packagist.org/packages/setasign/fpdi)
19
+
20
+ Because FPDI can be used with FPDF or TCPDF we didn't added a fixed dependency in the main
21
+ composer.json file but we added metadata packages for both
22
+ [FPDF](https://github.com/Setasign/FPDI-FPDF) and
23
+ [TCPDF](https://github.com/Setasign/FPDI-TCPDF).
24
+
25
+ ### Evaluate Dependencies Automatically
26
+
27
+ For FPDF add following [package](https://github.com/Setasign/FPDI-FPDF) to your composer.json:
28
+ ```json
29
+ {
30
+ "require": {
31
+ "setasign/fpdi-fpdf": "^2.0"
32
+ }
33
+ }
34
+ ```
35
+
36
+ For TCPDF add following [package](https://github.com/Setasign/FPDI-TCPDF) to your composer.json:
37
+ ```json
38
+ {
39
+ "require": {
40
+ "setasign/fpdi-tcpdf": "^2.0"
41
+ }
42
+ }
43
+ ```
44
+
45
+ ### Manual Dependencies
46
+
47
+ If you don't want to use the metadata packages, it is up to you to add the dependencies to your
48
+ composer.json file.
49
+
50
+ To use FPDI with FPDF include following in your composer.json file:
51
+
52
+ ```json
53
+ {
54
+ "require": {
55
+ "setasign/fpdf": "^1.8",
56
+ "setasign/fpdi": "^2.0"
57
+ }
58
+ }
59
+ ```
60
+
61
+ If you want to use TCPDF, your have to update your composer.json respectively to:
62
+
63
+ ```json
64
+ {
65
+ "require": {
66
+ "tecnickcom/tcpdf": "^6.2",
67
+ "setasign/fpdi": "^2.0"
68
+ }
69
+ }
70
+ ```
71
+
72
+ ## Manual Installation
73
+
74
+ If you do not use composer, just require the autoload.php in the /src folder:
75
+
76
+ ```php
77
+ require_once('src/autoload.php');
78
+ ```
79
+
80
+ If you have a PSR-4 autoloader implemented, just register the src path as follows:
81
+ ```php
82
+ $loader = new \Example\Psr4AutoloaderClass;
83
+ $loader->register();
84
+ $loader->addNamespace('setasign\Fpdi', 'path/to/src/');
85
+ ```
86
+
87
+ ## Changes to Version 1
88
+
89
+ Version 2 is a complete rewrite from scratch of FPDI which comes with:
90
+ - Namespaced code
91
+ - Clean and up-to-date code base and style
92
+ - PSR-4 compatible autoloading
93
+ - Performance improvements by up to 100%
94
+ - Less memory consumption
95
+ - Native support for reading PDFs from strings or stream-resources
96
+ - Support for documents with "invalid" data before their file-header
97
+ - Optimized page tree resolving
98
+ - Usage of individual exceptions
99
+ - Several test types (unit, functional and visual tests)
100
+
101
+ We tried to keep the main methods and logical workflow the same as in version 1 but please
102
+ notice that there were incompatible changes which you should consider when updating to
103
+ version 2:
104
+ - You need to load the code using the `src/autoload.php` file instead of `classes/FPDI.php`.
105
+ - The classes and traits are namespaced now: `setasign\Fpdi`
106
+ - Page boundaries beginning with a slash, such as `/MediaBox`, are not supported anymore. Remove
107
+ the slash or use a constant of `PdfReader\PageBoundaries`.
108
+ - The parameters $x, $y, $width and $height of the `useTemplate()` or `getTemplateSize()`
109
+ method have more logical correct default values now. Passing `0` as width or height will
110
+ result in an `InvalidArgumentException` now.
111
+ - The return value of `getTemplateSize()` had changed to an array with more speaking keys
112
+ and reusability: Use `width` instead of `w` and `height` instead of `h`.
113
+ - If you want to use **FPDI with TCPDF** you need to refactor your code to use the class `TcpdfFpdi`
114
+ instead of `FPDI`.
115
+
116
+ ## Example and Documentation
117
+
118
+ A simple example, that imports a single page and places this onto a new created page:
119
+
120
+ ```php
121
+ <?php
122
+ use setasign\Fpdi;
123
+
124
+ // setup the autoload function
125
+ require_once('vendor/autoload.php');
126
+
127
+ // initiate FPDI
128
+ $pdf = new Fpdi\Fpdi();
129
+ // add a page
130
+ $pdf->AddPage();
131
+ // set the source file
132
+ $pdf->setSourceFile("Fantastic-Speaker.pdf");
133
+ // import page 1
134
+ $tplId = $pdf->importPage(1);
135
+ // use the imported page and place it at point 10,10 with a width of 100 mm
136
+ $pdf->useTemplate($tplId, 10, 10, 100);
137
+
138
+ $pdf->Output();
139
+ ```
140
+
141
+ A full end-user documentation and API reference is available [here](https://manuals.setasign.com/fpdi-manual/).
includes/lib/FPDI/composer.json ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "name": "setasign/fpdi",
3
+ "homepage": "https://www.setasign.com/fpdi",
4
+ "description": "FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF. Because it is also possible to use FPDI with TCPDF, there are no fixed dependencies defined. Please see suggestions for packages which evaluates the dependencies automatically.",
5
+ "type": "library",
6
+ "keywords": [
7
+ "pdf",
8
+ "fpdi",
9
+ "fpdf"
10
+ ],
11
+ "license": "MIT",
12
+ "autoload": {
13
+ "psr-4": {
14
+ "setasign\\Fpdi\\": "src/"
15
+ }
16
+ },
17
+ "require": {
18
+ "php": "^5.6 || ^7.0",
19
+ "ext-zlib": "*"
20
+ },
21
+ "authors": [
22
+ {
23
+ "name": "Jan Slabon",
24
+ "email": "jan.slabon@setasign.com",
25
+ "homepage": "https://www.setasign.com"
26
+ },
27
+ {
28
+ "name": "Maximilian Kresse",
29
+ "email": "maximilian.kresse@setasign.com",
30
+ "homepage": "https://www.setasign.com"
31
+ }
32
+ ],
33
+ "suggest": {
34
+ "setasign/fpdf": "FPDI will extend this class but as it is also possible to use \"tecnickcom/tcpdf\" as an alternative there's no fixed dependency configured.",
35
+ "setasign/fpdi-fpdf": "Use this package to automatically evaluate dependencies to FPDF.",
36
+ "setasign/fpdi-tcpdf": "Use this package to automatically evaluate dependencies to TCPDF."
37
+ },
38
+ "require-dev": {
39
+ "phpunit/phpunit": "~5.7",
40
+ "setasign/fpdf": "~1.8",
41
+ "tecnickcom/tcpdf": "~6.2"
42
+ },
43
+ "autoload-dev": {
44
+ "psr-4": {
45
+ "setasign\\Fpdi\\": "tests/"
46
+ }
47
+ }
48
+ }
includes/lib/FPDI/src/FpdfTpl.php ADDED
@@ -0,0 +1,428 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi;
12
+
13
+ /**
14
+ * Class FpdfTpl
15
+ *
16
+ * This class adds a templating feature to FPDF.
17
+ *
18
+ * @package setasign\Fpdi
19
+ */
20
+ class FpdfTpl extends \FPDF
21
+ {
22
+ /**
23
+ * Data of all created templates.
24
+ *
25
+ * @var array
26
+ */
27
+ protected $templates = [];
28
+
29
+ /**
30
+ * The template id for the currently created template.
31
+ *
32
+ * @var null|int
33
+ */
34
+ protected $currentTemplateId;
35
+
36
+ /**
37
+ * A counter for template ids.
38
+ *
39
+ * @var int
40
+ */
41
+ protected $templateId = 0;
42
+
43
+ /**
44
+ * Set the page format of the current page.
45
+ *
46
+ * @param array $size An array with two values defining the size.
47
+ * @param string $orientation "L" for landscape, "P" for portrait.
48
+ */
49
+ public function setPageFormat($size, $orientation)
50
+ {
51
+ if (!\in_array($orientation, ['P', 'L'], true)) {
52
+ throw new \InvalidArgumentException(\sprintf(
53
+ 'Invalid page orientation "%s"! Only "P" and "L" are allowed!',
54
+ $orientation
55
+ ));
56
+ }
57
+
58
+ $size = $this->_getpagesize($size);
59
+
60
+ if ($orientation != $this->CurOrientation
61
+ || $size[0] != $this->CurPageSize[0]
62
+ || $size[1] != $this->CurPageSize[1]
63
+ ) {
64
+ // New size or orientation
65
+ if ($orientation === 'P') {
66
+ $this->w = $size[0];
67
+ $this->h = $size[1];
68
+ } else {
69
+ $this->w = $size[1];
70
+ $this->h = $size[0];
71
+ }
72
+ $this->wPt = $this->w * $this->k;
73
+ $this->hPt = $this->h * $this->k;
74
+ $this->PageBreakTrigger = $this->h - $this->bMargin;
75
+ $this->CurOrientation = $orientation;
76
+ $this->CurPageSize = $size;
77
+
78
+ $this->PageInfo[$this->page]['size'] = array($this->wPt, $this->hPt);
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Draws a template onto the page or another template.
84
+ *
85
+ * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
86
+ * ratio.
87
+ *
88
+ * @param mixed $tpl The template id
89
+ * @param array|float|int $x The abscissa of upper-left corner. Alternatively you could use an assoc array
90
+ * with the keys "x", "y", "width", "height", "adjustPageSize".
91
+ * @param float|int $y The ordinate of upper-left corner.
92
+ * @param float|int|null $width The width.
93
+ * @param float|int|null $height The height.
94
+ * @param bool $adjustPageSize
95
+ * @return array The size
96
+ * @see FpdfTpl::getTemplateSize()
97
+ */
98
+ public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
99
+ {
100
+ if (!isset($this->templates[$tpl])) {
101
+ throw new \InvalidArgumentException('Template does not exist!');
102
+ }
103
+
104
+ if (\is_array($x)) {
105
+ unset($x['tpl']);
106
+ \extract($x, EXTR_IF_EXISTS);
107
+ /** @noinspection NotOptimalIfConditionsInspection */
108
+ /** @noinspection CallableParameterUseCaseInTypeContextInspection */
109
+ if (\is_array($x)) {
110
+ $x = 0;
111
+ }
112
+ }
113
+
114
+ $template = $this->templates[$tpl];
115
+
116
+ $originalSize = $this->getTemplateSize($tpl);
117
+ $newSize = $this->getTemplateSize($tpl, $width, $height);
118
+ if ($adjustPageSize) {
119
+ $this->setPageFormat($newSize, $newSize['orientation']);
120
+ }
121
+
122
+ $this->_out(
123
+ // reset standard values, translate and scale
124
+ \sprintf(
125
+ 'q 0 J 1 w 0 j 0 G 0 g %.4F 0 0 %.4F %.4F %.4F cm /%s Do Q',
126
+ ($newSize['width'] / $originalSize['width']),
127
+ ($newSize['height'] / $originalSize['height']),
128
+ $x * $this->k,
129
+ ($this->h - $y - $newSize['height']) * $this->k,
130
+ $template['id']
131
+ )
132
+ );
133
+
134
+ return $newSize;
135
+ }
136
+
137
+ /**
138
+ * Get the size of a template.
139
+ *
140
+ * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
141
+ * ratio.
142
+ *
143
+ * @param mixed $tpl The template id
144
+ * @param float|int|null $width The width.
145
+ * @param float|int|null $height The height.
146
+ * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P)
147
+ */
148
+ public function getTemplateSize($tpl, $width = null, $height = null)
149
+ {
150
+ if (!isset($this->templates[$tpl])) {
151
+ return false;
152
+ }
153
+
154
+ if ($width === null && $height === null) {
155
+ $width = $this->templates[$tpl]['width'];
156
+ $height = $this->templates[$tpl]['height'];
157
+ } elseif ($width === null) {
158
+ $width = $height * $this->templates[$tpl]['width'] / $this->templates[$tpl]['height'];
159
+ }
160
+
161
+ if ($height === null) {
162
+ $height = $width * $this->templates[$tpl]['height'] / $this->templates[$tpl]['width'];
163
+ }
164
+
165
+ if ($height <= 0. || $width <= 0.) {
166
+ throw new \InvalidArgumentException('Width or height parameter needs to be larger than zero.');
167
+ }
168
+
169
+ return [
170
+ 'width' => $width,
171
+ 'height' => $height,
172
+ 0 => $width,
173
+ 1 => $height,
174
+ 'orientation' => $width > $height ? 'L' : 'P'
175
+ ];
176
+ }
177
+
178
+ /**
179
+ * Begins a new template.
180
+ *
181
+ * @param float|int|null $width The width of the template. If null, the current page width is used.
182
+ * @param float|int|null $height The height of the template. If null, the current page height is used.
183
+ * @return int A template identifier.
184
+ */
185
+ public function beginTemplate($width = null, $height = null)
186
+ {
187
+ if ($width === null) {
188
+ $width = $this->w;
189
+ }
190
+
191
+ if ($height === null) {
192
+ $height = $this->h;
193
+ }
194
+
195
+ $templateId = $this->getNextTemplateId();
196
+
197
+ // initiate buffer with current state of FPDF
198
+ $buffer = "2 J\n"
199
+ . \sprintf('%.2F w', $this->LineWidth * $this->k) . "\n";
200
+
201
+ if ($this->FontFamily) {
202
+ $buffer .= \sprintf("BT /F%d %.2F Tf ET\n", $this->CurrentFont['i'], $this->FontSizePt);
203
+ }
204
+
205
+ if ($this->DrawColor !== '0 G') {
206
+ $buffer .= $this->DrawColor . "\n";
207
+ }
208
+ if ($this->FillColor !== '0 g') {
209
+ $buffer .= $this->FillColor . "\n";
210
+ }
211
+
212
+ $this->templates[$templateId] = [
213
+ 'objectNumber' => null,
214
+ 'id' => 'TPL' . $templateId,
215
+ 'buffer' => $buffer,
216
+ 'width' => $width,
217
+ 'height' => $height,
218
+ 'state' => [
219
+ 'x' => $this->x,
220
+ 'y' => $this->y,
221
+ 'AutoPageBreak' => $this->AutoPageBreak,
222
+ 'bMargin' => $this->bMargin,
223
+ 'tMargin' => $this->tMargin,
224
+ 'lMargin' => $this->lMargin,
225
+ 'rMargin' => $this->rMargin,
226
+ 'h' => $this->h,
227
+ 'w' => $this->w,
228
+ 'FontFamily' => $this->FontFamily,
229
+ 'FontStyle' => $this->FontStyle,
230
+ 'FontSizePt' => $this->FontSizePt,
231
+ 'FontSize' => $this->FontSize
232
+ ]
233
+ ];
234
+
235
+ $this->SetAutoPageBreak(false);
236
+ $this->currentTemplateId = $templateId;
237
+
238
+ $this->h = $height;
239
+ $this->w = $width;
240
+
241
+ $this->SetXY($this->lMargin, $this->tMargin);
242
+ $this->SetRightMargin($this->w - $width + $this->rMargin);
243
+
244
+ return $templateId;
245
+ }
246
+
247
+ /**
248
+ * Ends a template.
249
+ *
250
+ * @return bool|int|null A template identifier.
251
+ */
252
+ public function endTemplate()
253
+ {
254
+ if (null === $this->currentTemplateId) {
255
+ return false;
256
+ }
257
+
258
+ $templateId = $this->currentTemplateId;
259
+ $template = $this->templates[$templateId];
260
+
261
+ $state = $template['state'];
262
+ $this->SetXY($state['x'], $state['y']);
263
+ $this->tMargin = $state['tMargin'];
264
+ $this->lMargin = $state['lMargin'];
265
+ $this->rMargin = $state['rMargin'];
266
+ $this->h = $state['h'];
267
+ $this->w = $state['w'];
268
+ $this->SetAutoPageBreak($state['AutoPageBreak'], $state['bMargin']);
269
+
270
+ $this->FontFamily = $state['FontFamily'];
271
+ $this->FontStyle = $state['FontStyle'];
272
+ $this->FontSizePt = $state['FontSizePt'];
273
+ $this->FontSize = $state['FontSize'];
274
+
275
+ $fontKey = $this->FontFamily . $this->FontStyle;
276
+ if ($fontKey) {
277
+ $this->CurrentFont =& $this->fonts[$fontKey];
278
+ } else {
279
+ unset($this->CurrentFont);
280
+ }
281
+
282
+ $this->currentTemplateId = null;
283
+
284
+ return $templateId;
285
+ }
286
+
287
+ /**
288
+ * Get the next template id.
289
+ *
290
+ * @return int
291
+ */
292
+ protected function getNextTemplateId()
293
+ {
294
+ return $this->templateId++;
295
+ }
296
+
297
+ /* overwritten FPDF methods: */
298
+
299
+ /**
300
+ * @inheritdoc
301
+ */
302
+ public function Link($x, $y, $w, $h, $link)
303
+ {
304
+ if ($this->currentTemplateId !== null) {
305
+ throw new \BadMethodCallException('Links cannot be set when writing to a template.');
306
+ }
307
+ parent::Link($x, $y, $w, $h, $link);
308
+ }
309
+
310
+ /**
311
+ * @inheritdoc
312
+ */
313
+ public function SetLink($link, $y = 0, $page = -1)
314
+ {
315
+ if ($this->currentTemplateId !== null) {
316
+ throw new \BadMethodCallException('Links cannot be set when writing to a template.');
317
+ }
318
+ return parent::SetLink($link, $y, $page);
319
+ }
320
+
321
+ /**
322
+ * @inheritdoc
323
+ */
324
+ public function SetDrawColor($r, $g = null, $b = null)
325
+ {
326
+ parent::SetDrawColor($r, $g, $b);
327
+ if ($this->page === 0 && $this->currentTemplateId !== null) {
328
+ $this->_out($this->DrawColor);
329
+ }
330
+ }
331
+
332
+ /**
333
+ * @inheritdoc
334
+ */
335
+ public function SetFillColor($r, $g = null, $b = null)
336
+ {
337
+ parent::SetFillColor($r, $g, $b);
338
+ if ($this->page === 0 && $this->currentTemplateId !== null) {
339
+ $this->_out($this->FillColor);
340
+ }
341
+ }
342
+
343
+ /**
344
+ * @inheritdoc
345
+ */
346
+ public function SetLineWidth($width)
347
+ {
348
+ parent::SetLineWidth($width);
349
+ if ($this->page === 0 && $this->currentTemplateId !== null) {
350
+ $this->_out(\sprintf('%.2F w', $width * $this->k));
351
+ }
352
+ }
353
+
354
+ /**
355
+ * @inheritdoc
356
+ */
357
+ public function SetFont($family, $style = '', $size = 0)
358
+ {
359
+ parent::SetFont($family, $style, $size);
360
+ if ($this->page === 0 && $this->currentTemplateId !== null) {
361
+ $this->_out(\sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
362
+ }
363
+ }
364
+
365
+ /**
366
+ * @inheritdoc
367
+ */
368
+ public function SetFontSize($size)
369
+ {
370
+ parent::SetFontSize($size);
371
+ if ($this->page === 0 && $this->currentTemplateId !== null) {
372
+ $this->_out(sprintf('BT /F%d %.2F Tf ET', $this->CurrentFont['i'], $this->FontSizePt));
373
+ }
374
+ }
375
+
376
+ /**
377
+ * @inheritdoc
378
+ */
379
+ protected function _putimages()
380
+ {
381
+ parent::_putimages();
382
+
383
+ foreach ($this->templates as $key => $template) {
384
+ $this->_newobj();
385
+ $this->templates[$key]['objectNumber'] = $this->n;
386
+
387
+ $this->_put('<</Type /XObject /Subtype /Form /FormType 1');
388
+ $this->_put(\sprintf('/BBox[0 0 %.2F %.2F]', $template['width'] * $this->k, $template['height'] * $this->k));
389
+ $this->_put('/Resources 2 0 R'); // default resources dictionary of FPDF
390
+
391
+ if ($this->compress) {
392
+ $buffer = \gzcompress($template['buffer']);
393
+ $this->_put('/Filter/FlateDecode');
394
+ } else {
395
+ $buffer = $template['buffer'];
396
+ }
397
+
398
+ $this->_put('/Length ' . \strlen($buffer));
399
+ $this->_put('>>');
400
+ $this->_putstream($buffer);
401
+ $this->_put('endobj');
402
+ }
403
+ }
404
+
405
+ /**
406
+ * @inheritdoc
407
+ */
408
+ protected function _putxobjectdict()
409
+ {
410
+ foreach ($this->templates as $key => $template) {
411
+ $this->_put('/' . $template['id'] . ' ' . $template['objectNumber'] . ' 0 R');
412
+ }
413
+
414
+ parent::_putxobjectdict();
415
+ }
416
+
417
+ /**
418
+ * @inheritdoc
419
+ */
420
+ public function _out($s)
421
+ {
422
+ if ($this->currentTemplateId !== null) {
423
+ $this->templates[$this->currentTemplateId]['buffer'] .= $s . "\n";
424
+ } else {
425
+ parent::_out($s);
426
+ }
427
+ }
428
+ }
includes/lib/FPDI/src/Fpdi.php ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi;
12
+
13
+ use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException;
14
+ use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
15
+ use setasign\Fpdi\PdfParser\Type\PdfNull;
16
+
17
+ /**
18
+ * Class Fpdi
19
+ *
20
+ * This class let you import pages of existing PDF documents into a reusable structure for FPDF.
21
+ *
22
+ * @package setasign\Fpdi
23
+ */
24
+ class Fpdi extends FpdfTpl
25
+ {
26
+ use FpdiTrait;
27
+
28
+ /**
29
+ * FPDI version
30
+ *
31
+ * @string
32
+ */
33
+ const VERSION = '2.0.0';
34
+
35
+ /**
36
+ * Draws an imported page or a template onto the page or another template.
37
+ *
38
+ * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
39
+ * ratio.
40
+ *
41
+ * @param mixed $tpl The template id
42
+ * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
43
+ * with the keys "x", "y", "width", "height", "adjustPageSize".
44
+ * @param float|int $y The ordinate of upper-left corner.
45
+ * @param float|int|null $width The width.
46
+ * @param float|int|null $height The height.
47
+ * @param bool $adjustPageSize
48
+ * @return array The size
49
+ * @see Fpdi::getTemplateSize()
50
+ */
51
+ public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
52
+ {
53
+ if (isset($this->importedPages[$tpl])) {
54
+ $size = $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize);
55
+ if ($this->currentTemplateId !== null) {
56
+ $this->templates[$this->currentTemplateId]['resources']['templates']['importedPages'][$tpl] = $tpl;
57
+ }
58
+ return $size;
59
+ }
60
+
61
+ return parent::useTemplate($tpl, $x, $y, $width, $height, $adjustPageSize);
62
+ }
63
+
64
+ /**
65
+ * Get the size of an imported page or template.
66
+ *
67
+ * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
68
+ * ratio.
69
+ *
70
+ * @param mixed $tpl The template id
71
+ * @param float|int|null $width The width.
72
+ * @param float|int|null $height The height.
73
+ * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P)
74
+ */
75
+ public function getTemplateSize($tpl, $width = null, $height = null)
76
+ {
77
+ $size = parent::getTemplateSize($tpl, $width, $height);
78
+ if (false === $size) {
79
+ return $this->getImportedPageSize($tpl, $width, $height);
80
+ }
81
+
82
+ return $size;
83
+ }
84
+
85
+ /**
86
+ * @inheritdoc
87
+ */
88
+ protected function _putimages()
89
+ {
90
+ $this->currentReaderId = null;
91
+ parent::_putimages();
92
+
93
+ foreach ($this->importedPages as $key => $pageData) {
94
+ $this->_newobj();
95
+ $this->importedPages[$key]['objectNumber'] = $this->n;
96
+ $this->currentReaderId = $pageData['readerId'];
97
+ $this->writePdfType($pageData['stream']);
98
+ $this->_put('endobj');
99
+ }
100
+
101
+ foreach (\array_keys($this->readers) as $readerId) {
102
+ $parser = $this->getPdfReader($readerId)->getParser();
103
+ $this->currentReaderId = $readerId;
104
+
105
+ while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) {
106
+ try {
107
+ $object = $parser->getIndirectObject($objectNumber);
108
+
109
+ } catch (CrossReferenceException $e) {
110
+ if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) {
111
+ $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull());
112
+ } else {
113
+ throw $e;
114
+ }
115
+ }
116
+
117
+ $this->writePdfType($object);
118
+ }
119
+ }
120
+
121
+ $this->currentReaderId = null;
122
+ }
123
+
124
+ /**
125
+ * @inheritdoc
126
+ */
127
+ protected function _putxobjectdict()
128
+ {
129
+ foreach ($this->importedPages as $key => $pageData) {
130
+ $this->_put('/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R');
131
+ }
132
+
133
+ parent::_putxobjectdict();
134
+ }
135
+
136
+ /**
137
+ * @inheritdoc
138
+ */
139
+ protected function _put($s, $newLine = true)
140
+ {
141
+ if ($newLine) {
142
+ $this->buffer .= $s . "\n";
143
+ } else {
144
+ $this->buffer .= $s;
145
+ }
146
+ }
147
+ }
includes/lib/FPDI/src/FpdiException.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi;
12
+
13
+ /**
14
+ * Base exception class for the FPDI package.
15
+ *
16
+ * @package setasign\Fpdi
17
+ */
18
+ class FpdiException extends \Exception
19
+ {
20
+ }
includes/lib/FPDI/src/FpdiTrait.php ADDED
@@ -0,0 +1,523 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\StreamReader;
15
+ use setasign\Fpdi\PdfParser\Type\PdfArray;
16
+ use setasign\Fpdi\PdfParser\Type\PdfBoolean;
17
+ use setasign\Fpdi\PdfParser\Type\PdfDictionary;
18
+ use setasign\Fpdi\PdfParser\Type\PdfHexString;
19
+ use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
20
+ use setasign\Fpdi\PdfParser\Type\PdfIndirectObjectReference;
21
+ use setasign\Fpdi\PdfParser\Type\PdfName;
22
+ use setasign\Fpdi\PdfParser\Type\PdfNull;
23
+ use setasign\Fpdi\PdfParser\Type\PdfNumeric;
24
+ use setasign\Fpdi\PdfParser\Type\PdfStream;
25
+ use setasign\Fpdi\PdfParser\Type\PdfString;
26
+ use setasign\Fpdi\PdfParser\Type\PdfToken;
27
+ use setasign\Fpdi\PdfParser\Type\PdfType;
28
+ use setasign\Fpdi\PdfReader\PageBoundaries;
29
+ use setasign\Fpdi\PdfReader\PdfReader;
30
+ use setasign\Fpdi\PdfReader\PdfReaderException;
31
+ use /* This namespace/class is used by the commercial FPDI PDF-Parser add-on. */
32
+ /** @noinspection PhpUndefinedClassInspection */
33
+ /** @noinspection PhpUndefinedNamespaceInspection */
34
+ setasign\FpdiPdfParser\PdfParser\PdfParser as FpdiPdfParser;
35
+
36
+ /**
37
+ * The FpdiTrait
38
+ *
39
+ * This trait offers the core functionalities of FPDI. By passing them to a trait we can reuse it with e.g. TCPDF in a
40
+ * very easy way.
41
+ *
42
+ * @package setasign\Fpdi
43
+ */
44
+ trait FpdiTrait
45
+ {
46
+ /**
47
+ * The pdf reader instances.
48
+ *
49
+ * @var PdfReader[]
50
+ */
51
+ protected $readers = [];
52
+
53
+ /**
54
+ * The current reader id.
55
+ *
56
+ * @var string
57
+ */
58
+ protected $currentReaderId;
59
+
60
+ /**
61
+ * Data of all imported pages.
62
+ *
63
+ * @var array
64
+ */
65
+ protected $importedPages = [];
66
+
67
+ /**
68
+ * A map from object numbers of imported objects to new assigned object numbers by FPDF.
69
+ *
70
+ * @var array
71
+ */
72
+ protected $objectMap = [];
73
+
74
+ /**
75
+ * An array with information about objects, which needs to be copied to the resulting document.
76
+ *
77
+ * @var array
78
+ */
79
+ protected $objectsToCopy = [];
80
+
81
+ /**
82
+ * Set the minimal PDF version.
83
+ *
84
+ * @param string $pdfVersion
85
+ */
86
+ protected function setMinPdfVersion($pdfVersion)
87
+ {
88
+ if (\version_compare($pdfVersion, $this->PDFVersion, '>')) {
89
+ $this->PDFVersion = $pdfVersion;
90
+ }
91
+ }
92
+
93
+ /** @noinspection PhpUndefinedClassInspection */
94
+ /**
95
+ * Get a new pdf parser instance.
96
+ *
97
+ * @param StreamReader $streamReader
98
+ * @return PdfParser|FpdiPdfParser
99
+ */
100
+ protected function getPdfParserInstance(StreamReader $streamReader)
101
+ {
102
+ /** @noinspection PhpUndefinedClassInspection */
103
+ if (\class_exists(FpdiPdfParser::class)) {
104
+ /** @noinspection PhpUndefinedClassInspection */
105
+ return new FpdiPdfParser($streamReader);
106
+ }
107
+
108
+ return new PdfParser($streamReader);
109
+ }
110
+
111
+ /**
112
+ * Get an unique reader id by the $file parameter.
113
+ *
114
+ * @param string|resource|PdfReader|StreamReader $file An open file descriptor, a path to a file, a PdfReader
115
+ * instance or a StreamReader instance.
116
+ * @return string
117
+ */
118
+ protected function getPdfReaderId($file)
119
+ {
120
+ if (\is_resource($file)) {
121
+ $id = (string) $file;
122
+ } elseif (\is_string($file)) {
123
+ $id = \realpath($file);
124
+ if (false === $id) {
125
+ $id = $file;
126
+ }
127
+ } elseif (\is_object($file)) {
128
+ $id = \spl_object_hash($file);
129
+ } else {
130
+ throw new \InvalidArgumentException(
131
+ \sprintf('Invalid type in $file parameter (%s)', \gettype($file))
132
+ );
133
+ }
134
+
135
+ if (isset($this->readers[$id])) {
136
+ return $id;
137
+ }
138
+
139
+ if (\is_resource($file)) {
140
+ $streamReader = new StreamReader($file);
141
+ } elseif (\is_string($file)) {
142
+ $streamReader = StreamReader::createByFile($file);
143
+ } else {
144
+ $streamReader = $file;
145
+ }
146
+
147
+ $reader = new PdfReader($this->getPdfParserInstance($streamReader));
148
+ $this->readers[$id] = $reader;
149
+
150
+ return $id;
151
+ }
152
+
153
+ /**
154
+ * Get a pdf reader instance by its id.
155
+ *
156
+ * @param string $id
157
+ * @return PdfReader
158
+ */
159
+ protected function getPdfReader($id)
160
+ {
161
+ if (isset($this->readers[$id])) {
162
+ return $this->readers[$id];
163
+ }
164
+
165
+ throw new \InvalidArgumentException(
166
+ \sprintf('No pdf reader with the given id (%s) exists.', $id)
167
+ );
168
+ }
169
+
170
+ /**
171
+ * Set the source PDF file.
172
+ *
173
+ * @param string|resource|StreamReader $file Path to the file or a stream resource or a StreamReader instance.
174
+ * @return int The page count of the PDF document.
175
+ */
176
+ public function setSourceFile($file)
177
+ {
178
+ $this->currentReaderId = $this->getPdfReaderId($file);
179
+ $this->objectsToCopy[$this->currentReaderId] = [];
180
+
181
+ $reader = $this->getPdfReader($this->currentReaderId);
182
+ $this->setMinPdfVersion($reader->getPdfVersion());
183
+
184
+ return $reader->getPageCount();
185
+ }
186
+
187
+ /**
188
+ * Imports a page.
189
+ *
190
+ * @param int $pageNumber The page number.
191
+ * @param string $box The page boundary to import. Default set to PageBoundaries::CROP_BOX.
192
+ * @param bool $groupXObject Define the form XObject as a group XObject to support transparency (if used).
193
+ * @return string A unique string identifying the imported page.
194
+ * @see PageBoundaries
195
+ * @throws PdfReaderException
196
+ */
197
+ public function importPage($pageNumber, $box = PageBoundaries::CROP_BOX, $groupXObject = true)
198
+ {
199
+ if (null === $this->currentReaderId) {
200
+ throw new \BadMethodCallException('No reader initiated. Call setSourceFile() first.');
201
+ }
202
+
203
+ $pageId = $this->currentReaderId;
204
+
205
+ $pageNumber = (int)$pageNumber;
206
+ $pageId .= '|' . $pageNumber . '|' . ($groupXObject ? '1' : '0');
207
+
208
+ // for backwards compatibility with FPDI 1
209
+ $box = \ltrim($box, '/');
210
+ if (!PageBoundaries::isValidName($box)) {
211
+ throw new \InvalidArgumentException(
212
+ \sprintf('Box name is invalid: "%s"', $box)
213
+ );
214
+ }
215
+
216
+ $pageId .= '|' . $box;
217
+
218
+ if (isset($this->importedPages[$pageId])) {
219
+ return $pageId;
220
+ }
221
+
222
+ $reader = $this->getPdfReader($this->currentReaderId);
223
+ $page = $reader->getPage($pageNumber);
224
+
225
+ $bbox = $page->getBoundary($box);
226
+ if ($bbox === false) {
227
+ throw new PdfReaderException(
228
+ \sprintf("Page doesn't have a boundary box (%s).", $box),
229
+ PdfReaderException::MISSING_DATA
230
+ );
231
+ }
232
+
233
+ $dict = new PdfDictionary();
234
+ $dict->value['Type'] = PdfName::create('XObject');
235
+ $dict->value['Subtype'] = PdfName::create('Form');
236
+ $dict->value['FormType'] = PdfNumeric::create(1);
237
+ $dict->value['BBox'] = $bbox->toPdfArray();
238
+
239
+ if ($groupXObject) {
240
+ $this->setMinPdfVersion('1.4');
241
+ $dict->value['Group'] = PdfDictionary::create([
242
+ 'Type' => PdfName::create('Group'),
243
+ 'S' => PdfName::create('Transparency')
244
+ ]);
245
+ }
246
+
247
+ $resources = $page->getAttribute('Resources');
248
+ if ($resources !== null) {
249
+ $dict->value['Resources'] = $resources;
250
+ }
251
+
252
+ list($width, $height) = $page->getWidthAndHeight($box);
253
+
254
+ $a = 1;
255
+ $b = 0;
256
+ $c = 0;
257
+ $d = 1;
258
+ $e = -$bbox->getLlx();
259
+ $f = -$bbox->getLly();
260
+
261
+ $rotation = $page->getRotation();
262
+
263
+ if ($rotation !== 0) {
264
+ $rotation *= -1;
265
+ $angle = $rotation * M_PI/180;
266
+ $a = \cos($angle);
267
+ $b = \sin($angle);
268
+ $c = -$b;
269
+ $d = $a;
270
+
271
+ switch ($rotation) {
272
+ case -90:
273
+ $e = -$bbox->getLly();
274
+ $f = $bbox->getUrx();
275
+ break;
276
+ case -180:
277
+ $e = $bbox->getUrx();
278
+ $f = $bbox->getUry();
279
+ break;
280
+ case -270:
281
+ $e = $bbox->getUry();
282
+ $f = -$bbox->getLlx();
283
+ break;
284
+ }
285
+ }
286
+
287
+ // we need to rotate/translate
288
+ if ($a != 1 || $b != 0 || $c != 0 || $d != 1 || $e != 0 || $f != 0) {
289
+ $dict->value['Matrix'] = PdfArray::create([
290
+ PdfNumeric::create($a), PdfNumeric::create($b), PdfNumeric::create($c),
291
+ PdfNumeric::create($d), PdfNumeric::create($e), PdfNumeric::create($f)
292
+ ]);
293
+ }
294
+
295
+ // try to use the existing content stream
296
+ $pageDict = $page->getPageDictionary();
297
+
298
+ $contentsObject = PdfType::resolve(PdfDictionary::get($pageDict, 'Contents'), $reader->getParser(), true);
299
+ $contents = PdfType::resolve($contentsObject, $reader->getParser());
300
+
301
+ // just copy the stream reference if it is only a single stream
302
+ if (($contentsIsStream = ($contents instanceof PdfStream))
303
+ || ($contents instanceof PdfArray && \count($contents->value) === 1)
304
+ ) {
305
+ if ($contentsIsStream) {
306
+ /**
307
+ * @var PdfIndirectObject $contentsObject
308
+ */
309
+ $stream = $contents;
310
+ } else {
311
+ $stream = PdfType::resolve($contents->value[0], $reader->getParser());
312
+ }
313
+
314
+ $filter = PdfDictionary::get($stream->value, 'Filter');
315
+ if (!$filter instanceof PdfNull) {
316
+ $dict->value['Filter'] = $filter;
317
+ }
318
+ $length = PdfType::resolve(PdfDictionary::get($stream->value, 'Length'), $reader->getParser());
319
+ $dict->value['Length'] = $length;
320
+ $stream->value = $dict;
321
+
322
+ // otherwise extract it from the array and re-compress the whole stream
323
+ } else {
324
+ $streamContent = $this->compress
325
+ ? \gzcompress($page->getContentStream())
326
+ : $page->getContentStream();
327
+
328
+ $dict->value['Length'] = PdfNumeric::create(\strlen($streamContent));
329
+ if ($this->compress) {
330
+ $dict->value['Filter'] = PdfName::create('FlateDecode');
331
+ }
332
+
333
+ $stream = PdfStream::create($dict, $streamContent);
334
+ }
335
+
336
+ $this->importedPages[$pageId] = [
337
+ 'objectNumber' => null,
338
+ 'readerId' => $this->currentReaderId,
339
+ 'id' => 'TPL' . $this->getNextTemplateId(),
340
+ 'width' => $width / $this->k,
341
+ 'height' => $height / $this->k,
342
+ 'stream' => $stream
343
+ ];
344
+
345
+ return $pageId;
346
+ }
347
+
348
+ /**
349
+ * Draws an imported page onto the page.
350
+ *
351
+ * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
352
+ * ratio.
353
+ *
354
+ * @param mixed $pageId The page id
355
+ * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
356
+ * with the keys "x", "y", "width", "height", "adjustPageSize".
357
+ * @param float|int $y The ordinate of upper-left corner.
358
+ * @param float|int|null $width The width.
359
+ * @param float|int|null $height The height.
360
+ * @param bool $adjustPageSize
361
+ * @return array The size.
362
+ * @see Fpdi::getTemplateSize()
363
+ */
364
+ public function useImportedPage($pageId, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
365
+ {
366
+ if (\is_array($x)) {
367
+ unset($x['pageId']);
368
+ \extract($x, EXTR_IF_EXISTS);
369
+ /** @noinspection NotOptimalIfConditionsInspection */
370
+ if (\is_array($x)) {
371
+ $x = 0;
372
+ }
373
+ }
374
+
375
+ if (!isset($this->importedPages[$pageId])) {
376
+ throw new \InvalidArgumentException('Imported page does not exist!');
377
+ }
378
+
379
+ $importedPage = $this->importedPages[$pageId];
380
+
381
+ $originalSize = $this->getTemplateSize($pageId);
382
+ $newSize = $this->getTemplateSize($pageId, $width, $height);
383
+ if ($adjustPageSize) {
384
+ $this->setPageFormat($newSize, $newSize['orientation']);
385
+ }
386
+
387
+ $this->_out(
388
+ // reset standard values, translate and scale
389
+ \sprintf(
390
+ 'q 0 J 1 w 0 j 0 G 0 g %.4F 0 0 %.4F %.4F %.4F cm /%s Do Q',
391
+ ($newSize['width'] / $originalSize['width']),
392
+ ($newSize['height'] / $originalSize['height']),
393
+ $x * $this->k,
394
+ ($this->h - $y - $newSize['height']) * $this->k,
395
+ $importedPage['id']
396
+ )
397
+ );
398
+
399
+ return $newSize;
400
+ }
401
+
402
+ /**
403
+ * Get the size of an imported page.
404
+ *
405
+ * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
406
+ * ratio.
407
+ *
408
+ * @param mixed $tpl The template id
409
+ * @param float|int|null $width The width.
410
+ * @param float|int|null $height The height.
411
+ * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P)
412
+ */
413
+ public function getImportedPageSize($tpl, $width = null, $height = null)
414
+ {
415
+ if (isset($this->importedPages[$tpl])) {
416
+ $importedPage = $this->importedPages[$tpl];
417
+
418
+ if ($width === null && $height === null) {
419
+ $width = $importedPage['width'];
420
+ $height = $importedPage['height'];
421
+ } elseif ($width === null) {
422
+ $width = $height * $importedPage['width'] / $importedPage['height'];
423
+ }
424
+
425
+ if ($height === null) {
426
+ $height = $width * $importedPage['height'] / $importedPage['width'];
427
+ }
428
+
429
+ if ($height <= 0. || $width <= 0.) {
430
+ throw new \InvalidArgumentException('Width or height parameter needs to be larger than zero.');
431
+ }
432
+
433
+ return [
434
+ 'width' => $width,
435
+ 'height' => $height,
436
+ 0 => $width,
437
+ 1 => $height,
438
+ 'orientation' => $width > $height ? 'L' : 'P'
439
+ ];
440
+ }
441
+
442
+ return false;
443
+ }
444
+
445
+ /**
446
+ * Writes a PdfType object to the resulting buffer.
447
+ *
448
+ * @param PdfType $value
449
+ */
450
+ protected function writePdfType(PdfType $value)
451
+ {
452
+ if ($value instanceof PdfNumeric) {
453
+ if (\is_int($value->value)) {
454
+ $this->_put($value->value . ' ', false);
455
+ } else {
456
+ $this->_put(\rtrim(\rtrim(\sprintf('%.5F', $value->value), '0'), '.') . ' ', false);
457
+ }
458
+
459
+ } elseif ($value instanceof PdfName) {
460
+ $this->_put('/' . $value->value . ' ', false);
461
+
462
+ } elseif ($value instanceof PdfString) {
463
+ $this->_put('(' . $value->value . ')', false);
464
+
465
+ } elseif ($value instanceof PdfHexString) {
466
+ $this->_put('<' . $value->value . '>');
467
+
468
+ } elseif ($value instanceof PdfBoolean) {
469
+ $this->_put($value->value ? 'true ' : 'false ', false);
470
+
471
+ } elseif ($value instanceof PdfArray) {
472
+ $this->_put('[', false);
473
+ foreach ($value->value as $entry) {
474
+ $this->writePdfType($entry);
475
+ }
476
+ $this->_put(']');
477
+
478
+ } elseif ($value instanceof PdfDictionary) {
479
+ $this->_put('<<', false);
480
+ foreach ($value->value as $name => $entry) {
481
+ $this->_put('/' . $name . ' ', false);
482
+ $this->writePdfType($entry);
483
+ }
484
+ $this->_put('>>');
485
+
486
+ } elseif ($value instanceof PdfToken) {
487
+ $this->_put($value->value);
488
+
489
+ } elseif ($value instanceof PdfNull) {
490
+ $this->_put('null ');
491
+
492
+ } elseif ($value instanceof PdfStream) {
493
+ /**
494
+ * @var $value PdfStream
495
+ */
496
+ $this->writePdfType($value->value);
497
+ $this->_put('stream');
498
+ $this->_put($value->getStream());
499
+ $this->_put('endstream');
500
+
501
+ } elseif ($value instanceof PdfIndirectObjectReference) {
502
+ if (!isset($this->objectMap[$this->currentReaderId])) {
503
+ $this->objectMap[$this->currentReaderId] = [];
504
+ }
505
+
506
+ if (!isset($this->objectMap[$this->currentReaderId][$value->value])) {
507
+ $this->objectMap[$this->currentReaderId][$value->value] = ++$this->n;
508
+ $this->objectsToCopy[$this->currentReaderId][] = $value->value;
509
+ }
510
+
511
+ $this->_put($this->objectMap[$this->currentReaderId][$value->value] . ' 0 R ', false);
512
+
513
+ } elseif ($value instanceof PdfIndirectObject) {
514
+ /**
515
+ * @var $value PdfIndirectObject
516
+ */
517
+ $n = $this->objectMap[$this->currentReaderId][$value->objectNumber];
518
+ $this->_newobj($n);
519
+ $this->writePdfType($value->value);
520
+ $this->_put('endobj');
521
+ }
522
+ }
523
+ }
includes/lib/FPDI/src/PdfParser/CrossReference/AbstractReader.php ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\CrossReference;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\Type\PdfDictionary;
15
+ use setasign\Fpdi\PdfParser\Type\PdfToken;
16
+
17
+ /**
18
+ * Abstract class for cross-reference reader classes.
19
+ *
20
+ * @package setasign\Fpdi\PdfParser\CrossReference
21
+ */
22
+ abstract class AbstractReader
23
+ {
24
+ /**
25
+ * @var PdfParser
26
+ */
27
+ protected $parser;
28
+
29
+ /**
30
+ * @var PdfDictionary
31
+ */
32
+ protected $trailer;
33
+
34
+ /**
35
+ * AbstractReader constructor.
36
+ *
37
+ * @param PdfParser $parser
38
+ */
39
+ public function __construct(PdfParser $parser)
40
+ {
41
+ $this->parser = $parser;
42
+ $this->readTrailer();
43
+ }
44
+
45
+ /**
46
+ * Get the trailer dictionary.
47
+ *
48
+ * @return PdfDictionary
49
+ */
50
+ public function getTrailer()
51
+ {
52
+ return $this->trailer;
53
+ }
54
+
55
+ /**
56
+ * Read the trailer dictionary.
57
+ *
58
+ * @throws CrossReferenceException
59
+ */
60
+ protected function readTrailer()
61
+ {
62
+ $trailerKeyword = $this->parser->readValue();
63
+ if ($trailerKeyword === false ||
64
+ !($trailerKeyword instanceof PdfToken) ||
65
+ $trailerKeyword->value !== 'trailer'
66
+ ) {
67
+ throw new CrossReferenceException(
68
+ \sprintf(
69
+ 'Unexpected end of cross reference. "trailer"-keyword expected, got: %s',
70
+ $trailerKeyword instanceof PdfToken ? $trailerKeyword->value : 'nothing'
71
+ ),
72
+ CrossReferenceException::UNEXPECTED_END
73
+ );
74
+ }
75
+
76
+ $trailer = $this->parser->readValue();
77
+ if ($trailer === false || !($trailer instanceof PdfDictionary)) {
78
+ throw new CrossReferenceException(
79
+ 'Unexpected end of cross reference. Trailer not found.',
80
+ CrossReferenceException::UNEXPECTED_END
81
+ );
82
+ }
83
+
84
+ $this->trailer = $trailer;
85
+ }
86
+ }
includes/lib/FPDI/src/PdfParser/CrossReference/CrossReference.php ADDED
@@ -0,0 +1,295 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\CrossReference;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\Type\PdfDictionary;
15
+ use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
16
+ use setasign\Fpdi\PdfParser\Type\PdfNumeric;
17
+ use setasign\Fpdi\PdfParser\Type\PdfStream;
18
+ use setasign\Fpdi\PdfParser\Type\PdfToken;
19
+
20
+ /**
21
+ * Class CrossReference
22
+ *
23
+ * This class processes the standard cross reference of a PDF document.
24
+ *
25
+ * @package setasign\Fpdi\PdfParser\CrossReference
26
+ */
27
+ class CrossReference
28
+ {
29
+ /**
30
+ * The byte length in which the "startxref" keyword should be searched.
31
+ *
32
+ * @var int
33
+ */
34
+ static public $trailerSearchLength = 5500;
35
+
36
+ /**
37
+ * @var int
38
+ */
39
+ protected $fileHeaderOffset = 0;
40
+
41
+ /**
42
+ * @var PdfParser
43
+ */
44
+ protected $parser;
45
+
46
+ /**
47
+ * @var ReaderInterface[]
48
+ */
49
+ protected $readers = [];
50
+
51
+ /**
52
+ * CrossReference constructor.
53
+ *
54
+ * @param PdfParser $parser
55
+ */
56
+ public function __construct(PdfParser $parser, $fileHeaderOffset = 0)
57
+ {
58
+ $this->parser = $parser;
59
+ $this->fileHeaderOffset = $fileHeaderOffset;
60
+
61
+ $offset = $this->findStartXref();
62
+ $reader = null;
63
+ while ($offset !== false) {
64
+ $reader = $this->readXref($offset + $this->fileHeaderOffset);
65
+ $trailer = $reader->getTrailer();
66
+ $this->checkForEncryption($trailer);
67
+ $this->readers[] = $reader;
68
+
69
+ if (isset($trailer->value['Prev'])) {
70
+ $offset = $trailer->value['Prev']->value;
71
+ } else {
72
+ $offset = false;
73
+ }
74
+ }
75
+
76
+ // fix faulty sub-section header
77
+ if ($reader instanceof FixedReader) {
78
+ /**
79
+ * @var FixedReader $reader
80
+ */
81
+ $reader->fixFaultySubSectionShift();
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Get the size of the cross reference.
87
+ *
88
+ * @return integer
89
+ */
90
+ public function getSize()
91
+ {
92
+ return $this->getTrailer()->value['Size']->value;
93
+ }
94
+
95
+ /**
96
+ * Get the trailer dictionary.
97
+ *
98
+ * @return PdfDictionary
99
+ */
100
+ public function getTrailer()
101
+ {
102
+ return $this->readers[0]->getTrailer();
103
+ }
104
+
105
+ /**
106
+ * Get the cross reference readser instances.
107
+ *
108
+ * @return ReaderInterface[]
109
+ */
110
+ public function getReaders()
111
+ {
112
+ return $this->readers;
113
+ }
114
+
115
+ /**
116
+ * Get the offset by an object number.
117
+ *
118
+ * @param int $objectNumber
119
+ * @return integer|bool
120
+ */
121
+ public function getOffsetFor($objectNumber)
122
+ {
123
+ foreach ($this->getReaders() as $reader) {
124
+ $offset = $reader->getOffsetFor($objectNumber);
125
+ if (false !== $offset) {
126
+ return $offset;
127
+ }
128
+ }
129
+
130
+ return false;
131
+ }
132
+
133
+ /**
134
+ * Get an indirect object by its object number.
135
+ *
136
+ * @param int $objectNumber
137
+ * @return PdfIndirectObject
138
+ * @throws CrossReferenceException
139
+ */
140
+ public function getIndirectObject($objectNumber)
141
+ {
142
+ $offset = $this->getOffsetFor($objectNumber);
143
+ if (false === $offset) {
144
+ throw new CrossReferenceException(
145
+ \sprintf('Object (id:%s) not found.', $objectNumber),
146
+ CrossReferenceException::OBJECT_NOT_FOUND
147
+ );
148
+ }
149
+
150
+ $parser = $this->parser;
151
+
152
+ $parser->getTokenizer()->clearStack();
153
+ $parser->getStreamReader()->reset($offset + $this->fileHeaderOffset);
154
+
155
+ $object = $parser->readValue();
156
+ if (false === $object || !($object instanceof PdfIndirectObject)) {
157
+ throw new CrossReferenceException(
158
+ \sprintf('Object (id:%s) not found at location (%s).', $objectNumber, $offset),
159
+ CrossReferenceException::OBJECT_NOT_FOUND
160
+ );
161
+ }
162
+
163
+ if ($object->objectNumber !== $objectNumber) {
164
+ throw new CrossReferenceException(
165
+ \sprintf('Wrong object found, got %s while %s was expected.', $object->objectNumber, $objectNumber),
166
+ CrossReferenceException::OBJECT_NOT_FOUND
167
+ );
168
+ }
169
+
170
+ return $object;
171
+ }
172
+
173
+ /**
174
+ * Read the cross-reference table at a given offset.
175
+ *
176
+ * Internally the method will try to evaluate the best reader for this cross-reference.
177
+ *
178
+ * @param int $offset
179
+ * @return ReaderInterface
180
+ * @throws CrossReferenceException
181
+ */
182
+ protected function readXref($offset)
183
+ {
184
+ $this->parser->getStreamReader()->reset($offset);
185
+ $this->parser->getTokenizer()->clearStack();
186
+ $initValue = $this->parser->readValue();
187
+
188
+ return $this->initReaderInstance($initValue);
189
+ }
190
+
191
+ /**
192
+ * Get a cross-reference reader instance.
193
+ *
194
+ * @param PdfToken|PdfIndirectObject $initValue
195
+ * @return ReaderInterface|bool
196
+ * @throws CrossReferenceException
197
+ */
198
+ protected function initReaderInstance($initValue)
199
+ {
200
+ $position = $this->parser->getStreamReader()->getPosition()
201
+ + $this->parser->getStreamReader()->getOffset() + $this->fileHeaderOffset;
202
+
203
+ if ($initValue instanceof PdfToken && $initValue->value === 'xref') {
204
+ try {
205
+ return new FixedReader($this->parser);
206
+ } catch (CrossReferenceException $e) {
207
+ $this->parser->getStreamReader()->reset($position);
208
+ $this->parser->getTokenizer()->clearStack();
209
+
210
+ return new LineReader($this->parser);
211
+ }
212
+ }
213
+
214
+ if ($initValue instanceof PdfIndirectObject) {
215
+ // check for encryption
216
+ $stream = PdfStream::ensure($initValue->value);
217
+
218
+ $type = PdfDictionary::get($stream->value, 'Type');
219
+ if ($type->value !== 'XRef') {
220
+ throw new CrossReferenceException(
221
+ 'The xref position points to an incorrect object type.',
222
+ CrossReferenceException::INVALID_DATA
223
+ );
224
+ }
225
+
226
+ $this->checkForEncryption($stream->value);
227
+
228
+ throw new CrossReferenceException(
229
+ 'This PDF document probably uses a compression technique which is not supported by the ' .
230
+ 'free parser shipped with FPDI. (See https://www.setasign.com/fpdi-pdf-parser for more details)',
231
+ CrossReferenceException::COMPRESSED_XREF
232
+ );
233
+ }
234
+
235
+ throw new CrossReferenceException(
236
+ 'The xref position points to an incorrect object type.',
237
+ CrossReferenceException::INVALID_DATA
238
+ );
239
+ }
240
+
241
+ /**
242
+ * Check for encryption.
243
+ *
244
+ * @param PdfDictionary $dictionary
245
+ * @throws CrossReferenceException
246
+ */
247
+ protected function checkForEncryption(PdfDictionary $dictionary)
248
+ {
249
+ if (isset($dictionary->value['Encrypt'])) {
250
+ throw new CrossReferenceException(
251
+ 'This PDF document is encrypted and cannot be processed with FPDI.',
252
+ CrossReferenceException::ENCRYPTED
253
+ );
254
+ }
255
+ }
256
+
257
+ /**
258
+ * Find the start position for the first cross-reference.
259
+ *
260
+ * @return int The byte-offset position of the first cross-reference.
261
+ * @throws CrossReferenceException
262
+ */
263
+ protected function findStartXref()
264
+ {
265
+ $reader = $this->parser->getStreamReader();
266
+ $reader->reset(-self::$trailerSearchLength, self::$trailerSearchLength);
267
+
268
+ $buffer = $reader->getBuffer(false);
269
+ $pos = \strrpos($buffer, 'startxref');
270
+ $addOffset = 9;
271
+ if (false === $pos) {
272
+ // Some corrupted documents uses startref, instead of startxref
273
+ $pos = \strrpos($buffer, 'startref');
274
+ if (false === $pos) {
275
+ throw new CrossReferenceException(
276
+ 'Unable to find pointer to xref table',
277
+ CrossReferenceException::NO_STARTXREF_FOUND
278
+ );
279
+ }
280
+ $addOffset = 8;
281
+ }
282
+
283
+ $reader->setOffset($pos + $addOffset);
284
+
285
+ $value = $this->parser->readValue();
286
+ if (!($value instanceof PdfNumeric)) {
287
+ throw new CrossReferenceException(
288
+ 'Invalid data after startxref keyword.',
289
+ CrossReferenceException::INVALID_DATA
290
+ );
291
+ }
292
+
293
+ return $value->value;
294
+ }
295
+ }
includes/lib/FPDI/src/PdfParser/CrossReference/CrossReferenceException.php ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\CrossReference;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParserException;
14
+
15
+ /**
16
+ * Exception used by the CrossReference and Reader classes.
17
+ *
18
+ * @package setasign\Fpdi\PdfParser\CrossReference
19
+ */
20
+ class CrossReferenceException extends PdfParserException
21
+ {
22
+ /**
23
+ * @var int
24
+ */
25
+ const INVALID_DATA = 0x0101;
26
+
27
+ /**
28
+ * @var int
29
+ */
30
+ const XREF_MISSING = 0x0102;
31
+
32
+ /**
33
+ * @var int
34
+ */
35
+ const ENTRIES_TOO_LARGE = 0x0103;
36
+
37
+ /**
38
+ * @var int
39
+ */
40
+ const ENTRIES_TOO_SHORT = 0x0104;
41
+
42
+ /**
43
+ * @var int
44
+ */
45
+ const NO_ENTRIES = 0x0105;
46
+
47
+ /**
48
+ * @var int
49
+ */
50
+ const NO_TRAILER_FOUND = 0x0106;
51
+
52
+ /**
53
+ * @var int
54
+ */
55
+ const NO_STARTXREF_FOUND = 0x0107;
56
+
57
+ /**
58
+ * @var int
59
+ */
60
+ const NO_XREF_FOUND = 0x0108;
61
+
62
+ /**
63
+ * @var int
64
+ */
65
+ const UNEXPECTED_END = 0x0109;
66
+
67
+ /**
68
+ * @var int
69
+ */
70
+ const OBJECT_NOT_FOUND = 0x010A;
71
+
72
+ /**
73
+ * @var int
74
+ */
75
+ const COMPRESSED_XREF = 0x010B;
76
+
77
+ /**
78
+ * @var int
79
+ */
80
+ const ENCRYPTED = 0x010C;
81
+ }
includes/lib/FPDI/src/PdfParser/CrossReference/FixedReader.php ADDED
@@ -0,0 +1,193 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\CrossReference;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\StreamReader;
15
+
16
+ /**
17
+ * Class FixedReader
18
+ *
19
+ * This reader allows a very less overhead parsing of single entries of the cross-reference, because the main entries
20
+ * are only read when needed and not in a single run.
21
+ *
22
+ * @package setasign\Fpdi\PdfParser\CrossReference
23
+ */
24
+ class FixedReader extends AbstractReader implements ReaderInterface
25
+ {
26
+ /**
27
+ * @var StreamReader
28
+ */
29
+ protected $reader;
30
+
31
+ /**
32
+ * Data of subsections.
33
+ *
34
+ * @var array
35
+ */
36
+ protected $subSections;
37
+
38
+ /**
39
+ * FixedReader constructor.
40
+ *
41
+ * @param PdfParser $parser
42
+ */
43
+ public function __construct(PdfParser $parser)
44
+ {
45
+ $this->reader = $parser->getStreamReader();
46
+ $this->read();
47
+ parent::__construct($parser);
48
+ }
49
+
50
+ /**
51
+ * Get all subsection data.
52
+ *
53
+ * @return array
54
+ */
55
+ public function getSubSections()
56
+ {
57
+ return $this->subSections;
58
+ }
59
+
60
+ /**
61
+ * @inheritdoc
62
+ */
63
+ public function getOffsetFor($objectNumber)
64
+ {
65
+ foreach ($this->subSections as $offset => list($startObject, $objectCount)) {
66
+ if ($objectNumber >= $startObject && $objectNumber < ($startObject + $objectCount)) {
67
+ $position = $offset + 20 * ($objectNumber - $startObject);
68
+ $this->reader->ensure($position, 20);
69
+ $line = $this->reader->readBytes(20);
70
+ if ($line[17] === 'f') {
71
+ return false;
72
+ }
73
+
74
+ return (int) \substr($line, 0, 10);
75
+ }
76
+ }
77
+
78
+ return false;
79
+ }
80
+
81
+ /**
82
+ * Read the cross-reference.
83
+ *
84
+ * This reader will only read the subsections in this method. The offsets were resolved individually by this
85
+ * information.
86
+ *
87
+ * @throws CrossReferenceException
88
+ */
89
+ protected function read()
90
+ {
91
+ $subSections = [];
92
+
93
+ $startObject = $entryCount = $lastLineStart = null;
94
+ $validityChecked = false;
95
+ while (($line = $this->reader->readLine(20)) !== false) {
96
+ if (\strpos($line, 'trailer') !== false) {
97
+ $this->reader->reset($lastLineStart);
98
+ break;
99
+ }
100
+
101
+ // jump over if line content doesn't match the expected string
102
+ if (2 !== \sscanf($line, '%d %d', $startObject, $entryCount)) {
103
+ continue;
104
+ }
105
+
106
+ $oldPosition = $this->reader->getPosition();
107
+ $position = $oldPosition + $this->reader->getOffset();
108
+
109
+ if (!$validityChecked && $entryCount > 0) {
110
+ $nextLine = $this->reader->readBytes(21);
111
+ /* Check the next line for maximum of 20 bytes and not longer
112
+ * By catching 21 bytes and trimming the length should be still 21.
113
+ */
114
+ if (\strlen(\trim($nextLine)) !== 21) {
115
+ throw new CrossReferenceException(
116
+ 'Cross-reference entries are larger than 20 bytes.',
117
+ CrossReferenceException::ENTRIES_TOO_LARGE
118
+ );
119
+ }
120
+
121
+ /* Check for less than 20 bytes: cut the line to 20 bytes and trim; have to result in exactly 18 bytes.
122
+ * If it would have less bytes the substring would get the first bytes of the next line which would
123
+ * evaluate to a 20 bytes long string after trimming.
124
+ */
125
+ if (\strlen(\trim(\substr($nextLine, 0, 20))) !== 18) {
126
+ throw new CrossReferenceException(
127
+ 'Cross-reference entries are less than 20 bytes.',
128
+ CrossReferenceException::ENTRIES_TOO_SHORT
129
+ );
130
+ }
131
+
132
+ $validityChecked = true;
133
+ }
134
+
135
+ $subSections[$position] = [$startObject, $entryCount];
136
+
137
+ $lastLineStart = $position + $entryCount * 20;
138
+ $this->reader->reset($lastLineStart);
139
+ }
140
+
141
+ if (\count($subSections) === 0) {
142
+ throw new CrossReferenceException(
143
+ 'No entries found in cross-reference.',
144
+ CrossReferenceException::NO_ENTRIES
145
+ );
146
+ }
147
+
148
+ $this->subSections = $subSections;
149
+ }
150
+
151
+ /**
152
+ * Fixes an invalid object number shift.
153
+ *
154
+ * This method can be used to repair documents with an invalid subsection header:
155
+ *
156
+ * <code>
157
+ * xref
158
+ * 1 7
159
+ * 0000000000 65535 f
160
+ * 0000000009 00000 n
161
+ * 0000412075 00000 n
162
+ * 0000412172 00000 n
163
+ * 0000412359 00000 n
164
+ * 0000412417 00000 n
165
+ * 0000412468 00000 n
166
+ * </code>
167
+ *
168
+ * It shall only be called on the first table.
169
+ *
170
+ * @return bool
171
+ */
172
+ public function fixFaultySubSectionShift()
173
+ {
174
+ $subSections = $this->getSubSections();
175
+ if (\count($subSections) > 1) {
176
+ return false;
177
+ }
178
+
179
+ $subSection = \current($subSections);
180
+ if ($subSection[0] != 1) {
181
+ return false;
182
+ }
183
+
184
+ if ($this->getOffsetFor(1) === false) {
185
+ foreach ($subSections as $offset => list($startObject, $objectCount)) {
186
+ $this->subSections[$offset] = [$startObject - 1, $objectCount];
187
+ }
188
+ return true;
189
+ }
190
+
191
+ return false;
192
+ }
193
+ }
includes/lib/FPDI/src/PdfParser/CrossReference/LineReader.php ADDED
@@ -0,0 +1,173 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\CrossReference;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\StreamReader;
15
+
16
+ /**
17
+ * Class LineReader
18
+ *
19
+ * This reader class read all cross-reference entries in a single run.
20
+ * It supports reading cross-references with e.g. invalid data (e.g. entries with a length < or > 20 bytes).
21
+ *
22
+ * @package setasign\Fpdi\PdfParser\CrossReference
23
+ */
24
+ class LineReader extends AbstractReader implements ReaderInterface
25
+ {
26
+ /**
27
+ * The object offsets.
28
+ *
29
+ * @var array
30
+ */
31
+ protected $offsets;
32
+
33
+ /**
34
+ * LineReader constructor.
35
+ *
36
+ * @param PdfParser $parser
37
+ */
38
+ public function __construct(PdfParser $parser)
39
+ {
40
+ $this->read($this->extract($parser->getStreamReader()));
41
+ parent::__construct($parser);
42
+ }
43
+
44
+ /**
45
+ * @inheritdoc
46
+ */
47
+ public function getOffsetFor($objectNumber)
48
+ {
49
+ if (isset($this->offsets[$objectNumber])) {
50
+ return $this->offsets[$objectNumber][0];
51
+ }
52
+
53
+ return false;
54
+ }
55
+
56
+ /**
57
+ * Get all found offsets.
58
+ *
59
+ * @return array
60
+ */
61
+ public function getOffsets()
62
+ {
63
+ return $this->offsets;
64
+ }
65
+
66
+ /**
67
+ * Extracts the cross reference data from the stream reader.
68
+ *
69
+ * @param StreamReader $reader
70
+ * @return string
71
+ * @throws CrossReferenceException
72
+ */
73
+ protected function extract(StreamReader $reader)
74
+ {
75
+ $cycles = -1;
76
+ $bytesPerCycle = 100;
77
+
78
+ $reader->reset(null, $bytesPerCycle);
79
+
80
+ while (
81
+ ($trailerPos = \strpos($reader->getBuffer(false), 'trailer', \max($bytesPerCycle * $cycles++, 0))) === false
82
+ ) {
83
+ if (false === $reader->increaseLength($bytesPerCycle)) {
84
+ break;
85
+ }
86
+ }
87
+
88
+ if (false === $trailerPos) {
89
+ throw new CrossReferenceException(
90
+ 'Unexpected end of cross reference. trailer-keyword not found.',
91
+ CrossReferenceException::NO_TRAILER_FOUND
92
+ );
93
+ }
94
+
95
+ $xrefContent = \substr($reader->getBuffer(false), 0, $trailerPos);
96
+ $reader->reset($reader->getPosition() + $trailerPos);
97
+
98
+ return $xrefContent;
99
+ }
100
+
101
+ /**
102
+ * Read the cross-reference entries.
103
+ *
104
+ * @param string $xrefContent
105
+ * @throws CrossReferenceException
106
+ */
107
+ protected function read($xrefContent)
108
+ {
109
+ // get eol markers in the first 100 bytes
110
+ \preg_match_all("/(\r\n|\n|\r)/", \substr($xrefContent, 0, 100), $m);
111
+
112
+ if (\count($m[0]) === 0) {
113
+ throw new CrossReferenceException(
114
+ 'No data found in cross-reference.',
115
+ CrossReferenceException::INVALID_DATA
116
+ );
117
+ }
118
+
119
+ // count(array_count_values()) is faster then count(array_unique())
120
+ // @see https://github.com/symfony/symfony/pull/23731
121
+ // can be reverted for php7.2
122
+ $differentLineEndings = \count(\array_count_values($m[0]));
123
+ if ($differentLineEndings > 1) {
124
+ $lines = \preg_split("/(\r\n|\n|\r)/", $xrefContent, -1, PREG_SPLIT_NO_EMPTY);
125
+ } else {
126
+ $lines = \explode($m[0][0], $xrefContent);
127
+ }
128
+
129
+ unset($differentLineEndings, $m);
130
+ $linesCount = \count($lines);
131
+ $start = null;
132
+ $entryCount = 0;
133
+
134
+ $offsets = [];
135
+
136
+ /** @noinspection ForeachInvariantsInspection */
137
+ for ($i = 0; $i < $linesCount; $i++) {
138
+ $line = \trim($lines[$i]);
139
+ if ($line) {
140
+ $pieces = \explode(' ', $line);
141
+
142
+ $c = \count($pieces);
143
+ switch ($c) {
144
+ case 2:
145
+ $start = (int) $pieces[0];
146
+ $entryCount += (int) $pieces[1];
147
+ break;
148
+
149
+ /** @noinspection PhpMissingBreakStatementInspection */
150
+ case 3:
151
+ switch ($pieces[2]) {
152
+ case 'n':
153
+ $offsets[$start] = [(int) $pieces[0], (int) $pieces[1]];
154
+ $start++;
155
+ break 2;
156
+ case 'f':
157
+ $start++;
158
+ break 2;
159
+ }
160
+ // fall through if pieces doesn't match
161
+
162
+ default:
163
+ throw new CrossReferenceException(
164
+ \sprintf('Unexpected data in xref table (%s)', \implode(' ', $pieces)),
165
+ CrossReferenceException::INVALID_DATA
166
+ );
167
+ }
168
+ }
169
+ }
170
+
171
+ $this->offsets = $offsets;
172
+ }
173
+ }
includes/lib/FPDI/src/PdfParser/CrossReference/ReaderInterface.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\CrossReference;
12
+
13
+ use setasign\Fpdi\PdfParser\Type\PdfDictionary;
14
+
15
+ /**
16
+ * ReaderInterface for cross-reference readers.
17
+ *
18
+ * @package setasign\Fpdi\PdfParser\CrossReference
19
+ */
20
+ interface ReaderInterface
21
+ {
22
+ /**
23
+ * Get an offset by an object number.
24
+ *
25
+ * @param int $objectNumber
26
+ * @return int|bool False if the offset was not found.
27
+ */
28
+ public function getOffsetFor($objectNumber);
29
+
30
+ /**
31
+ * Get the trailer related to this cross reference.
32
+ *
33
+ * @return PdfDictionary
34
+ */
35
+ public function getTrailer();
36
+ }
includes/lib/FPDI/src/PdfParser/Filter/Ascii85.php ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Filter;
12
+
13
+ /**
14
+ * Class for handling ASCII base-85 encoded data
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Filter
17
+ */
18
+ class Ascii85 implements FilterInterface
19
+ {
20
+ /**
21
+ * Decode ASCII85 encoded string.
22
+ *
23
+ * @param string $data The input string
24
+ * @return string
25
+ * @throws Ascii85Exception
26
+ */
27
+ public function decode($data)
28
+ {
29
+ $out = '';
30
+ $state = 0;
31
+ $chn = null;
32
+
33
+ $l = \strlen($data);
34
+
35
+ /** @noinspection ForeachInvariantsInspection */
36
+ for ($k = 0; $k < $l; ++$k) {
37
+ $ch = \ord($data[$k]) & 0xff;
38
+
39
+ //Start <~
40
+ if ($k === 0 && $ch === 60 && isset($data[$k + 1]) && (\ord($data[$k + 1]) & 0xFF) === 126) {
41
+ $k++;
42
+ continue;
43
+ }
44
+ //End ~>
45
+ if ($ch === 126 && isset($data[$k + 1]) && (\ord($data[$k + 1]) & 0xFF) === 62) {
46
+ break;
47
+ }
48
+ if (\preg_match('/^\s$/', \chr($ch))) {
49
+ continue;
50
+ }
51
+ if ($ch === 122 /* z */ && $state === 0) {
52
+ $out .= \chr(0) . \chr(0) . \chr(0) . \chr(0);
53
+ continue;
54
+ }
55
+ if ($ch < 33 /* ! */ || $ch > 117 /* u */) {
56
+ throw new Ascii85Exception(
57
+ 'Illegal character found while ASCII85 decode.',
58
+ Ascii85Exception::ILLEGAL_CHAR_FOUND
59
+ );
60
+ }
61
+
62
+ $chn[$state] = $ch - 33;/* ! */
63
+ $state++;
64
+
65
+ if ($state === 5) {
66
+ $state = 0;
67
+ $r = 0;
68
+ for ($j = 0; $j < 5; ++$j) {
69
+ /** @noinspection UnnecessaryCastingInspection */
70
+ $r = (int)($r * 85 + $chn[$j]);
71
+ }
72
+
73
+ $out .= \chr($r >> 24)
74
+ . \chr($r >> 16)
75
+ . \chr($r >> 8)
76
+ . \chr($r);
77
+ }
78
+ }
79
+
80
+ if ($state === 1) {
81
+ throw new Ascii85Exception(
82
+ 'Illegal length while ASCII85 decode.',
83
+ Ascii85Exception::ILLEGAL_LENGTH
84
+ );
85
+ }
86
+
87
+ if ($state === 2) {
88
+ $r = $chn[0] * 85 * 85 * 85 * 85 + ($chn[1] + 1) * 85 * 85 * 85;
89
+ $out .= \chr($r >> 24);
90
+
91
+ } elseif ($state === 3) {
92
+ $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + ($chn[2] + 1) * 85 * 85;
93
+ $out .= \chr($r >> 24);
94
+ $out .= \chr($r >> 16);
95
+
96
+ } elseif ($state === 4) {
97
+ $r = $chn[0] * 85 * 85 * 85 * 85 + $chn[1] * 85 * 85 * 85 + $chn[2] * 85 * 85 + ($chn[3] + 1) * 85;
98
+ $out .= \chr($r >> 24);
99
+ $out .= \chr($r >> 16);
100
+ $out .= \chr($r >> 8);
101
+ }
102
+
103
+ return $out;
104
+ }
105
+ }
includes/lib/FPDI/src/PdfParser/Filter/Ascii85Exception.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Filter;
12
+
13
+ /**
14
+ * Exception for Ascii85 filter class
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Filter
17
+ */
18
+ class Ascii85Exception extends FilterException
19
+ {
20
+ /**
21
+ * @var integer
22
+ */
23
+ const ILLEGAL_CHAR_FOUND = 0x0301;
24
+
25
+ /**
26
+ * @var integer
27
+ */
28
+ const ILLEGAL_LENGTH = 0x0302;
29
+ }
includes/lib/FPDI/src/PdfParser/Filter/AsciiHex.php ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Filter;
12
+
13
+ /**
14
+ * Class for handling ASCII hexadecimal encoded data
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Filter
17
+ */
18
+ class AsciiHex implements FilterInterface
19
+ {
20
+ /**
21
+ * Converts an ASCII hexadecimal encoded string into its binary representation.
22
+ *
23
+ * @param string $data The input string
24
+ * @return string
25
+ */
26
+ public function decode($data)
27
+ {
28
+ $data = \preg_replace('/[^0-9A-Fa-f]/', '', \rtrim($data, '>'));
29
+ if ((\strlen($data) % 2) === 1) {
30
+ $data .= '0';
31
+ }
32
+
33
+ return \pack('H*', $data);
34
+ }
35
+
36
+ /**
37
+ * Converts a string into ASCII hexadecimal representation.
38
+ *
39
+ * @param string $data The input string
40
+ * @param boolean $leaveEOD
41
+ * @return string
42
+ */
43
+ public function encode($data, $leaveEOD = false)
44
+ {
45
+ $t = \unpack('H*', $data);
46
+ return \current($t)
47
+ . ($leaveEOD ? '' : '>');
48
+ }
49
+ }
includes/lib/FPDI/src/PdfParser/Filter/FilterException.php ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Filter;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParserException;
14
+
15
+ /**
16
+ * Exception for filters
17
+ *
18
+ * @package setasign\Fpdi\PdfParser\Filter
19
+ */
20
+ class FilterException extends PdfParserException
21
+ {
22
+ const UNSUPPORTED_FILTER = 0x0201;
23
+
24
+ const NOT_IMPLEMENTED = 0x0202;
25
+ }
includes/lib/FPDI/src/PdfParser/Filter/FilterInterface.php ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Filter;
12
+
13
+ /**
14
+ * Interface for filters
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Filter
17
+ */
18
+ interface FilterInterface
19
+ {
20
+ /**
21
+ * Decode a string.
22
+ *
23
+ * @param string $data The input string
24
+ * @return string
25
+ */
26
+ public function decode($data);
27
+ }
includes/lib/FPDI/src/PdfParser/Filter/Flate.php ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Filter;
12
+
13
+ /**
14
+ * Class for handling zlib/deflate encoded data
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Filter
17
+ */
18
+ class Flate implements FilterInterface
19
+ {
20
+ /**
21
+ * Checks whether the zlib extension is loaded.
22
+ *
23
+ * Used for testing purpose.
24
+ *
25
+ * @return boolean
26
+ * @internal
27
+ */
28
+ protected function extensionLoaded()
29
+ {
30
+ return \extension_loaded('zlib');
31
+ }
32
+
33
+ /**
34
+ * Decodes a flate compressed string.
35
+ *
36
+ * @param string $data The input string
37
+ * @return string
38
+ * @throws FlateException
39
+ */
40
+ public function decode($data)
41
+ {
42
+ if ($this->extensionLoaded()) {
43
+ $oData = $data;
44
+ $data = @((\strlen($data) > 0) ? \gzuncompress($data) : '');
45
+ if (false === $data) {
46
+ // Try this fallback
47
+ $tries = 1;
48
+ while ($tries < 10 && ($data === false || \strlen($data) < (\strlen($oData) - $tries - 1))) {
49
+ $data = @(\gzinflate(\substr($oData, $tries)));
50
+ $tries++;
51
+ }
52
+
53
+ if (false === $data) {
54
+ throw new FlateException(
55
+ 'Error while decompressing stream.',
56
+ FlateException::DECOMPRESS_ERROR
57
+ );
58
+ }
59
+ }
60
+ } else {
61
+ throw new FlateException(
62
+ 'To handle FlateDecode filter, enable zlib support in PHP.',
63
+ FlateException::NO_ZLIB
64
+ );
65
+ }
66
+
67
+ return $data;
68
+ }
69
+ }
includes/lib/FPDI/src/PdfParser/Filter/FlateException.php ADDED
@@ -0,0 +1,29 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Filter;
12
+
13
+ /**
14
+ * Exception for flate filter class
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Filter
17
+ */
18
+ class FlateException extends FilterException
19
+ {
20
+ /**
21
+ * @var integer
22
+ */
23
+ const NO_ZLIB = 0x0401;
24
+
25
+ /**
26
+ * @var integer
27
+ */
28
+ const DECOMPRESS_ERROR = 0x0402;
29
+ }
includes/lib/FPDI/src/PdfParser/Filter/Lzw.php ADDED
@@ -0,0 +1,190 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Filter;
12
+
13
+ /**
14
+ * Class for handling LZW encoded data
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Filter
17
+ */
18
+ class Lzw implements FilterInterface
19
+ {
20
+ /**
21
+ * @var null|string
22
+ */
23
+ protected $data;
24
+
25
+ /**
26
+ * @var array
27
+ */
28
+ protected $sTable = [];
29
+
30
+ /**
31
+ * @var int
32
+ */
33
+ protected $dataLength = 0;
34
+
35
+ /**
36
+ * @var int
37
+ */
38
+ protected $tIdx;
39
+
40
+ /**
41
+ * @var int
42
+ */
43
+ protected $bitsToGet = 9;
44
+
45
+ /**
46
+ * @var int
47
+ */
48
+ protected $bytePointer;
49
+
50
+ /**
51
+ * @var int
52
+ */
53
+ protected $nextData = 0;
54
+
55
+ /**
56
+ * @var int
57
+ */
58
+ protected $nextBits = 0;
59
+
60
+ /**
61
+ * @var array
62
+ */
63
+ protected $andTable = [511, 1023, 2047, 4095];
64
+
65
+ /**
66
+ * Method to decode LZW compressed data.
67
+ *
68
+ * @param string $data The compressed data
69
+ * @return string The uncompressed data
70
+ * @throws LzwException
71
+ */
72
+ public function decode($data)
73
+ {
74
+ if ($data[0] == 0x00 && $data[1] == 0x01) {
75
+ throw new LzwException(
76
+ 'LZW flavour not supported.',
77
+ LzwException::LZW_FLAVOUR_NOT_SUPPORTED
78
+ );
79
+ }
80
+
81
+ $this->initsTable();
82
+
83
+ $this->data = $data;
84
+ $this->dataLength = \strlen($data);
85
+
86
+ // Initialize pointers
87
+ $this->bytePointer = 0;
88
+
89
+ $this->nextData = 0;
90
+ $this->nextBits = 0;
91
+
92
+ $oldCode = 0;
93
+
94
+ $uncompData = '';
95
+
96
+ while (($code = $this->getNextCode()) != 257) {
97
+ if ($code == 256) {
98
+ $this->initsTable();
99
+ $code = $this->getNextCode();
100
+
101
+ if ($code == 257) {
102
+ break;
103
+ }
104
+
105
+ $uncompData .= $this->sTable[$code];
106
+ $oldCode = $code;
107
+
108
+ } else {
109
+ if ($code < $this->tIdx) {
110
+ $string = $this->sTable[$code];
111
+ $uncompData .= $string;
112
+
113
+ $this->addStringToTable($this->sTable[$oldCode], $string[0]);
114
+ $oldCode = $code;
115
+ } else {
116
+ $string = $this->sTable[$oldCode];
117
+ $string .= $string[0];
118
+ $uncompData .= $string;
119
+
120
+ $this->addStringToTable($string);
121
+ $oldCode = $code;
122
+ }
123
+ }
124
+ }
125
+
126
+ return $uncompData;
127
+ }
128
+
129
+ /**
130
+ * Initialize the string table.
131
+ */
132
+ protected function initsTable()
133
+ {
134
+ $this->sTable = [];
135
+
136
+ for ($i = 0; $i < 256; $i++) {
137
+ $this->sTable[$i] = \chr($i);
138
+ }
139
+
140
+ $this->tIdx = 258;
141
+ $this->bitsToGet = 9;
142
+ }
143
+
144
+ /**
145
+ * Add a new string to the string table.
146
+ *
147
+ * @param string $oldString
148
+ * @param string $newString
149
+ */
150
+ protected function addStringToTable($oldString, $newString = '')
151
+ {
152
+ $string = $oldString . $newString;
153
+
154
+ // Add this new String to the table
155
+ $this->sTable[$this->tIdx++] = $string;
156
+
157
+ if ($this->tIdx == 511) {
158
+ $this->bitsToGet = 10;
159
+ } elseif ($this->tIdx == 1023) {
160
+ $this->bitsToGet = 11;
161
+ } elseif ($this->tIdx == 2047) {
162
+ $this->bitsToGet = 12;
163
+ }
164
+ }
165
+
166
+ /**
167
+ * Returns the next 9, 10, 11 or 12 bits.
168
+ *
169
+ * @return integer
170
+ */
171
+ protected function getNextCode()
172
+ {
173
+ if ($this->bytePointer == $this->dataLength) {
174
+ return 257;
175
+ }
176
+
177
+ $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff);
178
+ $this->nextBits += 8;
179
+
180
+ if ($this->nextBits < $this->bitsToGet) {
181
+ $this->nextData = ($this->nextData << 8) | (\ord($this->data[$this->bytePointer++]) & 0xff);
182
+ $this->nextBits += 8;
183
+ }
184
+
185
+ $code = ($this->nextData >> ($this->nextBits - $this->bitsToGet)) & $this->andTable[$this->bitsToGet - 9];
186
+ $this->nextBits -= $this->bitsToGet;
187
+
188
+ return $code;
189
+ }
190
+ }
includes/lib/FPDI/src/PdfParser/Filter/LzwException.php ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Filter;
12
+
13
+ /**
14
+ * Exception for LZW filter class
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Filter
17
+ */
18
+ class LzwException extends FilterException
19
+ {
20
+ /**
21
+ * @var integer
22
+ */
23
+ const LZW_FLAVOUR_NOT_SUPPORTED = 0x0501;
24
+ }
includes/lib/FPDI/src/PdfParser/PdfParser.php ADDED
@@ -0,0 +1,305 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser;
12
+
13
+ use setasign\Fpdi\PdfParser\CrossReference\CrossReference;
14
+ use setasign\Fpdi\PdfParser\Type\PdfArray;
15
+ use setasign\Fpdi\PdfParser\Type\PdfBoolean;
16
+ use setasign\Fpdi\PdfParser\Type\PdfDictionary;
17
+ use setasign\Fpdi\PdfParser\Type\PdfHexString;
18
+ use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
19
+ use setasign\Fpdi\PdfParser\Type\PdfIndirectObjectReference;
20
+ use setasign\Fpdi\PdfParser\Type\PdfName;
21
+ use setasign\Fpdi\PdfParser\Type\PdfNull;
22
+ use setasign\Fpdi\PdfParser\Type\PdfNumeric;
23
+ use setasign\Fpdi\PdfParser\Type\PdfString;
24
+ use setasign\Fpdi\PdfParser\Type\PdfToken;
25
+ use setasign\Fpdi\PdfParser\Type\PdfType;
26
+
27
+ /**
28
+ * A PDF parser class
29
+ *
30
+ * @package setasign\Fpdi\PdfParser
31
+ */
32
+ class PdfParser
33
+ {
34
+ /**
35
+ * @var StreamReader
36
+ */
37
+ protected $streamReader;
38
+
39
+ /**
40
+ * @var Tokenizer
41
+ */
42
+ protected $tokenizer;
43
+
44
+ /**
45
+ * The file header.
46
+ *
47
+ * @var string
48
+ */
49
+ protected $fileHeader;
50
+
51
+ /**
52
+ * The offset to the file header.
53
+ *
54
+ * @var int
55
+ */
56
+ protected $fileHeaderOffset;
57
+
58
+ /**
59
+ * @var CrossReference
60
+ */
61
+ protected $xref;
62
+
63
+ /**
64
+ * All read objects.
65
+ *
66
+ * @var array
67
+ */
68
+ protected $objects = [];
69
+
70
+ /**
71
+ * PdfParser constructor.
72
+ *
73
+ * @param StreamReader $streamReader
74
+ */
75
+ public function __construct(StreamReader $streamReader)
76
+ {
77
+ $this->streamReader = $streamReader;
78
+ $this->tokenizer = new Tokenizer($streamReader);
79
+ }
80
+
81
+ /**
82
+ * Removes cycled references.
83
+ *
84
+ * @internal
85
+ */
86
+ public function cleanUp()
87
+ {
88
+ $this->xref = null;
89
+ }
90
+
91
+ /**
92
+ * Get the stream reader instance.
93
+ *
94
+ * @return StreamReader
95
+ */
96
+ public function getStreamReader()
97
+ {
98
+ return $this->streamReader;
99
+ }
100
+
101
+ /**
102
+ * Get the tokenizer instance.
103
+ *
104
+ * @return Tokenizer
105
+ */
106
+ public function getTokenizer()
107
+ {
108
+ return $this->tokenizer;
109
+ }
110
+
111
+ /**
112
+ * Resolves the file header.
113
+ *
114
+ * @throws PdfParserException
115
+ */
116
+ protected function resolveFileHeader()
117
+ {
118
+ if ($this->fileHeader) {
119
+ return $this->fileHeaderOffset;
120
+ }
121
+
122
+ $this->streamReader->reset(0);
123
+ $offset = false;
124
+ $maxIterations = 1000;
125
+ while (true) {
126
+ $buffer = $this->streamReader->getBuffer(false);
127
+ $offset = \strpos($buffer, '%PDF-');
128
+ if (false === $offset) {
129
+ if (!$this->streamReader->increaseLength(100) || (--$maxIterations === 0)) {
130
+ throw new PdfParserException(
131
+ 'Unable to find PDF file header.',
132
+ PdfParserException::FILE_HEADER_NOT_FOUND
133
+ );
134
+ }
135
+ continue;
136
+ }
137
+ break;
138
+ }
139
+
140
+ $this->fileHeaderOffset = $offset;
141
+ $this->streamReader->setOffset($offset);
142
+
143
+ $this->fileHeader = \trim($this->streamReader->readLine());
144
+ return $this->fileHeaderOffset;
145
+ }
146
+
147
+ /**
148
+ * Get the cross reference instance.
149
+ *
150
+ * @return CrossReference
151
+ */
152
+ public function getCrossReference()
153
+ {
154
+ if (null === $this->xref) {
155
+ $this->xref = new CrossReference($this, $this->resolveFileHeader());
156
+ }
157
+
158
+ return $this->xref;
159
+ }
160
+
161
+ /**
162
+ * Get the PDF version.
163
+ *
164
+ * @return int[] An array of major and minor version.
165
+ * @throws PdfParserException
166
+ */
167
+ public function getPdfVersion()
168
+ {
169
+ $this->resolveFileHeader();
170
+
171
+ if (\preg_match('/%PDF-(\d)\.(\d)/', $this->fileHeader, $result) === 0) {
172
+ throw new PdfParserException(
173
+ 'Unable to extract PDF version from file header.',
174
+ PdfParserException::PDF_VERSION_NOT_FOUND
175
+ );
176
+ }
177
+ list(, $major, $minor) = $result;
178
+
179
+ $catalog = $this->getCatalog();
180
+ if (isset($catalog->value['Version'])) {
181
+ $versionParts = \explode('.', PdfName::unescape(PdfType::resolve($catalog->value['Version'], $this)->value));
182
+ if (count($versionParts) === 2) {
183
+ list($major, $minor) = $versionParts;
184
+ }
185
+ }
186
+
187
+ return [(int) $major, (int) $minor];
188
+ }
189
+
190
+ /**
191
+ * Get the catalog dictionary.
192
+ *
193
+ * @return PdfDictionary
194
+ */
195
+ public function getCatalog()
196
+ {
197
+ $xref = $this->getCrossReference();
198
+ $trailer = $xref->getTrailer();
199
+
200
+ $catalog = PdfType::resolve(PdfDictionary::get($trailer, 'Root'), $this);
201
+
202
+ return PdfDictionary::ensure($catalog);
203
+ }
204
+
205
+ /**
206
+ * Get an indirect object by its object number.
207
+ *
208
+ * @param int $objectNumber
209
+ * @param bool $cache
210
+ * @return PdfIndirectObject
211
+ */
212
+ public function getIndirectObject($objectNumber, $cache = false)
213
+ {
214
+ $objectNumber = (int) $objectNumber;
215
+ if (isset($this->objects[$objectNumber])) {
216
+ return $this->objects[$objectNumber];
217
+ }
218
+
219
+ $xref = $this->getCrossReference();
220
+ $object = $xref->getIndirectObject($objectNumber);
221
+
222
+ if ($cache) {
223
+ $this->objects[$objectNumber] = $object;
224
+ }
225
+
226
+ return $object;
227
+ }
228
+
229
+ /**
230
+ * Read a PDF value.
231
+ *
232
+ * @param null|bool|string $token
233
+ * @return bool|PdfArray|PdfBoolean|PdfHexString|PdfName|PdfNull|PdfNumeric|PdfString|PdfToken|PdfIndirectObjectReference
234
+ */
235
+ public function readValue($token = null)
236
+ {
237
+ if (null === $token) {
238
+ $token = $this->tokenizer->getNextToken();
239
+ }
240
+
241
+ if (false === $token) {
242
+ return false;
243
+ }
244
+
245
+ switch ($token) {
246
+ case '(':
247
+ return PdfString::parse($this->streamReader);
248
+
249
+ case '<':
250
+ if ($this->streamReader->getByte() === '<') {
251
+ $this->streamReader->addOffset(1);
252
+ return PdfDictionary::parse($this->tokenizer, $this->streamReader, $this);
253
+ }
254
+
255
+ return PdfHexString::parse($this->streamReader);
256
+
257
+ case '/':
258
+ return PdfName::parse($this->tokenizer, $this->streamReader);
259
+
260
+ case '[':
261
+ return PdfArray::parse($this->tokenizer, $this);
262
+
263
+ default:
264
+ if (\is_numeric($token)) {
265
+ if (($token2 = $this->tokenizer->getNextToken()) !== false) {
266
+ if (\is_numeric($token2)) {
267
+ if (($token3 = $this->tokenizer->getNextToken()) !== false) {
268
+ switch ($token3) {
269
+ case 'obj':
270
+ return PdfIndirectObject::parse(
271
+ $token,
272
+ $token2,
273
+ $this,
274
+ $this->tokenizer,
275
+ $this->streamReader
276
+ );
277
+ case 'R':
278
+ return PdfIndirectObjectReference::create($token, $token2);
279
+ }
280
+
281
+ $this->tokenizer->pushStack($token3);
282
+ }
283
+ }
284
+
285
+ $this->tokenizer->pushStack($token2);
286
+ }
287
+
288
+ return PdfNumeric::create($token);
289
+ }
290
+
291
+ if ('true' === $token || 'false' === $token) {
292
+ return PdfBoolean::create('true' === $token);
293
+ }
294
+
295
+ if ('null' === $token) {
296
+ return new PdfNull();
297
+ }
298
+
299
+ $v = new PdfToken();
300
+ $v->value = $token;
301
+
302
+ return $v;
303
+ }
304
+ }
305
+ }
includes/lib/FPDI/src/PdfParser/PdfParserException.php ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser;
12
+
13
+ use setasign\Fpdi\FpdiException;
14
+
15
+ /**
16
+ * Exception for the pdf parser class
17
+ *
18
+ * @package setasign\Fpdi\PdfParser
19
+ */
20
+ class PdfParserException extends FpdiException
21
+ {
22
+ /**
23
+ * @var int
24
+ */
25
+ const NOT_IMPLEMENTED = 0x0001;
26
+
27
+ /**
28
+ * @var int
29
+ */
30
+ const IMPLEMENTED_IN_FPDI_PDF_PARSER = 0x0002;
31
+
32
+ /**
33
+ * @var int
34
+ */
35
+ const INVALID_DATA_TYPE = 0x0003;
36
+
37
+ /**
38
+ * @var int
39
+ */
40
+ const FILE_HEADER_NOT_FOUND = 0x0004;
41
+
42
+ /**
43
+ * @var int
44
+ */
45
+ const PDF_VERSION_NOT_FOUND = 0x0005;
46
+
47
+ /**
48
+ * @var int
49
+ */
50
+ const INVALID_DATA_SIZE = 0x0006;
51
+ }
includes/lib/FPDI/src/PdfParser/StreamReader.php ADDED
@@ -0,0 +1,461 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser;
12
+
13
+ /**
14
+ * A stream reader class
15
+ *
16
+ * @package setasign\Fpdi\PdfParser
17
+ */
18
+ class StreamReader
19
+ {
20
+ /**
21
+ * Creates a stream reader instance by a string value.
22
+ *
23
+ * @param string $content
24
+ * @param int $maxMemory
25
+ * @return StreamReader
26
+ */
27
+ public static function createByString($content, $maxMemory = 2097152)
28
+ {
29
+ $h = \fopen('php://temp/maxmemory:' . ((int) $maxMemory), 'r+b');
30
+ \fwrite($h, $content);
31
+ \rewind($h);
32
+
33
+ return new self($h, true);
34
+ }
35
+
36
+ /**
37
+ * Creates a stream reader instance by a filename.
38
+ *
39
+ * @param string $filename
40
+ * @return StreamReader
41
+ */
42
+ public static function createByFile($filename)
43
+ {
44
+ $h = \fopen($filename, 'rb');
45
+ return new self($h, true);
46
+ }
47
+
48
+ /**
49
+ * Defines whether the stream should be closed when the stream reader instance is deconstructed or not.
50
+ *
51
+ * @var bool
52
+ */
53
+ protected $closeStream;
54
+
55
+ /**
56
+ * The stream resource.
57
+ *
58
+ * @var resource
59
+ */
60
+ protected $stream;
61
+
62
+ /**
63
+ * The byte-offset position in the stream.
64
+ *
65
+ * @var int
66
+ */
67
+ protected $position;
68
+
69
+ /**
70
+ * The byte-offset position in the buffer.
71
+ *
72
+ * @var int
73
+ */
74
+ protected $offset;
75
+
76
+ /**
77
+ * The buffer length.
78
+ *
79
+ * @var int
80
+ */
81
+ protected $bufferLength;
82
+
83
+ /**
84
+ * The total length of the stream.
85
+ *
86
+ * @var int
87
+ */
88
+ protected $totalLength;
89
+
90
+ /**
91
+ * The buffer.
92
+ *
93
+ * @var string
94
+ */
95
+ protected $buffer;
96
+
97
+ /**
98
+ * StreamReader constructor.
99
+ *
100
+ * @param resource $stream
101
+ * @param bool $closeStream Defines whether to close the stream resource if the instance is destructed or not.
102
+ */
103
+ public function __construct($stream, $closeStream = false)
104
+ {
105
+ if (!\is_resource($stream)) {
106
+ throw new \InvalidArgumentException(
107
+ 'No stream given.'
108
+ );
109
+ }
110
+
111
+ $metaData = \stream_get_meta_data($stream);
112
+ if (!$metaData['seekable']) {
113
+ throw new \InvalidArgumentException(
114
+ 'Given stream is not seekable!'
115
+ );
116
+ }
117
+
118
+ $this->stream = $stream;
119
+ $this->closeStream = $closeStream;
120
+ $this->reset();
121
+ }
122
+
123
+ /**
124
+ * The destructor.
125
+ */
126
+ public function __destruct()
127
+ {
128
+ if ($this->closeStream) {
129
+ \fclose($this->stream);
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Returns the byte length of the buffer.
135
+ *
136
+ * @param bool $atOffset
137
+ * @return int
138
+ */
139
+ public function getBufferLength($atOffset = false)
140
+ {
141
+ if ($atOffset === false) {
142
+ return $this->bufferLength;
143
+ }
144
+
145
+ return $this->bufferLength - $this->offset;
146
+ }
147
+
148
+ /**
149
+ * Get the current position in the stream.
150
+ *
151
+ * @return int
152
+ */
153
+ public function getPosition()
154
+ {
155
+ return $this->position;
156
+ }
157
+
158
+ /**
159
+ * Returns the current buffer.
160
+ *
161
+ * @param bool $atOffset
162
+ * @return string
163
+ */
164
+ public function getBuffer($atOffset = true)
165
+ {
166
+ if (false === $atOffset) {
167
+ return $this->buffer;
168
+ }
169
+
170
+ $string = \substr($this->buffer, $this->offset);
171
+
172
+ return (string) $string;
173
+ }
174
+
175
+ /**
176
+ * Gets a byte at a specific position in the buffer.
177
+ *
178
+ * If the position is invalid the method will return false.
179
+ *
180
+ * If the $position parameter is set to null the value of $this->offset will be used.
181
+ *
182
+ * @param int|null $position
183
+ * @return string|bool
184
+ */
185
+ public function getByte($position = null)
186
+ {
187
+ $position = (int) (null !== $position ? $position : $this->offset);
188
+ if ($position >= $this->bufferLength &&
189
+ (!$this->increaseLength() || $position >= $this->bufferLength)
190
+ ) {
191
+ return false;
192
+ }
193
+
194
+ return $this->buffer[$position];
195
+ }
196
+
197
+ /**
198
+ * Returns a byte at a specific position, and set the offset to the next byte position.
199
+ *
200
+ * If the position is invalid the method will return false.
201
+ *
202
+ * If the $position parameter is set to null the value of $this->offset will be used.
203
+ *
204
+ * @param int|null $position
205
+ * @return string|bool
206
+ */
207
+ public function readByte($position = null)
208
+ {
209
+ if (null !== $position) {
210
+ $position = (int) $position;
211
+ // check if needed bytes are available in the current buffer
212
+ if (!($position >= $this->position && $position < $this->position + $this->bufferLength)) {
213
+ $this->reset($position);
214
+ $offset = $this->offset;
215
+ } else {
216
+ $offset = $position - $this->position;
217
+ }
218
+ } else {
219
+ $offset = $this->offset;
220
+ }
221
+
222
+ if ($offset >= $this->bufferLength &&
223
+ ((!$this->increaseLength()) || $offset >= $this->bufferLength)
224
+ ) {
225
+ return false;
226
+ }
227
+
228
+ $this->offset = $offset + 1;
229
+ return $this->buffer[$offset];
230
+ }
231
+
232
+ /**
233
+ * Read bytes from the current or a specific offset position and set the internal pointer to the next byte.
234
+ *
235
+ * If the position is invalid the method will return false.
236
+ *
237
+ * If the $position parameter is set to null the value of $this->offset will be used.
238
+ *
239
+ * @param int $length
240
+ * @param int|null $position
241
+ * @return string
242
+ */
243
+ public function readBytes($length, $position = null)
244
+ {
245
+ $length = (int) $length;
246
+ if (null !== $position) {
247
+ // check if needed bytes are available in the current buffer
248
+ if (!($position >= $this->position && $position < $this->position + $this->bufferLength)) {
249
+ $this->reset($position, $length);
250
+ $offset = $this->offset;
251
+ } else {
252
+ $offset = $position - $this->position;
253
+ }
254
+ } else {
255
+ $offset = $this->offset;
256
+ }
257
+
258
+ if (($offset + $length) > $this->bufferLength &&
259
+ ((!$this->increaseLength($length)) || ($offset + $length) > $this->bufferLength)
260
+ ) {
261
+ return false;
262
+ }
263
+
264
+ $bytes = \substr($this->buffer, $offset, $length);
265
+ $this->offset = $offset + $length;
266
+
267
+ return $bytes;
268
+ }
269
+
270
+ /**
271
+ * Read a line from the current position.
272
+ *
273
+ * @param int $length
274
+ * @return string|bool
275
+ */
276
+ public function readLine($length = 1024)
277
+ {
278
+ if (false === $this->ensureContent()) {
279
+ return false;
280
+ }
281
+
282
+ $line = '';
283
+ while ($this->ensureContent()) {
284
+ $char = $this->readByte();
285
+
286
+ if ($char === "\n") {
287
+ break;
288
+ }
289
+
290
+ if ($char === "\r") {
291
+ if ($this->getByte() === "\n") {
292
+ $this->addOffset(1);
293
+ }
294
+ break;
295
+ }
296
+
297
+ $line .= $char;
298
+
299
+ if (\strlen($line) >= $length) {
300
+ break;
301
+ }
302
+ }
303
+
304
+ return $line;
305
+ }
306
+
307
+ /**
308
+ * Set the offset position in the current buffer.
309
+ *
310
+ * @param int $offset
311
+ */
312
+ public function setOffset($offset)
313
+ {
314
+ if ($offset > $this->bufferLength || $offset < 0) {
315
+ throw new \OutOfRangeException(
316
+ \sprintf('Offset (%s) out of range (length: %s)', $offset, $this->bufferLength)
317
+ );
318
+ }
319
+
320
+ $this->offset = (int) $offset;
321
+ }
322
+
323
+ /**
324
+ * Returns the current offset in the current buffer.
325
+ *
326
+ * @return int
327
+ */
328
+ public function getOffset()
329
+ {
330
+ return $this->offset;
331
+ }
332
+
333
+ /**
334
+ * Add an offset to the current offset.
335
+ *
336
+ * @param int $offset
337
+ */
338
+ public function addOffset($offset)
339
+ {
340
+ $this->setOffset($this->offset + $offset);
341
+ }
342
+
343
+ /**
344
+ * Make sure that there is at least one character beyond the current offset in the buffer.
345
+ *
346
+ * @return bool
347
+ */
348
+ public function ensureContent()
349
+ {
350
+ while ($this->offset >= $this->bufferLength) {
351
+ if (!$this->increaseLength()) {
352
+ return false;
353
+ }
354
+ }
355
+ return true;
356
+ }
357
+
358
+ /**
359
+ * Returns the stream.
360
+ *
361
+ * @return resource
362
+ */
363
+ public function getStream()
364
+ {
365
+ return $this->stream;
366
+ }
367
+
368
+ /**
369
+ * Gets the total available length.
370
+ *
371
+ * @return int
372
+ */
373
+ public function getTotalLength()
374
+ {
375
+ if (null === $this->totalLength) {
376
+ $stat = \fstat($this->stream);
377
+ $this->totalLength = $stat['size'];
378
+ }
379
+
380
+ return $this->totalLength;
381
+ }
382
+
383
+ /**
384
+ * Resets the buffer to a position and re-read the buffer with the given length.
385
+ *
386
+ * If the $pos parameter is negative the start buffer position will be the $pos'th position from
387
+ * the end of the file.
388
+ *
389
+ * If the $pos parameter is negative and the absolute value is bigger then the totalLength of
390
+ * the file $pos will set to zero.
391
+ *
392
+ * @param int|null $pos Start position of the new buffer
393
+ * @param int $length Length of the new buffer. Mustn't be negative
394
+ */
395
+ public function reset($pos = 0, $length = 200)
396
+ {
397
+ if (null === $pos) {
398
+ $pos = $this->position + $this->offset;
399
+ } elseif ($pos < 0) {
400
+ $pos = \max(0, $this->getTotalLength() + $pos);
401
+ }
402
+
403
+ \fseek($this->stream, $pos);
404
+
405
+ $this->position = $pos;
406
+ $this->buffer = $length > 0 ? \fread($this->stream, $length) : '';
407
+ $this->bufferLength = \strlen($this->buffer);
408
+ $this->offset = 0;
409
+
410
+ // If a stream wrapper is in use it is possible that
411
+ // length values > 8096 will be ignored, so use the
412
+ // increaseLength()-method to correct that behavior
413
+ if ($this->bufferLength < $length && $this->increaseLength($length - $this->bufferLength)) {
414
+ // increaseLength parameter is $minLength, so cut to have only the required bytes in the buffer
415
+ $this->buffer = \substr($this->buffer, 0, $length);
416
+ $this->bufferLength = \strlen($this->buffer);
417
+ }
418
+ }
419
+
420
+ /**
421
+ * Ensures bytes in the buffer with a specific length and location in the file.
422
+ *
423
+ * @param int $pos
424
+ * @param int $length
425
+ * @see reset()
426
+ */
427
+ public function ensure($pos, $length)
428
+ {
429
+ if ($pos >= $this->position
430
+ && $pos < ($this->position + $this->bufferLength)
431
+ && ($this->position + $this->bufferLength) >= ($pos + $length)
432
+ ) {
433
+ $this->offset = $pos - $this->position;
434
+ } else {
435
+ $this->reset($pos, $length);
436
+ }
437
+ }
438
+
439
+ /**
440
+ * Forcefully read more data into the buffer.
441
+ *
442
+ * @param int $minLength
443
+ * @return bool Returns false if the stream reaches the end
444
+ */
445
+ public function increaseLength($minLength = 100)
446
+ {
447
+ $length = \max($minLength, 100);
448
+
449
+ if (\feof($this->stream) || $this->getTotalLength() === $this->position + $this->bufferLength) {
450
+ return false;
451
+ }
452
+
453
+ $newLength = $this->bufferLength + $length;
454
+ do {
455
+ $this->buffer .= \fread($this->stream, $newLength - $this->bufferLength);
456
+ $this->bufferLength = \strlen($this->buffer);
457
+ } while (($this->bufferLength !== $newLength) && !\feof($this->stream));
458
+
459
+ return true;
460
+ }
461
+ }
includes/lib/FPDI/src/PdfParser/Tokenizer.php ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser;
12
+
13
+ /**
14
+ * A tokenizer class.
15
+ *
16
+ * @package setasign\Fpdi\PdfParser
17
+ */
18
+ class Tokenizer
19
+ {
20
+ /**
21
+ * @var StreamReader
22
+ */
23
+ protected $streamReader;
24
+
25
+ /**
26
+ * A token stack.
27
+ *
28
+ * @var string[]
29
+ */
30
+ protected $stack = [];
31
+
32
+ /**
33
+ * Tokenizer constructor.
34
+ *
35
+ * @param StreamReader $streamReader
36
+ */
37
+ public function __construct(StreamReader $streamReader)
38
+ {
39
+ $this->streamReader = $streamReader;
40
+ }
41
+
42
+ /**
43
+ * Get the stream reader instance.
44
+ *
45
+ * @return StreamReader
46
+ */
47
+ public function getStreamReader()
48
+ {
49
+ return $this->streamReader;
50
+ }
51
+
52
+ /**
53
+ * Clear the token stack.
54
+ */
55
+ public function clearStack()
56
+ {
57
+ $this->stack = [];
58
+ }
59
+
60
+ /**
61
+ * Push a token onto the stack.
62
+ *
63
+ * @param string $token
64
+ */
65
+ public function pushStack($token)
66
+ {
67
+ $this->stack[] = $token;
68
+ }
69
+
70
+ /**
71
+ * Get next token.
72
+ *
73
+ * @return bool|string
74
+ */
75
+ public function getNextToken()
76
+ {
77
+ $token = \array_pop($this->stack);
78
+ if (null !== $token) {
79
+ return $token;
80
+ }
81
+
82
+ if (($byte = $this->streamReader->readByte()) === false) {
83
+ return false;
84
+ }
85
+
86
+ if ($byte === "\x20" ||
87
+ $byte === "\x0A" ||
88
+ $byte === "\x0D" ||
89
+ $byte === "\x0C" ||
90
+ $byte === "\x09" ||
91
+ $byte === "\x00"
92
+ ) {
93
+ if (false === $this->leapWhiteSpaces()) {
94
+ return false;
95
+ }
96
+ $byte = $this->streamReader->readByte();
97
+ }
98
+
99
+ switch ($byte) {
100
+ case '/':
101
+ case '[':
102
+ case ']':
103
+ case '(':
104
+ case ')':
105
+ case '{':
106
+ case '}':
107
+ case '<':
108
+ case '>':
109
+ return $byte;
110
+ case '%':
111
+ $this->streamReader->readLine();
112
+ return $this->getNextToken();
113
+ }
114
+
115
+ /* This way is faster than checking single bytes.
116
+ */
117
+ $bufferOffset = $this->streamReader->getOffset();
118
+ do {
119
+ $lastBuffer = $this->streamReader->getBuffer(false);
120
+ $pos = \strcspn(
121
+ $lastBuffer,
122
+ "\x00\x09\x0A\x0C\x0D\x20()<>[]{}/%",
123
+ $bufferOffset
124
+ );
125
+ } while (
126
+ // Break the loop if a delimiter or white space char is matched
127
+ // in the current buffer or increase the buffers length
128
+ $lastBuffer !== false &&
129
+ (
130
+ $bufferOffset + $pos === \strlen($lastBuffer) &&
131
+ $this->streamReader->increaseLength()
132
+ )
133
+ );
134
+
135
+ $result = \substr($lastBuffer, $bufferOffset - 1, $pos + 1);
136
+ $this->streamReader->setOffset($bufferOffset + $pos);
137
+
138
+ return $result;
139
+ }
140
+
141
+ /**
142
+ * Leap white spaces.
143
+ *
144
+ * @return boolean
145
+ */
146
+ public function leapWhiteSpaces()
147
+ {
148
+ do {
149
+ if (!$this->streamReader->ensureContent()) {
150
+ return false;
151
+ }
152
+
153
+ $buffer = $this->streamReader->getBuffer(false);
154
+ $matches = \strspn($buffer, "\x20\x0A\x0C\x0D\x09\x00", $this->streamReader->getOffset());
155
+ if ($matches > 0) {
156
+ $this->streamReader->addOffset($matches);
157
+ }
158
+ } while ($this->streamReader->getOffset() >= $this->streamReader->getBufferLength());
159
+
160
+ return true;
161
+ }
162
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfArray.php ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\Tokenizer;
15
+
16
+ /**
17
+ * Class representing a PDF array object
18
+ *
19
+ * @package setasign\Fpdi\PdfParser\Type
20
+ * @property array $value The value of the PDF type.
21
+ */
22
+ class PdfArray extends PdfType
23
+ {
24
+ /**
25
+ * Parses an array of the passed tokenizer and parser.
26
+ *
27
+ * @param Tokenizer $tokenizer
28
+ * @param PdfParser $parser
29
+ * @return bool|self
30
+ */
31
+ public static function parse(Tokenizer $tokenizer, PdfParser $parser)
32
+ {
33
+ $result = [];
34
+
35
+ // Recurse into this function until we reach the end of the array.
36
+ while (($token = $tokenizer->getNextToken()) !== ']') {
37
+ if ($token === false || ($value = $parser->readValue($token)) === false) {
38
+ return false;
39
+ }
40
+
41
+ $result[] = $value;
42
+ }
43
+
44
+ $v = new self;
45
+ $v->value = $result;
46
+
47
+ return $v;
48
+ }
49
+
50
+ /**
51
+ * Helper method to create an instance.
52
+ *
53
+ * @param PdfType[] $values
54
+ * @return self
55
+ */
56
+ public static function create(array $values = [])
57
+ {
58
+ $v = new self;
59
+ $v->value = $values;
60
+
61
+ return $v;
62
+ }
63
+
64
+ /**
65
+ * Ensures that the passed array is a PdfArray instance with a (optional) specific size.
66
+ *
67
+ * @param mixed $array
68
+ * @param null|int $size
69
+ * @return self
70
+ * @throws PdfTypeException
71
+ */
72
+ public static function ensure($array, $size = null)
73
+ {
74
+ $result = PdfType::ensureType(self::class, $array, 'Array value expected.');
75
+
76
+ if ($size !== null && \count($array->value) !== $size) {
77
+ throw new PdfTypeException(
78
+ \sprintf('Array with %s entries expected.', $size),
79
+ PdfTypeException::INVALID_DATA_SIZE
80
+ );
81
+ }
82
+
83
+ return $result;
84
+ }
85
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfBoolean.php ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ /**
14
+ * Class representing a boolean PDF object
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Type
17
+ */
18
+ class PdfBoolean extends PdfType
19
+ {
20
+ /**
21
+ * Helper method to create an instance.
22
+ *
23
+ * @param bool $value
24
+ * @return self
25
+ */
26
+ public static function create($value)
27
+ {
28
+ $v = new self;
29
+ $v->value = (boolean) $value;
30
+ return $v;
31
+ }
32
+
33
+ /**
34
+ * Ensures that the passed value is a PdfBoolean instance.
35
+ *
36
+ * @param mixed $value
37
+ * @return self
38
+ */
39
+ public static function ensure($value)
40
+ {
41
+ return PdfType::ensureType(self::class, $value, 'Boolean value expected.');
42
+ }
43
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfDictionary.php ADDED
@@ -0,0 +1,133 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\StreamReader;
15
+ use setasign\Fpdi\PdfParser\Tokenizer;
16
+
17
+ /**
18
+ * Class representing a PDF dictionary object
19
+ *
20
+ * @package setasign\Fpdi\PdfParser\Type
21
+ */
22
+ class PdfDictionary extends PdfType
23
+ {
24
+ /**
25
+ * Parses a dictionary of the passed tokenizer, stream-reader and parser.
26
+ *
27
+ * @param Tokenizer $tokenizer
28
+ * @param StreamReader $streamReader
29
+ * @param PdfParser $parser
30
+ * @return bool|self
31
+ */
32
+ public static function parse(Tokenizer $tokenizer, StreamReader $streamReader, PdfParser $parser)
33
+ {
34
+ $entries = [];
35
+
36
+ while (true) {
37
+ $token = $tokenizer->getNextToken();
38
+ if ($token === '>' && $streamReader->getByte() === '>') {
39
+ $streamReader->addOffset(1);
40
+ break;
41
+ }
42
+
43
+ $key = $parser->readValue($token);
44
+ if (false === $key) {
45
+ return false;
46
+ }
47
+
48
+ // ensure the first value to be a Name object
49
+ if (!($key instanceof PdfName)) {
50
+ $lastToken = null;
51
+ // ignore all other entries and search for the closing brackets
52
+ while (($token = $tokenizer->getNextToken()) !== '>' && $token !== false && $lastToken !== '>') {
53
+ $lastToken = $token;
54
+ }
55
+
56
+ if ($token === false) {
57
+ return false;
58
+ }
59
+
60
+ break;
61
+ }
62
+
63
+
64
+ $value = $parser->readValue();
65
+ if (false === $value) {
66
+ return false;
67
+ }
68
+
69
+ if ($value instanceof PdfNull) {
70
+ continue;
71
+ }
72
+
73
+ // catch missing value
74
+ if ($value instanceof PdfToken && $value->value === '>' && $streamReader->getByte() === '>') {
75
+ $streamReader->addOffset(1);
76
+ break;
77
+ }
78
+
79
+ $entries[$key->value] = $value;
80
+ }
81
+
82
+ $v = new self;
83
+ $v->value = $entries;
84
+
85
+ return $v;
86
+ }
87
+
88
+ /**
89
+ * Helper method to create an instance.
90
+ *
91
+ * @param PdfType[] $entries The keys are the name entries of the dictionary.
92
+ * @return self
93
+ */
94
+ public static function create(array $entries = [])
95
+ {
96
+ $v = new self;
97
+ $v->value = $entries;
98
+
99
+ return $v;
100
+ }
101
+
102
+ /**
103
+ * Get a value by its key from a dictionary or a default value.
104
+ *
105
+ * @param mixed $dictionary
106
+ * @param string $key
107
+ * @param PdfType|mixed|null $default
108
+ * @return PdfNull|PdfType
109
+ */
110
+ public static function get($dictionary, $key, PdfType $default = null)
111
+ {
112
+ $dictionary = self::ensure($dictionary);
113
+
114
+ if (isset($dictionary->value[$key])) {
115
+ return $dictionary->value[$key];
116
+ }
117
+
118
+ return $default === null
119
+ ? new PdfNull()
120
+ : $default;
121
+ }
122
+
123
+ /**
124
+ * Ensures that the passed value is a PdfDictionary instance.
125
+ *
126
+ * @param mixed $dictionary
127
+ * @return self
128
+ */
129
+ public static function ensure($dictionary)
130
+ {
131
+ return PdfType::ensureType(self::class, $dictionary, 'Dictionary value expected.');
132
+ }
133
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfHexString.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ use setasign\Fpdi\PdfParser\StreamReader;
14
+
15
+ /**
16
+ * Class representing a hexadecimal encoded PDF string object
17
+ *
18
+ * @package setasign\Fpdi\PdfParser\Type
19
+ */
20
+ class PdfHexString extends PdfType
21
+ {
22
+ /**
23
+ * Parses a hexadecimal string object from the stream reader.
24
+ *
25
+ * @param StreamReader $streamReader
26
+ * @return bool|self
27
+ */
28
+ public static function parse(StreamReader $streamReader)
29
+ {
30
+ $bufferOffset = $streamReader->getOffset();
31
+
32
+ /**
33
+ * @var string $buffer
34
+ * @var int $pos
35
+ */
36
+ while (true) {
37
+ $buffer = $streamReader->getBuffer(false);
38
+ $pos = \strpos($buffer, '>', $bufferOffset);
39
+ if (false === $pos) {
40
+ if (!$streamReader->increaseLength()) {
41
+ return false;
42
+ }
43
+ continue;
44
+ }
45
+
46
+ break;
47
+ }
48
+
49
+ $result = \substr($buffer, $bufferOffset, $pos - $bufferOffset);
50
+ $streamReader->setOffset($pos + 1);
51
+
52
+ $v = new self;
53
+ $v->value = $result;
54
+
55
+ return $v;
56
+ }
57
+
58
+ /**
59
+ * Helper method to create an instance.
60
+ *
61
+ * @param string $string The hex encoded string.
62
+ * @return self
63
+ */
64
+ public static function create($string)
65
+ {
66
+ $v = new self;
67
+ $v->value = $string;
68
+
69
+ return $v;
70
+ }
71
+
72
+ /**
73
+ * Ensures that the passed value is a PdfHexString instance.
74
+ *
75
+ * @param mixed $hexString
76
+ * @return self
77
+ */
78
+ public static function ensure($hexString)
79
+ {
80
+ return PdfType::ensureType(self::class, $hexString, 'Hex string value expected.');
81
+ }
82
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfIndirectObject.php ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\StreamReader;
15
+ use setasign\Fpdi\PdfParser\Tokenizer;
16
+
17
+ /**
18
+ * Class representing an indirect object
19
+ *
20
+ * @package setasign\Fpdi\PdfParser\Type
21
+ */
22
+ class PdfIndirectObject extends PdfType
23
+ {
24
+ /**
25
+ * Parses an indirect object from a tokenizer, parser and stream-reader.
26
+ *
27
+ * @param int $objectNumberToken
28
+ * @param int $objectGenerationNumberToken
29
+ * @param PdfParser $parser
30
+ * @param Tokenizer $tokenizer
31
+ * @param StreamReader $reader
32
+ * @return bool|self
33
+ */
34
+ public static function parse(
35
+ $objectNumberToken,
36
+ $objectGenerationNumberToken,
37
+ PdfParser $parser,
38
+ Tokenizer $tokenizer,
39
+ StreamReader $reader
40
+ ) {
41
+ $value = $parser->readValue();
42
+ if ($value === false) {
43
+ return false;
44
+ }
45
+
46
+ $nextToken = $tokenizer->getNextToken();
47
+ if ($nextToken === 'stream') {
48
+ $value = PdfStream::parse($value, $reader);
49
+ } elseif ($nextToken !== false) {
50
+ $tokenizer->pushStack($nextToken);
51
+ }
52
+
53
+ $v = new self;
54
+ $v->objectNumber = (int) $objectNumberToken;
55
+ $v->generationNumber = (int) $objectGenerationNumberToken;
56
+ $v->value = $value;
57
+
58
+ return $v;
59
+ }
60
+
61
+ /**
62
+ * Helper method to create an instance.
63
+ *
64
+ * @param int $objectNumber
65
+ * @param int $generationNumber
66
+ * @param PdfType $value
67
+ * @return self
68
+ */
69
+ public static function create($objectNumber, $generationNumber, PdfType $value)
70
+ {
71
+ $v = new self;
72
+ $v->objectNumber = (int) $objectNumber;
73
+ $v->generationNumber = (int) $generationNumber;
74
+ $v->value = $value;
75
+
76
+ return $v;
77
+ }
78
+
79
+ /**
80
+ * Ensures that the passed value is a PdfIndirectObject instance.
81
+ *
82
+ * @param mixed $indirectObject
83
+ * @return self
84
+ */
85
+ public static function ensure($indirectObject)
86
+ {
87
+ return PdfType::ensureType(self::class, $indirectObject, 'Indirect object expected.');
88
+ }
89
+
90
+ /**
91
+ * The object number.
92
+ *
93
+ * @var int
94
+ */
95
+ public $objectNumber;
96
+
97
+ /**
98
+ * The generation number.
99
+ *
100
+ * @var int
101
+ */
102
+ public $generationNumber;
103
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfIndirectObjectReference.php ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ /**
14
+ * Class representing an indirect object reference
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Type
17
+ */
18
+ class PdfIndirectObjectReference extends PdfType
19
+ {
20
+ /**
21
+ * Helper method to create an instance.
22
+ *
23
+ * @param int $objectNumber
24
+ * @param int $generationNumber
25
+ * @return self
26
+ */
27
+ public static function create($objectNumber, $generationNumber)
28
+ {
29
+ $v = new self;
30
+ $v->value = (int) $objectNumber;
31
+ $v->generationNumber = (int) $generationNumber;
32
+
33
+ return $v;
34
+ }
35
+
36
+ /**
37
+ * Ensures that the passed value is a PdfIndirectObject instance.
38
+ *
39
+ * @param mixed $value
40
+ * @return self
41
+ */
42
+ public static function ensure($value)
43
+ {
44
+ return PdfType::ensureType(self::class, $value, 'Indirect reference value expected.');
45
+ }
46
+
47
+ /**
48
+ * The generation number.
49
+ *
50
+ * @var int
51
+ */
52
+ public $generationNumber;
53
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfName.php ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ use setasign\Fpdi\PdfParser\StreamReader;
14
+ use setasign\Fpdi\PdfParser\Tokenizer;
15
+
16
+ /**
17
+ * Class representing a PDF name object
18
+ *
19
+ * @package setasign\Fpdi\PdfParser\Type
20
+ */
21
+ class PdfName extends PdfType
22
+ {
23
+ /**
24
+ * Parses a name object from the passed tokenizer and stream-reader.
25
+ *
26
+ * @param Tokenizer $tokenizer
27
+ * @param StreamReader $streamReader
28
+ * @return self
29
+ */
30
+ public static function parse(Tokenizer $tokenizer, StreamReader $streamReader)
31
+ {
32
+ $v = new self;
33
+ if (\strspn($streamReader->getByte(), "\x00\x09\x0A\x0C\x0D\x20()<>[]{}/%") === 0) {
34
+ $v->value = (string) $tokenizer->getNextToken();
35
+ return $v;
36
+ }
37
+
38
+ $v->value = '';
39
+ return $v;
40
+ }
41
+
42
+ /**
43
+ * Unescapes a name string.
44
+ *
45
+ * @param string $value
46
+ * @return string
47
+ */
48
+ static public function unescape($value)
49
+ {
50
+ if (false === strpos($value, '#'))
51
+ return $value;
52
+
53
+ return preg_replace_callback('/#[a-fA-F\d]{2}/', function($matches) {
54
+ return chr(hexdec($matches[0]));
55
+ }, $value);
56
+ }
57
+
58
+ /**
59
+ * Helper method to create an instance.
60
+ *
61
+ * @param string $string
62
+ * @return self
63
+ */
64
+ public static function create($string)
65
+ {
66
+ $v = new self;
67
+ $v->value = $string;
68
+
69
+ return $v;
70
+ }
71
+
72
+ /**
73
+ * Ensures that the passed value is a PdfName instance.
74
+ *
75
+ * @param mixed $name
76
+ * @return self
77
+ */
78
+ public static function ensure($name)
79
+ {
80
+ return PdfType::ensureType(self::class, $name, 'Name value expected.');
81
+ }
82
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfNull.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ /**
14
+ * Class representing a PDF null object
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Type
17
+ */
18
+ class PdfNull extends PdfType
19
+ {
20
+ // empty body
21
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfNumeric.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ /**
14
+ * Class representing a numeric PDF object
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Type
17
+ */
18
+ class PdfNumeric extends PdfType
19
+ {
20
+ /**
21
+ * Helper method to create an instance.
22
+ *
23
+ * @param int|float $value
24
+ * @return PdfNumeric
25
+ */
26
+ public static function create($value)
27
+ {
28
+ $v = new self;
29
+ $v->value = $value + 0;
30
+
31
+ return $v;
32
+ }
33
+
34
+ /**
35
+ * Ensures that the passed value is a PdfNumeric instance.
36
+ *
37
+ * @param mixed $value
38
+ * @return self
39
+ */
40
+ public static function ensure($value)
41
+ {
42
+ return PdfType::ensureType(self::class, $value, 'Numeric value expected.');
43
+ }
44
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfStream.php ADDED
@@ -0,0 +1,275 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ use setasign\Fpdi\PdfParser\Filter\Ascii85;
14
+ use setasign\Fpdi\PdfParser\Filter\AsciiHex;
15
+ use setasign\Fpdi\PdfParser\Filter\FilterException;
16
+ use setasign\Fpdi\PdfParser\Filter\Flate;
17
+ use setasign\Fpdi\PdfParser\Filter\Lzw;
18
+ use setasign\Fpdi\PdfParser\PdfParserException;
19
+ use setasign\Fpdi\PdfParser\StreamReader;
20
+ use setasign\FpdiPdfParser\PdfParser\Filter\Predictor;
21
+
22
+ /**
23
+ * Class representing a PDF stream object
24
+ *
25
+ * @package setasign\Fpdi\PdfParser\Type
26
+ */
27
+ class PdfStream extends PdfType
28
+ {
29
+ /**
30
+ * Parses a stream from a stream reader.
31
+ *
32
+ * @param PdfDictionary $dictionary
33
+ * @param StreamReader $reader
34
+ * @return self
35
+ * @throws PdfTypeException
36
+ */
37
+ public static function parse(PdfDictionary $dictionary, StreamReader $reader)
38
+ {
39
+ $v = new self;
40
+ $v->value = $dictionary;
41
+ $v->reader = $reader;
42
+
43
+ $offset = $reader->getOffset();
44
+
45
+ // Find the first "newline"
46
+ while (($firstByte = $reader->getByte($offset)) !== false) {
47
+ if ($firstByte !== "\n" && $firstByte !== "\r") {
48
+ $offset++;
49
+ } else {
50
+ break;
51
+ }
52
+ }
53
+
54
+ if (false === $firstByte) {
55
+ throw new PdfTypeException(
56
+ 'Unable to parse stream data. No newline after the stream keyword found.',
57
+ PdfTypeException::NO_NEWLINE_AFTER_STREAM_KEYWORD
58
+ );
59
+ }
60
+
61
+ $sndByte = $reader->getByte($offset + 1);
62
+ if ($firstByte === "\n" || $firstByte === "\r") {
63
+ $offset++;
64
+ }
65
+
66
+ if ($sndByte === "\n" && $firstByte !== "\n") {
67
+ $offset++;
68
+ }
69
+
70
+ $reader->setOffset($offset);
71
+ // let's only save the byte-offset and read the stream only when needed
72
+ $v->stream = $reader->getPosition() + $reader->getOffset();
73
+
74
+ return $v;
75
+ }
76
+
77
+ /**
78
+ * Helper method to create an instance.
79
+ *
80
+ * @param PdfDictionary $dictionary
81
+ * @param string $stream
82
+ * @return self
83
+ */
84
+ public static function create(PdfDictionary $dictionary, $stream)
85
+ {
86
+ $v = new self;
87
+ $v->value = $dictionary;
88
+ $v->stream = (string) $stream;
89
+
90
+ return $v;
91
+ }
92
+
93
+ /**
94
+ * Ensures that the passed value is a PdfStream instance.
95
+ *
96
+ * @param mixed $stream
97
+ * @return self
98
+ */
99
+ public static function ensure($stream)
100
+ {
101
+ return PdfType::ensureType(self::class, $stream, 'Stream value expected.');
102
+ }
103
+
104
+ /**
105
+ * The stream or its byte-offset position.
106
+ *
107
+ * @var int|string
108
+ */
109
+ protected $stream;
110
+
111
+ /**
112
+ * The stream reader instance.
113
+ *
114
+ * @var StreamReader
115
+ */
116
+ protected $reader;
117
+
118
+ /**
119
+ * Get the stream data.
120
+ *
121
+ * @param bool $cache Whether cache the stream data or not.
122
+ * @return bool|string
123
+ */
124
+ public function getStream($cache = false)
125
+ {
126
+ if (\is_int($this->stream)) {
127
+ $length = PdfDictionary::get($this->value, 'Length');
128
+ $this->reader->reset($this->stream, $length->value);
129
+ if (!($length instanceof PdfNumeric) || $length->value === 0) {
130
+ while (true) {
131
+ $buffer = $this->reader->getBuffer(false);
132
+ $length = \strpos($buffer, 'endstream');
133
+ if (false === $length) {
134
+ if (!$this->reader->increaseLength(100000)) {
135
+ return false;
136
+ }
137
+ continue;
138
+ }
139
+ break;
140
+ }
141
+
142
+ $buffer = \substr($buffer, 0, $length);
143
+ $lastByte = \substr($buffer, -1);
144
+
145
+ // Check for EOL
146
+ if ($lastByte === "\n") {
147
+ $buffer = \substr($buffer, 0, -1);
148
+ }
149
+
150
+ $lastByte = \substr($buffer, -1);
151
+ if ($lastByte === "\r") {
152
+ $buffer = \substr($buffer, 0, -1);
153
+ }
154
+
155
+ } else {
156
+ $buffer = $this->reader->getBuffer(false);
157
+ }
158
+ if ($cache === false) {
159
+ return $buffer;
160
+ }
161
+
162
+ $this->stream = $buffer;
163
+ $this->reader = null;
164
+ }
165
+
166
+ return $this->stream;
167
+ }
168
+
169
+ /**
170
+ * Get the unfiltered stream data.
171
+ *
172
+ * @return string
173
+ * @throws FilterException
174
+ * @throws PdfParserException
175
+ */
176
+ public function getUnfilteredStream()
177
+ {
178
+ $stream = $this->getStream();
179
+ $filters = PdfDictionary::get($this->value, 'Filter');
180
+ if ($filters instanceof PdfNull) {
181
+ return $stream;
182
+ }
183
+
184
+ if ($filters instanceof PdfArray) {
185
+ $filters = $filters->value;
186
+ } else {
187
+ $filters = [$filters];
188
+ }
189
+
190
+ $decodeParams = PdfDictionary::get($this->value, 'DecodeParms');
191
+ if ($decodeParams instanceof PdfArray) {
192
+ $decodeParams = $decodeParams->value;
193
+ } else {
194
+ $decodeParams = [$decodeParams];
195
+ }
196
+
197
+ foreach ($filters as $key => $filter) {
198
+ if (!($filter instanceof PdfName)) {
199
+ continue;
200
+ }
201
+
202
+ $decodeParam = null;
203
+ if (isset($decodeParams[$key])) {
204
+ $decodeParam = ($decodeParams[$key] instanceof PdfDictionary ? $decodeParams[$key] : null);
205
+ }
206
+
207
+ switch ($filter->value) {
208
+ case 'FlateDecode':
209
+ case 'Fl':
210
+ case 'LZWDecode':
211
+ case 'LZW':
212
+ if (\strpos($filter->value, 'LZW') === 0) {
213
+ $filterObject = new Lzw();
214
+ } else {
215
+ $filterObject = new Flate();
216
+ }
217
+
218
+ $stream = $filterObject->decode($stream);
219
+
220
+ if ($decodeParam instanceof PdfDictionary) {
221
+ $predictor = PdfDictionary::get($decodeParam, 'Predictor', PdfNumeric::create(1));
222
+ if ($predictor->value !== 1) {
223
+ if (!\class_exists(Predictor::class)) {
224
+ throw new PdfParserException(
225
+ 'This PDF document makes use of features which are only implemented in the ' .
226
+ 'commercial "FPDI PDF-Parser" add-on (see https://www.setasign.com/fpdi-pdf-' .
227
+ 'parser).',
228
+ PdfParserException::IMPLEMENTED_IN_FPDI_PDF_PARSER
229
+ );
230
+ }
231
+
232
+ $colors = PdfDictionary::get($decodeParam, 'Colors', PdfNumeric::create(1));
233
+ $bitsPerComponent = PdfDictionary::get(
234
+ $decodeParam,
235
+ 'BitsPerComponent',
236
+ PdfNumeric::create(8)
237
+ );
238
+
239
+ $columns = PdfDictionary::get($decodeParam, 'Columns', PdfNumeric::create(1));
240
+
241
+ $filterObject = new Predictor(
242
+ $predictor->value,
243
+ $colors->value,
244
+ $bitsPerComponent->value,
245
+ $columns->value
246
+ );
247
+
248
+ $stream = $filterObject->decode($stream);
249
+ }
250
+ }
251
+
252
+ break;
253
+ case 'ASCII85Decode':
254
+ case 'A85':
255
+ $filterObject = new Ascii85();
256
+ $stream = $filterObject->decode($stream);
257
+ break;
258
+
259
+ case 'ASCIIHexDecode':
260
+ case 'AHx':
261
+ $filterObject = new AsciiHex();
262
+ $stream = $filterObject->decode($stream);
263
+ break;
264
+
265
+ default:
266
+ throw new FilterException(
267
+ \sprintf('Unsupported filter "%s".', $filter->value),
268
+ FilterException::UNSUPPORTED_FILTER
269
+ );
270
+ }
271
+ }
272
+
273
+ return $stream;
274
+ }
275
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfString.php ADDED
@@ -0,0 +1,172 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ use setasign\Fpdi\PdfParser\StreamReader;
14
+
15
+ /**
16
+ * Class representing a PDF string object
17
+ *
18
+ * @package setasign\Fpdi\PdfParser\Type
19
+ */
20
+ class PdfString extends PdfType
21
+ {
22
+ /**
23
+ * Parses a string object from the stream reader.
24
+ *
25
+ * @param StreamReader $streamReader
26
+ * @return self
27
+ */
28
+ public static function parse(StreamReader $streamReader)
29
+ {
30
+ $pos = $startPos = $streamReader->getOffset();
31
+ $openBrackets = 1;
32
+ do {
33
+ $buffer = $streamReader->getBuffer(false);
34
+ for ($length = \strlen($buffer); $openBrackets !== 0 && $pos < $length; $pos++) {
35
+ switch ($buffer[$pos]) {
36
+ case '(':
37
+ $openBrackets++;
38
+ break;
39
+ case ')':
40
+ $openBrackets--;
41
+ break;
42
+ case '\\':
43
+ $pos++;
44
+ }
45
+ }
46
+ } while ($openBrackets !== 0 && $streamReader->increaseLength());
47
+
48
+ $result = \substr($buffer, $startPos, $openBrackets + $pos - $startPos - 1);
49
+ $streamReader->setOffset($pos);
50
+
51
+ $v = new self;
52
+ $v->value = $result;
53
+
54
+ return $v;
55
+ }
56
+
57
+ /**
58
+ * Helper method to create an instance.
59
+ *
60
+ * @param string $value The string needs to be escaped accordingly.
61
+ * @return self
62
+ */
63
+ public static function create($value)
64
+ {
65
+ $v = new self;
66
+ $v->value = $value;
67
+
68
+ return $v;
69
+ }
70
+
71
+ /**
72
+ * Ensures that the passed value is a PdfString instance.
73
+ *
74
+ * @param mixed $string
75
+ * @return self
76
+ */
77
+ public static function ensure($string)
78
+ {
79
+ return PdfType::ensureType(self::class, $string, 'String value expected.');
80
+ }
81
+
82
+ /**
83
+ * Unescapes escaped sequences in a PDF string according to the PDF specification.
84
+ *
85
+ * @param string $s
86
+ * @return string
87
+ */
88
+ public static function unescape($s)
89
+ {
90
+ $out = '';
91
+ /** @noinspection ForeachInvariantsInspection */
92
+ for ($count = 0, $n = \strlen($s); $count < $n; $count++) {
93
+ if ($s[$count] !== '\\') {
94
+ $out .= $s[$count];
95
+ } else {
96
+ // A backslash at the end of the string - ignore it
97
+ if ($count === ($n - 1)) {
98
+ break;
99
+ }
100
+
101
+ switch ($s[++$count]) {
102
+ case ')':
103
+ case '(':
104
+ case '\\':
105
+ $out .= $s[$count];
106
+ break;
107
+
108
+ case 'f':
109
+ $out .= "\x0C";
110
+ break;
111
+
112
+ case 'b':
113
+ $out .= "\x08";
114
+ break;
115
+
116
+ case 't':
117
+ $out .= "\x09";
118
+ break;
119
+
120
+ case 'r':
121
+ $out .= "\x0D";
122
+ break;
123
+
124
+ case 'n':
125
+ $out .= "\x0A";
126
+ break;
127
+
128
+ case "\r":
129
+ if ($count !== $n - 1 && $s[$count + 1] === "\n") {
130
+ $count++;
131
+ }
132
+ break;
133
+
134
+ case "\n":
135
+ break;
136
+
137
+ default:
138
+ $actualChar = \ord($s[$count]);
139
+ // ascii 48 = number 0
140
+ // ascii 57 = number 9
141
+ if ($actualChar >= 48 &&
142
+ $actualChar <= 57) {
143
+ $oct = '' . $s[$count];
144
+
145
+ /** @noinspection NotOptimalIfConditionsInspection */
146
+ if ($count + 1 < $n &&
147
+ \ord($s[$count + 1]) >= 48 &&
148
+ \ord($s[$count + 1]) <= 57
149
+ ) {
150
+ $count++;
151
+ $oct .= $s[$count];
152
+
153
+ /** @noinspection NotOptimalIfConditionsInspection */
154
+ if ($count + 1 < $n &&
155
+ \ord($s[$count + 1]) >= 48 &&
156
+ \ord($s[$count + 1]) <= 57
157
+ ) {
158
+ $oct .= $s[++$count];
159
+ }
160
+ }
161
+
162
+ $out .= \chr(\octdec($oct));
163
+ } else {
164
+ // If the character is not one of those defined, the backslash is ignored
165
+ $out .= $s[$count];
166
+ }
167
+ }
168
+ }
169
+ }
170
+ return $out;
171
+ }
172
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfToken.php ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ /**
14
+ * Class representing PDF token object
15
+ *
16
+ * @package setasign\Fpdi\PdfParser\Type
17
+ */
18
+ class PdfToken extends PdfType
19
+ {
20
+ /**
21
+ * Helper method to create an instance.
22
+ *
23
+ * @param string $token
24
+ * @return self
25
+ */
26
+ public static function create($token)
27
+ {
28
+ $v = new self;
29
+ $v->value = $token;
30
+
31
+ return $v;
32
+ }
33
+
34
+ /**
35
+ * Ensures that the passed value is a PdfToken instance.
36
+ *
37
+ * @param mixed $token
38
+ * @return self
39
+ */
40
+ public static function ensure($token)
41
+ {
42
+ return PdfType::ensureType(self::class, $token, 'Token value expected.');
43
+ }
44
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfType.php ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+
15
+ /**
16
+ * A class defining a PDF data type
17
+ *
18
+ * @package setasign\Fpdi\PdfParser\Type
19
+ */
20
+ class PdfType
21
+ {
22
+ /**
23
+ * Resolves a PdfType value to its value.
24
+ *
25
+ * This method is used to evaluate indirect and direct object references until a final value is reached.
26
+ *
27
+ * @param PdfType $value
28
+ * @param PdfParser $parser
29
+ * @param bool $stopAtIndirectObject
30
+ * @return PdfType
31
+ */
32
+ public static function resolve(PdfType $value, PdfParser $parser, $stopAtIndirectObject = false)
33
+ {
34
+ if ($value instanceof PdfIndirectObject) {
35
+ if ($stopAtIndirectObject === true) {
36
+ return $value;
37
+ }
38
+
39
+ return self::resolve($value->value, $parser, $stopAtIndirectObject);
40
+ }
41
+
42
+ if ($value instanceof PdfIndirectObjectReference) {
43
+ return self::resolve($parser->getIndirectObject($value->value), $parser, $stopAtIndirectObject);
44
+ }
45
+
46
+ return $value;
47
+ }
48
+
49
+ /**
50
+ * Ensure that a value is an instance of a specific PDF type.
51
+ *
52
+ * @param string $type
53
+ * @param PdfType $value
54
+ * @param string $errorMessage
55
+ * @return mixed
56
+ * @throws PdfTypeException
57
+ */
58
+ protected static function ensureType($type, $value, $errorMessage)
59
+ {
60
+ if (!($value instanceof $type)) {
61
+ throw new PdfTypeException(
62
+ $errorMessage,
63
+ PdfTypeException::INVALID_DATA_TYPE
64
+ );
65
+ }
66
+
67
+ return $value;
68
+ }
69
+
70
+ /**
71
+ * The value of the PDF type.
72
+ *
73
+ * @var mixed
74
+ */
75
+ public $value;
76
+ }
includes/lib/FPDI/src/PdfParser/Type/PdfTypeException.php ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfParser\Type;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParserException;
14
+
15
+ /**
16
+ * Exception class for pdf type classes
17
+ *
18
+ * @package setasign\Fpdi\PdfParser\Type
19
+ */
20
+ class PdfTypeException extends PdfParserException
21
+ {
22
+ /**
23
+ * @var int
24
+ */
25
+ const NO_NEWLINE_AFTER_STREAM_KEYWORD = 0x0601;
26
+ }
includes/lib/FPDI/src/PdfReader/DataStructure/Rectangle.php ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfReader\DataStructure;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\Type\PdfArray;
15
+ use setasign\Fpdi\PdfParser\Type\PdfNumeric;
16
+ use setasign\Fpdi\PdfParser\Type\PdfType;
17
+
18
+ /**
19
+ * Class representing a rectangle
20
+ *
21
+ * @package setasign\Fpdi\PdfReader\DataStructure
22
+ */
23
+ class Rectangle
24
+ {
25
+ /**
26
+ * @var int|float
27
+ */
28
+ protected $llx;
29
+
30
+ /**
31
+ * @var int|float
32
+ */
33
+ protected $lly;
34
+
35
+ /**
36
+ * @var int|float
37
+ */
38
+ protected $urx;
39
+
40
+ /**
41
+ * @var int|float
42
+ */
43
+ protected $ury;
44
+
45
+ /**
46
+ * Create a rectangle instance by a PdfArray.
47
+ *
48
+ * @param PdfArray|mixed $array
49
+ * @param PdfParser $parser
50
+ * @return Rectangle
51
+ */
52
+ public static function byPdfArray($array, PdfParser $parser)
53
+ {
54
+ $array = PdfArray::ensure(PdfType::resolve($array, $parser), 4)->value;
55
+ $ax = PdfNumeric::ensure(PdfType::resolve($array[0], $parser))->value;
56
+ $ay = PdfNumeric::ensure(PdfType::resolve($array[1], $parser))->value;
57
+ $bx = PdfNumeric::ensure(PdfType::resolve($array[2], $parser))->value;
58
+ $by = PdfNumeric::ensure(PdfType::resolve($array[3], $parser))->value;
59
+
60
+ return new self($ax, $ay, $bx, $by);
61
+ }
62
+
63
+ /**
64
+ * Rectangle constructor.
65
+ *
66
+ * @param float|int $ax
67
+ * @param float|int $ay
68
+ * @param float|int $bx
69
+ * @param float|int $by
70
+ */
71
+ public function __construct($ax, $ay, $bx, $by)
72
+ {
73
+ $this->llx = \min($ax, $bx);
74
+ $this->lly = \min($ay, $by);
75
+ $this->urx = \max($ax, $bx);
76
+ $this->ury = \max($ay, $by);
77
+ }
78
+
79
+ /**
80
+ * Get the width of the rectangle.
81
+ *
82
+ * @return float|int
83
+ */
84
+ public function getWidth()
85
+ {
86
+ return $this->urx - $this->llx;
87
+ }
88
+
89
+ /**
90
+ * Get the height of the rectangle.
91
+ *
92
+ * @return float|int
93
+ */
94
+ public function getHeight()
95
+ {
96
+ return $this->ury - $this->lly;
97
+ }
98
+
99
+ /**
100
+ * Get the lower left abscissa.
101
+ *
102
+ * @return float|int
103
+ */
104
+ public function getLlx()
105
+ {
106
+ return $this->llx;
107
+ }
108
+
109
+ /**
110
+ * Get the lower left ordinate.
111
+ *
112
+ * @return float|int
113
+ */
114
+ public function getLly()
115
+ {
116
+ return $this->lly;
117
+ }
118
+
119
+ /**
120
+ * Get the upper right abscissa.
121
+ *
122
+ * @return float|int
123
+ */
124
+ public function getUrx()
125
+ {
126
+ return $this->urx;
127
+ }
128
+
129
+ /**
130
+ * Get the upper right ordinate.
131
+ *
132
+ * @return float|int
133
+ */
134
+ public function getUry()
135
+ {
136
+ return $this->ury;
137
+ }
138
+
139
+ /**
140
+ * Get the rectangle as an array.
141
+ *
142
+ * @return array
143
+ */
144
+ public function toArray()
145
+ {
146
+ return [
147
+ $this->llx,
148
+ $this->lly,
149
+ $this->urx,
150
+ $this->ury
151
+ ];
152
+ }
153
+
154
+ /**
155
+ * Get the rectangle as a PdfArray.
156
+ *
157
+ * @return PdfArray
158
+ */
159
+ public function toPdfArray()
160
+ {
161
+ $array = new PdfArray();
162
+ $array->value[] = PdfNumeric::create($this->llx);
163
+ $array->value[] = PdfNumeric::create($this->lly);
164
+ $array->value[] = PdfNumeric::create($this->urx);
165
+ $array->value[] = PdfNumeric::create($this->ury);
166
+
167
+ return $array;
168
+ }
169
+ }
includes/lib/FPDI/src/PdfReader/Page.php ADDED
@@ -0,0 +1,251 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfReader;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\Type\PdfArray;
15
+ use setasign\Fpdi\PdfParser\Type\PdfDictionary;
16
+ use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
17
+ use setasign\Fpdi\PdfParser\Type\PdfNull;
18
+ use setasign\Fpdi\PdfParser\Type\PdfNumeric;
19
+ use setasign\Fpdi\PdfParser\Type\PdfStream;
20
+ use setasign\Fpdi\PdfParser\Type\PdfType;
21
+ use setasign\Fpdi\PdfReader\DataStructure\Rectangle;
22
+
23
+ /**
24
+ * Class representing a page of a PDF document
25
+ *
26
+ * @package setasign\Fpdi\PdfReader
27
+ */
28
+ class Page
29
+ {
30
+ /**
31
+ * @var PdfIndirectObject
32
+ */
33
+ protected $pageObject;
34
+
35
+ /**
36
+ * @var PdfDictionary
37
+ */
38
+ protected $pageDictionary;
39
+
40
+ /**
41
+ * @var PdfParser
42
+ */
43
+ protected $parser;
44
+
45
+ /**
46
+ * Inherited attributes
47
+ *
48
+ * @var null|array
49
+ */
50
+ protected $inheritedAttributes;
51
+
52
+ /**
53
+ * Page constructor.
54
+ *
55
+ * @param PdfIndirectObject $page
56
+ * @param PdfParser $parser
57
+ */
58
+ public function __construct(PdfIndirectObject $page, PdfParser $parser)
59
+ {
60
+ $this->pageObject = $page;
61
+ $this->parser = $parser;
62
+ }
63
+
64
+ /**
65
+ * Get the indirect object of this page.
66
+ *
67
+ * @return PdfIndirectObject
68
+ */
69
+ public function getPageObject()
70
+ {
71
+ return $this->pageObject;
72
+ }
73
+
74
+ /**
75
+ * Get the dictionary of this page.
76
+ *
77
+ * @return PdfDictionary
78
+ */
79
+ public function getPageDictionary()
80
+ {
81
+ if (null === $this->pageDictionary) {
82
+ $this->pageDictionary = PdfDictionary::ensure(PdfType::resolve($this->getPageObject(), $this->parser));
83
+ }
84
+
85
+ return $this->pageDictionary;
86
+ }
87
+
88
+ /**
89
+ * Get a page attribute.
90
+ *
91
+ * @param string $name
92
+ * @param bool $inherited
93
+ * @return PdfType|null
94
+ */
95
+ public function getAttribute($name, $inherited = true)
96
+ {
97
+ $dict = $this->getPageDictionary();
98
+
99
+ if (isset($dict->value[$name])) {
100
+ return $dict->value[$name];
101
+ }
102
+
103
+ $inheritedKeys = ['Resources', 'MediaBox', 'CropBox', 'Rotate'];
104
+ if ($inherited && \in_array($name, $inheritedKeys, true)) {
105
+ if (null === $this->inheritedAttributes) {
106
+ $this->inheritedAttributes = [];
107
+ $inheritedKeys = \array_filter($inheritedKeys, function ($key) use ($dict) {
108
+ return !isset($dict->value[$key]);
109
+ });
110
+
111
+ if (\count($inheritedKeys) > 0) {
112
+ $parentDict = PdfType::resolve(PdfDictionary::get($dict, 'Parent'), $this->parser);
113
+ while ($parentDict instanceof PdfDictionary) {
114
+ foreach ($inheritedKeys as $index => $key) {
115
+ if (isset($parentDict->value[$key])) {
116
+ $this->inheritedAttributes[$key] = $parentDict->value[$key];
117
+ unset($inheritedKeys[$index]);
118
+ }
119
+ }
120
+
121
+ /** @noinspection NotOptimalIfConditionsInspection */
122
+ if (isset($parentDict->value['Parent']) && \count($inheritedKeys) > 0) {
123
+ $parentDict = PdfType::resolve(PdfDictionary::get($parentDict, 'Parent'), $this->parser);
124
+ } else {
125
+ break;
126
+ }
127
+ }
128
+ }
129
+ }
130
+
131
+ if (isset($this->inheritedAttributes[$name])) {
132
+ return $this->inheritedAttributes[$name];
133
+ }
134
+ }
135
+
136
+ return null;
137
+ }
138
+
139
+ /**
140
+ * Get the rotation value.
141
+ *
142
+ * @return int
143
+ */
144
+ public function getRotation()
145
+ {
146
+ $rotation = $this->getAttribute('Rotate');
147
+ if (null === $rotation) {
148
+ return 0;
149
+ }
150
+
151
+ $rotation = PdfNumeric::ensure(PdfType::resolve($rotation, $this->parser))->value % 360;
152
+
153
+ if ($rotation < 0) {
154
+ $rotation += 360;
155
+ }
156
+
157
+ return $rotation;
158
+ }
159
+
160
+ /**
161
+ * Get a boundary of this page.
162
+ *
163
+ * @param string $box
164
+ * @param bool $fallback
165
+ * @return bool|Rectangle
166
+ * @see PageBoundaries
167
+ */
168
+ public function getBoundary($box = PageBoundaries::CROP_BOX, $fallback = true)
169
+ {
170
+ $value = $this->getAttribute($box);
171
+
172
+ if (null !== $value) {
173
+ return Rectangle::byPdfArray($value, $this->parser);
174
+ }
175
+
176
+ if (false === $fallback) {
177
+ return false;
178
+ }
179
+
180
+ switch ($box) {
181
+ case PageBoundaries::BLEED_BOX:
182
+ case PageBoundaries::TRIM_BOX:
183
+ case PageBoundaries::ART_BOX:
184
+ return $this->getBoundary(PageBoundaries::CROP_BOX, true);
185
+ case PageBoundaries::CROP_BOX:
186
+ return $this->getBoundary(PageBoundaries::MEDIA_BOX, true);
187
+ }
188
+
189
+ return false;
190
+ }
191
+
192
+ /**
193
+ * Get the width and height of this page.
194
+ *
195
+ * @param string $box
196
+ * @param bool $fallback
197
+ * @return array|bool
198
+ */
199
+ public function getWidthAndHeight($box = PageBoundaries::CROP_BOX, $fallback = true)
200
+ {
201
+ $boundary = $this->getBoundary($box, $fallback);
202
+ if (false === $boundary) {
203
+ return false;
204
+ }
205
+
206
+ $rotation = $this->getRotation();
207
+ $interchange = ($rotation / 90) % 2;
208
+
209
+ return [
210
+ $interchange ? $boundary->getHeight() : $boundary->getWidth(),
211
+ $interchange ? $boundary->getWidth() : $boundary->getHeight()
212
+ ];
213
+ }
214
+
215
+ /**
216
+ * Get the raw content stream.
217
+ *
218
+ * @return string
219
+ * @throws PdfReaderException
220
+ */
221
+ public function getContentStream()
222
+ {
223
+ $dict = $this->getPageDictionary();
224
+ $contents = PdfType::resolve(PdfDictionary::get($dict, 'Contents'), $this->parser);
225
+ if ($contents instanceof PdfNull) {
226
+ return '';
227
+ }
228
+
229
+ if ($contents instanceof PdfArray) {
230
+ $result = [];
231
+ foreach ($contents->value as $content) {
232
+ $content = PdfType::resolve($content, $this->parser);
233
+ if (!($content instanceof PdfStream)) {
234
+ continue;
235
+ }
236
+ $result[] = $content->getUnfilteredStream();
237
+ }
238
+
239
+ return \implode("\n", $result);
240
+ }
241
+
242
+ if ($contents instanceof PdfStream) {
243
+ return $contents->getUnfilteredStream();
244
+ }
245
+
246
+ throw new PdfReaderException(
247
+ 'Array or stream expected.',
248
+ PdfReaderException::UNEXPECTED_DATA_TYPE
249
+ );
250
+ }
251
+ }
includes/lib/FPDI/src/PdfReader/PageBoundaries.php ADDED
@@ -0,0 +1,96 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfReader;
12
+
13
+ /**
14
+ * An abstract class for page boundary constants and some helper methods
15
+ *
16
+ * @package setasign\Fpdi\PdfReader
17
+ */
18
+ abstract class PageBoundaries
19
+ {
20
+ /**
21
+ * MediaBox
22
+ *
23
+ * The media box defines the boundaries of the physical medium on which the page is to be printed.
24
+ *
25
+ * @see PDF 32000-1:2008 - 14.11.2 Page Boundaries
26
+ * @var string
27
+ */
28
+ const MEDIA_BOX = 'MediaBox';
29
+
30
+ /**
31
+ * CropBox
32
+ *
33
+ * The crop box defines the region to which the contents of the page shall be clipped (cropped) when displayed or
34
+ * printed.
35
+ *
36
+ * @see PDF 32000-1:2008 - 14.11.2 Page Boundaries
37
+ * @var string
38
+ */
39
+ const CROP_BOX = 'CropBox';
40
+
41
+ /**
42
+ * BleedBox
43
+ *
44
+ * The bleed box defines the region to which the contents of the page shall be clipped when output in a
45
+ * production environment.
46
+ *
47
+ * @see PDF 32000-1:2008 - 14.11.2 Page Boundaries
48
+ * @var string
49
+ */
50
+ const BLEED_BOX = 'BleedBox';
51
+
52
+ /**
53
+ * TrimBox
54
+ *
55
+ * The trim box defines the intended dimensions of the finished page after trimming.
56
+ *
57
+ * @see PDF 32000-1:2008 - 14.11.2 Page Boundaries
58
+ * @var string
59
+ */
60
+ const TRIM_BOX = 'TrimBox';
61
+
62
+ /**
63
+ * ArtBox
64
+ *
65
+ * The art box defines the extent of the page’s meaningful content (including potential white space) as intended
66
+ * by the page’s creator.
67
+ *
68
+ * @see PDF 32000-1:2008 - 14.11.2 Page Boundaries
69
+ * @var string
70
+ */
71
+ const ART_BOX = 'ArtBox';
72
+
73
+ /**
74
+ * All page boundaries
75
+ *
76
+ * @var array
77
+ */
78
+ public static $all = array(
79
+ self::MEDIA_BOX,
80
+ self::CROP_BOX,
81
+ self::BLEED_BOX,
82
+ self::TRIM_BOX,
83
+ self::ART_BOX
84
+ );
85
+
86
+ /**
87
+ * Checks if a name is a valid page boundary name.
88
+ *
89
+ * @param string $name The boundary name
90
+ * @return boolean A boolean value whether the name is valid or not.
91
+ */
92
+ public static function isValidName($name)
93
+ {
94
+ return \in_array($name, self::$all, true);
95
+ }
96
+ }
includes/lib/FPDI/src/PdfReader/PdfReader.php ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfReader;
12
+
13
+ use setasign\Fpdi\PdfParser\PdfParser;
14
+ use setasign\Fpdi\PdfParser\Type\PdfArray;
15
+ use setasign\Fpdi\PdfParser\Type\PdfDictionary;
16
+ use setasign\Fpdi\PdfParser\Type\PdfIndirectObjectReference;
17
+ use setasign\Fpdi\PdfParser\Type\PdfNumeric;
18
+ use setasign\Fpdi\PdfParser\Type\PdfType;
19
+
20
+ /**
21
+ * A PDF reader class
22
+ *
23
+ * @package setasign\Fpdi\PdfReader
24
+ */
25
+ class PdfReader
26
+ {
27
+ /**
28
+ * @var PdfParser
29
+ */
30
+ protected $parser;
31
+
32
+ /**
33
+ * @var int
34
+ */
35
+ protected $pageCount;
36
+
37
+ /**
38
+ * Indirect objects of resolved pages.
39
+ *
40
+ * @var PdfIndirectObjectReference[]
41
+ */
42
+ protected $pages = [];
43
+
44
+ /**
45
+ * PdfReader constructor.
46
+ *
47
+ * @param PdfParser $parser
48
+ */
49
+ public function __construct(PdfParser $parser)
50
+ {
51
+ $this->parser = $parser;
52
+ }
53
+
54
+ /**
55
+ * PdfReader destructor.
56
+ */
57
+ public function __destruct()
58
+ {
59
+ if ($this->parser !== null) {
60
+ /** @noinspection PhpInternalEntityUsedInspection */
61
+ $this->parser->cleanUp();
62
+ }
63
+ }
64
+
65
+ /**
66
+ * Get the pdf parser instance.
67
+ *
68
+ * @return PdfParser
69
+ */
70
+ public function getParser()
71
+ {
72
+ return $this->parser;
73
+ }
74
+
75
+ /**
76
+ * Get the PDF version.
77
+ *
78
+ * @return string
79
+ */
80
+ public function getPdfVersion()
81
+ {
82
+ return \implode('.', $this->parser->getPdfVersion());
83
+ }
84
+
85
+ /**
86
+ * Get the page count.
87
+ *
88
+ * @return int
89
+ */
90
+ public function getPageCount()
91
+ {
92
+ if ($this->pageCount === null) {
93
+ $catalog = $this->parser->getCatalog();
94
+
95
+ $pages = PdfType::resolve(PdfDictionary::get($catalog, 'Pages'), $this->parser);
96
+ $count = PdfType::resolve(PdfDictionary::get($pages, 'Count'), $this->parser);
97
+
98
+ $this->pageCount = PdfNumeric::ensure($count)->value;
99
+ }
100
+
101
+ return $this->pageCount;
102
+ }
103
+
104
+ /**
105
+ * Get a page instance.
106
+ *
107
+ * @param int $pageNumber
108
+ * @return Page
109
+ */
110
+ public function getPage($pageNumber)
111
+ {
112
+ if (!\is_numeric($pageNumber)) {
113
+ throw new \InvalidArgumentException(
114
+ 'Page number needs to be a number.'
115
+ );
116
+ }
117
+
118
+ if ($pageNumber < 1 || $pageNumber > $this->getPageCount()) {
119
+ throw new \InvalidArgumentException(
120
+ \sprintf(
121
+ 'Page number "%s" out of available page range (1 - %s)',
122
+ $pageNumber,
123
+ $this->getPageCount()
124
+ )
125
+ );
126
+ }
127
+
128
+ $this->readPages();
129
+
130
+ $page = $this->pages[$pageNumber - 1];
131
+
132
+ if ($page instanceof PdfIndirectObjectReference) {
133
+ $readPages = function ($kids) use (&$readPages) {
134
+ $kids = PdfArray::ensure($kids);
135
+
136
+ /** @noinspection LoopWhichDoesNotLoopInspection */
137
+ foreach ($kids->value as $reference) {
138
+ $reference = PdfIndirectObjectReference::ensure($reference);
139
+ $object = $this->parser->getIndirectObject($reference->value);
140
+ $type = PdfDictionary::get($object->value, 'Type');
141
+
142
+ if ($type->value === 'Pages') {
143
+ return $readPages(PdfDictionary::get($object->value, 'Kids'));
144
+ }
145
+
146
+ return $object;
147
+ }
148
+
149
+ throw new PdfReaderException(
150
+ 'Kids array cannot be empty.',
151
+ PdfReaderException::KIDS_EMPTY
152
+ );
153
+ };
154
+
155
+ $page = $this->parser->getIndirectObject($page->value);
156
+ $dict = PdfType::resolve($page, $this->parser);
157
+ $type = PdfDictionary::get($dict, 'Type');
158
+ if ($type->value === 'Pages') {
159
+ $kids = PdfType::resolve(PdfDictionary::get($dict, 'Kids'), $this->parser);
160
+ $page = $this->pages[$pageNumber - 1] = $readPages($kids);
161
+ } else {
162
+ $this->pages[$pageNumber - 1] = $page;
163
+ }
164
+ }
165
+
166
+ return new Page($page, $this->parser);
167
+ }
168
+
169
+ /**
170
+ * Walk the page tree and resolve all indirect objects of all pages.
171
+ */
172
+ protected function readPages()
173
+ {
174
+ if (\count($this->pages) > 0) {
175
+ return;
176
+ }
177
+
178
+ $readPages = function ($kids, $count) use (&$readPages) {
179
+ $kids = PdfArray::ensure($kids);
180
+ $isLeaf = $count->value === \count($kids->value);
181
+
182
+ foreach ($kids->value as $reference) {
183
+ $reference = PdfIndirectObjectReference::ensure($reference);
184
+
185
+ if ($isLeaf) {
186
+ $this->pages[] = $reference;
187
+ continue;
188
+ }
189
+
190
+ $object = $this->parser->getIndirectObject($reference->value);
191
+ $type = PdfDictionary::get($object->value, 'Type');
192
+
193
+ if ($type->value === 'Pages') {
194
+ $readPages(PdfDictionary::get($object->value, 'Kids'), PdfDictionary::get($object->value, 'Count'));
195
+ } else {
196
+ $this->pages[] = $object;
197
+ }
198
+ }
199
+ };
200
+
201
+ $catalog = $this->parser->getCatalog();
202
+ $pages = PdfType::resolve(PdfDictionary::get($catalog, 'Pages'), $this->parser);
203
+ $count = PdfType::resolve(PdfDictionary::get($pages, 'Count'), $this->parser);
204
+ $kids = PdfType::resolve(PdfDictionary::get($pages, 'Kids'), $this->parser);
205
+ $readPages($kids, $count);
206
+ }
207
+ }
includes/lib/FPDI/src/PdfReader/PdfReaderException.php ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi\PdfReader;
12
+
13
+ use setasign\Fpdi\FpdiException;
14
+
15
+ /**
16
+ * Exception for the pdf reader class
17
+ *
18
+ * @package setasign\Fpdi\PdfReader
19
+ */
20
+ class PdfReaderException extends FpdiException
21
+ {
22
+ /**
23
+ * @var int
24
+ */
25
+ const KIDS_EMPTY = 0x0101;
26
+
27
+ /**
28
+ * @var int
29
+ */
30
+ const UNEXPECTED_DATA_TYPE = 0x0102;
31
+
32
+ /**
33
+ * @var int
34
+ */
35
+ const MISSING_DATA = 0x0103;
36
+ }
includes/lib/FPDI/src/TcpdfFpdi.php ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ namespace setasign\Fpdi;
12
+
13
+ use setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException;
14
+ use setasign\Fpdi\PdfParser\Filter\AsciiHex;
15
+ use setasign\Fpdi\PdfParser\Type\PdfHexString;
16
+ use setasign\Fpdi\PdfParser\Type\PdfIndirectObject;
17
+ use setasign\Fpdi\PdfParser\Type\PdfNull;
18
+ use setasign\Fpdi\PdfParser\Type\PdfNumeric;
19
+ use setasign\Fpdi\PdfParser\Type\PdfStream;
20
+ use setasign\Fpdi\PdfParser\Type\PdfString;
21
+ use setasign\Fpdi\PdfParser\Type\PdfType;
22
+
23
+ /**
24
+ * Class TcpdfFpdi
25
+ *
26
+ * This class let you import pages of existing PDF documents into a reusable structure for TCPDF.
27
+ *
28
+ * @package setasign\Fpdi
29
+ */
30
+ class TcpdfFpdi extends \TCPDF
31
+ {
32
+ use FpdiTrait {
33
+ writePdfType as fpdiWritePdfType;
34
+ useImportedPage as fpdiUseImportedPage;
35
+ }
36
+
37
+ /**
38
+ * FPDI version
39
+ *
40
+ * @string
41
+ */
42
+ const VERSION = '2.0.0';
43
+
44
+ /**
45
+ * A counter for template ids.
46
+ *
47
+ * @var int
48
+ */
49
+ protected $templateId = 0;
50
+
51
+ /**
52
+ * The currently used object number.
53
+ *
54
+ * @var int
55
+ */
56
+ protected $currentObjectNumber;
57
+
58
+ /**
59
+ * Get the next template id.
60
+ *
61
+ * @return int
62
+ */
63
+ protected function getNextTemplateId()
64
+ {
65
+ return $this->templateId++;
66
+ }
67
+
68
+ /**
69
+ * Draws an imported page onto the page or another template.
70
+ *
71
+ * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
72
+ * ratio.
73
+ *
74
+ * @param mixed $tpl The template id
75
+ * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
76
+ * with the keys "x", "y", "width", "height", "adjustPageSize".
77
+ * @param float|int $y The ordinate of upper-left corner.
78
+ * @param float|int|null $width The width.
79
+ * @param float|int|null $height The height.
80
+ * @param bool $adjustPageSize
81
+ * @return array The size
82
+ * @see FpdiTrait::getTemplateSize()
83
+ */
84
+ public function useTemplate($tpl, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
85
+ {
86
+ return $this->useImportedPage($tpl, $x, $y, $width, $height, $adjustPageSize);
87
+ }
88
+
89
+ /**
90
+ * Draws an imported page onto the page.
91
+ *
92
+ * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
93
+ * ratio.
94
+ *
95
+ * @param mixed $pageId The page id
96
+ * @param float|int|array $x The abscissa of upper-left corner. Alternatively you could use an assoc array
97
+ * with the keys "x", "y", "width", "height", "adjustPageSize".
98
+ * @param float|int $y The ordinate of upper-left corner.
99
+ * @param float|int|null $width The width.
100
+ * @param float|int|null $height The height.
101
+ * @param bool $adjustPageSize
102
+ * @return array The size.
103
+ * @see Fpdi::getTemplateSize()
104
+ */
105
+ public function useImportedPage($pageId, $x = 0, $y = 0, $width = null, $height = null, $adjustPageSize = false)
106
+ {
107
+ $size = $this->fpdiUseImportedPage($pageId, $x, $y, $width, $height, $adjustPageSize);
108
+ if ($this->inxobj) {
109
+ $importedPage = $this->importedPages[$pageId];
110
+ $this->xobjects[$this->xobjid]['importedPages'][$importedPage['id']] = $pageId;
111
+ }
112
+
113
+ return $size;
114
+ }
115
+
116
+ /**
117
+ * Get the size of an imported page.
118
+ *
119
+ * Omit one of the size parameters (width, height) to calculate the other one automatically in view to the aspect
120
+ * ratio.
121
+ *
122
+ * @param mixed $tpl The template id
123
+ * @param float|int|null $width The width.
124
+ * @param float|int|null $height The height.
125
+ * @return array|bool An array with following keys: width, height, 0 (=width), 1 (=height), orientation (L or P)
126
+ */
127
+ public function getTemplateSize($tpl, $width = null, $height = null)
128
+ {
129
+ return $this->getImportedPageSize($tpl, $width, $height);
130
+ }
131
+
132
+ /**
133
+ * @inheritdoc
134
+ */
135
+ protected function _getxobjectdict()
136
+ {
137
+ $out = parent::_getxobjectdict();
138
+
139
+ foreach ($this->importedPages as $key => $pageData) {
140
+ $out .= '/' . $pageData['id'] . ' ' . $pageData['objectNumber'] . ' 0 R ';
141
+ }
142
+
143
+ return $out;
144
+ }
145
+
146
+ /**
147
+ * @inheritdoc
148
+ */
149
+ protected function _putxobjects()
150
+ {
151
+ foreach ($this->importedPages as $key => $pageData) {
152
+ $this->currentObjectNumber = $this->_newobj();
153
+ $this->importedPages[$key]['objectNumber'] = $this->currentObjectNumber;
154
+ $this->currentReaderId = $pageData['readerId'];
155
+ $this->writePdfType($pageData['stream']);
156
+ $this->_put('endobj');
157
+ }
158
+
159
+ foreach (\array_keys($this->readers) as $readerId) {
160
+ $parser = $this->getPdfReader($readerId)->getParser();
161
+ $this->currentReaderId = $readerId;
162
+
163
+ while (($objectNumber = \array_pop($this->objectsToCopy[$readerId])) !== null) {
164
+ try {
165
+ $object = $parser->getIndirectObject($objectNumber);
166
+
167
+ } catch (CrossReferenceException $e) {
168
+ if ($e->getCode() === CrossReferenceException::OBJECT_NOT_FOUND) {
169
+ $object = PdfIndirectObject::create($objectNumber, 0, new PdfNull());
170
+ } else {
171
+ throw $e;
172
+ }
173
+ }
174
+
175
+ $this->writePdfType($object);
176
+ }
177
+ }
178
+
179
+ // let's prepare resources for imported pages in templates
180
+ foreach ($this->xobjects as $xObjectId => $data) {
181
+ if (!isset($data['importedPages'])) {
182
+ continue;
183
+ }
184
+
185
+ foreach ($data['importedPages'] as $id => $pageKey) {
186
+ $page = $this->importedPages[$pageKey];
187
+ $this->xobjects[$xObjectId]['xobjects'][$id] = ['n' => $page['objectNumber']];
188
+ }
189
+ }
190
+
191
+
192
+ parent::_putxobjects();
193
+ $this->currentObjectNumber = null;
194
+ }
195
+
196
+ /**
197
+ * Append content to the buffer of TCPDF.
198
+ *
199
+ * @param string $s
200
+ * @param bool $newLine
201
+ */
202
+ protected function _put($s, $newLine = true)
203
+ {
204
+ if ($newLine) {
205
+ $this->setBuffer($s . "\n");
206
+ } else {
207
+ $this->setBuffer($s);
208
+ }
209
+ }
210
+
211
+ /**
212
+ * Begin a new object and return the object number.
213
+ *
214
+ * @param int|string $objid Object ID (leave empty to get a new ID).
215
+ * @return int object number
216
+ */
217
+ protected function _newobj($objid = '')
218
+ {
219
+ $this->_out($this->_getobj($objid));
220
+ return $this->n;
221
+ }
222
+
223
+ /**
224
+ * Writes a PdfType object to the resulting buffer.
225
+ *
226
+ * @param PdfType $value
227
+ */
228
+ protected function writePdfType(PdfType $value)
229
+ {
230
+ if (!$this->encrypted) {
231
+ $this->fpdiWritePdfType($value);
232
+ return;
233
+ }
234
+
235
+ if ($value instanceof PdfString) {
236
+ $string = PdfString::unescape($value->value);
237
+ $string = $this->_encrypt_data($this->currentObjectNumber, $string);
238
+ $value->value = \TCPDF_STATIC::_escape($string);
239
+
240
+ } elseif ($value instanceof PdfHexString) {
241
+ $filter = new AsciiHex();
242
+ $string = $filter->decode($value->value);
243
+ $string = $this->_encrypt_data($this->currentObjectNumber, $string);
244
+ $value->value = $filter->encode($string, true);
245
+
246
+ } elseif ($value instanceof PdfStream) {
247
+ $stream = $value->getStream();
248
+ $stream = $this->_encrypt_data($this->currentObjectNumber, $stream);
249
+ $dictionary = $value->value;
250
+ $dictionary->value['Length'] = PdfNumeric::create(\strlen($stream));
251
+ $value = PdfStream::create($dictionary, $stream);
252
+
253
+ } elseif ($value instanceof PdfIndirectObject) {
254
+ /**
255
+ * @var $value PdfIndirectObject
256
+ */
257
+ $this->currentObjectNumber = $this->objectMap[$this->currentReaderId][$value->objectNumber];
258
+ }
259
+
260
+ $this->fpdiWritePdfType($value);
261
+ }
262
+ }
includes/lib/FPDI/src/autoload.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file is part of FPDI
4
+ *
5
+ * @package setasign\Fpdi
6
+ * @copyright Copyright (c) 2017 Setasign - Jan Slabon (https://www.setasign.com)
7
+ * @license http://opensource.org/licenses/mit-license The MIT License
8
+ * @version 2.0.0
9
+ */
10
+
11
+ spl_autoload_register(function ($class) {
12
+ if (strpos($class, 'setasign\Fpdi\\') === 0) {
13
+ $filename = str_replace('\\', DIRECTORY_SEPARATOR, substr($class, 14)) . '.php';
14
+ $fullpath = __DIR__ . DIRECTORY_SEPARATOR . $filename;
15
+
16
+ if (file_exists($fullpath)) {
17
+ /** @noinspection PhpIncludeInspection */
18
+ require_once $fullpath;
19
+ }
20
+ }
21
+ });
includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Report Tool
4
  *
5
- * @version 3.4.0
6
  * @since 2.2.1
7
  * @author Algoritmika Ltd.
8
  */
@@ -59,7 +59,7 @@ class WCJ_PDF_Invoicing_Report_Tool {
59
  /**
60
  * generate_report_zip.
61
  *
62
- * @version 3.4.0
63
  * @since 2.3.10
64
  */
65
  function generate_report_zip() {
@@ -74,7 +74,7 @@ class WCJ_PDF_Invoicing_Report_Tool {
74
  $_month = ( ! empty( $_POST['report_month'] ) ) ? $_POST['report_month'] : date( 'n' );
75
  $_invoice_type = ( ! empty( $_POST['invoice_type'] ) ) ? $_POST['invoice_type'] : 'invoice';
76
  if ( ! empty( $_year ) && ! empty( $_month ) && ! empty( $_invoice_type ) ) {
77
- if ( $this->check_user_roles() ) {
78
  $result = $this->get_invoices_report_zip( $_year, $_month, $_invoice_type );
79
  if ( false === $result ) {
80
  $this->notice = '<div class="error"><p><strong>' . __( 'Sorry, but something went wrong...', 'woocommerce-jetpack' ) . '</strong></p></div>';
@@ -164,7 +164,7 @@ class WCJ_PDF_Invoicing_Report_Tool {
164
  /**
165
  * get_invoices_report_zip.
166
  *
167
- * @version 3.1.0
168
  * @since 2.3.10
169
  */
170
  function get_invoices_report_zip( $year, $month, $invoice_type_id ) {
@@ -174,7 +174,7 @@ class WCJ_PDF_Invoicing_Report_Tool {
174
  }
175
  $zip = new ZipArchive();
176
  $zip_file_name = $this->get_report_file_name( $year, $month, $invoice_type_id, 'zip' );
177
- $zip_file_path = sys_get_temp_dir() . '/' . $zip_file_name;
178
  if ( file_exists( $zip_file_path ) ) {
179
  unlink ( $zip_file_path );
180
  }
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Report Tool
4
  *
5
+ * @version 3.5.0
6
  * @since 2.2.1
7
  * @author Algoritmika Ltd.
8
  */
59
  /**
60
  * generate_report_zip.
61
  *
62
+ * @version 3.5.0
63
  * @since 2.3.10
64
  */
65
  function generate_report_zip() {
74
  $_month = ( ! empty( $_POST['report_month'] ) ) ? $_POST['report_month'] : date( 'n' );
75
  $_invoice_type = ( ! empty( $_POST['invoice_type'] ) ) ? $_POST['invoice_type'] : 'invoice';
76
  if ( ! empty( $_year ) && ! empty( $_month ) && ! empty( $_invoice_type ) ) {
77
+ if ( $this->check_user_roles( $_invoice_type ) ) {
78
  $result = $this->get_invoices_report_zip( $_year, $_month, $_invoice_type );
79
  if ( false === $result ) {
80
  $this->notice = '<div class="error"><p><strong>' . __( 'Sorry, but something went wrong...', 'woocommerce-jetpack' ) . '</strong></p></div>';
164
  /**
165
  * get_invoices_report_zip.
166
  *
167
+ * @version 3.5.0
168
  * @since 2.3.10
169
  */
170
  function get_invoices_report_zip( $year, $month, $invoice_type_id ) {
174
  }
175
  $zip = new ZipArchive();
176
  $zip_file_name = $this->get_report_file_name( $year, $month, $invoice_type_id, 'zip' );
177
+ $zip_file_path = wcj_get_invoicing_temp_dir() . '/' . $zip_file_name;
178
  if ( file_exists( $zip_file_path ) ) {
179
  unlink ( $zip_file_path );
180
  }
includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Display
4
  *
5
- * @version 3.4.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -173,8 +173,9 @@ class WCJ_PDF_Invoicing_Display extends WCJ_Module {
173
  /**
174
  * Output custom columns for products
175
  *
176
- * @param string $column
177
  * @version 2.4.7
 
 
178
  */
179
  function render_order_columns( $column ) {
180
  $invoice_types_ids = wcj_get_enabled_invoice_types_ids();
@@ -276,7 +277,7 @@ class WCJ_PDF_Invoicing_Display extends WCJ_Module {
276
  /**
277
  * create_invoices_meta_box.
278
  *
279
- * @version 3.4.0
280
  * @since 2.8.0
281
  */
282
  function create_invoices_meta_box() {
@@ -306,7 +307,18 @@ class WCJ_PDF_Invoicing_Display extends WCJ_Module {
306
  $query_args = array( 'delete_invoice_for_order_id' => $order_id, 'invoice_type_id' => $invoice_type['id'] );
307
  $the_url = add_query_arg( $query_args, remove_query_arg( 'create_invoice_for_order_id' ) );
308
  $the_name = __( 'Delete', 'woocommerce-jetpack' );
309
- $actions = array( $view_link . ' | ' . '<a class="wcj_need_confirmation" href="' . $the_url . '">' . $the_name . '</a>' );
 
 
 
 
 
 
 
 
 
 
 
310
  } else {
311
  // "Create" link
312
  $query_args = array( 'create_invoice_for_order_id' => $order_id, 'invoice_type_id' => $invoice_type['id'] );
2
  /**
3
  * Booster for WooCommerce - PDF Invoicing - Display
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
173
  /**
174
  * Output custom columns for products
175
  *
 
176
  * @version 2.4.7
177
+ * @param string $column
178
+ * @todo clean up
179
  */
180
  function render_order_columns( $column ) {
181
  $invoice_types_ids = wcj_get_enabled_invoice_types_ids();
277
  /**
278
  * create_invoices_meta_box.
279
  *
280
+ * @version 3.5.0
281
  * @since 2.8.0
282
  */
283
  function create_invoices_meta_box() {
307
  $query_args = array( 'delete_invoice_for_order_id' => $order_id, 'invoice_type_id' => $invoice_type['id'] );
308
  $the_url = add_query_arg( $query_args, remove_query_arg( 'create_invoice_for_order_id' ) );
309
  $the_name = __( 'Delete', 'woocommerce-jetpack' );
310
+ $delete_link = '<a class="wcj_need_confirmation" href="' . $the_url . '">' . $the_name . '</a>';
311
+ // Numbering
312
+ if ( 'yes' === get_option( 'wcj_invoicing_add_order_meta_box_numbering', 'yes' ) ) {
313
+ $number_option = 'wcj_invoicing_' . $invoice_type['id'] . '_number_id';
314
+ $number_input = '<input style="width:100%;" type="number"' .
315
+ ' id="' . $number_option . '" name="' . $number_option . '" value="' . get_post_meta( $order_id, '_' . $number_option, true ) . '">' .
316
+ '<input type="hidden" name="woojetpack_pdf_invoicing_save_post" value="woojetpack_pdf_invoicing_save_post">';
317
+ } else {
318
+ $number_input = '';
319
+ }
320
+ // Actions
321
+ $actions = array( $view_link . ' | ' . $delete_link . '<br>' . $number_input );
322
  } else {
323
  // "Create" link
324
  $query_args = array( 'create_invoice_for_order_id' => $order_id, 'invoice_type_id' => $invoice_type['id'] );
includes/price-by-country/class-wcj-price-by-country-core.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Price by Country - Core
4
  *
5
- * @version 3.4.5
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -38,7 +38,7 @@ class WCJ_Price_by_Country_Core {
38
  /**
39
  * init.
40
  *
41
- * @version 3.4.5
42
  * @since 2.9.0
43
  */
44
  function init() {
@@ -46,6 +46,9 @@ class WCJ_Price_by_Country_Core {
46
  if ( isset( $_REQUEST[ 'wcj-country' ] ) ) {
47
  wcj_session_set( 'wcj-country', $_REQUEST[ 'wcj-country' ] );
48
  }
 
 
 
49
  }
50
 
51
  /**
2
  /**
3
  * Booster for WooCommerce - Price by Country - Core
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
38
  /**
39
  * init.
40
  *
41
+ * @version 3.5.0
42
  * @since 2.9.0
43
  */
44
  function init() {
46
  if ( isset( $_REQUEST[ 'wcj-country' ] ) ) {
47
  wcj_session_set( 'wcj-country', $_REQUEST[ 'wcj-country' ] );
48
  }
49
+ if ( isset( $_REQUEST[ 'wcj_country_selector' ] ) ) {
50
+ wcj_session_set( 'wcj-country', $_REQUEST[ 'wcj_country_selector' ] );
51
+ }
52
  }
53
 
54
  /**
includes/settings/meta-box/wcj-settings-meta-box-admin-tools.php CHANGED
@@ -2,14 +2,15 @@
2
  /**
3
  * Booster for WooCommerce - Settings Meta Box - Admin Tools
4
  *
5
- * @version 3.3.0
6
  * @since 3.3.0
7
  * @author Algoritmika Ltd.
 
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
- $products = wcj_get_product_ids_for_meta_box_options( get_the_ID() );
13
  $settings = array();
14
  foreach ( $products as $product_id => $desc ) {
15
  $settings = array_merge( $settings, array(
2
  /**
3
  * Booster for WooCommerce - Settings Meta Box - Admin Tools
4
  *
5
+ * @version 3.5.0
6
  * @since 3.3.0
7
  * @author Algoritmika Ltd.
8
+ * @todo (maybe) sort `$products` with available variations listed at the top
9
  */
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
12
 
13
+ $products = wcj_get_product_ids_for_meta_box_options( get_the_ID(), true );
14
  $settings = array();
15
  foreach ( $products as $product_id => $desc ) {
16
  $settings = array_merge( $settings, array(
includes/settings/meta-box/wcj-settings-meta-box-max-products-per-user.php ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings Meta Box - Max Products per User
4
+ *
5
+ * @version 3.5.0
6
+ * @since 3.5.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ return array(
13
+ array(
14
+ 'title' => __( 'Max Qty', 'woocommerce-jetpack' ),
15
+ 'name' => 'wcj_max_products_per_user_qty',
16
+ 'default' => 0,
17
+ 'type' => 'number',
18
+ 'tooltip' => __( 'If set to zero, and "All Products" section is enabled - global maximum quantity will be used; in case if "All Products" section is disabled - no maximum quantity will be used.', 'woocommerce-jetpack' ),
19
+ 'custom_attributes' => 'min="0"',
20
+ ),
21
+ );
includes/settings/meta-box/wcj-settings-meta-box-order-numbers.php ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings Meta Box - Order Numbers
4
+ *
5
+ * @version 3.5.0
6
+ * @since 3.5.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ return array(
13
+ array(
14
+ 'title' => __( 'Number', 'woocommerce-jetpack' ),
15
+ 'name' => 'wcj_order_number',
16
+ 'default' => '',
17
+ 'type' => 'number',
18
+ 'custom_attributes' => 'required min="1"',
19
+ ),
20
+ );
includes/settings/meta-box/wcj-settings-meta-box-pdf-invoicing.php ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings Meta Box - PDF Invoicing
4
+ *
5
+ * @version 3.5.0
6
+ * @since 3.5.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ $order_id = get_the_ID();
13
+ $_order = wc_get_order( $order_id );
14
+ if ( ! $_order ) {
15
+ return array();
16
+ }
17
+ $options = array();
18
+ $invoice_types = wcj_get_enabled_invoice_types();
19
+ if ( ! empty( $invoice_types ) ) {
20
+ foreach ( $invoice_types as $invoice_type ) {
21
+ if ( wcj_is_invoice_created( $order_id, $invoice_type['id'] ) ) {
22
+ $options = array_merge( $options, array(
23
+ array(
24
+ 'title' => sprintf( __( '%s number', 'woocommerce-jetpack' ), $invoice_type['title'] ),
25
+ 'name' => 'wcj_invoicing_' . $invoice_type['id'] . '_number_id',
26
+ 'default' => '',
27
+ 'type' => 'number',
28
+ ),
29
+ ) );
30
+ }
31
+ }
32
+ }
33
+ return $options;
includes/settings/wcj-settings-left-to-free-shipping.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Left to Free Shipping
4
  *
5
- * @version 3.3.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -17,9 +17,10 @@ return array(
17
  sprintf( __( 'You can also use <em>Booster - Left to Free Shipping</em> widget, %s shortcode or %s function.', 'woocommerce-jetpack' ),
18
  '<code>[wcj_get_left_to_free_shipping content=""]</code>',
19
  '<code>wcj_get_left_to_free_shipping( $content );</code>' ) . '<br>' . '<br>' .
20
- sprintf( __( 'In content replaced values are: %s and %s.', 'woocommerce-jetpack' ),
21
  '<code>%left_to_free%</code>',
22
- '<code>%free_shipping_min_amount%</code>' ),
 
23
  'id' => 'wcj_shipping_left_to_free_info_options',
24
  ),
25
  array(
@@ -30,7 +31,6 @@ return array(
30
  'type' => 'checkbox',
31
  ),
32
  array(
33
- 'title' => '',
34
  'desc' => __( 'Content', 'woocommerce-jetpack' ),
35
  'desc_tip' => __( 'You can use HTML and/or shortcodes (e.g. [wcj_wpml]) here.', 'woocommerce-jetpack' ),
36
  'id' => 'wcj_shipping_left_to_free_info_content_cart',
@@ -39,15 +39,14 @@ return array(
39
  'css' => 'width:100%;height:100px;',
40
  ),
41
  array(
42
- 'title' => '',
43
  'desc' => __( 'Position', 'woocommerce-jetpack' ),
 
44
  'id' => 'wcj_shipping_left_to_free_info_position_cart',
45
  'default' => 'woocommerce_after_cart_totals',
46
  'type' => 'select',
47
  'options' => wcj_get_cart_filters(),
48
  ),
49
  array(
50
- 'title' => '',
51
  'desc' => __( 'Position Order (Priority)', 'woocommerce-jetpack' ),
52
  'id' => 'wcj_shipping_left_to_free_info_priority_cart',
53
  'default' => 10,
@@ -63,7 +62,6 @@ return array(
63
  'desc_tip' => apply_filters( 'booster_message', '', 'desc' ),
64
  ),
65
  array(
66
- 'title' => '',
67
  'desc' => __( 'Content', 'woocommerce-jetpack' ),
68
  'desc_tip' => __( 'You can use HTML and/or shortcodes (e.g. [wcj_wpml]) here.', 'woocommerce-jetpack' ),
69
  'id' => 'wcj_shipping_left_to_free_info_content_mini_cart',
@@ -72,7 +70,6 @@ return array(
72
  'css' => 'width:100%;height:100px;',
73
  ),
74
  array(
75
- 'title' => '',
76
  'desc' => __( 'Position', 'woocommerce-jetpack' ),
77
  'id' => 'wcj_shipping_left_to_free_info_position_mini_cart',
78
  'default' => 'woocommerce_after_mini_cart',
@@ -84,7 +81,6 @@ return array(
84
  ),
85
  ),
86
  array(
87
- 'title' => '',
88
  'desc' => __( 'Position Order (Priority)', 'woocommerce-jetpack' ),
89
  'id' => 'wcj_shipping_left_to_free_info_priority_mini_cart',
90
  'default' => 10,
@@ -100,7 +96,6 @@ return array(
100
  'desc_tip' => apply_filters( 'booster_message', '', 'desc' ),
101
  ),
102
  array(
103
- 'title' => '',
104
  'desc' => __( 'Content', 'woocommerce-jetpack' ),
105
  'desc_tip' => __( 'You can use HTML and/or shortcodes (e.g. [wcj_wpml]) here.', 'woocommerce-jetpack' ),
106
  'id' => 'wcj_shipping_left_to_free_info_content_checkout',
@@ -109,7 +104,6 @@ return array(
109
  'css' => 'width:100%;height:100px;',
110
  ),
111
  array(
112
- 'title' => '',
113
  'desc' => __( 'Position', 'woocommerce-jetpack' ),
114
  'id' => 'wcj_shipping_left_to_free_info_position_checkout',
115
  'default' => 'woocommerce_checkout_after_order_review',
@@ -127,7 +121,6 @@ return array(
127
  ),
128
  ),
129
  array(
130
- 'title' => '',
131
  'desc' => __( 'Position Order (Priority)', 'woocommerce-jetpack' ),
132
  'id' => 'wcj_shipping_left_to_free_info_priority_checkout',
133
  'default' => 10,
2
  /**
3
  * Booster for WooCommerce - Settings - Left to Free Shipping
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
17
  sprintf( __( 'You can also use <em>Booster - Left to Free Shipping</em> widget, %s shortcode or %s function.', 'woocommerce-jetpack' ),
18
  '<code>[wcj_get_left_to_free_shipping content=""]</code>',
19
  '<code>wcj_get_left_to_free_shipping( $content );</code>' ) . '<br>' . '<br>' .
20
+ sprintf( __( 'In content replaced values are: %s, %s and %s.', 'woocommerce-jetpack' ),
21
  '<code>%left_to_free%</code>',
22
+ '<code>%free_shipping_min_amount%</code>',
23
+ '<code>%cart_total%</code>' ),
24
  'id' => 'wcj_shipping_left_to_free_info_options',
25
  ),
26
  array(
31
  'type' => 'checkbox',
32
  ),
33
  array(
 
34
  'desc' => __( 'Content', 'woocommerce-jetpack' ),
35
  'desc_tip' => __( 'You can use HTML and/or shortcodes (e.g. [wcj_wpml]) here.', 'woocommerce-jetpack' ),
36
  'id' => 'wcj_shipping_left_to_free_info_content_cart',
39
  'css' => 'width:100%;height:100px;',
40
  ),
41
  array(
 
42
  'desc' => __( 'Position', 'woocommerce-jetpack' ),
43
+ 'desc_tip' => __( 'Please note, that depending on the "Position" you select, your customer may have to reload the cart page to see the updated left to free shipping value. For example, if you select "After cart totals" position, then left to free shipping value will be updated as soon as customer updates the cart. However if you select "After cart" position instead – message will not be updated, and customer will have to reload the page. In other words, message position should be inside that page part that is automatically updated on cart update.', 'woocommerce-jetpack' ),
44
  'id' => 'wcj_shipping_left_to_free_info_position_cart',
45
  'default' => 'woocommerce_after_cart_totals',
46
  'type' => 'select',
47
  'options' => wcj_get_cart_filters(),
48
  ),
49
  array(
 
50
  'desc' => __( 'Position Order (Priority)', 'woocommerce-jetpack' ),
51
  'id' => 'wcj_shipping_left_to_free_info_priority_cart',
52
  'default' => 10,
62
  'desc_tip' => apply_filters( 'booster_message', '', 'desc' ),
63
  ),
64
  array(
 
65
  'desc' => __( 'Content', 'woocommerce-jetpack' ),
66
  'desc_tip' => __( 'You can use HTML and/or shortcodes (e.g. [wcj_wpml]) here.', 'woocommerce-jetpack' ),
67
  'id' => 'wcj_shipping_left_to_free_info_content_mini_cart',
70
  'css' => 'width:100%;height:100px;',
71
  ),
72
  array(
 
73
  'desc' => __( 'Position', 'woocommerce-jetpack' ),
74
  'id' => 'wcj_shipping_left_to_free_info_position_mini_cart',
75
  'default' => 'woocommerce_after_mini_cart',
81
  ),
82
  ),
83
  array(
 
84
  'desc' => __( 'Position Order (Priority)', 'woocommerce-jetpack' ),
85
  'id' => 'wcj_shipping_left_to_free_info_priority_mini_cart',
86
  'default' => 10,
96
  'desc_tip' => apply_filters( 'booster_message', '', 'desc' ),
97
  ),
98
  array(
 
99
  'desc' => __( 'Content', 'woocommerce-jetpack' ),
100
  'desc_tip' => __( 'You can use HTML and/or shortcodes (e.g. [wcj_wpml]) here.', 'woocommerce-jetpack' ),
101
  'id' => 'wcj_shipping_left_to_free_info_content_checkout',
104
  'css' => 'width:100%;height:100px;',
105
  ),
106
  array(
 
107
  'desc' => __( 'Position', 'woocommerce-jetpack' ),
108
  'id' => 'wcj_shipping_left_to_free_info_position_checkout',
109
  'default' => 'woocommerce_checkout_after_order_review',
121
  ),
122
  ),
123
  array(
 
124
  'desc' => __( 'Position Order (Priority)', 'woocommerce-jetpack' ),
125
  'id' => 'wcj_shipping_left_to_free_info_priority_checkout',
126
  'default' => 10,
includes/settings/wcj-settings-max-products-per-user.php ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings - Max Products per User
4
+ *
5
+ * @version 3.5.0
6
+ * @since 3.5.0
7
+ * @author Algoritmika Ltd.
8
+ */
9
+
10
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
+
12
+ return array(
13
+ array(
14
+ 'title' => __( 'All Products', 'woocommerce-jetpack' ),
15
+ 'type' => 'title',
16
+ 'id' => 'wcj_max_products_per_user_global_options',
17
+ ),
18
+ array(
19
+ 'title' => __( 'All Products', 'woocommerce-jetpack' ),
20
+ 'desc' => '<strong>' . __( 'Enable section', 'woocommerce-jetpack' ) . '</strong>',
21
+ 'id' => 'wcj_max_products_per_user_global_enabled',
22
+ 'default' => 'no',
23
+ 'type' => 'checkbox',
24
+ ),
25
+ array(
26
+ 'title' => __( 'Maximum Allowed Each Product\'s Quantity per User', 'woocommerce-jetpack' ),
27
+ 'id' => 'wcj_max_products_per_user_global_max_qty',
28
+ 'default' => 1,
29
+ 'type' => 'number',
30
+ 'custom_attributes' => array( 'min' => 1 ),
31
+ ),
32
+ array(
33
+ 'type' => 'sectionend',
34
+ 'id' => 'wcj_max_products_per_user_global_options',
35
+ ),
36
+ array(
37
+ 'title' => __( 'Per Product', 'woocommerce-jetpack' ),
38
+ 'type' => 'title',
39
+ 'id' => 'wcj_max_products_per_user_local_options',
40
+ ),
41
+ array(
42
+ 'title' => __( 'Per Product', 'woocommerce-jetpack' ),
43
+ 'desc' => '<strong>' . __( 'Enable section', 'woocommerce-jetpack' ) . '</strong>',
44
+ 'desc_tip' => __( 'This will add new meta box to each product\'s edit page.', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_message', '', 'desc' ),
45
+ 'id' => 'wcj_max_products_per_user_local_enabled',
46
+ 'default' => 'no',
47
+ 'type' => 'checkbox',
48
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
49
+ ),
50
+ array(
51
+ 'type' => 'sectionend',
52
+ 'id' => 'wcj_max_products_per_user_local_options',
53
+ ),
54
+ array(
55
+ 'title' => __( 'General Options', 'woocommerce-jetpack' ),
56
+ 'type' => 'title',
57
+ 'id' => 'wcj_max_products_per_user_general_options',
58
+ ),
59
+ array(
60
+ 'title' => __( 'Customer Message', 'woocommerce-jetpack' ),
61
+ 'desc' => wcj_message_replaced_values( array( '%max_qty%', '%product_title%', '%qty_already_bought%', '%remaining_qty%' ) ),
62
+ 'id' => 'wcj_max_products_per_user_message',
63
+ 'default' => __( 'You can only buy maximum %max_qty% pcs. of %product_title% (you already bought %qty_already_bought% pcs.).', 'woocommerce-jetpack' ),
64
+ 'type' => 'custom_textarea',
65
+ 'css' => 'width:100%;height:100px;',
66
+ ),
67
+ array(
68
+ 'title' => __( 'Block Checkout Page', 'woocommerce-jetpack' ),
69
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
70
+ 'desc_tip' => __( 'This will stop customer from accessing the checkout page on exceeded quantities. Customer will be redirected to the cart page.', 'woocommerce-jetpack' ),
71
+ 'id' => 'wcj_max_products_per_user_stop_from_seeing_checkout',
72
+ 'default' => 'no',
73
+ 'type' => 'checkbox',
74
+ ),
75
+ array(
76
+ 'title' => __( 'Calculate Data', 'woocommerce-jetpack' ),
77
+ 'id' => 'wcj_max_products_per_user_calculate_data',
78
+ 'default' => '',
79
+ 'type' => 'custom_link',
80
+ 'link' => '<a class="button" href="' .
81
+ add_query_arg( 'wcj_max_products_per_user_calculate_data', '1', remove_query_arg( 'wcj_max_products_per_user_calculate_data_finished' ) ) . '">' .
82
+ __( 'Calculate Data', 'woocommerce-jetpack' ) .
83
+ '</a>',
84
+ ),
85
+ array(
86
+ 'type' => 'sectionend',
87
+ 'id' => 'wcj_max_products_per_user_general_options',
88
+ ),
89
+ );
includes/settings/wcj-settings-order-numbers.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Order Numbers
4
  *
5
- * @version 3.3.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) add `wcj_order_number_counter_previous_order_date` as `hidden` field (for proper module reset)
@@ -114,6 +114,24 @@ return array(
114
  'default' => 'yes',
115
  'type' => 'checkbox',
116
  ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  array(
118
  'type' => 'sectionend',
119
  'id' => 'wcj_order_numbers_options',
2
  /**
3
  * Booster for WooCommerce - Settings - Order Numbers
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) add `wcj_order_number_counter_previous_order_date` as `hidden` field (for proper module reset)
114
  'default' => 'yes',
115
  'type' => 'checkbox',
116
  ),
117
+ array(
118
+ 'title' => __( 'Enable Editable Order Number Meta Box', 'woocommerce-jetpack' ),
119
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
120
+ 'id' => 'wcj_order_number_editable_order_number_meta_box_enabled',
121
+ 'default' => 'no',
122
+ 'type' => 'checkbox',
123
+ 'desc_tip' => apply_filters( 'booster_message', '', 'desc' ),
124
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
125
+ ),
126
+ array(
127
+ 'title' => __( 'Minimal Order ID', 'woocommerce-jetpack' ),
128
+ 'desc_tip' => __( 'If you wish to disable order numbering for some (older) orders, you can set order ID to start here.', 'woocommerce-jetpack' ) . ' ' .
129
+ __( 'Set to zero to enable numbering for all orders.', 'woocommerce-jetpack' ),
130
+ 'id' => 'wcj_order_numbers_min_order_id',
131
+ 'default' => 0,
132
+ 'type' => 'number',
133
+ 'custom_attributes' => array( 'min' => 0 ),
134
+ ),
135
  array(
136
  'type' => 'sectionend',
137
  'id' => 'wcj_order_numbers_options',
includes/settings/wcj-settings-payment-gateways-by-country.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Gateways by Country or State
4
  *
5
- * @version 3.4.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo change `textarea` to `readonly`
@@ -17,7 +17,28 @@ $settings = array(
17
  'id' => 'wcj_gateways_by_location_general_options',
18
  ),
19
  array(
20
- 'title' => __( 'Postcode Type', 'woocommerce-jetpack' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  'id' => 'wcj_gateways_by_location_postcodes_type',
22
  'type' => 'select',
23
  'default' => 'billing',
@@ -33,8 +54,7 @@ $settings = array(
33
  array(
34
  'title' => __( 'Payment Gateways', 'woocommerce-jetpack' ),
35
  'type' => 'title',
36
- 'desc' => __( 'Country and state are defined from customer\'s entered billing address.', 'woocommerce-jetpack' ) . '<br>' .
37
- __( 'If any field is left empty - it\'s ignored.', 'woocommerce-jetpack' ),
38
  'id' => 'wcj_payment_gateways_by_country_gateways_options',
39
  ),
40
  );
2
  /**
3
  * Booster for WooCommerce - Settings - Gateways by Country or State
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo change `textarea` to `readonly`
17
  'id' => 'wcj_gateways_by_location_general_options',
18
  ),
19
  array(
20
+ 'title' => __( 'Detect Country by', 'woocommerce-jetpack' ),
21
+ 'id' => 'wcj_gateways_by_location_country_type',
22
+ 'type' => 'select',
23
+ 'default' => 'billing',
24
+ 'options' => array(
25
+ 'billing' => __( 'Billing country', 'woocommerce-jetpack' ),
26
+ 'shipping' => __( 'Shipping country', 'woocommerce-jetpack' ),
27
+ 'by_ip' => __( 'Country by IP', 'woocommerce-jetpack' ),
28
+ ),
29
+ ),
30
+ array(
31
+ 'title' => __( 'Detect State by', 'woocommerce-jetpack' ),
32
+ 'id' => 'wcj_gateways_by_location_state_type',
33
+ 'type' => 'select',
34
+ 'default' => 'billing',
35
+ 'options' => array(
36
+ 'billing' => __( 'Billing state', 'woocommerce-jetpack' ),
37
+ 'shipping' => __( 'Shipping state', 'woocommerce-jetpack' ),
38
+ ),
39
+ ),
40
+ array(
41
+ 'title' => __( 'Detect Postcode by', 'woocommerce-jetpack' ),
42
  'id' => 'wcj_gateways_by_location_postcodes_type',
43
  'type' => 'select',
44
  'default' => 'billing',
54
  array(
55
  'title' => __( 'Payment Gateways', 'woocommerce-jetpack' ),
56
  'type' => 'title',
57
+ 'desc' => __( 'If any field is left empty - it\'s ignored.', 'woocommerce-jetpack' ),
 
58
  'id' => 'wcj_payment_gateways_by_country_gateways_options',
59
  ),
60
  );
includes/settings/wcj-settings-payment-gateways-by-shipping.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce Settings - Payment Gateways by Shipping
4
  *
5
- * @version 2.8.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) remove COD, Custom Booster Payment Gateways (and maybe other payment gateways) that already have `enable_for_methods` option
@@ -10,20 +10,36 @@
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
12
 
13
- $shipping_methods = array();
14
- if ( is_admin() ) {
15
- foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
16
- $shipping_methods[ $method->id ] = $method->get_method_title();
17
- }
18
- }
19
  $settings = array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20
  array(
21
  'title' => __( 'Payment Gateways', 'woocommerce-jetpack' ),
22
  'type' => 'title',
23
  'desc' => __( 'If payment gateway is only available for certain methods, set it up here. Leave blank to enable for all methods.', 'woocommerce-jetpack' ),
24
  'id' => 'wcj_payment_gateways_by_shipping_options',
25
  ),
26
- );
27
  $gateways = WC()->payment_gateways->payment_gateways();
28
  foreach ( $gateways as $key => $gateway ) {
29
  if ( ! in_array( $key, array( 'bacs', 'cod' ) ) ) {
@@ -41,7 +57,7 @@ foreach ( $gateways as $key => $gateway ) {
41
  'title' => $gateway->title,
42
  'desc_tip' => $desc_tip,
43
  'desc' => __( 'Enable for shipping methods', 'woocommerce' ),
44
- 'id' => 'wcj_gateways_by_shipping_enable_' . $key,
45
  'default' => '',
46
  'type' => 'multiselect',
47
  'class' => 'chosen_select',
2
  /**
3
  * Booster for WooCommerce Settings - Payment Gateways by Shipping
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) remove COD, Custom Booster Payment Gateways (and maybe other payment gateways) that already have `enable_for_methods` option
10
 
11
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
12
 
13
+ $use_shipping_instance = ( 'yes' === get_option( 'wcj_payment_gateways_by_shipping_use_shipping_instance', 'no' ) );
14
+ $shipping_methods = ( $use_shipping_instance ? wcj_get_shipping_methods_instances() : wcj_get_shipping_methods() );
 
 
 
 
15
  $settings = array(
16
+ array(
17
+ 'title' => __( 'General Options', 'woocommerce-jetpack' ),
18
+ 'type' => 'title',
19
+ 'id' => 'wcj_payment_gateways_by_shipping_general_options',
20
+ ),
21
+ array(
22
+ 'title' => __( 'Use Shipping Instances', 'woocommerce-jetpack' ),
23
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
24
+ 'desc_tip' => __( 'Enable this if you want to use shipping methods instances instead of shipping methods.', 'woocommerce-jetpack' ) . ' ' .
25
+ __( 'Save changes after enabling this option.', 'woocommerce-jetpack' ),
26
+ 'type' => 'checkbox',
27
+ 'id' => 'wcj_payment_gateways_by_shipping_use_shipping_instance',
28
+ 'default' => 'no',
29
+ ),
30
+ array(
31
+ 'type' => 'sectionend',
32
+ 'id' => 'wcj_payment_gateways_by_shipping_general_options',
33
+ ),
34
+ );
35
+ $settings = array_merge( $settings, array(
36
  array(
37
  'title' => __( 'Payment Gateways', 'woocommerce-jetpack' ),
38
  'type' => 'title',
39
  'desc' => __( 'If payment gateway is only available for certain methods, set it up here. Leave blank to enable for all methods.', 'woocommerce-jetpack' ),
40
  'id' => 'wcj_payment_gateways_by_shipping_options',
41
  ),
42
+ ) );
43
  $gateways = WC()->payment_gateways->payment_gateways();
44
  foreach ( $gateways as $key => $gateway ) {
45
  if ( ! in_array( $key, array( 'bacs', 'cod' ) ) ) {
57
  'title' => $gateway->title,
58
  'desc_tip' => $desc_tip,
59
  'desc' => __( 'Enable for shipping methods', 'woocommerce' ),
60
+ 'id' => ( $use_shipping_instance ? 'wcj_gateways_by_shipping_enable_instance_' . $key : 'wcj_gateways_by_shipping_enable_' . $key ),
61
  'default' => '',
62
  'type' => 'multiselect',
63
  'class' => 'chosen_select',
includes/settings/wcj-settings-pdf-invoicing-advanced.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Advanced
4
  *
5
- * @version 3.4.3
6
  * @since 3.3.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) create "Tools (Options)" submodule
@@ -92,7 +92,7 @@ return array(
92
  array(
93
  'title' => __( 'Actions', 'woocommerce-jetpack' ),
94
  'type' => 'custom_link',
95
- 'link' => '<a class="button-primary" href="' . add_query_arg( 'wcj_download_fonts', '1' ) . '">' .
96
  ( $is_full_fonts ? __( 'Re-download', 'woocommerce-jetpack' ) : __( 'Download', 'woocommerce-jetpack' ) )
97
  . '</a>',
98
  'id' => 'wcj_invoicing_fonts_manager_styling_option',
@@ -120,6 +120,12 @@ return array(
120
  'default' => 'yes',
121
  'type' => 'checkbox',
122
  ),
 
 
 
 
 
 
123
  array(
124
  'type' => 'sectionend',
125
  'id' => 'wcj_invoicing_general_display_options',
2
  /**
3
  * Booster for WooCommerce - Settings - PDF Invoicing - Advanced
4
  *
5
+ * @version 3.5.0
6
  * @since 3.3.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) create "Tools (Options)" submodule
92
  array(
93
  'title' => __( 'Actions', 'woocommerce-jetpack' ),
94
  'type' => 'custom_link',
95
+ 'link' => '<a class="button" href="' . add_query_arg( 'wcj_download_fonts', '1' ) . '">' .
96
  ( $is_full_fonts ? __( 'Re-download', 'woocommerce-jetpack' ) : __( 'Download', 'woocommerce-jetpack' ) )
97
  . '</a>',
98
  'id' => 'wcj_invoicing_fonts_manager_styling_option',
120
  'default' => 'yes',
121
  'type' => 'checkbox',
122
  ),
123
+ array(
124
+ 'desc' => __( 'Add editable numbers', 'woocommerce-jetpack' ),
125
+ 'id' => 'wcj_invoicing_add_order_meta_box_numbering',
126
+ 'default' => 'yes',
127
+ 'type' => 'checkbox',
128
+ ),
129
  array(
130
  'type' => 'sectionend',
131
  'id' => 'wcj_invoicing_general_display_options',
includes/settings/wcj-settings-price-by-user-role.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Price by User Role
4
  *
5
- * @version 3.2.2
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -108,61 +108,79 @@ foreach ( wcj_get_user_roles() as $role_key => $role_data ) {
108
  ),
109
  ) );
110
  }
111
- $product_cats_options = array();
112
- $product_cats = get_terms( 'product_cat', 'orderby=name&hide_empty=0' );
113
- if ( ! empty( $product_cats ) && ! is_wp_error( $product_cats ) ){
114
- foreach ( $product_cats as $product_cat ) {
115
- $product_cats_options[ $product_cat->term_id ] = $product_cat->name;
116
- }
117
- }
118
  $settings = array_merge( $settings, array(
119
  array(
120
  'type' => 'sectionend',
121
  'id' => 'wcj_price_by_user_role_multipliers_options',
122
  ),
 
 
123
  array(
124
- 'title' => __( 'Price by User Role by Products Categories', 'woocommerce-jetpack' ),
125
- 'type' => 'title',
126
- 'id' => 'wcj_price_by_user_role_categories_options',
 
127
  ),
128
  array(
129
- 'title' => __( 'Categories', 'woocommerce-jetpack' ),
130
- 'desc_tip' => __( 'Save module\'s settings after changing this option to see new settings fields.', 'woocommerce-jetpack' ),
131
- 'id' => 'wcj_price_by_user_role_categories',
132
- 'default' => '',
133
- 'type' => 'multiselect',
134
- 'class' => 'chosen_select',
135
- 'options' => $product_cats_options,
136
- 'desc' => apply_filters( 'booster_message', '', 'desc' ),
137
- 'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
138
  ),
139
- ) );
140
- $categories = apply_filters( 'booster_option', '', get_option( 'wcj_price_by_user_role_categories', '' ) );
141
- if ( ! empty( $categories ) ) {
142
- foreach ( $categories as $category ) {
143
- foreach ( wcj_get_user_roles() as $role_key => $role_data ) {
144
- $settings = array_merge( $settings, array(
145
- array(
146
- 'title' => $product_cats_options[ $category ] . ': ' . $role_data['name'],
147
- 'id' => 'wcj_price_by_user_role_cat_' . $category . '_' . $role_key,
148
- 'default' => 1,
149
- 'type' => 'wcj_number_plus_checkbox_start',
150
- 'custom_attributes' => array( 'step' => '0.000001', 'min' => '0', ),
151
- ),
152
- array(
153
- 'desc' => __( 'Make Empty Price', 'woocommerce-jetpack' ),
154
- 'id' => 'wcj_price_by_user_role_cat_empty_price_' . $category . '_' . $role_key,
155
- 'default' => 'no',
156
- 'type' => 'wcj_number_plus_checkbox_end',
157
- ),
158
- ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
  }
160
  }
 
 
 
 
 
 
161
  }
162
- $settings = array_merge( $settings, array(
163
- array(
164
- 'type' => 'sectionend',
165
- 'id' => 'wcj_price_by_user_role_categories_options',
166
- ),
167
- ) );
168
  return $settings;
2
  /**
3
  * Booster for WooCommerce - Settings - Price by User Role
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
108
  ),
109
  ) );
110
  }
 
 
 
 
 
 
 
111
  $settings = array_merge( $settings, array(
112
  array(
113
  'type' => 'sectionend',
114
  'id' => 'wcj_price_by_user_role_multipliers_options',
115
  ),
116
+ ) );
117
+ $taxonomies = array(
118
  array(
119
+ 'title' => __( 'Products Categories', 'woocommerce-jetpack' ),
120
+ 'name' => 'categories',
121
+ 'id' => 'product_cat',
122
+ 'option_id' => 'cat',
123
  ),
124
  array(
125
+ 'title' => __( 'Products Tags', 'woocommerce-jetpack' ),
126
+ 'name' => 'tags',
127
+ 'id' => 'product_tag',
128
+ 'option_id' => 'tag',
 
 
 
 
 
129
  ),
130
+ );
131
+ foreach ( $taxonomies as $taxonomy ) {
132
+ $product_taxonomies_options = array();
133
+ $product_taxonomies = get_terms( $taxonomy['id'], 'orderby=name&hide_empty=0' );
134
+ if ( ! empty( $product_taxonomies ) && ! is_wp_error( $product_taxonomies ) ){
135
+ foreach ( $product_taxonomies as $product_taxonomy ) {
136
+ $product_taxonomies_options[ $product_taxonomy->term_id ] = $product_taxonomy->name;
137
+ }
138
+ }
139
+ $settings = array_merge( $settings, array(
140
+ array(
141
+ 'title' => sprintf( __( 'Price by User Role by %s', 'woocommerce-jetpack' ), $taxonomy['title'] ),
142
+ 'type' => 'title',
143
+ 'id' => 'wcj_price_by_user_role_' . $taxonomy['name'] . '_options',
144
+ ),
145
+ array(
146
+ 'title' => $taxonomy['title'],
147
+ 'desc_tip' => __( 'Save module\'s settings after changing this option to see new settings fields.', 'woocommerce-jetpack' ),
148
+ 'id' => 'wcj_price_by_user_role_' . $taxonomy['name'],
149
+ 'default' => '',
150
+ 'type' => 'multiselect',
151
+ 'class' => 'chosen_select',
152
+ 'options' => $product_taxonomies_options,
153
+ 'desc' => apply_filters( 'booster_message', '', 'desc' ),
154
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
155
+ ),
156
+ ) );
157
+ $_taxonomies = apply_filters( 'booster_option', '', get_option( 'wcj_price_by_user_role_' . $taxonomy['name'], '' ) );
158
+ if ( ! empty( $_taxonomies ) ) {
159
+ foreach ( $_taxonomies as $_taxonomy ) {
160
+ foreach ( wcj_get_user_roles() as $role_key => $role_data ) {
161
+ $settings = array_merge( $settings, array(
162
+ array(
163
+ 'title' => $product_taxonomies_options[ $_taxonomy ] . ': ' . $role_data['name'],
164
+ 'id' => 'wcj_price_by_user_role_' . $taxonomy['option_id'] . '_' . $_taxonomy . '_' . $role_key,
165
+ 'default' => 1,
166
+ 'type' => 'wcj_number_plus_checkbox_start',
167
+ 'custom_attributes' => array( 'step' => '0.000001', 'min' => '0', ),
168
+ ),
169
+ array(
170
+ 'desc' => __( 'Make Empty Price', 'woocommerce-jetpack' ),
171
+ 'id' => 'wcj_price_by_user_role_' . $taxonomy['option_id'] . '_empty_price_' . $_taxonomy . '_' . $role_key,
172
+ 'default' => 'no',
173
+ 'type' => 'wcj_number_plus_checkbox_end',
174
+ ),
175
+ ) );
176
+ }
177
  }
178
  }
179
+ $settings = array_merge( $settings, array(
180
+ array(
181
+ 'type' => 'sectionend',
182
+ 'id' => 'wcj_price_by_user_role_' . $taxonomy['name'] . '_options',
183
+ ),
184
+ ) );
185
  }
 
 
 
 
 
 
186
  return $settings;
includes/settings/wcj-settings-price-formats.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Price Formats
4
  *
5
- * @version 3.2.4
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) add `desc_tip` to `wcj_price_formats_general_trim_zeros`
@@ -108,7 +108,7 @@ for ( $i = 1; $i <= apply_filters( 'booster_option', 1, get_option( 'wcj_price_f
108
  array(
109
  'desc' => __( 'Number of Decimals', 'woocommerce-jetpack' ),
110
  'id' => 'wcj_price_formats_number_of_decimals_' . $i,
111
- 'default' => wc_get_price_decimals(),
112
  'type' => 'number',
113
  'custom_attributes' => array( 'min' => 0, 'step' => 1 ),
114
  'css' => 'width:300px;',
2
  /**
3
  * Booster for WooCommerce - Settings - Price Formats
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  * @todo (maybe) add `desc_tip` to `wcj_price_formats_general_trim_zeros`
108
  array(
109
  'desc' => __( 'Number of Decimals', 'woocommerce-jetpack' ),
110
  'id' => 'wcj_price_formats_number_of_decimals_' . $i,
111
+ 'default' => get_option( 'woocommerce_price_num_decimals', 2 ),
112
  'type' => 'number',
113
  'custom_attributes' => array( 'min' => 0, 'step' => 1 ),
114
  'css' => 'width:300px;',
includes/settings/wcj-settings-product-by-country.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Product Visibility by Country
4
  *
5
- * @version 3.1.1
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -39,6 +39,13 @@ return array(
39
  'default' => 'no',
40
  'type' => 'checkbox',
41
  ),
 
 
 
 
 
 
 
42
  array(
43
  'type' => 'sectionend',
44
  'id' => 'wcj_product_by_country_options',
2
  /**
3
  * Booster for WooCommerce - Settings - Product Visibility by Country
4
  *
5
+ * @version 3.5.0
6
  * @since 2.9.0
7
  * @author Algoritmika Ltd.
8
  */
39
  'default' => 'no',
40
  'type' => 'checkbox',
41
  ),
42
+ array(
43
+ 'desc_tip' => __( 'Enable this if you are still seeing hidden products in "Products" widgets.', 'woocommerce-jetpack' ),
44
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
45
+ 'id' => 'wcj_product_by_country_query_widgets',
46
+ 'default' => 'no',
47
+ 'type' => 'checkbox',
48
+ ),
49
  array(
50
  'type' => 'sectionend',
51
  'id' => 'wcj_product_by_country_options',
includes/settings/wcj-settings-product-custom-info.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Product Info
4
  *
5
- * @version 3.4.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -10,9 +10,11 @@
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
  $is_multiselect_products = ( 'yes' === get_option( 'wcj_list_for_products', 'yes' ) );
13
- $products = ( $is_multiselect_products ? wcj_get_products() : false );
14
- $product_cats = wcj_get_terms( 'product_cat' );
15
- $product_tags = wcj_get_terms( 'product_tag' );
 
 
16
  $settings = array();
17
  $single_or_archive_array = array( 'single', 'archive' );
18
 
@@ -67,6 +69,16 @@ foreach ( $single_or_archive_array as $single_or_archive ) {
67
  array( 'id' => 'wcj_product_custom_info_products_to_exclude_' . $single_or_archive . '_' . $i, 'default' => '' ),
68
  ), $is_multiselect_products );
69
 
 
 
 
 
 
 
 
 
 
 
70
  $settings = array_merge( $settings, array(
71
  array(
72
  'title' => sprintf( __( 'Block #%s', 'woocommerce-jetpack' ), $i ),
@@ -113,59 +125,51 @@ foreach ( $single_or_archive_array as $single_or_archive ) {
113
  'default' => 10,
114
  'type' => 'number',
115
  ),
116
- array(
117
  'title' => __( 'Product Categories to Include', 'woocommerce-jetpack' ),
118
  'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
119
  'id' => 'wcj_product_custom_info_product_cats_to_include_' . $single_or_archive . '_' . $i,
120
- 'default' => '',
121
- 'type' => 'multiselect',
122
- 'class' => 'chosen_select',
123
- 'options' => $product_cats,
124
  ),
125
- array(
126
  'title' => __( 'Product Categories to Exclude', 'woocommerce-jetpack' ),
127
  'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
128
  'id' => 'wcj_product_custom_info_product_cats_to_exclude_' . $single_or_archive . '_' . $i,
129
- 'default' => '',
130
- 'type' => 'multiselect',
131
- 'class' => 'chosen_select',
132
- 'options' => $product_cats,
133
  ),
134
- array(
135
  'title' => __( 'Product Tags to Include', 'woocommerce-jetpack' ),
136
  'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
137
  'id' => 'wcj_product_custom_info_product_tags_to_include_' . $single_or_archive . '_' . $i,
138
- 'default' => '',
139
- 'type' => 'multiselect',
140
- 'class' => 'chosen_select',
141
- 'options' => $product_tags,
142
  ),
143
- array(
144
  'title' => __( 'Product Tags to Exclude', 'woocommerce-jetpack' ),
145
  'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
146
  'id' => 'wcj_product_custom_info_product_tags_to_exclude_' . $single_or_archive . '_' . $i,
147
- 'default' => '',
148
- 'type' => 'multiselect',
149
- 'class' => 'chosen_select',
150
- 'options' => $product_tags,
151
  ),
152
- wcj_get_settings_as_multiselect_or_text(
153
- array(
154
- 'title' => __( 'Products to Include', 'woocommerce-jetpack' ),
155
- 'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
156
- 'id' => 'wcj_product_custom_info_products_to_include_' . $single_or_archive . '_' . $i,
157
- 'default' => '',
158
- ),
159
  $products,
160
  $is_multiselect_products
161
  ),
162
- wcj_get_settings_as_multiselect_or_text(
163
- array(
164
- 'title' => __( 'Products to Exclude', 'woocommerce-jetpack' ),
165
- 'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
166
- 'id' => 'wcj_product_custom_info_products_to_exclude_' . $single_or_archive . '_' . $i,
167
- 'default' => '',
168
- ),
169
  $products,
170
  $is_multiselect_products
171
  ),
2
  /**
3
  * Booster for WooCommerce - Settings - Product Info
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
  $is_multiselect_products = ( 'yes' === get_option( 'wcj_list_for_products', 'yes' ) );
13
+ $is_multiselect_cats = ( 'yes' === get_option( 'wcj_list_for_products_cats', 'yes' ) );
14
+ $is_multiselect_tags = ( 'yes' === get_option( 'wcj_list_for_products_tags', 'yes' ) );
15
+ $products = ( $is_multiselect_products ? wcj_get_products() : false );
16
+ $product_cats = ( $is_multiselect_cats ? wcj_get_terms( 'product_cat' ) : false );
17
+ $product_tags = ( $is_multiselect_tags ? wcj_get_terms( 'product_tag' ) : false );
18
  $settings = array();
19
  $single_or_archive_array = array( 'single', 'archive' );
20
 
69
  array( 'id' => 'wcj_product_custom_info_products_to_exclude_' . $single_or_archive . '_' . $i, 'default' => '' ),
70
  ), $is_multiselect_products );
71
 
72
+ wcj_maybe_convert_and_update_option_value( array(
73
+ array( 'id' => 'wcj_product_custom_info_product_cats_to_include_' . $single_or_archive . '_' . $i, 'default' => '' ),
74
+ array( 'id' => 'wcj_product_custom_info_product_cats_to_exclude_' . $single_or_archive . '_' . $i, 'default' => '' ),
75
+ ), $is_multiselect_cats );
76
+
77
+ wcj_maybe_convert_and_update_option_value( array(
78
+ array( 'id' => 'wcj_product_custom_info_product_tags_to_include_' . $single_or_archive . '_' . $i, 'default' => '' ),
79
+ array( 'id' => 'wcj_product_custom_info_product_tags_to_exclude_' . $single_or_archive . '_' . $i, 'default' => '' ),
80
+ ), $is_multiselect_tags );
81
+
82
  $settings = array_merge( $settings, array(
83
  array(
84
  'title' => sprintf( __( 'Block #%s', 'woocommerce-jetpack' ), $i ),
125
  'default' => 10,
126
  'type' => 'number',
127
  ),
128
+ wcj_get_settings_as_multiselect_or_text( array(
129
  'title' => __( 'Product Categories to Include', 'woocommerce-jetpack' ),
130
  'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
131
  'id' => 'wcj_product_custom_info_product_cats_to_include_' . $single_or_archive . '_' . $i,
132
+ 'default' => '' ),
133
+ $product_cats,
134
+ $is_multiselect_cats
 
135
  ),
136
+ wcj_get_settings_as_multiselect_or_text( array(
137
  'title' => __( 'Product Categories to Exclude', 'woocommerce-jetpack' ),
138
  'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
139
  'id' => 'wcj_product_custom_info_product_cats_to_exclude_' . $single_or_archive . '_' . $i,
140
+ 'default' => '' ),
141
+ $product_cats,
142
+ $is_multiselect_cats
 
143
  ),
144
+ wcj_get_settings_as_multiselect_or_text( array(
145
  'title' => __( 'Product Tags to Include', 'woocommerce-jetpack' ),
146
  'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
147
  'id' => 'wcj_product_custom_info_product_tags_to_include_' . $single_or_archive . '_' . $i,
148
+ 'default' => '' ),
149
+ $product_tags,
150
+ $is_multiselect_tags
 
151
  ),
152
+ wcj_get_settings_as_multiselect_or_text( array(
153
  'title' => __( 'Product Tags to Exclude', 'woocommerce-jetpack' ),
154
  'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
155
  'id' => 'wcj_product_custom_info_product_tags_to_exclude_' . $single_or_archive . '_' . $i,
156
+ 'default' => '' ),
157
+ $product_tags,
158
+ $is_multiselect_tags
 
159
  ),
160
+ wcj_get_settings_as_multiselect_or_text( array(
161
+ 'title' => __( 'Products to Include', 'woocommerce-jetpack' ),
162
+ 'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
163
+ 'id' => 'wcj_product_custom_info_products_to_include_' . $single_or_archive . '_' . $i,
164
+ 'default' => '' ),
 
 
165
  $products,
166
  $is_multiselect_products
167
  ),
168
+ wcj_get_settings_as_multiselect_or_text( array(
169
+ 'title' => __( 'Products to Exclude', 'woocommerce-jetpack' ),
170
+ 'desc_tip' => __( 'Leave blank to disable the option.', 'woocommerce-jetpack' ),
171
+ 'id' => 'wcj_product_custom_info_products_to_exclude_' . $single_or_archive . '_' . $i,
172
+ 'default' => '' ),
 
 
173
  $products,
174
  $is_multiselect_products
175
  ),
includes/settings/wcj-settings-product-listings.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Admin Tools
4
  *
5
- * @version 3.4.5
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -67,6 +67,16 @@ return array(
67
  'default' => 'yes',
68
  'type' => 'checkbox',
69
  ),
 
 
 
 
 
 
 
 
 
 
70
  array(
71
  'type' => 'sectionend',
72
  'id' => 'wcj_product_listings_shop_page_options',
2
  /**
3
  * Booster for WooCommerce - Settings - Admin Tools
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
67
  'default' => 'yes',
68
  'type' => 'checkbox',
69
  ),
70
+ array(
71
+ 'title' => __( 'Exclude Categories Products', 'woocommerce-jetpack' ),
72
+ 'desc_tip' => __(' Excludes one or more categories products from the shop page. Leave blank to disable.', 'woocommerce-jetpack' ),
73
+ 'id' => 'wcj_product_listings_exclude_cats_products_on_shop',
74
+ 'default' => '',
75
+ 'type' => 'multiselect',
76
+ 'class' => 'chosen_select',
77
+ 'css' => 'width: 450px;',
78
+ 'options' => $product_cats,
79
+ ),
80
  array(
81
  'type' => 'sectionend',
82
  'id' => 'wcj_product_listings_shop_page_options',
includes/settings/wcj-settings-shipping-by-condition.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Shipping by Condition
4
  *
5
- * @version 3.2.4
6
  * @since 3.2.1
7
  * @author Algoritmika Ltd.
8
  */
@@ -11,7 +11,29 @@ if ( ! defined( 'ABSPATH' ) ) {
11
  exit; // Exit if accessed directly
12
  }
13
 
 
 
14
  $settings = array();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  foreach ( $this->condition_options as $options_id => $options_data ) {
16
  $settings = array_merge( $settings, array(
17
  array(
@@ -29,8 +51,9 @@ foreach ( $this->condition_options as $options_id => $options_data ) {
29
  ),
30
  ) );
31
  $settings = array_merge( $settings, $this->get_additional_section_settings( $options_id ) );
32
- foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
33
- if ( ! in_array( $method->id, array( 'flat_rate', 'local_pickup' ) ) ) {
 
34
  $custom_attributes = apply_filters( 'booster_message', '', 'disabled' );
35
  if ( '' == $custom_attributes ) {
36
  $custom_attributes = array();
@@ -42,10 +65,10 @@ foreach ( $this->condition_options as $options_id => $options_data ) {
42
  }
43
  $settings = array_merge( $settings, array(
44
  array(
45
- 'title' => $method->get_method_title(),
46
  'desc_tip' => $desc_tip,
47
  'desc' => '<br>' . sprintf( __( 'Include %s', 'woocommerce-jetpack' ), $options_data['title'] ),
48
- 'id' => 'wcj_shipping_' . $options_id . '_include_' . $method->id,
49
  'default' => '',
50
  'type' => 'multiselect',
51
  'class' => 'chosen_select',
@@ -56,7 +79,7 @@ foreach ( $this->condition_options as $options_id => $options_data ) {
56
  array(
57
  'desc_tip' => $desc_tip,
58
  'desc' => '<br>' . sprintf( __( 'Exclude %s', 'woocommerce-jetpack' ), $options_data['title'] ),
59
- 'id' => 'wcj_shipping_' . $options_id . '_exclude_' . $method->id,
60
  'default' => '',
61
  'type' => 'multiselect',
62
  'class' => 'chosen_select',
2
  /**
3
  * Booster for WooCommerce - Settings - Shipping by Condition
4
  *
5
+ * @version 3.5.0
6
  * @since 3.2.1
7
  * @author Algoritmika Ltd.
8
  */
11
  exit; // Exit if accessed directly
12
  }
13
 
14
+ $use_shipping_instances = ( 'yes' === get_option( 'wcj_' . $this->id . '_use_shipping_instance', 'no' ) );
15
+ $shipping_methods = ( $use_shipping_instances ? wcj_get_shipping_methods_instances( true ) : WC()->shipping()->load_shipping_methods() );
16
  $settings = array();
17
+ $settings = array_merge( $settings, array(
18
+ array(
19
+ 'title' => __( 'General Options', 'woocommerce-jetpack' ),
20
+ 'type' => 'title',
21
+ 'id' => 'wcj_' . $this->id . '_general_options',
22
+ ),
23
+ array(
24
+ 'title' => __( 'Use Shipping Instances', 'woocommerce-jetpack' ),
25
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
26
+ 'desc_tip' => __( 'Enable this if you want to use shipping methods instances instead of shipping methods.', 'woocommerce-jetpack' ) . ' ' .
27
+ __( 'Save changes after enabling this option.', 'woocommerce-jetpack' ),
28
+ 'type' => 'checkbox',
29
+ 'id' => 'wcj_' . $this->id . '_use_shipping_instance',
30
+ 'default' => 'no',
31
+ ),
32
+ array(
33
+ 'type' => 'sectionend',
34
+ 'id' => 'wcj_' . $this->id . '_general_options',
35
+ ),
36
+ ) );
37
  foreach ( $this->condition_options as $options_id => $options_data ) {
38
  $settings = array_merge( $settings, array(
39
  array(
51
  ),
52
  ) );
53
  $settings = array_merge( $settings, $this->get_additional_section_settings( $options_id ) );
54
+ foreach ( $shipping_methods as $method ) {
55
+ $method_id = ( $use_shipping_instances ? $method['shipping_method_id'] : $method->id );
56
+ if ( ! in_array( $method_id, array( 'flat_rate', 'local_pickup' ) ) ) {
57
  $custom_attributes = apply_filters( 'booster_message', '', 'disabled' );
58
  if ( '' == $custom_attributes ) {
59
  $custom_attributes = array();
65
  }
66
  $settings = array_merge( $settings, array(
67
  array(
68
+ 'title' => ( $use_shipping_instances ? $method['zone_name'] . ': ' . $method['shipping_method_title']: $method->get_method_title() ),
69
  'desc_tip' => $desc_tip,
70
  'desc' => '<br>' . sprintf( __( 'Include %s', 'woocommerce-jetpack' ), $options_data['title'] ),
71
+ 'id' => 'wcj_shipping_' . $options_id . '_include_' . ( $use_shipping_instances ? 'instance_' . $method['shipping_method_instance_id'] : $method->id ),
72
  'default' => '',
73
  'type' => 'multiselect',
74
  'class' => 'chosen_select',
79
  array(
80
  'desc_tip' => $desc_tip,
81
  'desc' => '<br>' . sprintf( __( 'Exclude %s', 'woocommerce-jetpack' ), $options_data['title'] ),
82
+ 'id' => 'wcj_shipping_' . $options_id . '_exclude_' . ( $use_shipping_instances ? 'instance_' . $method['shipping_method_instance_id'] : $method->id ),
83
  'default' => '',
84
  'type' => 'multiselect',
85
  'class' => 'chosen_select',
includes/settings/wcj-settings-shipping-by-order-amount.php CHANGED
@@ -2,14 +2,33 @@
2
  /**
3
  * Booster for WooCommerce Settings - Shipping Methods by Min/Max Order Amount
4
  *
5
- * @version 3.2.1
6
  * @since 3.2.1
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
 
12
  $settings = array(
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  array(
14
  'title' => __( 'Shipping Methods by Min/Max Order Amount', 'woocommerce-jetpack' ),
15
  'type' => 'title',
@@ -17,8 +36,10 @@ $settings = array(
17
  'id' => 'wcj_shipping_by_order_amount_options',
18
  ),
19
  );
20
- foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
21
- if ( ! in_array( $method->id, array( 'flat_rate', 'free_shipping' ) ) ) {
 
 
22
  $custom_attributes = apply_filters( 'booster_message', '', 'disabled' );
23
  if ( '' == $custom_attributes ) {
24
  $custom_attributes = array();
@@ -31,10 +52,10 @@ foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
31
  $custom_attributes = array_merge( $custom_attributes, array( 'min' => 0 ) );
32
  $settings = array_merge( $settings, array(
33
  array(
34
- 'title' => $method->get_method_title(),
35
  'desc_tip' => $desc_tip,
36
  'desc' => '<br>' . __( 'Minimum order amount', 'woocommerce-jetpack' ),
37
- 'id' => 'wcj_shipping_by_order_amount_min_' . $method->id,
38
  'default' => 0,
39
  'type' => 'number',
40
  'custom_attributes' => $custom_attributes,
@@ -42,7 +63,7 @@ foreach ( WC()->shipping()->load_shipping_methods() as $method ) {
42
  array(
43
  'desc_tip' => $desc_tip,
44
  'desc' => '<br>' . __( 'Maximum order amount', 'woocommerce-jetpack' ),
45
- 'id' => 'wcj_shipping_by_order_amount_max_' . $method->id,
46
  'default' => 0,
47
  'type' => 'number',
48
  'custom_attributes' => $custom_attributes,
2
  /**
3
  * Booster for WooCommerce Settings - Shipping Methods by Min/Max Order Amount
4
  *
5
+ * @version 3.5.0
6
  * @since 3.2.1
7
  * @author Algoritmika Ltd.
8
  */
9
 
10
  if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
11
 
12
+ $use_shipping_instances = ( 'yes' === get_option( 'wcj_shipping_by_order_amount_use_shipping_instance', 'no' ) );
13
  $settings = array(
14
+ array(
15
+ 'title' => __( 'General Options', 'woocommerce-jetpack' ),
16
+ 'type' => 'title',
17
+ 'id' => 'wcj_shipping_by_order_amount_general_options',
18
+ ),
19
+ array(
20
+ 'title' => __( 'Use Shipping Instances', 'woocommerce-jetpack' ),
21
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
22
+ 'desc_tip' => __( 'Enable this if you want to use shipping methods instances instead of shipping methods.', 'woocommerce-jetpack' ) . ' ' .
23
+ __( 'Save changes after enabling this option.', 'woocommerce-jetpack' ),
24
+ 'type' => 'checkbox',
25
+ 'id' => 'wcj_shipping_by_order_amount_use_shipping_instance',
26
+ 'default' => 'no',
27
+ ),
28
+ array(
29
+ 'type' => 'sectionend',
30
+ 'id' => 'wcj_shipping_by_order_amount_general_options',
31
+ ),
32
  array(
33
  'title' => __( 'Shipping Methods by Min/Max Order Amount', 'woocommerce-jetpack' ),
34
  'type' => 'title',
36
  'id' => 'wcj_shipping_by_order_amount_options',
37
  ),
38
  );
39
+ $shipping_methods = ( $use_shipping_instances ? wcj_get_shipping_methods_instances( true ) : WC()->shipping()->load_shipping_methods() );
40
+ foreach ( $shipping_methods as $method ) {
41
+ $method_id = ( $use_shipping_instances ? $method['shipping_method_id'] : $method->id );
42
+ if ( ! in_array( $method_id, array( 'flat_rate', 'free_shipping' ) ) ) {
43
  $custom_attributes = apply_filters( 'booster_message', '', 'disabled' );
44
  if ( '' == $custom_attributes ) {
45
  $custom_attributes = array();
52
  $custom_attributes = array_merge( $custom_attributes, array( 'min' => 0 ) );
53
  $settings = array_merge( $settings, array(
54
  array(
55
+ 'title' => ( $use_shipping_instances ? $method['zone_name'] . ': ' . $method['shipping_method_title']: $method->get_method_title() ),
56
  'desc_tip' => $desc_tip,
57
  'desc' => '<br>' . __( 'Minimum order amount', 'woocommerce-jetpack' ),
58
+ 'id' => 'wcj_shipping_by_order_amount_min_' . ( $use_shipping_instances ? 'instance_' . $method['shipping_method_instance_id'] : $method->id ),
59
  'default' => 0,
60
  'type' => 'number',
61
  'custom_attributes' => $custom_attributes,
63
  array(
64
  'desc_tip' => $desc_tip,
65
  'desc' => '<br>' . __( 'Maximum order amount', 'woocommerce-jetpack' ),
66
+ 'id' => 'wcj_shipping_by_order_amount_max_' . ( $use_shipping_instances ? 'instance_' . $method['shipping_method_instance_id'] : $method->id ),
67
  'default' => 0,
68
  'type' => 'number',
69
  'custom_attributes' => $custom_attributes,
includes/settings/wcj-settings-shipping-description.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Shipping Descriptions
4
  *
5
- * @version 3.4.0
6
  * @since 3.4.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -27,7 +27,21 @@ $settings = array(
27
  'cart_only' => __( 'Only on cart page', 'woocommerce-jetpack' ),
28
  'checkout_only' => __( 'Only on checkout page', 'woocommerce-jetpack' ),
29
  ),
30
- 'desc_tip' => __( 'Possible values: on both cart and checkout pages; only on cart page; only on checkout page', 'woocommerce-jetpack' ),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
31
  'desc' => apply_filters( 'booster_message', '', 'desc' ),
32
  'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
33
  ),
2
  /**
3
  * Booster for WooCommerce - Settings - Shipping Descriptions
4
  *
5
+ * @version 3.5.0
6
  * @since 3.4.0
7
  * @author Algoritmika Ltd.
8
  */
27
  'cart_only' => __( 'Only on cart page', 'woocommerce-jetpack' ),
28
  'checkout_only' => __( 'Only on checkout page', 'woocommerce-jetpack' ),
29
  ),
30
+ 'desc_tip' => __( 'Possible values: on both cart and checkout pages; only on cart page; only on checkout page.', 'woocommerce-jetpack' ),
31
+ 'desc' => apply_filters( 'booster_message', '', 'desc' ),
32
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
33
+ ),
34
+ array(
35
+ 'title' => __( 'Description Position', 'woocommerce-jetpack' ),
36
+ 'id' => 'wcj_shipping_descriptions_position',
37
+ 'default' => 'after',
38
+ 'type' => 'select',
39
+ 'options' => array(
40
+ 'after' => __( 'After the label', 'woocommerce-jetpack' ),
41
+ 'before' => __( 'Before the label', 'woocommerce-jetpack' ),
42
+ 'instead' => __( 'Instead of the label', 'woocommerce-jetpack' ),
43
+ ),
44
+ 'desc_tip' => __( 'Possible values: after the label; before the label; instead of the label.', 'woocommerce-jetpack' ),
45
  'desc' => apply_filters( 'booster_message', '', 'desc' ),
46
  'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
47
  ),
includes/settings/wcj-settings-shipping-time.php ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * Booster for WooCommerce - Settings - Shipping Time
4
+ *
5
+ * @version 3.5.0
6
+ * @since 3.5.0
7
+ * @author Algoritmika Ltd.
8
+ * @todo estimated date calculation
9
+ * @todo add e.g.: "... order before 2 PM to receive"
10
+ * @todo check for `WC()` etc. to exist
11
+ * @todo other display options (besides shortcode)
12
+ * @todo (maybe) rename to "Delivery Time"
13
+ * @todo (maybe) global fallback time
14
+ */
15
+
16
+ if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
17
+
18
+ $use_shipping_instances = ( 'yes' === get_option( 'wcj_shipping_time_use_shipping_instance', 'no' ) );
19
+ $use_shipping_classes = ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_shipping_time_use_shipping_classes', 'no' ) ) );
20
+ $shipping_methods = ( $use_shipping_instances ? wcj_get_shipping_methods_instances( true ) : WC()->shipping()->load_shipping_methods() );
21
+ $shipping_classes_data = ( $use_shipping_classes ? wcj_get_shipping_classes() : array( '' => '' ) );
22
+ $settings = array();
23
+ $settings = array_merge( $settings, array(
24
+ array(
25
+ 'title' => __( 'General Options', 'woocommerce-jetpack' ),
26
+ 'type' => 'title',
27
+ 'id' => 'wcj_shipping_time_general_options',
28
+ ),
29
+ array(
30
+ 'title' => __( 'Use Shipping Instances', 'woocommerce-jetpack' ),
31
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
32
+ 'desc_tip' => __( 'Enable this if you want to use shipping methods instances instead of shipping methods.', 'woocommerce-jetpack' ) . ' ' .
33
+ __( 'Save changes after enabling this option.', 'woocommerce-jetpack' ),
34
+ 'type' => 'checkbox',
35
+ 'id' => 'wcj_shipping_time_use_shipping_instance',
36
+ 'default' => 'no',
37
+ ),
38
+ array(
39
+ 'title' => __( 'Use Shipping Classes', 'woocommerce-jetpack' ),
40
+ 'desc' => __( 'Enable', 'woocommerce-jetpack' ),
41
+ 'desc_tip' => __( 'Enable this if you want to set options for each shipping class separately.', 'woocommerce-jetpack' ) . ' ' .
42
+ __( 'Save changes after enabling this option.', 'woocommerce-jetpack' ) . ' ' . apply_filters( 'booster_message', '', 'desc' ),
43
+ 'type' => 'checkbox',
44
+ 'id' => 'wcj_shipping_time_use_shipping_classes',
45
+ 'default' => 'no',
46
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'disabled' ),
47
+ ),
48
+ array(
49
+ 'type' => 'sectionend',
50
+ 'id' => 'wcj_shipping_time_general_options',
51
+ ),
52
+ ) );
53
+ $settings = array_merge( $settings, array(
54
+ array(
55
+ 'title' => __( 'Shipping Time Options', 'woocommerce-jetpack' ),
56
+ 'desc' => __( 'Set estimated shipping time in <strong>days</strong>.', 'woocommerce-jetpack' ),
57
+ 'type' => 'title',
58
+ 'id' => 'wcj_shipping_time_options',
59
+ ),
60
+ ) );
61
+ foreach ( $shipping_methods as $method ) {
62
+ $method_id = ( $use_shipping_instances ? $method['shipping_method_id'] : $method->id );
63
+ foreach ( $shipping_classes_data as $shipping_class_id => $shipping_class_name ) {
64
+ $settings = array_merge( $settings, array(
65
+ array(
66
+ 'title' => ( $use_shipping_instances ? $method['zone_name'] . ': ' . $method['shipping_method_title']: $method->get_method_title() ),
67
+ 'desc' => ( $use_shipping_classes ? $shipping_class_name : '' ),
68
+ 'id' => 'wcj_shipping_time_' .
69
+ ( $use_shipping_instances ? 'instance_' . $method['shipping_method_instance_id'] : $method->id ) .
70
+ ( $use_shipping_classes ? '_class_' . $shipping_class_id : '' ),
71
+ 'type' => 'text',
72
+ 'default' => '',
73
+ ),
74
+ ) );
75
+ }
76
+ }
77
+ $settings = array_merge( $settings, array(
78
+ array(
79
+ 'type' => 'sectionend',
80
+ 'id' => 'wcj_shipping_time_options',
81
+ ),
82
+ ) );
83
+ return $settings;
includes/settings/wcj-settings-sku.php CHANGED
@@ -2,9 +2,10 @@
2
  /**
3
  * Booster for WooCommerce - Settings - SKU
4
  *
5
- * @version 3.4.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
 
8
  * @todo tags (check SKU plugin); template: '{category_prefix}{tag_prefix}{prefix}{sku_number}{suffix}{tag_suffix}{category_suffix}{variation_suffix}'
9
  * @todo add "Sequential Number Generation - By Category" to SKU plugin
10
  */
@@ -74,10 +75,20 @@ $settings = array(
74
  'default' => '',
75
  'type' => 'text',
76
  ),
 
 
 
 
 
 
 
 
 
 
77
  array(
78
  'title' => __( 'Template', 'woocommerce-jetpack' ),
79
  'desc_tip' => __( 'SKU template.', 'woocommerce-jetpack' ),
80
- 'desc' => wcj_message_replaced_values( array( '{category_prefix}', '{category_suffix}', '{prefix}', '{suffix}', '{variation_suffix}', '{sku_number}' ) ),
81
  'id' => 'wcj_sku_template',
82
  'default' => '{category_prefix}{prefix}{sku_number}{suffix}{category_suffix}{variation_suffix}',
83
  'type' => 'text',
2
  /**
3
  * Booster for WooCommerce - Settings - SKU
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
+ * @todo deprecate `wcj_sku_prefix` and `wcj_sku_suffix` (as user can now add it directly to "Template")
9
  * @todo tags (check SKU plugin); template: '{category_prefix}{tag_prefix}{prefix}{sku_number}{suffix}{tag_suffix}{category_suffix}{variation_suffix}'
10
  * @todo add "Sequential Number Generation - By Category" to SKU plugin
11
  */
75
  'default' => '',
76
  'type' => 'text',
77
  ),
78
+ array(
79
+ 'title' => __( 'Attributes Separator', 'woocommerce-jetpack' ),
80
+ 'desc_tip' => sprintf( __( 'Used in %s.', 'woocommerce-jetpack' ), '<em>{variation_attributes}</em>' ),
81
+ 'id' => 'wcj_sku_variations_product_slug_sep',
82
+ 'default' => '-',
83
+ 'type' => 'text',
84
+ 'css' => 'width:50px;',
85
+ 'desc' => apply_filters( 'booster_message', '', 'desc' ),
86
+ 'custom_attributes' => apply_filters( 'booster_message', '', 'readonly' ),
87
+ ),
88
  array(
89
  'title' => __( 'Template', 'woocommerce-jetpack' ),
90
  'desc_tip' => __( 'SKU template.', 'woocommerce-jetpack' ),
91
+ 'desc' => wcj_message_replaced_values( array( '{category_prefix}', '{category_suffix}', '{prefix}', '{suffix}', '{variation_suffix}', '{sku_number}', '{product_slug}', '{parent_product_slug}', '{variation_attributes}' ) ),
92
  'id' => 'wcj_sku_template',
93
  'default' => '{category_prefix}{prefix}{sku_number}{suffix}{category_suffix}{variation_suffix}',
94
  'type' => 'text',
includes/settings/wcj-settings-stock.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Settings - Stock
4
  *
5
- * @version 3.4.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
@@ -30,6 +30,7 @@ return array(
30
  'type' => 'checkbox',
31
  ),
32
  array(
 
33
  'id' => 'wcj_stock_custom_in_stock',
34
  'default' => '',
35
  'type' => 'custom_textarea',
@@ -71,6 +72,7 @@ return array(
71
  'type' => 'checkbox',
72
  ),
73
  array(
 
74
  'id' => 'wcj_stock_custom_out_of_stock',
75
  'default' => '',
76
  'type' => 'custom_textarea',
@@ -108,6 +110,7 @@ return array(
108
  ),
109
  array(
110
  'title' => __( 'HTML', 'woocommerce-jetpack' ),
 
111
  'desc' => wcj_message_replaced_values( array( '%class%', '%availability%' ) ) . '. ' . apply_filters( 'booster_message', '', 'desc' ),
112
  'id' => 'wcj_stock_custom_stock_html',
113
  'default' => '<p class="stock %class%">%availability%</p>',
2
  /**
3
  * Booster for WooCommerce - Settings - Stock
4
  *
5
+ * @version 3.5.0
6
  * @since 2.8.0
7
  * @author Algoritmika Ltd.
8
  */
30
  'type' => 'checkbox',
31
  ),
32
  array(
33
+ 'desc_tip' => __( 'You can also use shortcodes here.', 'woocommerce-jetpack' ),
34
  'id' => 'wcj_stock_custom_in_stock',
35
  'default' => '',
36
  'type' => 'custom_textarea',
72
  'type' => 'checkbox',
73
  ),
74
  array(
75
+ 'desc_tip' => __( 'You can also use shortcodes here.', 'woocommerce-jetpack' ),
76
  'id' => 'wcj_stock_custom_out_of_stock',
77
  'default' => '',
78
  'type' => 'custom_textarea',
110
  ),
111
  array(
112
  'title' => __( 'HTML', 'woocommerce-jetpack' ),
113
+ 'desc_tip' => __( 'You can also use shortcodes here.', 'woocommerce-jetpack' ),
114
  'desc' => wcj_message_replaced_values( array( '%class%', '%availability%' ) ) . '. ' . apply_filters( 'booster_message', '', 'desc' ),
115
  'id' => 'wcj_stock_custom_stock_html',
116
  'default' => '<p class="stock %class%">%availability%</p>',
includes/shortcodes/class-wcj-shortcodes-general.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes - General
4
  *
5
- * @version 3.4.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,7 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 3.4.0
19
  */
20
  function __construct() {
21
 
@@ -48,6 +48,7 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
48
  'wcj_request_value',
49
  'wcj_selector',
50
  'wcj_session_value',
 
51
  'wcj_site_url',
52
  'wcj_store_address',
53
  'wcj_tcpdf_barcode',
@@ -106,6 +107,21 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
106
 
107
  }
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
  /**
110
  * wcj_wc_session_value.
111
  *
@@ -857,12 +873,17 @@ class WCJ_General_Shortcodes extends WCJ_Shortcodes {
857
  /**
858
  * wcj_cart_total.
859
  *
860
- * @version 2.8.0
861
  * @since 2.8.0
862
  */
863
  function wcj_cart_total( $atts ) {
864
  if ( $_cart = WC()->cart ) {
865
- return $_cart->get_cart_total();
 
 
 
 
 
866
  }
867
  return '';
868
  }
2
  /**
3
  * Booster for WooCommerce - Shortcodes - General
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.5.0
19
  */
20
  function __construct() {
21
 
48
  'wcj_request_value',
49
  'wcj_selector',
50
  'wcj_session_value',
51
+ 'wcj_shipping_time_table',
52
  'wcj_site_url',
53
  'wcj_store_address',
54
  'wcj_tcpdf_barcode',
107
 
108
  }
109
 
110
+ /**
111
+ * wcj_shipping_time_table.
112
+ *
113
+ * @version 3.5.0
114
+ * @since 3.5.0
115
+ * @todo `$atts['shipping_class_term_id']` - class term ID is not visible anywhere for admin, so probably need to use `slug` instead
116
+ */
117
+ function wcj_shipping_time_table( $atts ) {
118
+ $do_use_shipping_instances = ( 'yes' === get_option( 'wcj_shipping_time_use_shipping_instance', 'no' ) );
119
+ $do_use_shipping_classes = ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_shipping_time_use_shipping_classes', 'no' ) ) );
120
+ $shipping_class_term_id = ( isset( $atts['shipping_class_term_id'] ) ? $atts['shipping_class_term_id'] : '0' );
121
+ $option_id_shipping_class = ( $do_use_shipping_classes ? '_class_' . $shipping_class_term_id : '' );
122
+ return wcj_get_shipping_time_table( $do_use_shipping_instances, $option_id_shipping_class );
123
+ }
124
+
125
  /**
126
  * wcj_wc_session_value.
127
  *
873
  /**
874
  * wcj_cart_total.
875
  *
876
+ * @version 3.5.0
877
  * @since 2.8.0
878
  */
879
  function wcj_cart_total( $atts ) {
880
  if ( $_cart = WC()->cart ) {
881
+ if ( 1 != $atts['multiply_by'] ) {
882
+ $cart_total = wc_prices_include_tax() ? WC()->cart->get_cart_contents_total() + WC()->cart->get_cart_contents_tax() : WC()->cart->get_cart_contents_total();
883
+ return wc_price( $atts['multiply_by'] * $cart_total );
884
+ } else {
885
+ return $_cart->get_cart_total();
886
+ }
887
  }
888
  return '';
889
  }
includes/shortcodes/class-wcj-shortcodes-orders.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Orders
4
  *
5
- * @version 3.4.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,7 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 3.4.0
19
  */
20
  function __construct() {
21
 
@@ -28,6 +28,7 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
28
  'wcj_order_currency',
29
  'wcj_order_custom_field',
30
  'wcj_order_custom_meta_field',
 
31
  'wcj_order_customer_meta',
32
  'wcj_order_customer_note',
33
  'wcj_order_customer_user',
@@ -428,6 +429,22 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
428
  return '';
429
  }
430
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
431
  /**
432
  * wcj_order_customer_user_roles.
433
  *
@@ -713,41 +730,36 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
713
  /**
714
  * wcj_order_notes.
715
  *
716
- * @version 3.4.0
717
  * @since 3.4.0
718
  * @todo (maybe) run `strip_tags` on `comment_content`
719
  */
720
  function wcj_order_notes( $atts ) {
 
721
  if ( '' == $atts['type'] || 'customer_notes' === $atts['type'] ) {
722
- $notes = array();
723
  foreach ( $this->the_order->get_customer_order_notes() as $note ) {
724
  $notes[] = $note->comment_content;
725
  }
726
- return implode( $atts['sep'], $notes );
727
  } else { // 'private_notes' or 'all_notes'
728
- $notes = array();
729
  $args = array(
730
  'post_id' => wcj_get_order_id( $this->the_order ),
731
  'approve' => 'approve',
732
  'type' => '',
733
  );
734
-
735
  remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
736
-
737
  $comments = get_comments( $args );
738
-
739
  foreach ( $comments as $comment ) {
740
-
741
  if ( 'private_notes' === $atts['type'] && get_comment_meta( $comment->comment_ID, 'is_customer_note', true ) ) {
742
  continue;
743
  }
744
  $notes[] = make_clickable( $comment->comment_content );
745
  }
746
-
747
  add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
748
-
749
- return implode( $atts['sep'], $notes );
750
  }
 
 
 
 
751
  }
752
 
753
  /**
@@ -801,7 +813,7 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
801
  /**
802
  * wcj_order_items
803
  *
804
- * @version 2.8.0
805
  * @since 2.5.7
806
  */
807
  function wcj_order_items( $atts ) {
@@ -815,6 +827,12 @@ class WCJ_Orders_Shortcodes extends WCJ_Shortcodes {
815
  case '_qty_x_name':
816
  $items[] = ( isset( $item['qty'] ) && isset( $item['name'] ) ) ? $item['qty'] . ' x ' . $item['name'] : '';
817
  break;
 
 
 
 
 
 
818
  default: // case 'name' etc.
819
  $items[] = ( isset( $item[ $atts['field'] ] ) ) ? $item[ $atts['field'] ] : '';
820
  break;
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Orders
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.5.0
19
  */
20
  function __construct() {
21
 
28
  'wcj_order_currency',
29
  'wcj_order_custom_field',
30
  'wcj_order_custom_meta_field',
31
+ 'wcj_order_customer_data',
32
  'wcj_order_customer_meta',
33
  'wcj_order_customer_note',
34
  'wcj_order_customer_user',
429
  return '';
430
  }
431
 
432
+ /**
433
+ * wcj_order_customer_data.
434
+ *
435
+ * @version 3.5.0
436
+ * @since 3.5.0
437
+ * @todo add similar `[wcj_customer_data]`
438
+ */
439
+ function wcj_order_customer_data( $atts ) {
440
+ if ( '' != $atts['key'] && ( $_customer_id = ( WCJ_IS_WC_VERSION_BELOW_3 ? $this->the_order->customer_user : $this->the_order->get_customer_id() ) ) ) {
441
+ if ( ( $user_data = get_userdata( $_customer_id ) ) && isset( $user_data->{$atts['key']} ) ) {
442
+ return $user_data->{$atts['key']};
443
+ }
444
+ }
445
+ return '';
446
+ }
447
+
448
  /**
449
  * wcj_order_customer_user_roles.
450
  *
730
  /**
731
  * wcj_order_notes.
732
  *
733
+ * @version 3.5.0
734
  * @since 3.4.0
735
  * @todo (maybe) run `strip_tags` on `comment_content`
736
  */
737
  function wcj_order_notes( $atts ) {
738
+ $notes = array();
739
  if ( '' == $atts['type'] || 'customer_notes' === $atts['type'] ) {
 
740
  foreach ( $this->the_order->get_customer_order_notes() as $note ) {
741
  $notes[] = $note->comment_content;
742
  }
 
743
  } else { // 'private_notes' or 'all_notes'
 
744
  $args = array(
745
  'post_id' => wcj_get_order_id( $this->the_order ),
746
  'approve' => 'approve',
747
  'type' => '',
748
  );
 
749
  remove_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
 
750
  $comments = get_comments( $args );
 
751
  foreach ( $comments as $comment ) {
 
752
  if ( 'private_notes' === $atts['type'] && get_comment_meta( $comment->comment_ID, 'is_customer_note', true ) ) {
753
  continue;
754
  }
755
  $notes[] = make_clickable( $comment->comment_content );
756
  }
 
757
  add_filter( 'comments_clauses', array( 'WC_Comments', 'exclude_order_comments' ) );
 
 
758
  }
759
+ if ( isset( $atts['limit'] ) && $atts['limit'] > 0 ) {
760
+ $notes = array_slice( $notes, 0, $atts['limit'] );
761
+ }
762
+ return implode( $atts['sep'], $notes );
763
  }
764
 
765
  /**
813
  /**
814
  * wcj_order_items
815
  *
816
+ * @version 3.5.0
817
  * @since 2.5.7
818
  */
819
  function wcj_order_items( $atts ) {
827
  case '_qty_x_name':
828
  $items[] = ( isset( $item['qty'] ) && isset( $item['name'] ) ) ? $item['qty'] . ' x ' . $item['name'] : '';
829
  break;
830
+ case '_sku':
831
+ $_product_id = ( 0 != $item['variation_id'] ? $item['variation_id'] : $item['product_id'] );
832
+ if ( $_product = wc_get_product( $_product_id ) ) {
833
+ $items[] = $_product->get_sku();
834
+ }
835
+ break;
836
  default: // case 'name' etc.
837
  $items[] = ( isset( $item[ $atts['field'] ] ) ) ? $item[ $atts['field'] ] : '';
838
  break;
includes/shortcodes/class-wcj-shortcodes-products.php CHANGED
@@ -2,7 +2,7 @@
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Products
4
  *
5
- * @version 3.4.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
@@ -15,7 +15,7 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
15
  /**
16
  * Constructor.
17
  *
18
- * @version 3.4.0
19
  * @todo (maybe) add `[wcj_product_stock_price]`
20
  */
21
  function __construct() {
@@ -52,6 +52,7 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
52
  'wcj_product_regular_price',
53
  'wcj_product_sale_price',
54
  'wcj_product_shipping_class',
 
55
  'wcj_product_short_description',
56
  'wcj_product_sku',
57
  'wcj_product_stock_availability',
@@ -589,6 +590,21 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
589
  : '';
590
  }
591
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
592
  /**
593
  * wcj_product_shipping_class.
594
  *
@@ -728,7 +744,7 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
728
  /**
729
  * Returns product (modified) price.
730
  *
731
- * @version 3.4.0
732
  * @todo variable products: a) not range; and b) price by country.
733
  * @return string The product (modified) price
734
  */
@@ -756,6 +772,14 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
756
  $max = $max * $meta_value;
757
  }
758
  }
 
 
 
 
 
 
 
 
759
  if ( 'yes' !== $atts['hide_currency'] ) {
760
  $min = wc_price( $min, array( 'currency' => $atts['currency'] ) );
761
  $max = wc_price( $max, array( 'currency' => $atts['currency'] ) );
@@ -781,6 +805,13 @@ class WCJ_Products_Shortcodes extends WCJ_Shortcodes {
781
  $the_price = $the_price * $meta_value;
782
  }
783
  }
 
 
 
 
 
 
 
784
  return ( 'yes' === $atts['hide_currency'] ) ? $the_price : wc_price( $the_price, array( 'currency' => $atts['currency'] ) );
785
  }
786
  }
2
  /**
3
  * Booster for WooCommerce - Shortcodes - Products
4
  *
5
+ * @version 3.5.0
6
  * @author Algoritmika Ltd.
7
  */
8
 
15
  /**
16
  * Constructor.
17
  *
18
+ * @version 3.5.0
19
  * @todo (maybe) add `[wcj_product_stock_price]`
20
  */
21
  function __construct() {
52
  'wcj_product_regular_price',
53
  'wcj_product_sale_price',
54
  'wcj_product_shipping_class',
55
+ 'wcj_product_shipping_time_table',
56
  'wcj_product_short_description',
57
  'wcj_product_sku',
58
  'wcj_product_stock_availability',
590
  : '';
591
  }
592
 
593
+ /**
594
+ * wcj_product_shipping_time_table.
595
+ *
596
+ * @version 3.5.0
597
+ * @since 3.5.0
598
+ * @todo `$atts['shipping_method']` (i.e. `[wcj_product_shipping_time]`)
599
+ * @todo explode "from-to"
600
+ */
601
+ function wcj_product_shipping_time_table( $atts ) {
602
+ $do_use_shipping_instances = ( 'yes' === get_option( 'wcj_shipping_time_use_shipping_instance', 'no' ) );
603
+ $do_use_shipping_classes = ( 'yes' === apply_filters( 'booster_option', 'no', get_option( 'wcj_shipping_time_use_shipping_classes', 'no' ) ) );
604
+ $option_id_shipping_class = ( $do_use_shipping_classes ? '_class_' . wcj_get_product_shipping_class_term_id( $this->the_product ) : '' );
605
+ return wcj_get_shipping_time_table( $do_use_shipping_instances, $option_id_shipping_class );
606
+ }
607
+
608
  /**
609
  * wcj_product_shipping_class.
610
  *
744
  /**
745
  * Returns product (modified) price.
746
  *
747
+ * @version 3.5.0
748
  * @todo variable products: a) not range; and b) price by country.
749
  * @return string The product (modified) price
750
  */
772
  $max = $max * $meta_value;
773
  }
774
  }
775
+ if ( isset( $atts['multiply_by_attribute'] ) && '' !== $atts['multiply_by_attribute'] ) {
776
+ $attribute = $this->the_product->get_attribute( $atts['multiply_by_attribute'] );
777
+ $attribute = wcj_parse_number( $attribute );
778
+ if ( is_numeric( $attribute ) ) {
779
+ $min = $min * $attribute;
780
+ $max = $max * $attribute;
781
+ }
782
+ }
783
  if ( 'yes' !== $atts['hide_currency'] ) {
784
  $min = wc_price( $min, array( 'currency' => $atts['currency'] ) );
785
  $max = wc_price( $max, array( 'currency' => $atts['currency'] ) );
805
  $the_price = $the_price * $meta_value;
806
  }
807
  }
808
+ if ( isset( $atts['multiply_by_attribute'] ) && '' !== $atts['multiply_by_attribute'] ) {
809
+ $attribute = $this->the_product->get_attribute( $atts['multiply_by_attribute'] );
810
+ $attribute = wcj_parse_number( $attribute );
811
+ if ( is_numeric( $attribute ) ) {
812
+ $the_price = $the_price * $attribute;
813
+ }
814
+ }
815
  return ( 'yes' === $atts['hide_currency'] ) ? $the_price : wc_price( $the_price, array( 'currency' => $atts['currency'] ) );
816
  }
817
  }
langs/woocommerce-jetpack.pot CHANGED
@@ -113,8 +113,9 @@ msgstr ""
113
 
114
  #: includes/class-wcj-admin-bar.php:265
115
  #: includes/class-wcj-checkout-files-upload.php:146
116
- #: includes/class-wcj-eu-vat-number.php:129 includes/class-wcj-orders.php:109
117
- #: includes/class-wcj-orders.php:138
 
118
  #: includes/class-wcj-payment-gateways.php:91
119
  #: includes/class-wcj-track-users.php:117
120
  #: includes/class-wcj-track-users.php:213
@@ -210,7 +211,7 @@ msgstr ""
210
  msgid "Customer list"
211
  msgstr ""
212
 
213
- #: includes/class-wcj-admin-bar.php:390 includes/class-wcj-stock.php:27
214
  #: includes/reports/wcj-class-reports-stock.php:256
215
  #: includes/settings/wcj-settings-reports.php:127
216
  #: includes/settings/wcj-settings-reports.php:133
@@ -223,7 +224,7 @@ msgid "Low in stock"
223
  msgstr ""
224
 
225
  #: includes/class-wcj-admin-bar.php:398
226
- #: includes/shortcodes/class-wcj-shortcodes-products.php:560
227
  msgid "Out of stock"
228
  msgstr ""
229
 
@@ -261,9 +262,8 @@ msgstr ""
261
 
262
  #: includes/class-wcj-admin-bar.php:436
263
  #: includes/class-wcj-product-bulk-price-converter.php:149
264
- #: includes/class-wcj-sku.php:396
265
  #: includes/export/class-wcj-fields-helper.php:318
266
- #: includes/settings/wcj-settings-price-by-user-role.php:129
267
  #: includes/settings/wcj-settings-product-by-user.php:19
268
  #: includes/shortcodes/class-wcj-shortcodes-products-add-form.php:185
269
  #: includes/shortcodes/class-wcj-shortcodes-products-add-form.php:406
@@ -325,7 +325,7 @@ msgstr ""
325
  #: includes/settings/wcj-settings-checkout-custom-fields.php:170
326
  #: includes/settings/wcj-settings-checkout-custom-info.php:56
327
  #: includes/settings/wcj-settings-empty-cart.php:59
328
- #: includes/settings/wcj-settings-left-to-free-shipping.php:121
329
  #: includes/settings/wcj-settings-price-by-user-role.php:46
330
  msgid "Shipping"
331
  msgstr ""
@@ -414,7 +414,7 @@ msgid "Not Completed"
414
  msgstr ""
415
 
416
  #: includes/class-wcj-admin-orders-list.php:281
417
- #: includes/settings/wcj-settings-product-by-country.php:86
418
  msgid "All countries"
419
  msgstr ""
420
 
@@ -443,75 +443,75 @@ msgstr ""
443
  msgid "Customize WooCommerce admin products list."
444
  msgstr ""
445
 
446
- #: includes/class-wcj-admin-tools.php:23 includes/class-wcj-admin-tools.php:30
447
  msgid "Admin Tools"
448
  msgstr ""
449
 
450
- #: includes/class-wcj-admin-tools.php:24
451
  msgid "Booster for WooCommerce debug and log tools."
452
  msgstr ""
453
 
454
- #: includes/class-wcj-admin-tools.php:31
455
  msgid "Log."
456
  msgstr ""
457
 
458
- #: includes/class-wcj-admin-tools.php:32
459
  #: includes/settings/wcj-settings-admin-tools.php:19
460
  msgid "Log"
461
  msgstr ""
462
 
463
- #: includes/class-wcj-admin-tools.php:43
464
  #, php-format
465
  msgid "Current PHP memory limit: %s."
466
  msgstr ""
467
 
468
- #: includes/class-wcj-admin-tools.php:48
469
  #, php-format
470
  msgid "Current PHP time limit: %s seconds."
471
  msgstr ""
472
 
473
- #: includes/class-wcj-admin-tools.php:102
474
  #: includes/settings/wcj-settings-export.php:157
475
  #: includes/settings/wcj-settings-export.php:236
476
  msgid "Product Meta"
477
  msgstr ""
478
 
479
- #: includes/class-wcj-admin-tools.php:119
480
  #: includes/settings/wcj-settings-export.php:86
481
  #: includes/settings/wcj-settings-export.php:154
482
  msgid "Order Meta"
483
  msgstr ""
484
 
485
- #: includes/class-wcj-admin-tools.php:153
486
  msgid "Order Items Meta"
487
  msgstr ""
488
 
489
- #: includes/class-wcj-admin-tools.php:155
490
  msgid "Item Key"
491
  msgstr ""
492
 
493
- #: includes/class-wcj-admin-tools.php:155
494
  msgid "Item Meta Key"
495
  msgstr ""
496
 
497
- #: includes/class-wcj-admin-tools.php:155
498
  msgid "Item Meta Value"
499
  msgstr ""
500
 
501
- #: includes/class-wcj-admin-tools.php:181
502
  msgid "Delete Log"
503
  msgstr ""
504
 
505
- #: includes/class-wcj-admin-tools.php:184
506
  #, php-format
507
  msgid "Now: %s"
508
  msgstr ""
509
 
510
- #: includes/class-wcj-admin-tools.php:188
511
  msgid "Log is empty."
512
  msgstr ""
513
 
514
- #: includes/class-wcj-admin-tools.php:219
515
  msgid "NOT DEFINED"
516
  msgstr ""
517
 
@@ -676,9 +676,9 @@ msgstr ""
676
  #: includes/class-wcj-checkout-files-upload.php:554
677
  #: includes/class-wcj-checkout-files-upload.php:555
678
  #: includes/settings/wcj-settings-checkout-files-upload.php:107
679
- #: includes/settings/wcj-settings-sku.php:216
680
  #: includes/settings/wcj-settings-sorting.php:144
681
- #: includes/settings/wcj-settings-stock.php:130
682
  msgid "Remove"
683
  msgstr ""
684
 
@@ -749,16 +749,37 @@ msgstr ""
749
  msgid "Automatic currency exchange rates for WooCommerce."
750
  msgstr ""
751
 
752
- #: includes/class-wcj-currency-exchange-rates.php:167
753
  #: includes/settings/wcj-settings-currency-exchange-rates.php:46
754
  msgid "Exchange Rates Server"
755
  msgstr ""
756
 
757
- #: includes/class-wcj-currency-exchange-rates.php:172
758
  #, php-format
759
  msgid "Use default: %s"
760
  msgstr ""
761
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
762
  #: includes/class-wcj-currency-external-products.php:23
763
  msgid "Currency for External Products"
764
  msgstr ""
@@ -775,21 +796,21 @@ msgstr ""
775
  msgid "Display prices for WooCommerce products in different currencies."
776
  msgstr ""
777
 
778
- #: includes/class-wcj-currency-per-product.php:172
779
  #: includes/settings/wcj-settings-currency-per-product.php:43
780
  msgid ""
781
  "Only one product can be added to the cart. Clear the cart or finish the "
782
  "order, before adding another product to the cart."
783
  msgstr ""
784
 
785
- #: includes/class-wcj-currency-per-product.php:187
786
  #: includes/settings/wcj-settings-currency-per-product.php:50
787
  msgid ""
788
  "Only products with same currency can be added to the cart. Clear the cart or "
789
  "finish the order, before adding products with another currency to the cart."
790
  msgstr ""
791
 
792
- #: includes/class-wcj-currency-per-product.php:233
793
  #, php-format
794
  msgctxt "Price range: from-to"
795
  msgid "%1$s&ndash;%2$s"
@@ -824,36 +845,46 @@ msgid ""
824
  "WooCommerce emails."
825
  msgstr ""
826
 
827
- #: includes/class-wcj-email-options.php:93
828
  msgid "Booster: Email Forwarding Options"
829
  msgstr ""
830
 
831
- #: includes/class-wcj-email-options.php:94
832
  msgid "Email Forwarding Options"
833
  msgstr ""
834
 
835
- #: includes/class-wcj-email-options.php:96
836
  msgid ""
837
  "This section lets you add another email recipient(s) to all WooCommerce "
838
  "emails. Leave blank to disable."
839
  msgstr ""
840
 
841
- #: includes/class-wcj-email-options.php:100
842
  msgid "Cc Email"
843
  msgstr ""
844
 
845
- #: includes/class-wcj-email-options.php:101
846
  msgid "Cc to email, e.g. youremail@yourdomain.com. Leave blank to disable."
847
  msgstr ""
848
 
849
- #: includes/class-wcj-email-options.php:107
850
  msgid "Bcc Email"
851
  msgstr ""
852
 
853
- #: includes/class-wcj-email-options.php:108
854
  msgid "Bcc to email, e.g. youremail@yourdomain.com. Leave blank to disable."
855
  msgstr ""
856
 
 
 
 
 
 
 
 
 
 
 
857
  #: includes/class-wcj-emails-verification.php:26
858
  msgid "Email Verification"
859
  msgstr ""
@@ -957,7 +988,7 @@ msgid "Booster: Send Email: %s"
957
  msgstr ""
958
 
959
  #: includes/class-wcj-empty-cart-button.php:25
960
- #: includes/shortcodes/class-wcj-shortcodes-general.php:364
961
  msgid "Empty Cart Button"
962
  msgstr ""
963
 
@@ -995,6 +1026,7 @@ msgstr ""
995
 
996
  #: includes/class-wcj-eu-vat-number.php:185 includes/class-wcj-orders.php:138
997
  #: includes/settings/wcj-settings-orders.php:83
 
998
  msgid "Country by IP"
999
  msgstr ""
1000
 
@@ -1188,9 +1220,9 @@ msgid "Role %s successfully deleted!"
1188
  msgstr ""
1189
 
1190
  #: includes/class-wcj-general.php:197 includes/class-wcj-general.php:210
1191
- #: includes/class-wcj-sku.php:394
1192
  #: includes/reports/wcj-class-reports-sales.php:192
1193
- #: includes/settings/wcj-settings-order-numbers.php:132
1194
  #: includes/settings/wcj-settings-product-by-user.php:161
1195
  #: includes/settings/wcj-settings-related-products.php:30
1196
  msgid "ID"
@@ -1206,7 +1238,7 @@ msgstr ""
1206
 
1207
  #: includes/class-wcj-general.php:197
1208
  #: includes/class-wcj-product-by-user.php:197
1209
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:92
1210
  #: includes/tools/class-wcj-order-statuses-tool.php:142
1211
  #: includes/tools/class-wcj-order-statuses-tool.php:214
1212
  msgid "Actions"
@@ -1217,7 +1249,7 @@ msgstr ""
1217
  #: includes/class-wcj-product-bulk-meta-editor.php:367
1218
  #: includes/class-wcj-product-by-user.php:206
1219
  #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:138
1220
- #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:308
1221
  #: includes/shortcodes/class-wcj-shortcodes-products-add-form.php:367
1222
  #: includes/tools/class-wcj-order-statuses-tool.php:157
1223
  msgid "Delete"
@@ -1232,6 +1264,7 @@ msgid "Add New Role"
1232
  msgstr ""
1233
 
1234
  #: includes/class-wcj-general.php:215
 
1235
  #: includes/settings/wcj-settings-admin-orders-list.php:134
1236
  #: includes/settings/wcj-settings-checkout-custom-fields.php:22
1237
  #: includes/settings/wcj-settings-checkout-custom-fields.php:29
@@ -1247,18 +1280,18 @@ msgstr ""
1247
  #: includes/settings/wcj-settings-order-min-amount.php:53
1248
  #: includes/settings/wcj-settings-orders.php:89
1249
  #: includes/settings/wcj-settings-orders.php:116
1250
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:117
1251
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:163
1252
- #: includes/settings/wcj-settings-product-by-country.php:110
1253
  #: includes/settings/wcj-settings-product-by-user.php:114
1254
  #: includes/settings/wcj-settings-product-open-pricing.php:108
1255
- #: includes/settings/wcj-settings-product-tabs.php:227
1256
  #: includes/settings/wcj-settings-purchase-data.php:134
1257
  #: includes/settings/wcj-settings-purchase-data.php:143
1258
  #: includes/settings/wcj-settings-purchase-data.php:162
1259
  #: includes/settings/wcj-settings-purchase-data.php:169
1260
- #: includes/settings/wcj-settings-sku.php:181
1261
- #: includes/settings/wcj-settings-sku.php:208
1262
  #: includes/shortcodes/class-wcj-shortcodes-products-add-form.php:425
1263
  #: includes/tools/class-wcj-order-statuses-tool.php:228
1264
  msgid "Add"
@@ -1267,7 +1300,7 @@ msgstr ""
1267
  #: includes/class-wcj-general.php:278 includes/class-wcj-general.php:320
1268
  #: includes/class-wcj-product-bulk-meta-editor.php:339
1269
  #: includes/class-wcj-product-bulk-price-converter.php:148
1270
- #: includes/class-wcj-sku.php:395
1271
  #: includes/reports/wcj-class-reports-sales.php:193
1272
  #: includes/reports/wcj-class-reports-stock.php:253
1273
  msgid "Product"
@@ -1302,15 +1335,72 @@ msgstr ""
1302
  #: includes/class-wcj-left-to-free-shipping.php:62
1303
  #: includes/class-wcj-left-to-free-shipping.php:72
1304
  #: includes/class-wcj-left-to-free-shipping.php:82
1305
- #: includes/functions/wcj-functions-general.php:514
1306
  #: includes/settings/wcj-settings-left-to-free-shipping.php:37
1307
- #: includes/settings/wcj-settings-left-to-free-shipping.php:70
1308
- #: includes/settings/wcj-settings-left-to-free-shipping.php:107
1309
  #: includes/widgets/class-wcj-widget-left-to-free-shipping.php:61
1310
  #, php-format
1311
  msgid "%left_to_free% left to free shipping"
1312
  msgstr ""
1313
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1314
  #: includes/class-wcj-mini-cart.php:24
1315
  msgid "Mini Cart Custom Info"
1316
  msgstr ""
@@ -1339,15 +1429,15 @@ msgstr ""
1339
  msgid "Enter prices for WooCommerce products in different currencies."
1340
  msgstr ""
1341
 
1342
- #: includes/class-wcj-multicurrency.php:24
1343
  msgid "Multicurrency (Currency Switcher)"
1344
  msgstr ""
1345
 
1346
- #: includes/class-wcj-multicurrency.php:25
1347
  msgid "Add multiple currencies (currency switcher) to WooCommerce."
1348
  msgstr ""
1349
 
1350
- #: includes/class-wcj-multicurrency.php:27
1351
  #, php-format
1352
  msgid ""
1353
  "After setting currencies in the Currencies Options section below, use %s "
@@ -1355,7 +1445,7 @@ msgid ""
1355
  "insert switcher in your <strong>PHP code</strong>, just use %s code."
1356
  msgstr ""
1357
 
1358
- #: includes/class-wcj-multicurrency.php:28
1359
  #: includes/widgets/class-wcj-widget-multicurrency.php:27
1360
  msgid "Booster - Multicurrency Switcher"
1361
  msgstr ""
@@ -1374,7 +1464,7 @@ msgstr ""
1374
  #: includes/class-wcj-purchase-data.php:94
1375
  #: includes/class-wcj-track-users.php:296
1376
  #: includes/classes/class-wcj-module.php:613
1377
- #: includes/functions/wcj-functions-general.php:34
1378
  #: includes/functions/wcj-functions-html.php:97
1379
  #: includes/reports/wcj-class-reports-monthly-sales.php:341
1380
  #: includes/settings/wcj-settings-empty-cart.php:80
@@ -1403,7 +1493,7 @@ msgstr ""
1403
  #: includes/class-wcj-offer-price.php:113
1404
  #: includes/functions/wcj-functions-reports.php:21
1405
  #: includes/functions/wcj-functions-reports.php:24
1406
- #: includes/settings/wcj-settings-order-numbers.php:133
1407
  #: includes/settings/wcj-settings-related-products.php:23
1408
  msgid "Date"
1409
  msgstr ""
@@ -1644,42 +1734,42 @@ msgstr ""
1644
  msgid "Minimum WooCommerce order amount (optionally by user role)."
1645
  msgstr ""
1646
 
1647
- #: includes/class-wcj-order-numbers.php:26
1648
  #: includes/settings/wcj-settings-order-numbers.php:15
1649
  msgid "Order Numbers"
1650
  msgstr ""
1651
 
1652
- #: includes/class-wcj-order-numbers.php:27
1653
  msgid ""
1654
  "WooCommerce sequential order numbering, custom order number prefix, suffix "
1655
  "and number width."
1656
  msgstr ""
1657
 
1658
- #: includes/class-wcj-order-numbers.php:33
1659
  msgid "Orders Renumerate"
1660
  msgstr ""
1661
 
1662
- #: includes/class-wcj-order-numbers.php:34
1663
  msgid "Tool renumerates all orders."
1664
  msgstr ""
1665
 
1666
- #: includes/class-wcj-order-numbers.php:179
1667
  msgid "Orders successfully renumerated!"
1668
  msgstr ""
1669
 
1670
- #: includes/class-wcj-order-numbers.php:182
1671
  #, php-format
1672
  msgid "Sequential number generation is enabled. Next order number will be %s."
1673
  msgstr ""
1674
 
1675
- #: includes/class-wcj-order-numbers.php:191
1676
  #, php-format
1677
  msgid ""
1678
  "Press the button below to renumerate all existing orders starting from order "
1679
  "counter settings in <a href=\"%s\">Order Numbers</a> module."
1680
  msgstr ""
1681
 
1682
- #: includes/class-wcj-order-numbers.php:198
1683
  msgid "Renumerate orders"
1684
  msgstr ""
1685
 
@@ -1770,11 +1860,11 @@ msgstr ""
1770
  msgid "Set allowed currencies for WooCommerce payment gateways to show up."
1771
  msgstr ""
1772
 
1773
- #: includes/class-wcj-payment-gateways-by-shipping.php:25
1774
  msgid "Gateways by Shipping"
1775
  msgstr ""
1776
 
1777
- #: includes/class-wcj-payment-gateways-by-shipping.php:26
1778
  msgid "Set \"enable for shipping methods\" for WooCommerce payment gateways."
1779
  msgstr ""
1780
 
@@ -1888,28 +1978,29 @@ msgstr ""
1888
  msgid "Invoices Monthly Reports."
1889
  msgstr ""
1890
 
1891
- #: includes/class-wcj-pdf-invoicing.php:89
1892
- #: includes/class-wcj-pdf-invoicing.php:90
1893
  #: includes/settings/wcj-settings-price-by-country.php:174
1894
  #: includes/settings/wcj-settings-price-by-country.php:179
1895
  #: includes/settings/wcj-settings-price-by-country.php:184
1896
  msgid "Generate"
1897
  msgstr ""
1898
 
1899
- #: includes/class-wcj-pdf-invoicing.php:97
1900
- #: includes/class-wcj-pdf-invoicing.php:98
1901
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:95
1902
- msgid "Download"
 
 
1903
  msgstr ""
1904
 
1905
- #: includes/class-wcj-pdf-invoicing.php:115
1906
  #, php-format
1907
  msgid "Document generated."
1908
  msgid_plural "%s documents generated."
1909
  msgstr[0] ""
1910
  msgstr[1] ""
1911
 
1912
- #: includes/class-wcj-pdf-invoicing.php:122
1913
  #: includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php:172
1914
  #, php-format
1915
  msgid ""
@@ -1917,17 +2008,11 @@ msgid ""
1917
  "hosting provider."
1918
  msgstr ""
1919
 
1920
- #: includes/class-wcj-pdf-invoicing.php:128
1921
  msgid "Booster: ZipArchive error."
1922
  msgstr ""
1923
 
1924
- #: includes/class-wcj-pdf-invoicing.php:250
1925
- #: includes/classes/class-wcj-pdf-invoice.php:232
1926
- #: includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php:245
1927
- msgid "Unexpected error"
1928
- msgstr ""
1929
-
1930
- #: includes/class-wcj-pdf-invoicing.php:376
1931
  msgid "You are not allowed to view the invoice."
1932
  msgstr ""
1933
 
@@ -2024,8 +2109,8 @@ msgstr ""
2024
  #: includes/settings/wcj-settings-checkout-files-upload.php:291
2025
  #: includes/settings/wcj-settings-coupon-code-generator.php:32
2026
  #: includes/settings/wcj-settings-currency-exchange-rates.php:54
2027
- #: includes/settings/wcj-settings-currency-exchange-rates.php:84
2028
- #: includes/settings/wcj-settings-currency-exchange-rates.php:92
2029
  #: includes/settings/wcj-settings-currency-per-product.php:66
2030
  #: includes/settings/wcj-settings-currency-per-product.php:73
2031
  #: includes/settings/wcj-settings-currency-per-product.php:80
@@ -2040,9 +2125,10 @@ msgstr ""
2040
  #: includes/settings/wcj-settings-general.php:151
2041
  #: includes/settings/wcj-settings-general.php:202
2042
  #: includes/settings/wcj-settings-global-discount.php:52
2043
- #: includes/settings/wcj-settings-left-to-free-shipping.php:27
2044
- #: includes/settings/wcj-settings-left-to-free-shipping.php:58
2045
- #: includes/settings/wcj-settings-left-to-free-shipping.php:95
 
2046
  #: includes/settings/wcj-settings-more-button-labels.php:28
2047
  #: includes/settings/wcj-settings-multicurrency-base-price.php:40
2048
  #: includes/settings/wcj-settings-multicurrency-base-price.php:55
@@ -2053,6 +2139,7 @@ msgstr ""
2053
  #: includes/settings/wcj-settings-order-numbers.php:97
2054
  #: includes/settings/wcj-settings-order-numbers.php:105
2055
  #: includes/settings/wcj-settings-order-numbers.php:112
 
2056
  #: includes/settings/wcj-settings-order-quantities.php:53
2057
  #: includes/settings/wcj-settings-order-quantities.php:111
2058
  #: includes/settings/wcj-settings-order-quantities.php:137
@@ -2060,10 +2147,11 @@ msgstr ""
2060
  #: includes/settings/wcj-settings-orders.php:25
2061
  #: includes/settings/wcj-settings-orders.php:53
2062
  #: includes/settings/wcj-settings-orders.php:72
2063
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:54
 
2064
  #: includes/settings/wcj-settings-pdf-invoicing-display.php:113
2065
  #: includes/settings/wcj-settings-pdf-invoicing-footer.php:23
2066
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:23
2067
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:23
2068
  #: includes/settings/wcj-settings-pdf-invoicing-styling.php:73
2069
  #: includes/settings/wcj-settings-price-by-country.php:69
@@ -2095,6 +2183,7 @@ msgstr ""
2095
  #: includes/settings/wcj-settings-product-by-country.php:21
2096
  #: includes/settings/wcj-settings-product-by-country.php:29
2097
  #: includes/settings/wcj-settings-product-by-country.php:37
 
2098
  #: includes/settings/wcj-settings-product-by-date.php:21
2099
  #: includes/settings/wcj-settings-product-by-date.php:53
2100
  #: includes/settings/wcj-settings-product-by-time.php:21
@@ -2114,9 +2203,9 @@ msgstr ""
2114
  #: includes/settings/wcj-settings-product-open-pricing.php:87
2115
  #: includes/settings/wcj-settings-product-open-pricing.php:94
2116
  #: includes/settings/wcj-settings-product-price-by-formula.php:30
2117
- #: includes/settings/wcj-settings-product-tabs.php:23
2118
- #: includes/settings/wcj-settings-product-tabs.php:212
2119
- #: includes/settings/wcj-settings-product-tabs.php:220
2120
  #: includes/settings/wcj-settings-products-xml.php:73
2121
  #: includes/settings/wcj-settings-purchase-data.php:22
2122
  #: includes/settings/wcj-settings-purchase-data.php:29
@@ -2129,21 +2218,25 @@ msgstr ""
2129
  #: includes/settings/wcj-settings-related-products.php:112
2130
  #: includes/settings/wcj-settings-related-products.php:119
2131
  #: includes/settings/wcj-settings-related-products.php:149
 
 
2132
  #: includes/settings/wcj-settings-shipping-calculator.php:20
2133
  #: includes/settings/wcj-settings-shipping-calculator.php:27
2134
  #: includes/settings/wcj-settings-shipping-calculator.php:34
2135
  #: includes/settings/wcj-settings-shipping-calculator.php:41
2136
  #: includes/settings/wcj-settings-shipping-options.php:63
 
 
2137
  #: includes/settings/wcj-settings-shipping.php:24
2138
- #: includes/settings/wcj-settings-sku.php:50
2139
- #: includes/settings/wcj-settings-sku.php:157
2140
- #: includes/settings/wcj-settings-sku.php:165
2141
- #: includes/settings/wcj-settings-sku.php:173
2142
- #: includes/settings/wcj-settings-sku.php:200
2143
  #: includes/settings/wcj-settings-stock.php:27
2144
- #: includes/settings/wcj-settings-stock.php:40
2145
- #: includes/settings/wcj-settings-stock.php:68
2146
- #: includes/settings/wcj-settings-stock.php:81
2147
  #: includes/settings/wcj-settings-track-users.php:47
2148
  #: includes/settings/wcj-settings-wholesale-price.php:22
2149
  #: includes/settings/wcj-settings-wholesale-price.php:29
@@ -2494,7 +2587,7 @@ msgid "Products category"
2494
  msgstr ""
2495
 
2496
  #: includes/class-wcj-product-bulk-price-converter.php:260
2497
- #: includes/shortcodes/class-wcj-shortcodes-products.php:350
2498
  msgid "Any"
2499
  msgstr ""
2500
 
@@ -2518,21 +2611,21 @@ msgstr ""
2518
  msgid "Change Prices"
2519
  msgstr ""
2520
 
2521
- #: includes/class-wcj-product-by-country.php:25
2522
  msgid "Product Visibility by Country"
2523
  msgstr ""
2524
 
2525
- #: includes/class-wcj-product-by-country.php:26
2526
  msgid "Display WooCommerce products by customer's country."
2527
  msgstr ""
2528
 
2529
- #: includes/class-wcj-product-by-country.php:28
2530
  msgid ""
2531
  "When enabled, module will add new \"Booster: Product Visibility by Country\" "
2532
  "meta box to each product's edit page."
2533
  msgstr ""
2534
 
2535
- #: includes/class-wcj-product-by-country.php:65
2536
  #: includes/widgets/class-wcj-widget-country-switcher.php:69
2537
  #: includes/widgets/class-wcj-widget-selector.php:64
2538
  msgid "Countries"
@@ -2629,7 +2722,7 @@ msgid "Status"
2629
  msgstr ""
2630
 
2631
  #: includes/class-wcj-product-by-user.php:197
2632
- #: includes/class-wcj-product-tabs.php:574
2633
  #: includes/gateways/class-wc-gateway-wcj-custom.php:66
2634
  #: includes/input-fields/wcj-product-input-fields-options.php:51
2635
  #: includes/settings/wcj-settings-export.php:75
@@ -2638,10 +2731,10 @@ msgstr ""
2638
  #: includes/settings/wcj-settings-product-add-to-cart.php:300
2639
  #: includes/settings/wcj-settings-product-addons.php:92
2640
  #: includes/settings/wcj-settings-product-by-user.php:167
2641
- #: includes/settings/wcj-settings-product-tabs.php:52
2642
- #: includes/settings/wcj-settings-product-tabs.php:368
2643
- #: includes/settings/wcj-settings-product-tabs.php:389
2644
- #: includes/settings/wcj-settings-product-tabs.php:410
2645
  #: includes/settings/wcj-settings-purchase-data.php:66
2646
  #: includes/settings/wcj-settings-related-products.php:24
2647
  #: includes/settings/meta-box/wcj-settings-meta-box-product-addons.php:57
@@ -2664,7 +2757,9 @@ msgstr ""
2664
 
2665
  #: includes/class-wcj-product-custom-info.php:24
2666
  #: includes/admin/class-wc-settings-jetpack.php:467
2667
- #: includes/functions/wcj-functions-general.php:314
 
 
2668
  msgid "Product Info"
2669
  msgstr ""
2670
 
@@ -2695,7 +2790,7 @@ msgid ""
2695
  msgstr ""
2696
 
2697
  #: includes/class-wcj-product-custom-visibility.php:34
2698
- #: includes/settings/wcj-settings-product-by-country.php:56
2699
  #: includes/widgets/class-wcj-widget-selector.php:27
2700
  msgid "Booster - Selector"
2701
  msgstr ""
@@ -2715,47 +2810,47 @@ msgstr ""
2715
  #: includes/class-wcj-product-info.php:124
2716
  #: includes/settings/wcj-settings-offer-price.php:91
2717
  #: includes/settings/wcj-settings-product-add-to-cart.php:326
2718
- #: includes/settings/wcj-settings-product-custom-info.php:102
2719
  msgid "Before product"
2720
  msgstr ""
2721
 
2722
  #: includes/class-wcj-product-info.php:125
2723
  #: includes/settings/wcj-settings-product-add-to-cart.php:327
2724
- #: includes/settings/wcj-settings-product-custom-info.php:103
2725
  msgid "Before product title"
2726
  msgstr ""
2727
 
2728
  #: includes/class-wcj-product-info.php:126
2729
  #: includes/settings/wcj-settings-offer-price.php:92
2730
  #: includes/settings/wcj-settings-product-add-to-cart.php:328
2731
- #: includes/settings/wcj-settings-product-custom-info.php:106
2732
  msgid "After product"
2733
  msgstr ""
2734
 
2735
  #: includes/class-wcj-product-info.php:127
2736
  #: includes/settings/wcj-settings-product-add-to-cart.php:329
2737
- #: includes/settings/wcj-settings-product-custom-info.php:105
2738
  msgid "After product title"
2739
  msgstr ""
2740
 
2741
  #: includes/class-wcj-product-info.php:139
2742
  #: includes/settings/wcj-settings-offer-price.php:72
2743
  #: includes/settings/wcj-settings-product-add-to-cart.php:292
2744
- #: includes/settings/wcj-settings-product-custom-info.php:93
2745
  msgid "Inside single product summary"
2746
  msgstr ""
2747
 
2748
  #: includes/class-wcj-product-info.php:140
2749
  #: includes/settings/wcj-settings-offer-price.php:71
2750
  #: includes/settings/wcj-settings-product-add-to-cart.php:291
2751
- #: includes/settings/wcj-settings-product-custom-info.php:92
2752
  msgid "Before single product summary"
2753
  msgstr ""
2754
 
2755
  #: includes/class-wcj-product-info.php:141
2756
  #: includes/settings/wcj-settings-offer-price.php:73
2757
  #: includes/settings/wcj-settings-product-add-to-cart.php:293
2758
- #: includes/settings/wcj-settings-product-custom-info.php:94
2759
  msgid "After single product summary"
2760
  msgstr ""
2761
 
@@ -2763,14 +2858,14 @@ msgstr ""
2763
  #: includes/settings/wcj-settings-cart.php:51
2764
  #: includes/settings/wcj-settings-checkout-custom-info.php:47
2765
  #: includes/settings/wcj-settings-checkout-files-upload.php:51
2766
- #: includes/settings/wcj-settings-left-to-free-shipping.php:43
2767
- #: includes/settings/wcj-settings-left-to-free-shipping.php:76
2768
- #: includes/settings/wcj-settings-left-to-free-shipping.php:113
2769
  #: includes/settings/wcj-settings-mini-cart.php:46
2770
  #: includes/settings/wcj-settings-my-account.php:74
2771
  #: includes/settings/wcj-settings-product-add-to-cart.php:286
2772
  #: includes/settings/wcj-settings-product-add-to-cart.php:321
2773
- #: includes/settings/wcj-settings-product-custom-info.php:85
2774
  #: includes/settings/wcj-settings-product-info.php:50
2775
  #: includes/settings/wcj-settings-product-info.php:83
2776
  #: includes/settings/wcj-settings-products-per-page.php:36
@@ -2781,10 +2876,10 @@ msgstr ""
2781
  #: includes/settings/wcj-settings-checkout-custom-fields.php:157
2782
  #: includes/settings/wcj-settings-product-info.php:61
2783
  #: includes/settings/wcj-settings-product-info.php:94
2784
- #: includes/settings/wcj-settings-product-tabs.php:66
2785
- #: includes/settings/wcj-settings-product-tabs.php:378
2786
- #: includes/settings/wcj-settings-product-tabs.php:399
2787
- #: includes/settings/wcj-settings-product-tabs.php:420
2788
  msgid "Priority (i.e. Order)"
2789
  msgstr ""
2790
 
@@ -2807,7 +2902,7 @@ msgstr ""
2807
 
2808
  #: includes/class-wcj-product-input-fields.php:24
2809
  #: includes/admin/class-wc-settings-jetpack.php:468
2810
- #: includes/input-fields/class-wcj-product-input-fields-core.php:127
2811
  msgid "Product Input Fields"
2812
  msgstr ""
2813
 
@@ -2815,11 +2910,11 @@ msgstr ""
2815
  msgid "WooCommerce product input fields."
2816
  msgstr ""
2817
 
2818
- #: includes/class-wcj-product-listings.php:22
2819
  msgid "Product Listings"
2820
  msgstr ""
2821
 
2822
- #: includes/class-wcj-product-listings.php:23
2823
  msgid ""
2824
  "Change WooCommerce display options for shop and category pages: show/hide "
2825
  "categories count, exclude categories, show/hide empty categories."
@@ -2900,33 +2995,33 @@ msgid ""
2900
  "remove WooCommerce default product tabs."
2901
  msgstr ""
2902
 
2903
- #: includes/class-wcj-product-tabs.php:531
2904
  msgid "Booster: Custom Tabs"
2905
  msgstr ""
2906
 
2907
- #: includes/class-wcj-product-tabs.php:558
2908
  msgid "Total number of custom tabs"
2909
  msgstr ""
2910
 
2911
- #: includes/class-wcj-product-tabs.php:564
2912
- #: includes/input-fields/class-wcj-product-input-fields-core.php:153
2913
  msgid "Click \"Update\" product after you change this number."
2914
  msgstr ""
2915
 
2916
- #: includes/class-wcj-product-tabs.php:579
2917
  #: includes/settings/wcj-settings-checkout-custom-fields.php:108
2918
- #: includes/settings/wcj-settings-product-tabs.php:59
2919
  msgid "Key"
2920
  msgstr ""
2921
 
2922
- #: includes/class-wcj-product-tabs.php:584
2923
  #: includes/input-fields/wcj-product-input-fields-options.php:21
2924
  #: includes/settings/wcj-settings-related-products.php:59
2925
  #: includes/settings/wcj-settings-related-products.php:84
2926
  msgid "Order"
2927
  msgstr ""
2928
 
2929
- #: includes/class-wcj-product-tabs.php:589
2930
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:36
2931
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:51
2932
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:100
@@ -2934,35 +3029,35 @@ msgstr ""
2934
  #: includes/settings/wcj-settings-cart.php:44
2935
  #: includes/settings/wcj-settings-checkout-custom-info.php:40
2936
  #: includes/settings/wcj-settings-left-to-free-shipping.php:34
2937
- #: includes/settings/wcj-settings-left-to-free-shipping.php:67
2938
- #: includes/settings/wcj-settings-left-to-free-shipping.php:104
2939
  #: includes/settings/wcj-settings-mini-cart.php:39
2940
  #: includes/settings/wcj-settings-my-account.php:66
2941
- #: includes/settings/wcj-settings-product-custom-info.php:77
2942
- #: includes/settings/wcj-settings-product-tabs.php:72
2943
  #: includes/widgets/class-wcj-widget-left-to-free-shipping.php:59
2944
  msgid "Content"
2945
  msgstr ""
2946
 
2947
- #: includes/class-wcj-product-tabs.php:594
2948
  #: includes/settings/wcj-settings-cart-customization.php:63
2949
- #: includes/settings/wcj-settings-product-tabs.php:80
2950
  msgid "Link"
2951
  msgstr ""
2952
 
2953
- #: includes/class-wcj-product-tabs.php:596
2954
- #: includes/settings/wcj-settings-product-tabs.php:81
2955
  msgid ""
2956
  "If you wish to forward tab to new link, enter it here. In this case content "
2957
  "is ignored. Leave blank to show content."
2958
  msgstr ""
2959
 
2960
- #: includes/class-wcj-product-tabs.php:600
2961
- #: includes/settings/wcj-settings-product-tabs.php:88
2962
  msgid "Link - Open in New Window"
2963
  msgstr ""
2964
 
2965
- #: includes/class-wcj-product-tabs.php:603
2966
  #: includes/input-fields/wcj-product-input-fields-options.php:101
2967
  #: includes/settings/wcj-settings-admin-orders-list.php:84
2968
  #: includes/settings/wcj-settings-checkout-custom-fields.php:224
@@ -2989,7 +3084,7 @@ msgstr ""
2989
  msgid "No"
2990
  msgstr ""
2991
 
2992
- #: includes/class-wcj-product-tabs.php:604
2993
  #: includes/input-fields/wcj-product-input-fields-options.php:94
2994
  #: includes/settings/wcj-settings-checkout-custom-fields.php:218
2995
  #: includes/settings/wcj-settings-eu-vat-number.php:50
@@ -3021,9 +3116,9 @@ msgstr ""
3021
  msgid "Yes"
3022
  msgstr ""
3023
 
3024
- #: includes/class-wcj-product-tabs.php:612
3025
  #: includes/settings/wcj-settings-checkout-core-fields.php:71
3026
- #: includes/settings/wcj-settings-currency-exchange-rates.php:141
3027
  #: includes/settings/wcj-settings-order-numbers.php:46
3028
  #: includes/settings/wcj-settings-orders.php:137
3029
  #: includes/settings/wcj-settings-product-add-to-cart.php:64
@@ -3032,9 +3127,9 @@ msgstr ""
3032
  msgid "Disabled"
3033
  msgstr ""
3034
 
3035
- #: includes/class-wcj-product-tabs.php:615
3036
- #: includes/settings/wcj-settings-product-tabs.php:51
3037
- #: includes/settings/wcj-settings-product-tabs.php:250
3038
  msgid "Custom Product Tab"
3039
  msgstr ""
3040
 
@@ -3062,12 +3157,12 @@ msgid "WooCommerce products XML feeds."
3062
  msgstr ""
3063
 
3064
  #: includes/class-wcj-products-xml.php:95
3065
- #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:211
3066
  msgid "Once Weekly"
3067
  msgstr ""
3068
 
3069
  #: includes/class-wcj-products-xml.php:99
3070
- #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:215
3071
  msgid "Once a Minute"
3072
  msgstr ""
3073
 
@@ -3236,7 +3331,7 @@ msgid "Sale!"
3236
  msgstr ""
3237
 
3238
  #: includes/class-wcj-shipping-by-order-amount.php:26
3239
- #: includes/settings/wcj-settings-shipping-by-order-amount.php:14
3240
  msgid "Shipping Methods by Min/Max Order Amount"
3241
  msgstr ""
3242
 
@@ -3279,20 +3374,39 @@ msgstr ""
3279
  msgid "Shipping methods by <strong>products tags</strong>."
3280
  msgstr ""
3281
 
3282
- #: includes/class-wcj-shipping-by-products.php:117
3283
  msgid "\"Include\" Options"
3284
  msgstr ""
3285
 
3286
- #: includes/class-wcj-shipping-by-products.php:118
3287
  msgid ""
3288
  "Enable this checkbox if you want all products in cart to be valid (instead "
3289
  "of at least one)."
3290
  msgstr ""
3291
 
3292
- #: includes/class-wcj-shipping-by-products.php:119
3293
  msgid "Validate all"
3294
  msgstr ""
3295
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3296
  #: includes/class-wcj-shipping-by-user-role.php:25
3297
  msgid "Shipping Methods by Users"
3298
  msgstr ""
@@ -3346,7 +3460,7 @@ msgid "Shipping Descriptions"
3346
  msgstr ""
3347
 
3348
  #: includes/class-wcj-shipping-description.php:26
3349
- msgid "Add descriptions to shipping methods on frontend."
3350
  msgstr ""
3351
 
3352
  #: includes/class-wcj-shipping-icons.php:25
@@ -3354,7 +3468,7 @@ msgid "Shipping Icons"
3354
  msgstr ""
3355
 
3356
  #: includes/class-wcj-shipping-icons.php:26
3357
- msgid "Add icons to shipping methods on frontend."
3358
  msgstr ""
3359
 
3360
  #: includes/class-wcj-shipping-options.php:26
@@ -3395,6 +3509,21 @@ msgstr ""
3395
  msgid "Hide \"Flat Rate\" only"
3396
  msgstr ""
3397
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3398
  #: includes/class-wcj-shipping.php:24
3399
  #: includes/settings/wcj-settings-shipping.php:16
3400
  #: includes/settings/wcj-settings-shipping.php:23
@@ -3407,7 +3536,7 @@ msgstr ""
3407
  msgid "Add multiple custom shipping methods to WooCommerce."
3408
  msgstr ""
3409
 
3410
- #: includes/class-wcj-sku.php:23 includes/class-wcj-sku.php:397
3411
  #: includes/export/class-wcj-fields-helper.php:283
3412
  msgid "SKU"
3413
  msgstr ""
@@ -3424,22 +3553,36 @@ msgstr ""
3424
  msgid "The tool generates and sets product SKUs for existing products."
3425
  msgstr ""
3426
 
3427
- #: includes/class-wcj-sku.php:398
3428
  msgid "Old SKU"
3429
  msgstr ""
3430
 
3431
- #: includes/class-wcj-sku.php:404
3432
  msgid "SKUs generated and set successfully!"
3433
  msgstr ""
3434
 
3435
- #: includes/class-wcj-sku.php:413
3436
  msgid "Preview SKUs"
3437
  msgstr ""
3438
 
3439
- #: includes/class-wcj-sku.php:415
3440
  msgid "Set SKUs"
3441
  msgstr ""
3442
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3443
  #: includes/class-wcj-sorting.php:24
3444
  msgid "Sorting"
3445
  msgstr ""
@@ -3474,7 +3617,7 @@ msgstr ""
3474
  msgid "Sort by price: high to low"
3475
  msgstr ""
3476
 
3477
- #: includes/class-wcj-stock.php:28
3478
  msgid "WooCommerce products stock management."
3479
  msgstr ""
3480
 
@@ -3704,6 +3847,8 @@ msgid "Use List Instead of Comma Separated Text for Products in Settings"
3704
  msgstr ""
3705
 
3706
  #: includes/admin/class-wc-settings-jetpack.php:464
 
 
3707
  #, php-format
3708
  msgid "Supported modules: %s."
3709
  msgstr ""
@@ -3712,22 +3857,35 @@ msgstr ""
3712
  msgid "Products XML"
3713
  msgstr ""
3714
 
3715
- #: includes/admin/class-wc-settings-jetpack.php:494
 
 
 
 
 
 
 
 
 
3716
  #: includes/core/class-wcj-admin.php:97
3717
  msgid "Booster for WooCommerce"
3718
  msgstr ""
3719
 
3720
  #: includes/admin/class-wcj-settings-custom-fields.php:65
3721
  #, php-format
3722
- msgid "Grab %s rate from %s"
 
 
 
 
3723
  msgstr ""
3724
 
3725
- #: includes/admin/class-wcj-settings-custom-fields.php:259
3726
  #: includes/settings/wcj-settings-wpml.php:21
3727
  msgid "To use tools, module must be enabled."
3728
  msgstr ""
3729
 
3730
- #: includes/admin/class-wcj-settings-custom-fields.php:298
3731
  msgid "Save changes"
3732
  msgstr ""
3733
 
@@ -3826,9 +3984,9 @@ msgid ""
3826
  msgstr ""
3827
 
3828
  #: includes/admin/wcj-modules-cats.php:112
3829
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:34
3830
  #: includes/settings/wcj-settings-payment-gateways-by-currency.php:14
3831
- #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:21
3832
  #: includes/settings/wcj-settings-payment-gateways-by-user-role.php:14
3833
  #: includes/settings/wcj-settings-payment-gateways-min-max.php:65
3834
  msgid "Payment Gateways"
@@ -3850,19 +4008,19 @@ msgid ""
3850
  "Methods and more."
3851
  msgstr ""
3852
 
3853
- #: includes/admin/wcj-modules-cats.php:152
3854
  msgid "PDF Invoicing & Packing Slips"
3855
  msgstr ""
3856
 
3857
- #: includes/admin/wcj-modules-cats.php:153
3858
  msgid "PDF Documents"
3859
  msgstr ""
3860
 
3861
- #: includes/admin/wcj-modules-cats.php:169
3862
  msgid "Emails & Misc."
3863
  msgstr ""
3864
 
3865
- #: includes/admin/wcj-modules-cats.php:170
3866
  msgid "Emails, Reports, Export, Admin Tools, General Options and more."
3867
  msgstr ""
3868
 
@@ -3899,10 +4057,10 @@ msgid "disabled"
3899
  msgstr ""
3900
 
3901
  #: includes/classes/class-wcj-module.php:565
3902
- #: includes/settings/wcj-settings-product-tabs.php:152
3903
- #: includes/settings/wcj-settings-product-tabs.php:164
3904
- #: includes/settings/wcj-settings-product-tabs.php:176
3905
- #: includes/settings/wcj-settings-product-tabs.php:188
3906
  msgid "Deprecated"
3907
  msgstr ""
3908
 
@@ -3930,18 +4088,24 @@ msgstr ""
3930
  msgid "Enable Module"
3931
  msgstr ""
3932
 
3933
- #: includes/classes/class-wcj-pdf-invoice.php:83
3934
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:55
3935
  msgid "Company Name"
3936
  msgstr ""
3937
 
3938
- #: includes/classes/class-wcj-shortcodes.php:107
3939
- #: includes/shortcodes/class-wcj-shortcodes-general.php:364
 
 
 
 
 
 
3940
  #, php-format
3941
  msgid "\"%s\" module is not enabled!"
3942
  msgstr ""
3943
 
3944
- #: includes/classes/class-wcj-tcpdf.php:52
3945
  #: includes/settings/wcj-settings-pdf-invoicing-footer.php:31
3946
  msgid "Page %page_number% / %total_pages%"
3947
  msgstr ""
@@ -4136,44 +4300,44 @@ msgid "Plain text template"
4136
  msgstr ""
4137
 
4138
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:22
4139
- #: includes/settings/wcj-settings-currency-exchange-rates.php:38
4140
  #: includes/settings/wcj-settings-products-xml.php:129
4141
  msgid "Update Every Minute"
4142
  msgstr ""
4143
 
4144
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:23
4145
- #: includes/settings/wcj-settings-currency-exchange-rates.php:39
4146
  #: includes/settings/wcj-settings-products-xml.php:130
4147
  msgid "Update Hourly"
4148
  msgstr ""
4149
 
4150
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:24
4151
- #: includes/settings/wcj-settings-currency-exchange-rates.php:40
4152
  #: includes/settings/wcj-settings-products-xml.php:131
4153
  msgid "Update Twice Daily"
4154
  msgstr ""
4155
 
4156
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:25
4157
- #: includes/settings/wcj-settings-currency-exchange-rates.php:41
4158
  #: includes/settings/wcj-settings-products-xml.php:132
4159
  msgid "Update Daily"
4160
  msgstr ""
4161
 
4162
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:26
4163
- #: includes/settings/wcj-settings-currency-exchange-rates.php:42
4164
  #: includes/settings/wcj-settings-products-xml.php:133
4165
  msgid "Update Weekly"
4166
  msgstr ""
4167
 
4168
- #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:186
4169
  msgid "Cron job: exchange rates successfully updated"
4170
  msgstr ""
4171
 
4172
- #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:188
4173
  msgid "Cron job: exchange rates not updated, as currency_from == currency_to"
4174
  msgstr ""
4175
 
4176
- #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:191
4177
  msgid "Cron job: exchange rates update failed"
4178
  msgstr ""
4179
 
@@ -4616,18 +4780,18 @@ msgstr ""
4616
  msgid "Availability Class"
4617
  msgstr ""
4618
 
4619
- #: includes/functions/wcj-functions-admin.php:100
4620
  #, php-format
4621
  msgid ""
4622
  "<strong>Booster for WooCommerce</strong> plugin was successfully updated to "
4623
  "version <strong>%s</strong>."
4624
  msgstr ""
4625
 
4626
- #: includes/functions/wcj-functions-admin.php:123
4627
  msgid "Enter comma separated list of IDs."
4628
  msgstr ""
4629
 
4630
- #: includes/functions/wcj-functions-admin.php:197
4631
  #: includes/settings/wcj-settings-emails-verification.php:59
4632
  #: includes/settings/wcj-settings-emails-verification.php:67
4633
  #: includes/settings/wcj-settings-emails-verification.php:107
@@ -4635,1040 +4799,1040 @@ msgstr ""
4635
  msgid "Replaced value: %s"
4636
  msgstr ""
4637
 
4638
- #: includes/functions/wcj-functions-admin.php:197
4639
  #, php-format
4640
  msgid "Replaced values: %s"
4641
  msgstr ""
4642
 
4643
- #: includes/functions/wcj-functions-admin.php:226
4644
  msgid "Install Booster Plus to unlock all features"
4645
  msgstr ""
4646
 
4647
- #: includes/functions/wcj-functions-admin.php:227
4648
  #, php-format
4649
  msgid ""
4650
  "Some settings fields are locked and you will need %s to modify all locked "
4651
  "fields."
4652
  msgstr ""
4653
 
4654
- #: includes/functions/wcj-functions-admin.php:228
4655
  msgid "Buy now"
4656
  msgstr ""
4657
 
4658
- #: includes/functions/wcj-functions-admin.php:228
4659
  msgid "Visit Booster Site"
4660
  msgstr ""
4661
 
4662
- #: includes/functions/wcj-functions-admin.php:232
4663
  #, php-format
4664
  msgid "Get <a href=\"%s\" target=\"_blank\">Booster Plus</a> to change value."
4665
  msgstr ""
4666
 
4667
- #: includes/functions/wcj-functions-admin.php:235
4668
  #, php-format
4669
  msgid ""
4670
  "Get <a href=\"%s\" target=\"_blank\">Booster Plus</a> to enable \"%s\" "
4671
  "option."
4672
  msgstr ""
4673
 
4674
- #: includes/functions/wcj-functions-admin.php:238
4675
  #, php-format
4676
  msgid "Get Booster Plus to enable \"%s\" option."
4677
  msgstr ""
4678
 
4679
- #: includes/functions/wcj-functions-admin.php:241
4680
  #, php-format
4681
  msgid ""
4682
  "Get <a href=\"%s\" target=\"_blank\">Booster Plus</a> to change values below."
4683
  msgstr ""
4684
 
4685
- #: includes/functions/wcj-functions-admin.php:244
4686
  #, php-format
4687
  msgid ""
4688
  "Get <a href=\"%s\" target=\"_blank\">Booster Plus</a> to change values above."
4689
  msgstr ""
4690
 
4691
- #: includes/functions/wcj-functions-admin.php:247
4692
  msgid "Get Booster Plus to change value."
4693
  msgstr ""
4694
 
4695
- #: includes/functions/wcj-functions-country.php:147
4696
  msgid "Afghanistan"
4697
  msgstr ""
4698
 
4699
- #: includes/functions/wcj-functions-country.php:148
4700
  msgid "&#197;land Islands"
4701
  msgstr ""
4702
 
4703
- #: includes/functions/wcj-functions-country.php:149
4704
  msgid "Albania"
4705
  msgstr ""
4706
 
4707
- #: includes/functions/wcj-functions-country.php:150
4708
  msgid "Algeria"
4709
  msgstr ""
4710
 
4711
- #: includes/functions/wcj-functions-country.php:151
4712
  msgid "Andorra"
4713
  msgstr ""
4714
 
4715
- #: includes/functions/wcj-functions-country.php:152
4716
  msgid "Angola"
4717
  msgstr ""
4718
 
4719
- #: includes/functions/wcj-functions-country.php:153
4720
  msgid "Anguilla"
4721
  msgstr ""
4722
 
4723
- #: includes/functions/wcj-functions-country.php:154
4724
  msgid "Antarctica"
4725
  msgstr ""
4726
 
4727
- #: includes/functions/wcj-functions-country.php:155
4728
  msgid "Antigua and Barbuda"
4729
  msgstr ""
4730
 
4731
- #: includes/functions/wcj-functions-country.php:156
4732
  msgid "Argentina"
4733
  msgstr ""
4734
 
4735
- #: includes/functions/wcj-functions-country.php:157
4736
  msgid "Armenia"
4737
  msgstr ""
4738
 
4739
- #: includes/functions/wcj-functions-country.php:158
4740
  msgid "Aruba"
4741
  msgstr ""
4742
 
4743
- #: includes/functions/wcj-functions-country.php:159
4744
  msgid "Australia"
4745
  msgstr ""
4746
 
4747
- #: includes/functions/wcj-functions-country.php:160
4748
  msgid "Austria"
4749
  msgstr ""
4750
 
4751
- #: includes/functions/wcj-functions-country.php:161
4752
  msgid "Azerbaijan"
4753
  msgstr ""
4754
 
4755
- #: includes/functions/wcj-functions-country.php:162
4756
  msgid "Bahamas"
4757
  msgstr ""
4758
 
4759
- #: includes/functions/wcj-functions-country.php:163
4760
  msgid "Bahrain"
4761
  msgstr ""
4762
 
4763
- #: includes/functions/wcj-functions-country.php:164
4764
  msgid "Bangladesh"
4765
  msgstr ""
4766
 
4767
- #: includes/functions/wcj-functions-country.php:165
4768
  msgid "Barbados"
4769
  msgstr ""
4770
 
4771
- #: includes/functions/wcj-functions-country.php:166
4772
  msgid "Belarus"
4773
  msgstr ""
4774
 
4775
- #: includes/functions/wcj-functions-country.php:167
4776
  msgid "Belgium"
4777
  msgstr ""
4778
 
4779
- #: includes/functions/wcj-functions-country.php:168
4780
  msgid "Belau"
4781
  msgstr ""
4782
 
4783
- #: includes/functions/wcj-functions-country.php:169
4784
  msgid "Belize"
4785
  msgstr ""
4786
 
4787
- #: includes/functions/wcj-functions-country.php:170
4788
  msgid "Benin"
4789
  msgstr ""
4790
 
4791
- #: includes/functions/wcj-functions-country.php:171
4792
  msgid "Bermuda"
4793
  msgstr ""
4794
 
4795
- #: includes/functions/wcj-functions-country.php:172
4796
  msgid "Bhutan"
4797
  msgstr ""
4798
 
4799
- #: includes/functions/wcj-functions-country.php:173
4800
  msgid "Bolivia"
4801
  msgstr ""
4802
 
4803
- #: includes/functions/wcj-functions-country.php:174
4804
  msgid "Bonaire, Saint Eustatius and Saba"
4805
  msgstr ""
4806
 
4807
- #: includes/functions/wcj-functions-country.php:175
4808
  msgid "Bosnia and Herzegovina"
4809
  msgstr ""
4810
 
4811
- #: includes/functions/wcj-functions-country.php:176
4812
  msgid "Botswana"
4813
  msgstr ""
4814
 
4815
- #: includes/functions/wcj-functions-country.php:177
4816
  msgid "Bouvet Island"
4817
  msgstr ""
4818
 
4819
- #: includes/functions/wcj-functions-country.php:178
4820
  msgid "Brazil"
4821
  msgstr ""
4822
 
4823
- #: includes/functions/wcj-functions-country.php:179
4824
  msgid "British Indian Ocean Territory"
4825
  msgstr ""
4826
 
4827
- #: includes/functions/wcj-functions-country.php:180
4828
  msgid "British Virgin Islands"
4829
  msgstr ""
4830
 
4831
- #: includes/functions/wcj-functions-country.php:181
4832
  msgid "Brunei"
4833
  msgstr ""
4834
 
4835
- #: includes/functions/wcj-functions-country.php:182
4836
  msgid "Bulgaria"
4837
  msgstr ""
4838
 
4839
- #: includes/functions/wcj-functions-country.php:183
4840
  msgid "Burkina Faso"
4841
  msgstr ""
4842
 
4843
- #: includes/functions/wcj-functions-country.php:184
4844
  msgid "Burundi"
4845
  msgstr ""
4846
 
4847
- #: includes/functions/wcj-functions-country.php:185
4848
  msgid "Cambodia"
4849
  msgstr ""
4850
 
4851
- #: includes/functions/wcj-functions-country.php:186
4852
  msgid "Cameroon"
4853
  msgstr ""
4854
 
4855
- #: includes/functions/wcj-functions-country.php:187
4856
  msgid "Canada"
4857
  msgstr ""
4858
 
4859
- #: includes/functions/wcj-functions-country.php:188
4860
  msgid "Cape Verde"
4861
  msgstr ""
4862
 
4863
- #: includes/functions/wcj-functions-country.php:189
4864
  msgid "Cayman Islands"
4865
  msgstr ""
4866
 
4867
- #: includes/functions/wcj-functions-country.php:190
4868
  msgid "Central African Republic"
4869
  msgstr ""
4870
 
4871
- #: includes/functions/wcj-functions-country.php:191
4872
  msgid "Chad"
4873
  msgstr ""
4874
 
4875
- #: includes/functions/wcj-functions-country.php:192
4876
  msgid "Chile"
4877
  msgstr ""
4878
 
4879
- #: includes/functions/wcj-functions-country.php:193
4880
  msgid "China"
4881
  msgstr ""
4882
 
4883
- #: includes/functions/wcj-functions-country.php:194
4884
  msgid "Christmas Island"
4885
  msgstr ""
4886
 
4887
- #: includes/functions/wcj-functions-country.php:195
4888
  msgid "Cocos (Keeling) Islands"
4889
  msgstr ""
4890
 
4891
- #: includes/functions/wcj-functions-country.php:196
4892
  msgid "Colombia"
4893
  msgstr ""
4894
 
4895
- #: includes/functions/wcj-functions-country.php:197
4896
  msgid "Comoros"
4897
  msgstr ""
4898
 
4899
- #: includes/functions/wcj-functions-country.php:198
4900
  msgid "Congo (Brazzaville)"
4901
  msgstr ""
4902
 
4903
- #: includes/functions/wcj-functions-country.php:199
4904
  msgid "Congo (Kinshasa)"
4905
  msgstr ""
4906
 
4907
- #: includes/functions/wcj-functions-country.php:200
4908
  msgid "Cook Islands"
4909
  msgstr ""
4910
 
4911
- #: includes/functions/wcj-functions-country.php:201
4912
  msgid "Costa Rica"
4913
  msgstr ""
4914
 
4915
- #: includes/functions/wcj-functions-country.php:202
4916
  msgid "Croatia"
4917
  msgstr ""
4918
 
4919
- #: includes/functions/wcj-functions-country.php:203
4920
  msgid "Cuba"
4921
  msgstr ""
4922
 
4923
- #: includes/functions/wcj-functions-country.php:204
4924
  msgid "Cura&Ccedil;ao"
4925
  msgstr ""
4926
 
4927
- #: includes/functions/wcj-functions-country.php:205
4928
  msgid "Cyprus"
4929
  msgstr ""
4930
 
4931
- #: includes/functions/wcj-functions-country.php:206
4932
  msgid "Czech Republic"
4933
  msgstr ""
4934
 
4935
- #: includes/functions/wcj-functions-country.php:207
4936
  msgid "Denmark"
4937
  msgstr ""
4938
 
4939
- #: includes/functions/wcj-functions-country.php:208
4940
  msgid "Djibouti"
4941
  msgstr ""
4942
 
4943
- #: includes/functions/wcj-functions-country.php:209
4944
  msgid "Dominica"
4945
  msgstr ""
4946
 
4947
- #: includes/functions/wcj-functions-country.php:210
4948
  msgid "Dominican Republic"
4949
  msgstr ""
4950
 
4951
- #: includes/functions/wcj-functions-country.php:211
4952
  msgid "Ecuador"
4953
  msgstr ""
4954
 
4955
- #: includes/functions/wcj-functions-country.php:212
4956
  msgid "Egypt"
4957
  msgstr ""
4958
 
4959
- #: includes/functions/wcj-functions-country.php:213
4960
  msgid "El Salvador"
4961
  msgstr ""
4962
 
4963
- #: includes/functions/wcj-functions-country.php:214
4964
  msgid "Equatorial Guinea"
4965
  msgstr ""
4966
 
4967
- #: includes/functions/wcj-functions-country.php:215
4968
  msgid "Eritrea"
4969
  msgstr ""
4970
 
4971
- #: includes/functions/wcj-functions-country.php:216
4972
  msgid "Estonia"
4973
  msgstr ""
4974
 
4975
- #: includes/functions/wcj-functions-country.php:217
4976
  msgid "Ethiopia"
4977
  msgstr ""
4978
 
4979
- #: includes/functions/wcj-functions-country.php:218
4980
  msgid "Falkland Islands"
4981
  msgstr ""
4982
 
4983
- #: includes/functions/wcj-functions-country.php:219
4984
  msgid "Faroe Islands"
4985
  msgstr ""
4986
 
4987
- #: includes/functions/wcj-functions-country.php:220
4988
  msgid "Fiji"
4989
  msgstr ""
4990
 
4991
- #: includes/functions/wcj-functions-country.php:221
4992
  msgid "Finland"
4993
  msgstr ""
4994
 
4995
- #: includes/functions/wcj-functions-country.php:222
4996
  msgid "France"
4997
  msgstr ""
4998
 
4999
- #: includes/functions/wcj-functions-country.php:223
5000
  msgid "French Guiana"
5001
  msgstr ""
5002
 
5003
- #: includes/functions/wcj-functions-country.php:224
5004
  msgid "French Polynesia"
5005
  msgstr ""
5006
 
5007
- #: includes/functions/wcj-functions-country.php:225
5008
  msgid "French Southern Territories"
5009
  msgstr ""
5010
 
5011
- #: includes/functions/wcj-functions-country.php:226
5012
  msgid "Gabon"
5013
  msgstr ""
5014
 
5015
- #: includes/functions/wcj-functions-country.php:227
5016
  msgid "Gambia"
5017
  msgstr ""
5018
 
5019
- #: includes/functions/wcj-functions-country.php:228
5020
  msgid "Georgia"
5021
  msgstr ""
5022
 
5023
- #: includes/functions/wcj-functions-country.php:229
5024
  msgid "Germany"
5025
  msgstr ""
5026
 
5027
- #: includes/functions/wcj-functions-country.php:230
5028
  msgid "Ghana"
5029
  msgstr ""
5030
 
5031
- #: includes/functions/wcj-functions-country.php:231
5032
  msgid "Gibraltar"
5033
  msgstr ""
5034
 
5035
- #: includes/functions/wcj-functions-country.php:232
5036
  msgid "Greece"
5037
  msgstr ""
5038
 
5039
- #: includes/functions/wcj-functions-country.php:233
5040
  msgid "Greenland"
5041
  msgstr ""
5042
 
5043
- #: includes/functions/wcj-functions-country.php:234
5044
  msgid "Grenada"
5045
  msgstr ""
5046
 
5047
- #: includes/functions/wcj-functions-country.php:235
5048
  msgid "Guadeloupe"
5049
  msgstr ""
5050
 
5051
- #: includes/functions/wcj-functions-country.php:236
5052
  msgid "Guatemala"
5053
  msgstr ""
5054
 
5055
- #: includes/functions/wcj-functions-country.php:237
5056
  msgid "Guernsey"
5057
  msgstr ""
5058
 
5059
- #: includes/functions/wcj-functions-country.php:238
5060
  msgid "Guinea"
5061
  msgstr ""
5062
 
5063
- #: includes/functions/wcj-functions-country.php:239
5064
  msgid "Guinea-Bissau"
5065
  msgstr ""
5066
 
5067
- #: includes/functions/wcj-functions-country.php:240
5068
  msgid "Guyana"
5069
  msgstr ""
5070
 
5071
- #: includes/functions/wcj-functions-country.php:241
5072
  msgid "Haiti"
5073
  msgstr ""
5074
 
5075
- #: includes/functions/wcj-functions-country.php:242
5076
  msgid "Heard Island and McDonald Islands"
5077
  msgstr ""
5078
 
5079
- #: includes/functions/wcj-functions-country.php:243
5080
  msgid "Honduras"
5081
  msgstr ""
5082
 
5083
- #: includes/functions/wcj-functions-country.php:244
5084
  msgid "Hong Kong"
5085
  msgstr ""
5086
 
5087
- #: includes/functions/wcj-functions-country.php:245
5088
  msgid "Hungary"
5089
  msgstr ""
5090
 
5091
- #: includes/functions/wcj-functions-country.php:246
5092
  msgid "Iceland"
5093
  msgstr ""
5094
 
5095
- #: includes/functions/wcj-functions-country.php:247
5096
  msgid "India"
5097
  msgstr ""
5098
 
5099
- #: includes/functions/wcj-functions-country.php:248
5100
  msgid "Indonesia"
5101
  msgstr ""
5102
 
5103
- #: includes/functions/wcj-functions-country.php:249
5104
  msgid "Iran"
5105
  msgstr ""
5106
 
5107
- #: includes/functions/wcj-functions-country.php:250
5108
  msgid "Iraq"
5109
  msgstr ""
5110
 
5111
- #: includes/functions/wcj-functions-country.php:251
5112
  msgid "Republic of Ireland"
5113
  msgstr ""
5114
 
5115
- #: includes/functions/wcj-functions-country.php:252
5116
  msgid "Isle of Man"
5117
  msgstr ""
5118
 
5119
- #: includes/functions/wcj-functions-country.php:253
5120
  msgid "Israel"
5121
  msgstr ""
5122
 
5123
- #: includes/functions/wcj-functions-country.php:254
5124
  msgid "Italy"
5125
  msgstr ""
5126
 
5127
- #: includes/functions/wcj-functions-country.php:255
5128
  msgid "Ivory Coast"
5129
  msgstr ""
5130
 
5131
- #: includes/functions/wcj-functions-country.php:256
5132
  msgid "Jamaica"
5133
  msgstr ""
5134
 
5135
- #: includes/functions/wcj-functions-country.php:257
5136
  msgid "Japan"
5137
  msgstr ""
5138
 
5139
- #: includes/functions/wcj-functions-country.php:258
5140
  msgid "Jersey"
5141
  msgstr ""
5142
 
5143
- #: includes/functions/wcj-functions-country.php:259
5144
  msgid "Jordan"
5145
  msgstr ""
5146
 
5147
- #: includes/functions/wcj-functions-country.php:260
5148
  msgid "Kazakhstan"
5149
  msgstr ""
5150
 
5151
- #: includes/functions/wcj-functions-country.php:261
5152
  msgid "Kenya"
5153
  msgstr ""
5154
 
5155
- #: includes/functions/wcj-functions-country.php:262
5156
  msgid "Kiribati"
5157
  msgstr ""
5158
 
5159
- #: includes/functions/wcj-functions-country.php:263
5160
  msgid "Kuwait"
5161
  msgstr ""
5162
 
5163
- #: includes/functions/wcj-functions-country.php:264
5164
  msgid "Kyrgyzstan"
5165
  msgstr ""
5166
 
5167
- #: includes/functions/wcj-functions-country.php:265
5168
  msgid "Laos"
5169
  msgstr ""
5170
 
5171
- #: includes/functions/wcj-functions-country.php:266
5172
  msgid "Latvia"
5173
  msgstr ""
5174
 
5175
- #: includes/functions/wcj-functions-country.php:267
5176
  msgid "Lebanon"
5177
  msgstr ""
5178
 
5179
- #: includes/functions/wcj-functions-country.php:268
5180
  msgid "Lesotho"
5181
  msgstr ""
5182
 
5183
- #: includes/functions/wcj-functions-country.php:269
5184
  msgid "Liberia"
5185
  msgstr ""
5186
 
5187
- #: includes/functions/wcj-functions-country.php:270
5188
  msgid "Libya"
5189
  msgstr ""
5190
 
5191
- #: includes/functions/wcj-functions-country.php:271
5192
  msgid "Liechtenstein"
5193
  msgstr ""
5194
 
5195
- #: includes/functions/wcj-functions-country.php:272
5196
  msgid "Lithuania"
5197
  msgstr ""
5198
 
5199
- #: includes/functions/wcj-functions-country.php:273
5200
  msgid "Luxembourg"
5201
  msgstr ""
5202
 
5203
- #: includes/functions/wcj-functions-country.php:274
5204
  msgid "Macao S.A.R., China"
5205
  msgstr ""
5206
 
5207
- #: includes/functions/wcj-functions-country.php:275
5208
  msgid "Macedonia"
5209
  msgstr ""
5210
 
5211
- #: includes/functions/wcj-functions-country.php:276
5212
  msgid "Madagascar"
5213
  msgstr ""
5214
 
5215
- #: includes/functions/wcj-functions-country.php:277
5216
  msgid "Malawi"
5217
  msgstr ""
5218
 
5219
- #: includes/functions/wcj-functions-country.php:278
5220
  msgid "Malaysia"
5221
  msgstr ""
5222
 
5223
- #: includes/functions/wcj-functions-country.php:279
5224
  msgid "Maldives"
5225
  msgstr ""
5226
 
5227
- #: includes/functions/wcj-functions-country.php:280
5228
  msgid "Mali"
5229
  msgstr ""
5230
 
5231
- #: includes/functions/wcj-functions-country.php:281
5232
  msgid "Malta"
5233
  msgstr ""
5234
 
5235
- #: includes/functions/wcj-functions-country.php:282
5236
  msgid "Marshall Islands"
5237
  msgstr ""
5238
 
5239
- #: includes/functions/wcj-functions-country.php:283
5240
  msgid "Martinique"
5241
  msgstr ""
5242
 
5243
- #: includes/functions/wcj-functions-country.php:284
5244
  msgid "Mauritania"
5245
  msgstr ""
5246
 
5247
- #: includes/functions/wcj-functions-country.php:285
5248
  msgid "Mauritius"
5249
  msgstr ""
5250
 
5251
- #: includes/functions/wcj-functions-country.php:286
5252
  msgid "Mayotte"
5253
  msgstr ""
5254
 
5255
- #: includes/functions/wcj-functions-country.php:287
5256
  msgid "Mexico"
5257
  msgstr ""
5258
 
5259
- #: includes/functions/wcj-functions-country.php:288
5260
  msgid "Micronesia"
5261
  msgstr ""
5262
 
5263
- #: includes/functions/wcj-functions-country.php:289
5264
  msgid "Moldova"
5265
  msgstr ""
5266
 
5267
- #: includes/functions/wcj-functions-country.php:290
5268
  msgid "Monaco"
5269
  msgstr ""
5270
 
5271
- #: includes/functions/wcj-functions-country.php:291
5272
  msgid "Mongolia"
5273
  msgstr ""
5274
 
5275
- #: includes/functions/wcj-functions-country.php:292
5276
  msgid "Montenegro"
5277
  msgstr ""
5278
 
5279
- #: includes/functions/wcj-functions-country.php:293
5280
  msgid "Montserrat"
5281
  msgstr ""
5282
 
5283
- #: includes/functions/wcj-functions-country.php:294
5284
  msgid "Morocco"
5285
  msgstr ""
5286
 
5287
- #: includes/functions/wcj-functions-country.php:295
5288
  msgid "Mozambique"
5289
  msgstr ""
5290
 
5291
- #: includes/functions/wcj-functions-country.php:296
5292
  msgid "Myanmar"
5293
  msgstr ""
5294
 
5295
- #: includes/functions/wcj-functions-country.php:297
5296
  msgid "Namibia"
5297
  msgstr ""
5298
 
5299
- #: includes/functions/wcj-functions-country.php:298
5300
  msgid "Nauru"
5301
  msgstr ""
5302
 
5303
- #: includes/functions/wcj-functions-country.php:299
5304
  msgid "Nepal"
5305
  msgstr ""
5306
 
5307
- #: includes/functions/wcj-functions-country.php:300
5308
  msgid "Netherlands"
5309
  msgstr ""
5310
 
5311
- #: includes/functions/wcj-functions-country.php:301
5312
  msgid "Netherlands Antilles"
5313
  msgstr ""
5314
 
5315
- #: includes/functions/wcj-functions-country.php:302
5316
  msgid "New Caledonia"
5317
  msgstr ""
5318
 
5319
- #: includes/functions/wcj-functions-country.php:303
5320
  msgid "New Zealand"
5321
  msgstr ""
5322
 
5323
- #: includes/functions/wcj-functions-country.php:304
5324
  msgid "Nicaragua"
5325
  msgstr ""
5326
 
5327
- #: includes/functions/wcj-functions-country.php:305
5328
  msgid "Niger"
5329
  msgstr ""
5330
 
5331
- #: includes/functions/wcj-functions-country.php:306
5332
  msgid "Nigeria"
5333
  msgstr ""
5334
 
5335
- #: includes/functions/wcj-functions-country.php:307
5336
  msgid "Niue"
5337
  msgstr ""
5338
 
5339
- #: includes/functions/wcj-functions-country.php:308
5340
  msgid "Norfolk Island"
5341
  msgstr ""
5342
 
5343
- #: includes/functions/wcj-functions-country.php:309
5344
  msgid "North Korea"
5345
  msgstr ""
5346
 
5347
- #: includes/functions/wcj-functions-country.php:310
5348
  msgid "Norway"
5349
  msgstr ""
5350
 
5351
- #: includes/functions/wcj-functions-country.php:311
5352
  msgid "Oman"
5353
  msgstr ""
5354
 
5355
- #: includes/functions/wcj-functions-country.php:312
5356
  msgid "Pakistan"
5357
  msgstr ""
5358
 
5359
- #: includes/functions/wcj-functions-country.php:313
5360
  msgid "Palestinian Territory"
5361
  msgstr ""
5362
 
5363
- #: includes/functions/wcj-functions-country.php:314
5364
  msgid "Panama"
5365
  msgstr ""
5366
 
5367
- #: includes/functions/wcj-functions-country.php:315
5368
  msgid "Papua New Guinea"
5369
  msgstr ""
5370
 
5371
- #: includes/functions/wcj-functions-country.php:316
5372
  msgid "Paraguay"
5373
  msgstr ""
5374
 
5375
- #: includes/functions/wcj-functions-country.php:317
5376
  msgid "Peru"
5377
  msgstr ""
5378
 
5379
- #: includes/functions/wcj-functions-country.php:318
5380
  msgid "Philippines"
5381
  msgstr ""
5382
 
5383
- #: includes/functions/wcj-functions-country.php:319
5384
  msgid "Pitcairn"
5385
  msgstr ""
5386
 
5387
- #: includes/functions/wcj-functions-country.php:320
5388
  msgid "Poland"
5389
  msgstr ""
5390
 
5391
- #: includes/functions/wcj-functions-country.php:321
5392
  msgid "Portugal"
5393
  msgstr ""
5394
 
5395
- #: includes/functions/wcj-functions-country.php:322
5396
  msgid "Qatar"
5397
  msgstr ""
5398
 
5399
- #: includes/functions/wcj-functions-country.php:323
5400
  msgid "Reunion"
5401
  msgstr ""
5402
 
5403
- #: includes/functions/wcj-functions-country.php:324
5404
  msgid "Romania"
5405
  msgstr ""
5406
 
5407
- #: includes/functions/wcj-functions-country.php:325
5408
  msgid "Russia"
5409
  msgstr ""
5410
 
5411
- #: includes/functions/wcj-functions-country.php:326
5412
  msgid "Rwanda"
5413
  msgstr ""
5414
 
5415
- #: includes/functions/wcj-functions-country.php:327
5416
  msgid "Saint Barth&eacute;lemy"
5417
  msgstr ""
5418
 
5419
- #: includes/functions/wcj-functions-country.php:328
5420
  msgid "Saint Helena"
5421
  msgstr ""
5422
 
5423
- #: includes/functions/wcj-functions-country.php:329
5424
  msgid "Saint Kitts and Nevis"
5425
  msgstr ""
5426
 
5427
- #: includes/functions/wcj-functions-country.php:330
5428
  msgid "Saint Lucia"
5429
  msgstr ""
5430
 
5431
- #: includes/functions/wcj-functions-country.php:331
5432
  msgid "Saint Martin (French part)"
5433
  msgstr ""
5434
 
5435
- #: includes/functions/wcj-functions-country.php:332
5436
  msgid "Saint Martin (Dutch part)"
5437
  msgstr ""
5438
 
5439
- #: includes/functions/wcj-functions-country.php:333
5440
  msgid "Saint Pierre and Miquelon"
5441
  msgstr ""
5442
 
5443
- #: includes/functions/wcj-functions-country.php:334
5444
  msgid "Saint Vincent and the Grenadines"
5445
  msgstr ""
5446
 
5447
- #: includes/functions/wcj-functions-country.php:335
5448
  msgid "San Marino"
5449
  msgstr ""
5450
 
5451
- #: includes/functions/wcj-functions-country.php:336
5452
  msgid "S&atilde;o Tom&eacute; and Pr&iacute;ncipe"
5453
  msgstr ""
5454
 
5455
- #: includes/functions/wcj-functions-country.php:337
5456
  msgid "Saudi Arabia"
5457
  msgstr ""
5458
 
5459
- #: includes/functions/wcj-functions-country.php:338
5460
  msgid "Senegal"
5461
  msgstr ""
5462
 
5463
- #: includes/functions/wcj-functions-country.php:339
5464
  msgid "Serbia"
5465
  msgstr ""
5466
 
5467
- #: includes/functions/wcj-functions-country.php:340
5468
  msgid "Seychelles"
5469
  msgstr ""
5470
 
5471
- #: includes/functions/wcj-functions-country.php:341
5472
  msgid "Sierra Leone"
5473
  msgstr ""
5474
 
5475
- #: includes/functions/wcj-functions-country.php:342
5476
  msgid "Singapore"
5477
  msgstr ""
5478
 
5479
- #: includes/functions/wcj-functions-country.php:343
5480
  msgid "Slovakia"
5481
  msgstr ""
5482
 
5483
- #: includes/functions/wcj-functions-country.php:344
5484
  msgid "Slovenia"
5485
  msgstr ""
5486
 
5487
- #: includes/functions/wcj-functions-country.php:345
5488
  msgid "Solomon Islands"
5489
  msgstr ""
5490
 
5491
- #: includes/functions/wcj-functions-country.php:346
5492
  msgid "Somalia"
5493
  msgstr ""
5494
 
5495
- #: includes/functions/wcj-functions-country.php:347
5496
  msgid "South Africa"
5497
  msgstr ""
5498
 
5499
- #: includes/functions/wcj-functions-country.php:348
5500
  msgid "South Georgia/Sandwich Islands"
5501
  msgstr ""
5502
 
5503
- #: includes/functions/wcj-functions-country.php:349
5504
  msgid "South Korea"
5505
  msgstr ""
5506
 
5507
- #: includes/functions/wcj-functions-country.php:350
5508
  msgid "South Sudan"
5509
  msgstr ""
5510
 
5511
- #: includes/functions/wcj-functions-country.php:351
5512
  msgid "Spain"
5513
  msgstr ""
5514
 
5515
- #: includes/functions/wcj-functions-country.php:352
5516
  msgid "Sri Lanka"
5517
  msgstr ""
5518
 
5519
- #: includes/functions/wcj-functions-country.php:353
5520
  msgid "Sudan"
5521
  msgstr ""
5522
 
5523
- #: includes/functions/wcj-functions-country.php:354
5524
  msgid "Suriname"
5525
  msgstr ""
5526
 
5527
- #: includes/functions/wcj-functions-country.php:355
5528
  msgid "Svalbard and Jan Mayen"
5529
  msgstr ""
5530
 
5531
- #: includes/functions/wcj-functions-country.php:356
5532
  msgid "Swaziland"
5533
  msgstr ""
5534
 
5535
- #: includes/functions/wcj-functions-country.php:357
5536
  msgid "Sweden"
5537
  msgstr ""
5538
 
5539
- #: includes/functions/wcj-functions-country.php:358
5540
  msgid "Switzerland"
5541
  msgstr ""
5542
 
5543
- #: includes/functions/wcj-functions-country.php:359
5544
  msgid "Syria"
5545
  msgstr ""
5546
 
5547
- #: includes/functions/wcj-functions-country.php:360
5548
  msgid "Taiwan"
5549
  msgstr ""
5550
 
5551
- #: includes/functions/wcj-functions-country.php:361
5552
  msgid "Tajikistan"
5553
  msgstr ""
5554
 
5555
- #: includes/functions/wcj-functions-country.php:362
5556
  msgid "Tanzania"
5557
  msgstr ""
5558
 
5559
- #: includes/functions/wcj-functions-country.php:363
5560
  msgid "Thailand"
5561
  msgstr ""
5562
 
5563
- #: includes/functions/wcj-functions-country.php:364
5564
  msgid "Timor-Leste"
5565
  msgstr ""
5566
 
5567
- #: includes/functions/wcj-functions-country.php:365
5568
  msgid "Togo"
5569
  msgstr ""
5570
 
5571
- #: includes/functions/wcj-functions-country.php:366
5572
  msgid "Tokelau"
5573
  msgstr ""
5574
 
5575
- #: includes/functions/wcj-functions-country.php:367
5576
  msgid "Tonga"
5577
  msgstr ""
5578
 
5579
- #: includes/functions/wcj-functions-country.php:368
5580
  msgid "Trinidad and Tobago"
5581
  msgstr ""
5582
 
5583
- #: includes/functions/wcj-functions-country.php:369
5584
  msgid "Tunisia"
5585
  msgstr ""
5586
 
5587
- #: includes/functions/wcj-functions-country.php:370
5588
  msgid "Turkey"
5589
  msgstr ""
5590
 
5591
- #: includes/functions/wcj-functions-country.php:371
5592
  msgid "Turkmenistan"
5593
  msgstr ""
5594
 
5595
- #: includes/functions/wcj-functions-country.php:372
5596
  msgid "Turks and Caicos Islands"
5597
  msgstr ""
5598
 
5599
- #: includes/functions/wcj-functions-country.php:373
5600
  msgid "Tuvalu"
5601
  msgstr ""
5602
 
5603
- #: includes/functions/wcj-functions-country.php:374
5604
  msgid "Uganda"
5605
  msgstr ""
5606
 
5607
- #: includes/functions/wcj-functions-country.php:375
5608
  msgid "Ukraine"
5609
  msgstr ""
5610
 
5611
- #: includes/functions/wcj-functions-country.php:376
5612
  msgid "United Arab Emirates"
5613
  msgstr ""
5614
 
5615
- #: includes/functions/wcj-functions-country.php:377
5616
  msgid "United Kingdom (UK)"
5617
  msgstr ""
5618
 
5619
- #: includes/functions/wcj-functions-country.php:378
5620
  msgid "United States (US)"
5621
  msgstr ""
5622
 
5623
- #: includes/functions/wcj-functions-country.php:379
5624
  msgid "Uruguay"
5625
  msgstr ""
5626
 
5627
- #: includes/functions/wcj-functions-country.php:380
5628
  msgid "Uzbekistan"
5629
  msgstr ""
5630
 
5631
- #: includes/functions/wcj-functions-country.php:381
5632
  msgid "Vanuatu"
5633
  msgstr ""
5634
 
5635
- #: includes/functions/wcj-functions-country.php:382
5636
  msgid "Vatican"
5637
  msgstr ""
5638
 
5639
- #: includes/functions/wcj-functions-country.php:383
5640
  msgid "Venezuela"
5641
  msgstr ""
5642
 
5643
- #: includes/functions/wcj-functions-country.php:384
5644
  msgid "Vietnam"
5645
  msgstr ""
5646
 
5647
- #: includes/functions/wcj-functions-country.php:385
5648
  msgid "Wallis and Futuna"
5649
  msgstr ""
5650
 
5651
- #: includes/functions/wcj-functions-country.php:386
5652
  msgid "Western Sahara"
5653
  msgstr ""
5654
 
5655
- #: includes/functions/wcj-functions-country.php:387
5656
  msgid "Western Samoa"
5657
  msgstr ""
5658
 
5659
- #: includes/functions/wcj-functions-country.php:388
5660
  msgid "Yemen"
5661
  msgstr ""
5662
 
5663
- #: includes/functions/wcj-functions-country.php:389
5664
  msgid "Zambia"
5665
  msgstr ""
5666
 
5667
- #: includes/functions/wcj-functions-country.php:390
5668
  msgid "Zimbabwe"
5669
  msgstr ""
5670
 
5671
- #: includes/functions/wcj-functions-country.php:391
5672
  msgid "European Union"
5673
  msgstr ""
5674
 
@@ -5746,772 +5910,772 @@ msgstr ""
5746
  msgid "Once a minute"
5747
  msgstr ""
5748
 
5749
- #: includes/functions/wcj-functions-currencies.php:17
5750
  msgid "United Arab Emirates Dirham"
5751
  msgstr ""
5752
 
5753
- #: includes/functions/wcj-functions-currencies.php:18
5754
  msgid "Afghan afghani"
5755
  msgstr ""
5756
 
5757
- #: includes/functions/wcj-functions-currencies.php:19
5758
  msgid "Albanian lek"
5759
  msgstr ""
5760
 
5761
- #: includes/functions/wcj-functions-currencies.php:20
5762
  msgid "Armenian dram"
5763
  msgstr ""
5764
 
5765
- #: includes/functions/wcj-functions-currencies.php:21
5766
  msgid "Netherlands Antillean gulden"
5767
  msgstr ""
5768
 
5769
- #: includes/functions/wcj-functions-currencies.php:22
5770
  msgid "Angolan kwanza"
5771
  msgstr ""
5772
 
5773
- #: includes/functions/wcj-functions-currencies.php:23
5774
  msgid "Argentine Peso"
5775
  msgstr ""
5776
 
5777
- #: includes/functions/wcj-functions-currencies.php:24
5778
  msgid "Australian Dollars"
5779
  msgstr ""
5780
 
5781
- #: includes/functions/wcj-functions-currencies.php:25
5782
  msgid "Aruban florin"
5783
  msgstr ""
5784
 
5785
- #: includes/functions/wcj-functions-currencies.php:26
5786
  msgid "Azerbaijani manat"
5787
  msgstr ""
5788
 
5789
- #: includes/functions/wcj-functions-currencies.php:27
5790
  msgid "Bosnia and Herzegovina konvertibilna marka"
5791
  msgstr ""
5792
 
5793
- #: includes/functions/wcj-functions-currencies.php:28
5794
  msgid "Barbadian dollar"
5795
  msgstr ""
5796
 
5797
- #: includes/functions/wcj-functions-currencies.php:29
5798
  msgid "Bangladeshi Taka"
5799
  msgstr ""
5800
 
5801
- #: includes/functions/wcj-functions-currencies.php:30
5802
  msgid "Bulgarian Lev"
5803
  msgstr ""
5804
 
5805
- #: includes/functions/wcj-functions-currencies.php:31
5806
  msgid "Bahraini dinar"
5807
  msgstr ""
5808
 
5809
- #: includes/functions/wcj-functions-currencies.php:32
5810
  msgid "Burundi franc"
5811
  msgstr ""
5812
 
5813
- #: includes/functions/wcj-functions-currencies.php:33
5814
  msgid "Belarusian ruble"
5815
  msgstr ""
5816
 
5817
- #: includes/functions/wcj-functions-currencies.php:34
5818
  msgid "Brunei dollar"
5819
  msgstr ""
5820
 
5821
- #: includes/functions/wcj-functions-currencies.php:35
5822
  msgid "Bolivian boliviano"
5823
  msgstr ""
5824
 
5825
- #: includes/functions/wcj-functions-currencies.php:36
5826
  msgid "Brazilian Real"
5827
  msgstr ""
5828
 
5829
- #: includes/functions/wcj-functions-currencies.php:37
5830
  msgid "Bahamian dollar"
5831
  msgstr ""
5832
 
5833
- #: includes/functions/wcj-functions-currencies.php:38
5834
  msgid "Bhutanese ngultrum"
5835
  msgstr ""
5836
 
5837
- #: includes/functions/wcj-functions-currencies.php:39
5838
  msgid "Botswana pula"
5839
  msgstr ""
5840
 
5841
- #: includes/functions/wcj-functions-currencies.php:40
5842
  msgid "Belize dollar"
5843
  msgstr ""
5844
 
5845
- #: includes/functions/wcj-functions-currencies.php:41
5846
  msgid "Canadian Dollars"
5847
  msgstr ""
5848
 
5849
- #: includes/functions/wcj-functions-currencies.php:42
5850
  msgid "Congolese franc"
5851
  msgstr ""
5852
 
5853
- #: includes/functions/wcj-functions-currencies.php:43
5854
  msgid "Swiss Franc"
5855
  msgstr ""
5856
 
5857
- #: includes/functions/wcj-functions-currencies.php:44
5858
  msgid "Chilean Peso"
5859
  msgstr ""
5860
 
5861
- #: includes/functions/wcj-functions-currencies.php:45
5862
  msgid "Chinese Yuan"
5863
  msgstr ""
5864
 
5865
- #: includes/functions/wcj-functions-currencies.php:46
5866
  msgid "Colombian Peso"
5867
  msgstr ""
5868
 
5869
- #: includes/functions/wcj-functions-currencies.php:47
5870
  msgid "Costa Rican colon"
5871
  msgstr ""
5872
 
5873
- #: includes/functions/wcj-functions-currencies.php:48
5874
  msgid "Cuban peso"
5875
  msgstr ""
5876
 
5877
- #: includes/functions/wcj-functions-currencies.php:49
5878
  msgid "Cape Verdean escudo"
5879
  msgstr ""
5880
 
5881
- #: includes/functions/wcj-functions-currencies.php:50
5882
  msgid "Czech Koruna"
5883
  msgstr ""
5884
 
5885
- #: includes/functions/wcj-functions-currencies.php:51
5886
  msgid "Djiboutian franc"
5887
  msgstr ""
5888
 
5889
- #: includes/functions/wcj-functions-currencies.php:52
5890
  msgid "Danish Krone"
5891
  msgstr ""
5892
 
5893
- #: includes/functions/wcj-functions-currencies.php:53
5894
  msgid "Dominican Peso"
5895
  msgstr ""
5896
 
5897
- #: includes/functions/wcj-functions-currencies.php:54
5898
  msgid "Algerian dinar"
5899
  msgstr ""
5900
 
5901
- #: includes/functions/wcj-functions-currencies.php:55
5902
  msgid "Estonian kroon"
5903
  msgstr ""
5904
 
5905
- #: includes/functions/wcj-functions-currencies.php:56
5906
  msgid "Egyptian Pound"
5907
  msgstr ""
5908
 
5909
- #: includes/functions/wcj-functions-currencies.php:57
5910
  msgid "Eritrean nakfa"
5911
  msgstr ""
5912
 
5913
- #: includes/functions/wcj-functions-currencies.php:58
5914
  msgid "Ethiopian birr"
5915
  msgstr ""
5916
 
5917
- #: includes/functions/wcj-functions-currencies.php:59
5918
  msgid "Euros"
5919
  msgstr ""
5920
 
5921
- #: includes/functions/wcj-functions-currencies.php:60
5922
  msgid "Fijian dollar"
5923
  msgstr ""
5924
 
5925
- #: includes/functions/wcj-functions-currencies.php:61
5926
  msgid "Falkland Islands pound"
5927
  msgstr ""
5928
 
5929
- #: includes/functions/wcj-functions-currencies.php:62
5930
  msgid "Pounds Sterling"
5931
  msgstr ""
5932
 
5933
- #: includes/functions/wcj-functions-currencies.php:63
5934
  msgid "Georgian lari"
5935
  msgstr ""
5936
 
5937
- #: includes/functions/wcj-functions-currencies.php:64
5938
  msgid "Ghanaian cedi"
5939
  msgstr ""
5940
 
5941
- #: includes/functions/wcj-functions-currencies.php:65
5942
  msgid "Gibraltar pound"
5943
  msgstr ""
5944
 
5945
- #: includes/functions/wcj-functions-currencies.php:66
5946
  msgid "Guyanese dollar"
5947
  msgstr ""
5948
 
5949
- #: includes/functions/wcj-functions-currencies.php:67
5950
  msgid "Gambian dalasi"
5951
  msgstr ""
5952
 
5953
- #: includes/functions/wcj-functions-currencies.php:68
5954
  msgid "Guinean franc"
5955
  msgstr ""
5956
 
5957
- #: includes/functions/wcj-functions-currencies.php:69
5958
- #: includes/functions/wcj-functions-currencies.php:172
5959
  msgid "Central African CFA franc"
5960
  msgstr ""
5961
 
5962
- #: includes/functions/wcj-functions-currencies.php:70
5963
  msgid "Guatemalan quetzal"
5964
  msgstr ""
5965
 
5966
- #: includes/functions/wcj-functions-currencies.php:71
5967
  msgid "Hong Kong Dollar"
5968
  msgstr ""
5969
 
5970
- #: includes/functions/wcj-functions-currencies.php:72
5971
  msgid "Honduran lempira"
5972
  msgstr ""
5973
 
5974
- #: includes/functions/wcj-functions-currencies.php:73
5975
  msgid "Croatia kuna"
5976
  msgstr ""
5977
 
5978
- #: includes/functions/wcj-functions-currencies.php:74
5979
  msgid "Haitian gourde"
5980
  msgstr ""
5981
 
5982
- #: includes/functions/wcj-functions-currencies.php:75
5983
  msgid "Hungarian Forint"
5984
  msgstr ""
5985
 
5986
- #: includes/functions/wcj-functions-currencies.php:76
5987
  msgid "Indonesia Rupiah"
5988
  msgstr ""
5989
 
5990
- #: includes/functions/wcj-functions-currencies.php:77
5991
  msgid "Israeli Shekel"
5992
  msgstr ""
5993
 
5994
- #: includes/functions/wcj-functions-currencies.php:78
5995
  msgid "Indian Rupee"
5996
  msgstr ""
5997
 
5998
- #: includes/functions/wcj-functions-currencies.php:79
5999
  msgid "Iraqi dinar"
6000
  msgstr ""
6001
 
6002
- #: includes/functions/wcj-functions-currencies.php:80
6003
  msgid "Iranian rial"
6004
  msgstr ""
6005
 
6006
- #: includes/functions/wcj-functions-currencies.php:81
6007
  msgid "Icelandic krona"
6008
  msgstr ""
6009
 
6010
- #: includes/functions/wcj-functions-currencies.php:82
6011
  msgid "Yemeni rial"
6012
  msgstr ""
6013
 
6014
- #: includes/functions/wcj-functions-currencies.php:83
6015
  msgid "Jamaican dollar"
6016
  msgstr ""
6017
 
6018
- #: includes/functions/wcj-functions-currencies.php:84
6019
  msgid "Jordanian dinar"
6020
  msgstr ""
6021
 
6022
- #: includes/functions/wcj-functions-currencies.php:85
6023
  msgid "Japanese Yen"
6024
  msgstr ""
6025
 
6026
- #: includes/functions/wcj-functions-currencies.php:86
6027
  msgid "Kenyan shilling"
6028
  msgstr ""
6029
 
6030
- #: includes/functions/wcj-functions-currencies.php:87
6031
  msgid "Kyrgyzstani som"
6032
  msgstr ""
6033
 
6034
- #: includes/functions/wcj-functions-currencies.php:88
6035
  msgid "Cambodian riel"
6036
  msgstr ""
6037
 
6038
- #: includes/functions/wcj-functions-currencies.php:89
6039
  msgid "Lao kip"
6040
  msgstr ""
6041
 
6042
- #: includes/functions/wcj-functions-currencies.php:90
6043
  msgid "Cayman Islands dollar"
6044
  msgstr ""
6045
 
6046
- #: includes/functions/wcj-functions-currencies.php:91
6047
  msgid "Comorian franc"
6048
  msgstr ""
6049
 
6050
- #: includes/functions/wcj-functions-currencies.php:92
6051
  msgid "North Korean won"
6052
  msgstr ""
6053
 
6054
- #: includes/functions/wcj-functions-currencies.php:93
6055
  msgid "South Korean Won"
6056
  msgstr ""
6057
 
6058
- #: includes/functions/wcj-functions-currencies.php:94
6059
  msgid "Kuwaiti dinar"
6060
  msgstr ""
6061
 
6062
- #: includes/functions/wcj-functions-currencies.php:95
6063
  msgid "Kazakhstani tenge"
6064
  msgstr ""
6065
 
6066
- #: includes/functions/wcj-functions-currencies.php:96
6067
  msgid "Lao Kip"
6068
  msgstr ""
6069
 
6070
- #: includes/functions/wcj-functions-currencies.php:97
6071
  msgid "Lebanese lira"
6072
  msgstr ""
6073
 
6074
- #: includes/functions/wcj-functions-currencies.php:98
6075
  msgid "Libyan dinar"
6076
  msgstr ""
6077
 
6078
- #: includes/functions/wcj-functions-currencies.php:99
6079
  msgid "Sri Lankan rupee"
6080
  msgstr ""
6081
 
6082
- #: includes/functions/wcj-functions-currencies.php:100
6083
  msgid "Liberian dollar"
6084
  msgstr ""
6085
 
6086
- #: includes/functions/wcj-functions-currencies.php:101
6087
  msgid "Lesotho loti"
6088
  msgstr ""
6089
 
6090
- #: includes/functions/wcj-functions-currencies.php:102
6091
  msgid "Lithuanian litas"
6092
  msgstr ""
6093
 
6094
- #: includes/functions/wcj-functions-currencies.php:103
6095
  msgid "Latvian lats"
6096
  msgstr ""
6097
 
6098
- #: includes/functions/wcj-functions-currencies.php:104
6099
  msgid "Moroccan dirham"
6100
  msgstr ""
6101
 
6102
- #: includes/functions/wcj-functions-currencies.php:105
6103
  msgid "Moldovan leu"
6104
  msgstr ""
6105
 
6106
- #: includes/functions/wcj-functions-currencies.php:106
6107
  msgid "Malagasy ariary"
6108
  msgstr ""
6109
 
6110
- #: includes/functions/wcj-functions-currencies.php:107
6111
  msgid "Malaysian ringgit"
6112
  msgstr ""
6113
 
6114
- #: includes/functions/wcj-functions-currencies.php:108
6115
  msgid "Macedonian denar"
6116
  msgstr ""
6117
 
6118
- #: includes/functions/wcj-functions-currencies.php:109
6119
  msgid "Myanma kyat"
6120
  msgstr ""
6121
 
6122
- #: includes/functions/wcj-functions-currencies.php:110
6123
  msgid "Mongolian tugrik"
6124
  msgstr ""
6125
 
6126
- #: includes/functions/wcj-functions-currencies.php:111
6127
  msgid "Macanese pataca"
6128
  msgstr ""
6129
 
6130
- #: includes/functions/wcj-functions-currencies.php:112
6131
  msgid "Mauritanian ouguiya"
6132
  msgstr ""
6133
 
6134
- #: includes/functions/wcj-functions-currencies.php:113
6135
  msgid "Mauritian rupee"
6136
  msgstr ""
6137
 
6138
- #: includes/functions/wcj-functions-currencies.php:114
6139
  msgid "Maldivian rufiyaa"
6140
  msgstr ""
6141
 
6142
- #: includes/functions/wcj-functions-currencies.php:115
6143
  msgid "Malawian kwacha"
6144
  msgstr ""
6145
 
6146
- #: includes/functions/wcj-functions-currencies.php:116
6147
  msgid "Mexican Peso"
6148
  msgstr ""
6149
 
6150
- #: includes/functions/wcj-functions-currencies.php:117
6151
  msgid "Malaysian Ringgits"
6152
  msgstr ""
6153
 
6154
- #: includes/functions/wcj-functions-currencies.php:118
6155
  msgid "Mozambican metical"
6156
  msgstr ""
6157
 
6158
- #: includes/functions/wcj-functions-currencies.php:119
6159
  msgid "Namibian dollar"
6160
  msgstr ""
6161
 
6162
- #: includes/functions/wcj-functions-currencies.php:120
6163
  msgid "Nigerian Naira"
6164
  msgstr ""
6165
 
6166
- #: includes/functions/wcj-functions-currencies.php:121
6167
  msgid "Nicaraguan cordoba"
6168
  msgstr ""
6169
 
6170
- #: includes/functions/wcj-functions-currencies.php:122
6171
  msgid "Norwegian Krone"
6172
  msgstr ""
6173
 
6174
- #: includes/functions/wcj-functions-currencies.php:123
6175
  msgid "Nepali Rupee"
6176
  msgstr ""
6177
 
6178
- #: includes/functions/wcj-functions-currencies.php:124
6179
  msgid "New Zealand Dollar"
6180
  msgstr ""
6181
 
6182
- #: includes/functions/wcj-functions-currencies.php:125
6183
  msgid "Omani rial"
6184
  msgstr ""
6185
 
6186
- #: includes/functions/wcj-functions-currencies.php:126
6187
  msgid "Panamanian balboa"
6188
  msgstr ""
6189
 
6190
- #: includes/functions/wcj-functions-currencies.php:127
6191
  msgid "Peruvian nuevo sol"
6192
  msgstr ""
6193
 
6194
- #: includes/functions/wcj-functions-currencies.php:128
6195
  msgid "Papua New Guinean kina"
6196
  msgstr ""
6197
 
6198
- #: includes/functions/wcj-functions-currencies.php:129
6199
  msgid "Philippine Pesos"
6200
  msgstr ""
6201
 
6202
- #: includes/functions/wcj-functions-currencies.php:130
6203
  msgid "Paraguayan guarani"
6204
  msgstr ""
6205
 
6206
- #: includes/functions/wcj-functions-currencies.php:131
6207
  msgid "Pakistani Rupee"
6208
  msgstr ""
6209
 
6210
- #: includes/functions/wcj-functions-currencies.php:132
6211
  msgid "Polish Zloty"
6212
  msgstr ""
6213
 
6214
- #: includes/functions/wcj-functions-currencies.php:133
6215
  msgid "Paraguayan Guaran"
6216
  msgstr ""
6217
 
6218
- #: includes/functions/wcj-functions-currencies.php:134
6219
  msgid "Qatari riyal"
6220
  msgstr ""
6221
 
6222
- #: includes/functions/wcj-functions-currencies.php:135
6223
  msgid "Chinese renminbi"
6224
  msgstr ""
6225
 
6226
- #: includes/functions/wcj-functions-currencies.php:136
6227
  msgid "Romanian Leu"
6228
  msgstr ""
6229
 
6230
- #: includes/functions/wcj-functions-currencies.php:137
6231
  msgid "Serbian dinar"
6232
  msgstr ""
6233
 
6234
- #: includes/functions/wcj-functions-currencies.php:138
6235
  msgid "Russian Ruble"
6236
  msgstr ""
6237
 
6238
- #: includes/functions/wcj-functions-currencies.php:139
6239
  msgid "Rwandan franc"
6240
  msgstr ""
6241
 
6242
- #: includes/functions/wcj-functions-currencies.php:140
6243
  msgid "Saudi Riyal"
6244
  msgstr ""
6245
 
6246
- #: includes/functions/wcj-functions-currencies.php:141
6247
  msgid "Solomon Islands dollar"
6248
  msgstr ""
6249
 
6250
- #: includes/functions/wcj-functions-currencies.php:142
6251
  msgid "Seychellois rupee"
6252
  msgstr ""
6253
 
6254
- #: includes/functions/wcj-functions-currencies.php:143
6255
  msgid "Sudanese pound"
6256
  msgstr ""
6257
 
6258
- #: includes/functions/wcj-functions-currencies.php:144
6259
  msgid "Swedish Krona"
6260
  msgstr ""
6261
 
6262
- #: includes/functions/wcj-functions-currencies.php:145
6263
  msgid "Singapore Dollar"
6264
  msgstr ""
6265
 
6266
- #: includes/functions/wcj-functions-currencies.php:146
6267
  msgid "Saint Helena pound"
6268
  msgstr ""
6269
 
6270
- #: includes/functions/wcj-functions-currencies.php:147
6271
  msgid "Syrian pound"
6272
  msgstr ""
6273
 
6274
- #: includes/functions/wcj-functions-currencies.php:148
6275
  msgid "Slovak koruna"
6276
  msgstr ""
6277
 
6278
- #: includes/functions/wcj-functions-currencies.php:149
6279
  msgid "Sierra Leonean leone"
6280
  msgstr ""
6281
 
6282
- #: includes/functions/wcj-functions-currencies.php:150
6283
  msgid "Somali shilling"
6284
  msgstr ""
6285
 
6286
- #: includes/functions/wcj-functions-currencies.php:151
6287
  msgid "Surinamese dollar"
6288
  msgstr ""
6289
 
6290
- #: includes/functions/wcj-functions-currencies.php:152
6291
  msgid "Sao Tome and Principe dobra"
6292
  msgstr ""
6293
 
6294
- #: includes/functions/wcj-functions-currencies.php:153
6295
  msgid "Swazi lilangeni"
6296
  msgstr ""
6297
 
6298
- #: includes/functions/wcj-functions-currencies.php:154
6299
  msgid "Thai Baht"
6300
  msgstr ""
6301
 
6302
- #: includes/functions/wcj-functions-currencies.php:155
6303
  msgid "Tajikistani somoni"
6304
  msgstr ""
6305
 
6306
- #: includes/functions/wcj-functions-currencies.php:156
6307
  msgid "Turkmen manat"
6308
  msgstr ""
6309
 
6310
- #: includes/functions/wcj-functions-currencies.php:157
6311
  msgid "Tunisian dinar"
6312
  msgstr ""
6313
 
6314
- #: includes/functions/wcj-functions-currencies.php:158
6315
  msgid "Paanga"
6316
  msgstr ""
6317
 
6318
- #: includes/functions/wcj-functions-currencies.php:159
6319
  msgid "Turkish Lira"
6320
  msgstr ""
6321
 
6322
- #: includes/functions/wcj-functions-currencies.php:160
6323
  msgid "Trinidad and Tobago dollar"
6324
  msgstr ""
6325
 
6326
- #: includes/functions/wcj-functions-currencies.php:161
6327
  msgid "Taiwan New Dollars"
6328
  msgstr ""
6329
 
6330
- #: includes/functions/wcj-functions-currencies.php:162
6331
  msgid "Tanzanian shilling"
6332
  msgstr ""
6333
 
6334
- #: includes/functions/wcj-functions-currencies.php:163
6335
  msgid "Ukrainian Hryvnia"
6336
  msgstr ""
6337
 
6338
- #: includes/functions/wcj-functions-currencies.php:164
6339
  msgid "Ugandan shilling"
6340
  msgstr ""
6341
 
6342
- #: includes/functions/wcj-functions-currencies.php:165
6343
  msgid "Uruguayan peso"
6344
  msgstr ""
6345
 
6346
- #: includes/functions/wcj-functions-currencies.php:166
6347
  msgid "US Dollars"
6348
  msgstr ""
6349
 
6350
- #: includes/functions/wcj-functions-currencies.php:167
6351
  msgid "Uzbekistani som"
6352
  msgstr ""
6353
 
6354
- #: includes/functions/wcj-functions-currencies.php:168
6355
  msgid "Venezuelan bolivar"
6356
  msgstr ""
6357
 
6358
- #: includes/functions/wcj-functions-currencies.php:169
6359
  msgid "Vietnamese Dong"
6360
  msgstr ""
6361
 
6362
- #: includes/functions/wcj-functions-currencies.php:170
6363
  msgid "Vanuatu vatu"
6364
  msgstr ""
6365
 
6366
- #: includes/functions/wcj-functions-currencies.php:171
6367
  msgid "Samoan tala"
6368
  msgstr ""
6369
 
6370
- #: includes/functions/wcj-functions-currencies.php:173
6371
  msgid "East Caribbean dollar"
6372
  msgstr ""
6373
 
6374
- #: includes/functions/wcj-functions-currencies.php:174
6375
  msgid "Special Drawing Rights"
6376
  msgstr ""
6377
 
6378
- #: includes/functions/wcj-functions-currencies.php:175
6379
  msgid "West African CFA franc"
6380
  msgstr ""
6381
 
6382
- #: includes/functions/wcj-functions-currencies.php:176
6383
  msgid "CFP franc"
6384
  msgstr ""
6385
 
6386
- #: includes/functions/wcj-functions-currencies.php:177
6387
  msgid "South African rand"
6388
  msgstr ""
6389
 
6390
- #: includes/functions/wcj-functions-currencies.php:178
6391
  msgid "Zambian kwacha"
6392
  msgstr ""
6393
 
6394
- #: includes/functions/wcj-functions-currencies.php:179
6395
  msgid "Zimbabwean dollar"
6396
  msgstr ""
6397
 
6398
- #: includes/functions/wcj-functions-currencies.php:181
6399
  msgid "Auroracoin"
6400
  msgstr ""
6401
 
6402
- #: includes/functions/wcj-functions-currencies.php:182
6403
  msgid "BitConnect"
6404
  msgstr ""
6405
 
6406
- #: includes/functions/wcj-functions-currencies.php:183
6407
  msgid "Bitcoin Cash"
6408
  msgstr ""
6409
 
6410
- #: includes/functions/wcj-functions-currencies.php:184
6411
  msgid "Bitcoin"
6412
  msgstr ""
6413
 
6414
- #: includes/functions/wcj-functions-currencies.php:185
6415
  msgid "Coinye"
6416
  msgstr ""
6417
 
6418
- #: includes/functions/wcj-functions-currencies.php:186
6419
  msgid "DigitalNote"
6420
  msgstr ""
6421
 
6422
- #: includes/functions/wcj-functions-currencies.php:187
6423
  msgid "Emercoin"
6424
  msgstr ""
6425
 
6426
- #: includes/functions/wcj-functions-currencies.php:188
6427
  msgid "Ethereum Classic"
6428
  msgstr ""
6429
 
6430
- #: includes/functions/wcj-functions-currencies.php:189
6431
  msgid "Ethereum"
6432
  msgstr ""
6433
 
6434
- #: includes/functions/wcj-functions-currencies.php:190
6435
  msgid "Freemasoncoin"
6436
  msgstr ""
6437
 
6438
- #: includes/functions/wcj-functions-currencies.php:191
6439
  msgid "Gridcoin"
6440
  msgstr ""
6441
 
6442
- #: includes/functions/wcj-functions-currencies.php:192
6443
  msgid "IOTA"
6444
  msgstr ""
6445
 
6446
- #: includes/functions/wcj-functions-currencies.php:193
6447
  msgid "Litecoin"
6448
  msgstr ""
6449
 
6450
- #: includes/functions/wcj-functions-currencies.php:194
6451
  msgid "MazaCoin"
6452
  msgstr ""
6453
 
6454
- #: includes/functions/wcj-functions-currencies.php:195
6455
  msgid "Monero"
6456
  msgstr ""
6457
 
6458
- #: includes/functions/wcj-functions-currencies.php:196
6459
  msgid "Namecoin"
6460
  msgstr ""
6461
 
6462
- #: includes/functions/wcj-functions-currencies.php:197
6463
  msgid "NEM"
6464
  msgstr ""
6465
 
6466
- #: includes/functions/wcj-functions-currencies.php:198
6467
  msgid "Nxt"
6468
  msgstr ""
6469
 
6470
- #: includes/functions/wcj-functions-currencies.php:199
6471
  msgid "Omni"
6472
  msgstr ""
6473
 
6474
- #: includes/functions/wcj-functions-currencies.php:200
6475
  msgid "Peercoin"
6476
  msgstr ""
6477
 
6478
- #: includes/functions/wcj-functions-currencies.php:201
6479
  msgid "PotCoin"
6480
  msgstr ""
6481
 
6482
- #: includes/functions/wcj-functions-currencies.php:202
6483
  msgid "Primecoin"
6484
  msgstr ""
6485
 
6486
- #: includes/functions/wcj-functions-currencies.php:203
6487
  msgid "Ripple"
6488
  msgstr ""
6489
 
6490
- #: includes/functions/wcj-functions-currencies.php:204
6491
  msgid "SixEleven"
6492
  msgstr ""
6493
 
6494
- #: includes/functions/wcj-functions-currencies.php:205
6495
  msgid "Synereo AMP"
6496
  msgstr ""
6497
 
6498
- #: includes/functions/wcj-functions-currencies.php:206
6499
  msgid "Titcoin"
6500
  msgstr ""
6501
 
6502
- #: includes/functions/wcj-functions-currencies.php:207
6503
  msgid "Ubiq"
6504
  msgstr ""
6505
 
6506
- #: includes/functions/wcj-functions-currencies.php:208
6507
  msgid "Vertcoin"
6508
  msgstr ""
6509
 
6510
- #: includes/functions/wcj-functions-currencies.php:209
6511
  msgid "Zcash"
6512
  msgstr ""
6513
 
6514
- #: includes/functions/wcj-functions-currencies.php:211
6515
  msgid "myCred"
6516
  msgstr ""
6517
 
@@ -6523,6 +6687,10 @@ msgstr ""
6523
  msgid "European Central Bank (ECB)"
6524
  msgstr ""
6525
 
 
 
 
 
6526
  #: includes/functions/wcj-functions-exchange-rates.php:71
6527
  msgid "TCMB"
6528
  msgstr ""
@@ -6539,109 +6707,116 @@ msgstr ""
6539
  msgid "CoinMarketCap"
6540
  msgstr ""
6541
 
6542
- #: includes/functions/wcj-functions-general.php:508
6543
- #: includes/functions/wcj-functions-general.php:554
6544
- #: includes/settings/wcj-settings-left-to-free-shipping.php:141
6545
- msgid "You have Free delivery"
 
 
6546
  msgstr ""
6547
 
6548
- #: includes/functions/wcj-functions-general.php:575
6549
  msgid "Before cart"
6550
  msgstr ""
6551
 
6552
- #: includes/functions/wcj-functions-general.php:576
6553
  msgid "Before cart table"
6554
  msgstr ""
6555
 
6556
- #: includes/functions/wcj-functions-general.php:577
6557
  msgid "Before cart contents"
6558
  msgstr ""
6559
 
6560
- #: includes/functions/wcj-functions-general.php:578
6561
  msgid "Cart contents"
6562
  msgstr ""
6563
 
6564
- #: includes/functions/wcj-functions-general.php:579
6565
  msgid "Cart coupon"
6566
  msgstr ""
6567
 
6568
- #: includes/functions/wcj-functions-general.php:580
6569
  msgid "Cart actions"
6570
  msgstr ""
6571
 
6572
- #: includes/functions/wcj-functions-general.php:581
6573
  msgid "After cart contents"
6574
  msgstr ""
6575
 
6576
- #: includes/functions/wcj-functions-general.php:582
6577
  msgid "After cart table"
6578
  msgstr ""
6579
 
6580
- #: includes/functions/wcj-functions-general.php:583
6581
  msgid "Cart collaterals"
6582
  msgstr ""
6583
 
6584
- #: includes/functions/wcj-functions-general.php:584
6585
  msgid "After cart"
6586
  msgstr ""
6587
 
6588
- #: includes/functions/wcj-functions-general.php:586
6589
  msgid "Before cart totals"
6590
  msgstr ""
6591
 
6592
- #: includes/functions/wcj-functions-general.php:587
6593
  msgid "Cart totals: Before shipping"
6594
  msgstr ""
6595
 
6596
- #: includes/functions/wcj-functions-general.php:588
6597
  msgid "Cart totals: After shipping"
6598
  msgstr ""
6599
 
6600
- #: includes/functions/wcj-functions-general.php:589
6601
  msgid "Cart totals: Before order total"
6602
  msgstr ""
6603
 
6604
- #: includes/functions/wcj-functions-general.php:590
6605
  msgid "Cart totals: After order total"
6606
  msgstr ""
6607
 
6608
- #: includes/functions/wcj-functions-general.php:591
6609
  msgid "Proceed to checkout"
6610
  msgstr ""
6611
 
6612
- #: includes/functions/wcj-functions-general.php:592
6613
  msgid "After cart totals"
6614
  msgstr ""
6615
 
6616
- #: includes/functions/wcj-functions-general.php:594
6617
  msgid "Before shipping calculator"
6618
  msgstr ""
6619
 
6620
- #: includes/functions/wcj-functions-general.php:595
6621
  msgid "After shipping calculator"
6622
  msgstr ""
6623
 
6624
- #: includes/functions/wcj-functions-general.php:597
6625
  msgid "If cart is empty"
6626
  msgstr ""
6627
 
6628
- #: includes/functions/wcj-functions-invoicing.php:212
 
 
 
 
 
6629
  msgid "Invoice"
6630
  msgstr ""
6631
 
6632
- #: includes/functions/wcj-functions-invoicing.php:218
6633
  msgid "Proforma Invoice"
6634
  msgstr ""
6635
 
6636
- #: includes/functions/wcj-functions-invoicing.php:224
6637
  msgid "Packing Slip"
6638
  msgstr ""
6639
 
6640
- #: includes/functions/wcj-functions-invoicing.php:230
6641
  msgid "Credit Note"
6642
  msgstr ""
6643
 
6644
- #: includes/functions/wcj-functions-invoicing.php:240
6645
  msgid "Custom Document"
6646
  msgstr ""
6647
 
@@ -6679,57 +6854,67 @@ msgstr ""
6679
  msgid "Last Sale Order Status"
6680
  msgstr ""
6681
 
6682
- #: includes/functions/wcj-functions-reports.php:82
6683
  msgid "Last 14 days"
6684
  msgstr ""
6685
 
6686
- #: includes/functions/wcj-functions-reports.php:87
6687
  msgid "Last 30 days"
6688
  msgstr ""
6689
 
6690
- #: includes/functions/wcj-functions-reports.php:92
6691
  msgid "Last 3 months"
6692
  msgstr ""
6693
 
6694
- #: includes/functions/wcj-functions-reports.php:97
6695
  msgid "Last 6 months"
6696
  msgstr ""
6697
 
6698
- #: includes/functions/wcj-functions-reports.php:102
6699
  msgid "Last 12 months"
6700
  msgstr ""
6701
 
6702
- #: includes/functions/wcj-functions-reports.php:107
6703
  msgid "Last 24 months"
6704
  msgstr ""
6705
 
6706
- #: includes/functions/wcj-functions-reports.php:112
6707
  msgid "Last 36 months"
6708
  msgstr ""
6709
 
6710
- #: includes/functions/wcj-functions-reports.php:117
6711
  msgid "Same days last month"
6712
  msgstr ""
6713
 
6714
- #: includes/functions/wcj-functions-reports.php:122
6715
  msgid "Same days last year"
6716
  msgstr ""
6717
 
6718
- #: includes/functions/wcj-functions-reports.php:127
6719
  msgid "Last year"
6720
  msgstr ""
6721
 
6722
- #: includes/functions/wcj-functions-reports.php:132
6723
  msgid "Yesterday"
6724
  msgstr ""
6725
 
6726
- #: includes/functions/wcj-functions-reports.php:137
6727
  msgid "Today"
6728
  msgstr ""
6729
 
6730
- #: includes/functions/wcj-functions-users.php:121
6731
- #: includes/functions/wcj-functions-users.php:141
6732
- msgid "Guest"
 
 
 
 
 
 
 
 
 
 
6733
  msgstr ""
6734
 
6735
  #: includes/gateways/class-wc-gateway-wcj-custom.php:61
@@ -6786,7 +6971,7 @@ msgid ""
6786
  msgstr ""
6787
 
6788
  #: includes/gateways/class-wc-gateway-wcj-custom.php:108
6789
- #: includes/settings/wcj-settings-shipping-by-order-amount.php:36
6790
  msgid "Minimum order amount"
6791
  msgstr ""
6792
 
@@ -6797,7 +6982,7 @@ msgid ""
6797
  msgstr ""
6798
 
6799
  #: includes/gateways/class-wc-gateway-wcj-custom.php:117
6800
- #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:43
6801
  msgid "Enable for shipping methods"
6802
  msgstr ""
6803
 
@@ -6808,7 +6993,7 @@ msgid ""
6808
  msgstr ""
6809
 
6810
  #: includes/gateways/class-wc-gateway-wcj-custom.php:125
6811
- #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:50
6812
  msgid "Select shipping methods"
6813
  msgstr ""
6814
 
@@ -6868,29 +7053,29 @@ msgstr ""
6868
  msgid "Booster for WooCommerce: Custom Payment Gateway"
6869
  msgstr ""
6870
 
6871
- #: includes/input-fields/class-wcj-product-input-fields-core.php:110
6872
  msgid "Booster: Product Input Fields"
6873
  msgstr ""
6874
 
6875
- #: includes/input-fields/class-wcj-product-input-fields-core.php:147
6876
  msgid "Total number of "
6877
  msgstr ""
6878
 
6879
- #: includes/input-fields/class-wcj-product-input-fields-core.php:163
6880
- #: includes/input-fields/class-wcj-product-input-fields-core.php:322
6881
  #: includes/settings/wcj-settings-product-input-fields.php:83
6882
  msgid "Product Input Field"
6883
  msgstr ""
6884
 
6885
- #: includes/input-fields/class-wcj-product-input-fields-core.php:398
6886
  msgid "Wrong file type!"
6887
  msgstr ""
6888
 
6889
- #: includes/input-fields/class-wcj-product-input-fields-core.php:406
6890
  msgid "File is too big!"
6891
  msgstr ""
6892
 
6893
- #: includes/input-fields/class-wcj-product-input-fields-core.php:584
6894
  msgid "Select a country&hellip;"
6895
  msgstr ""
6896
 
@@ -6935,6 +7120,7 @@ msgstr ""
6935
 
6936
  #: includes/input-fields/wcj-product-input-fields-options.php:34
6937
  #: includes/settings/wcj-settings-checkout-custom-fields.php:122
 
6938
  msgid "Number"
6939
  msgstr ""
6940
 
@@ -7337,8 +7523,8 @@ msgstr ""
7337
 
7338
  #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-advanced.php:25
7339
  #: includes/settings/wcj-settings-order-min-amount.php:69
7340
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:60
7341
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:74
7342
  msgid "Advanced"
7343
  msgstr ""
7344
 
@@ -7416,24 +7602,24 @@ msgid "Display & Misc."
7416
  msgstr ""
7417
 
7418
  #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:129
7419
- #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:301
7420
  msgid "View"
7421
  msgstr ""
7422
 
7423
  #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:148
7424
- #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:314
7425
  msgid "Create"
7426
  msgstr ""
7427
 
7428
- #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:267
7429
  msgid "Booster: PDF Invoices"
7430
  msgstr ""
7431
 
7432
- #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:287
7433
  msgid "You have no document types enabled."
7434
  msgstr ""
7435
 
7436
- #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:320
7437
  msgid ""
7438
  "In case of partial refund, you need to reload the page to see created "
7439
  "document in this meta box."
@@ -7463,6 +7649,95 @@ msgstr ""
7463
  msgid "Templates"
7464
  msgstr ""
7465
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7466
  #: includes/price-by-country/class-wcj-price-by-country-group-generator.php:75
7467
  msgid "Create All Country Groups Failed."
7468
  msgstr ""
@@ -7787,6 +8062,8 @@ msgstr ""
7787
 
7788
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:17
7789
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:22
 
 
7790
  #: includes/settings/wcj-settings-product-add-to-cart.php:24
7791
  #: includes/settings/wcj-settings-product-by-date.php:20
7792
  msgid "All Products"
@@ -7800,21 +8077,23 @@ msgstr ""
7800
  #: includes/settings/wcj-settings-admin-orders-list.php:150
7801
  #: includes/settings/wcj-settings-admin-products-list.php:20
7802
  #: includes/settings/wcj-settings-admin-products-list.php:76
 
 
7803
  #: includes/settings/wcj-settings-my-account.php:40
7804
  #: includes/settings/wcj-settings-order-quantities.php:21
7805
  #: includes/settings/wcj-settings-order-quantities.php:79
7806
  #: includes/settings/wcj-settings-orders.php:107
7807
  #: includes/settings/wcj-settings-price-formats.php:37
7808
  #: includes/settings/wcj-settings-product-add-to-cart.php:273
7809
- #: includes/settings/wcj-settings-product-listings.php:128
7810
  #: includes/settings/wcj-settings-sale-flash.php:20
7811
  #: includes/settings/wcj-settings-sale-flash.php:65
7812
  #: includes/settings/wcj-settings-sale-flash.php:90
7813
- #: includes/settings/wcj-settings-shipping-by-condition.php:25
7814
  #: includes/settings/wcj-settings-shipping-options.php:21
7815
  #: includes/settings/wcj-settings-stock.php:20
7816
- #: includes/settings/wcj-settings-stock.php:61
7817
- #: includes/settings/wcj-settings-stock.php:102
7818
  #: includes/settings/wcj-settings-tax-display.php:27
7819
  #: includes/settings/wcj-settings-tax-display.php:44
7820
  #: includes/settings/wcj-settings-tax-display.php:101
@@ -7834,12 +8113,12 @@ msgstr ""
7834
  #: includes/settings/wcj-settings-general.php:121
7835
  #: includes/settings/wcj-settings-general.php:128
7836
  #: includes/settings/wcj-settings-general.php:135
7837
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:101
7838
  #: includes/settings/wcj-settings-price-by-user-role.php:56
7839
  #: includes/settings/wcj-settings-price-by-user-role.php:88
7840
  #: includes/settings/wcj-settings-product-add-to-cart.php:131
7841
  #: includes/settings/wcj-settings-product-open-pricing.php:80
7842
- #: includes/settings/wcj-settings-sku.php:224
7843
  #: includes/settings/meta-box/wcj-settings-meta-box-product-add-to-cart.php:67
7844
  msgid "Disable"
7845
  msgstr ""
@@ -7865,6 +8144,8 @@ msgstr ""
7865
 
7866
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:63
7867
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:68
 
 
7868
  #: includes/settings/wcj-settings-price-labels.php:22
7869
  #: includes/settings/wcj-settings-product-add-to-cart.php:39
7870
  #: includes/settings/wcj-settings-product-by-date.php:52
@@ -7915,7 +8196,7 @@ msgid "Category Groups Number"
7915
  msgstr ""
7916
 
7917
  #: includes/settings/wcj-settings-add-to-cart.php:29
7918
- #: includes/settings/wcj-settings-product-tabs.php:30
7919
  msgid "Click \"Save changes\" after you change this number."
7920
  msgstr ""
7921
 
@@ -8009,7 +8290,7 @@ msgstr ""
8009
  #: includes/settings/wcj-settings-add-to-cart.php:165
8010
  #: includes/settings/wcj-settings-add-to-cart.php:209
8011
  #: includes/settings/wcj-settings-add-to-cart.php:220
8012
- #: includes/settings/wcj-settings-product-custom-info.php:186
8013
  msgid "Leave blank to disable."
8014
  msgstr ""
8015
 
@@ -8230,7 +8511,7 @@ msgstr ""
8230
  #: includes/settings/wcj-settings-checkout-customization.php:68
8231
  #: includes/settings/wcj-settings-currency.php:21
8232
  #: includes/settings/wcj-settings-order-custom-statuses.php:63
8233
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:47
8234
  #: includes/settings/wcj-settings-product-bookings.php:92
8235
  #: includes/settings/wcj-settings-product-images.php:20
8236
  #: includes/settings/wcj-settings-product-images.php:27
@@ -8263,7 +8544,7 @@ msgid "Default columns order"
8263
  msgstr ""
8264
 
8265
  #: includes/settings/wcj-settings-admin-products-list.php:27
8266
- #: includes/settings/wcj-settings-price-by-user-role.php:130
8267
  #: includes/settings/wcj-settings-shipping.php:51
8268
  msgid ""
8269
  "Save module's settings after changing this option to see new settings fields."
@@ -8447,7 +8728,7 @@ msgstr ""
8447
  #: includes/settings/wcj-settings-checkout-custom-info.php:19
8448
  #: includes/settings/wcj-settings-mini-cart.php:19
8449
  #: includes/settings/wcj-settings-my-account.php:46
8450
- #: includes/settings/wcj-settings-product-custom-info.php:51
8451
  msgid "Total Blocks"
8452
  msgstr ""
8453
 
@@ -8462,7 +8743,7 @@ msgstr ""
8462
  #: includes/settings/wcj-settings-checkout-custom-info.php:84
8463
  #: includes/settings/wcj-settings-mini-cart.php:58
8464
  #: includes/settings/wcj-settings-my-account.php:119
8465
- #: includes/settings/wcj-settings-product-custom-info.php:111
8466
  msgid "Position Order (i.e. Priority)"
8467
  msgstr ""
8468
 
@@ -8482,12 +8763,18 @@ msgstr ""
8482
  #: includes/settings/wcj-settings-checkout-core-fields.php:16
8483
  #: includes/settings/wcj-settings-currency-exchange-rates.php:26
8484
  #: includes/settings/wcj-settings-emails-verification.php:14
 
8485
  #: includes/settings/wcj-settings-multicurrency.php:17
8486
  #: includes/settings/wcj-settings-offer-price.php:14
8487
  #: includes/settings/wcj-settings-order-quantities.php:131
8488
  #: includes/settings/wcj-settings-payment-gateways-by-country.php:15
 
8489
  #: includes/settings/wcj-settings-payment-gateways-min-max.php:15
8490
  #: includes/settings/wcj-settings-price-formats.php:15
 
 
 
 
8491
  msgid "General Options"
8492
  msgstr ""
8493
 
@@ -8662,7 +8949,7 @@ msgstr ""
8662
  #: includes/settings/wcj-settings-checkout-custom-fields.php:169
8663
  #: includes/settings/wcj-settings-checkout-custom-info.php:55
8664
  #: includes/settings/wcj-settings-empty-cart.php:58
8665
- #: includes/settings/wcj-settings-left-to-free-shipping.php:120
8666
  msgid "Billing"
8667
  msgstr ""
8668
 
@@ -8841,44 +9128,44 @@ msgstr ""
8841
  #: includes/settings/wcj-settings-checkout-custom-info.php:53
8842
  #: includes/settings/wcj-settings-checkout-files-upload.php:55
8843
  #: includes/settings/wcj-settings-empty-cart.php:56
8844
- #: includes/settings/wcj-settings-left-to-free-shipping.php:118
8845
  msgid "Before checkout form"
8846
  msgstr ""
8847
 
8848
  #: includes/settings/wcj-settings-checkout-custom-info.php:54
8849
  #: includes/settings/wcj-settings-empty-cart.php:57
8850
- #: includes/settings/wcj-settings-left-to-free-shipping.php:119
8851
  msgid "Before customer details"
8852
  msgstr ""
8853
 
8854
  #: includes/settings/wcj-settings-checkout-custom-info.php:57
8855
  #: includes/settings/wcj-settings-empty-cart.php:60
8856
- #: includes/settings/wcj-settings-left-to-free-shipping.php:122
8857
  msgid "After customer details"
8858
  msgstr ""
8859
 
8860
  #: includes/settings/wcj-settings-checkout-custom-info.php:58
8861
  #: includes/settings/wcj-settings-empty-cart.php:61
8862
- #: includes/settings/wcj-settings-left-to-free-shipping.php:123
8863
  msgid "Before order review"
8864
  msgstr ""
8865
 
8866
  #: includes/settings/wcj-settings-checkout-custom-info.php:59
8867
  #: includes/settings/wcj-settings-empty-cart.php:62
8868
- #: includes/settings/wcj-settings-left-to-free-shipping.php:124
8869
  msgid "Order review"
8870
  msgstr ""
8871
 
8872
  #: includes/settings/wcj-settings-checkout-custom-info.php:60
8873
  #: includes/settings/wcj-settings-empty-cart.php:63
8874
- #: includes/settings/wcj-settings-left-to-free-shipping.php:125
8875
  msgid "After order review"
8876
  msgstr ""
8877
 
8878
  #: includes/settings/wcj-settings-checkout-custom-info.php:61
8879
  #: includes/settings/wcj-settings-checkout-files-upload.php:56
8880
  #: includes/settings/wcj-settings-empty-cart.php:64
8881
- #: includes/settings/wcj-settings-left-to-free-shipping.php:126
8882
  msgid "After checkout form"
8883
  msgstr ""
8884
 
@@ -8972,11 +9259,12 @@ msgid "Billing city"
8972
  msgstr ""
8973
 
8974
  #: includes/settings/wcj-settings-checkout-customization.php:96
 
8975
  msgid "Billing state"
8976
  msgstr ""
8977
 
8978
  #: includes/settings/wcj-settings-checkout-customization.php:97
8979
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:25
8980
  msgid "Billing postcode"
8981
  msgstr ""
8982
 
@@ -9013,11 +9301,12 @@ msgid "Shipping city"
9013
  msgstr ""
9014
 
9015
  #: includes/settings/wcj-settings-checkout-customization.php:107
 
9016
  msgid "Shipping state"
9017
  msgstr ""
9018
 
9019
  #: includes/settings/wcj-settings-checkout-customization.php:108
9020
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:26
9021
  msgid "Shipping postcode"
9022
  msgstr ""
9023
 
@@ -9247,9 +9536,9 @@ msgstr ""
9247
  #: includes/settings/wcj-settings-eu-vat-number.php:203
9248
  #: includes/settings/wcj-settings-general.php:77
9249
  #: includes/settings/wcj-settings-payment-gateways.php:49
9250
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:42
9251
- #: includes/settings/wcj-settings-product-custom-info.php:180
9252
- #: includes/settings/wcj-settings-shipping-by-condition.php:78
9253
  msgid "Advanced Options"
9254
  msgstr ""
9255
 
@@ -9329,14 +9618,7 @@ msgstr ""
9329
  msgid "%s seconds till next update."
9330
  msgstr ""
9331
 
9332
- #: includes/settings/wcj-settings-currency-exchange-rates.php:28
9333
- msgid ""
9334
- "All currencies from all <strong>enabled</strong> modules (with \"Exchange "
9335
- "Rates Updates\" set to \"Automatically via Currency Exchange Rates module\") "
9336
- "will be automatically added to the list."
9337
- msgstr ""
9338
-
9339
- #: includes/settings/wcj-settings-currency-exchange-rates.php:32
9340
  #: includes/settings/wcj-settings-currency-per-product.php:102
9341
  #: includes/settings/wcj-settings-multicurrency-base-price.php:24
9342
  #: includes/settings/wcj-settings-multicurrency.php:22
@@ -9345,6 +9627,10 @@ msgstr ""
9345
  msgid "Exchange Rates Updates"
9346
  msgstr ""
9347
 
 
 
 
 
9348
  #: includes/settings/wcj-settings-currency-exchange-rates.php:53
9349
  msgid "Exchange Rates Rounding"
9350
  msgstr ""
@@ -9355,67 +9641,78 @@ msgstr ""
9355
  msgid "Rounding Precision"
9356
  msgstr ""
9357
 
9358
- #: includes/settings/wcj-settings-currency-exchange-rates.php:67
9359
- msgid "Exchange Rates Offset - Percent"
9360
  msgstr ""
9361
 
9362
  #: includes/settings/wcj-settings-currency-exchange-rates.php:68
9363
- #: includes/settings/wcj-settings-currency-exchange-rates.php:76
 
 
 
 
9364
  msgid ""
9365
  "If both percent and fixed offsets are set - percent offset is applied first "
9366
  "and fixed offset after that."
9367
  msgstr ""
9368
 
9369
- #: includes/settings/wcj-settings-currency-exchange-rates.php:75
9370
  msgid "Exchange Rates Offset - Fixed"
9371
  msgstr ""
9372
 
9373
- #: includes/settings/wcj-settings-currency-exchange-rates.php:83
9374
  msgid "Calculate with Inversion"
9375
  msgstr ""
9376
 
9377
- #: includes/settings/wcj-settings-currency-exchange-rates.php:85
9378
  msgid ""
9379
  "If your currency pair have very small exchange rate, you may want to invert "
9380
  "currencies before calculating the rate."
9381
  msgstr ""
9382
 
9383
- #: includes/settings/wcj-settings-currency-exchange-rates.php:91
9384
  msgid "Always Use cURL"
9385
  msgstr ""
9386
 
9387
- #: includes/settings/wcj-settings-currency-exchange-rates.php:93
9388
  msgid ""
9389
  "If for some reason currency exchange rates are not updating, try enabling "
9390
  "this option."
9391
  msgstr ""
9392
 
9393
- #: includes/settings/wcj-settings-currency-exchange-rates.php:112
9394
  msgid "Custom Currencies Options"
9395
  msgstr ""
9396
 
9397
- #: includes/settings/wcj-settings-currency-exchange-rates.php:114
9398
  #, php-format
9399
  msgid ""
9400
  "You can add more currencies in this section. E.g. this can be used to "
9401
  "display exchange rates with %s shortcodes."
9402
  msgstr ""
9403
 
9404
- #: includes/settings/wcj-settings-currency-exchange-rates.php:125
9405
  #: includes/settings/wcj-settings-currency.php:59
9406
  msgid "Total Custom Currencies"
9407
  msgstr ""
9408
 
9409
- #: includes/settings/wcj-settings-currency-exchange-rates.php:137
9410
  #: includes/settings/wcj-settings-currency.php:71
9411
  msgid "Custom Currency"
9412
  msgstr ""
9413
 
9414
- #: includes/settings/wcj-settings-currency-exchange-rates.php:156
9415
  #: includes/settings/wcj-settings-price-by-country.php:265
9416
  msgid "Exchange Rates"
9417
  msgstr ""
9418
 
 
 
 
 
 
 
 
9419
  #: includes/settings/wcj-settings-currency-external-products.php:14
9420
  msgid "Currency for External Products Options"
9421
  msgstr ""
@@ -9908,7 +10205,7 @@ msgid "Export Options"
9908
  msgstr ""
9909
 
9910
  #: includes/settings/wcj-settings-export.php:20
9911
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:156
9912
  msgid "CSV Separator"
9913
  msgstr ""
9914
 
@@ -10157,6 +10454,7 @@ msgid "PayPal Email per Product"
10157
  msgstr ""
10158
 
10159
  #: includes/settings/wcj-settings-general.php:152
 
10160
  #: includes/settings/wcj-settings-product-by-date.php:54
10161
  #: includes/settings/wcj-settings-product-by-time.php:54
10162
  msgid "This will add new meta box to each product's edit page."
@@ -10342,57 +10640,93 @@ msgstr ""
10342
 
10343
  #: includes/settings/wcj-settings-left-to-free-shipping.php:20
10344
  #, php-format
10345
- msgid "In content replaced values are: %s and %s."
10346
  msgstr ""
10347
 
10348
- #: includes/settings/wcj-settings-left-to-free-shipping.php:26
10349
  msgid "Info on Cart"
10350
  msgstr ""
10351
 
10352
  #: includes/settings/wcj-settings-left-to-free-shipping.php:35
10353
- #: includes/settings/wcj-settings-left-to-free-shipping.php:68
10354
- #: includes/settings/wcj-settings-left-to-free-shipping.php:105
10355
- #: includes/settings/wcj-settings-left-to-free-shipping.php:138
10356
  msgid "You can use HTML and/or shortcodes (e.g. [wcj_wpml]) here."
10357
  msgstr ""
10358
 
10359
- #: includes/settings/wcj-settings-left-to-free-shipping.php:51
10360
- #: includes/settings/wcj-settings-left-to-free-shipping.php:88
10361
- #: includes/settings/wcj-settings-left-to-free-shipping.php:131
 
 
 
 
 
 
 
 
 
 
 
 
10362
  msgid "Position Order (Priority)"
10363
  msgstr ""
10364
 
10365
- #: includes/settings/wcj-settings-left-to-free-shipping.php:57
10366
  msgid "Info on Mini Cart"
10367
  msgstr ""
10368
 
10369
- #: includes/settings/wcj-settings-left-to-free-shipping.php:81
10370
  #: includes/settings/wcj-settings-mini-cart.php:51
10371
  msgid "Before mini cart"
10372
  msgstr ""
10373
 
10374
- #: includes/settings/wcj-settings-left-to-free-shipping.php:82
10375
  #: includes/settings/wcj-settings-mini-cart.php:52
10376
  msgid "Before buttons"
10377
  msgstr ""
10378
 
10379
- #: includes/settings/wcj-settings-left-to-free-shipping.php:83
10380
  #: includes/settings/wcj-settings-mini-cart.php:53
10381
  msgid "After mini cart"
10382
  msgstr ""
10383
 
10384
- #: includes/settings/wcj-settings-left-to-free-shipping.php:94
10385
  msgid "Info on Checkout"
10386
  msgstr ""
10387
 
10388
- #: includes/settings/wcj-settings-left-to-free-shipping.php:137
10389
  msgid "Message on Free Shipping Reached"
10390
  msgstr ""
10391
 
10392
- #: includes/settings/wcj-settings-left-to-free-shipping.php:139
10393
  msgid "Set empty to disable."
10394
  msgstr ""
10395
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10396
  #: includes/settings/wcj-settings-mini-cart.php:14
10397
  msgid "Mini Cart Custom Info Blocks"
10398
  msgstr ""
@@ -10772,12 +11106,12 @@ msgid "Position On Single Product Page"
10772
  msgstr ""
10773
 
10774
  #: includes/settings/wcj-settings-offer-price.php:70
10775
- #: includes/settings/wcj-settings-product-custom-info.php:91
10776
  msgid "Before single product"
10777
  msgstr ""
10778
 
10779
  #: includes/settings/wcj-settings-offer-price.php:74
10780
- #: includes/settings/wcj-settings-product-custom-info.php:95
10781
  msgid "After single product"
10782
  msgstr ""
10783
 
@@ -10834,10 +11168,6 @@ msgstr ""
10834
  msgid "Customer Email"
10835
  msgstr ""
10836
 
10837
- #: includes/settings/wcj-settings-offer-price.php:170
10838
- msgid "Customer Message"
10839
- msgstr ""
10840
-
10841
  #: includes/settings/wcj-settings-offer-price.php:178
10842
  msgid "Send a Copy to Customer Checkbox"
10843
  msgstr ""
@@ -11056,18 +11386,18 @@ msgid ""
11056
  msgstr ""
11057
 
11058
  #: includes/settings/wcj-settings-order-numbers.php:21
11059
- #: includes/settings/wcj-settings-sku.php:21
11060
  msgid "Number Generation"
11061
  msgstr ""
11062
 
11063
  #: includes/settings/wcj-settings-order-numbers.php:26
11064
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:22
11065
- #: includes/settings/wcj-settings-sku.php:27
11066
  msgid "Sequential"
11067
  msgstr ""
11068
 
11069
  #: includes/settings/wcj-settings-order-numbers.php:28
11070
- #: includes/settings/wcj-settings-sku.php:28
11071
  msgid "Pseudorandom - Hash (max 10 digits)"
11072
  msgstr ""
11073
 
@@ -11180,33 +11510,51 @@ msgstr ""
11180
  msgid "Enable Order Admin Search by Custom Number"
11181
  msgstr ""
11182
 
11183
- #: includes/settings/wcj-settings-order-numbers.php:122
11184
- msgid "Orders Renumerate Tool Options"
11185
  msgstr ""
11186
 
11187
  #: includes/settings/wcj-settings-order-numbers.php:127
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11188
  msgid "Sort by"
11189
  msgstr ""
11190
 
11191
- #: includes/settings/wcj-settings-order-numbers.php:134
11192
  msgid "Last modified date"
11193
  msgstr ""
11194
 
11195
- #: includes/settings/wcj-settings-order-numbers.php:135
11196
  #: includes/settings/wcj-settings-related-products.php:22
11197
  msgid "Random"
11198
  msgstr ""
11199
 
11200
- #: includes/settings/wcj-settings-order-numbers.php:139
11201
  msgid "Sort Ascending or Descending"
11202
  msgstr ""
11203
 
11204
- #: includes/settings/wcj-settings-order-numbers.php:144
11205
  #: includes/settings/wcj-settings-related-products.php:90
11206
  msgid "Ascending"
11207
  msgstr ""
11208
 
11209
- #: includes/settings/wcj-settings-order-numbers.php:145
11210
  #: includes/settings/wcj-settings-related-products.php:91
11211
  msgid "Descending"
11212
  msgstr ""
@@ -11229,7 +11577,7 @@ msgstr ""
11229
  #: includes/settings/wcj-settings-order-quantities.php:44
11230
  #: includes/settings/wcj-settings-order-quantities.php:86
11231
  #: includes/settings/wcj-settings-order-quantities.php:102
11232
- #: includes/settings/wcj-settings-shipping-by-order-amount.php:16
11233
  msgid "Set to zero to disable."
11234
  msgstr ""
11235
 
@@ -11279,6 +11627,7 @@ msgid "Action on variation change"
11279
  msgstr ""
11280
 
11281
  #: includes/settings/wcj-settings-order-quantities.php:157
 
11282
  msgid "Do nothing"
11283
  msgstr ""
11284
 
@@ -11410,51 +11759,63 @@ msgid "Regenerate"
11410
  msgstr ""
11411
 
11412
  #: includes/settings/wcj-settings-payment-gateways-by-country.php:20
11413
- msgid "Postcode Type"
11414
  msgstr ""
11415
 
11416
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:36
11417
- msgid "Country and state are defined from customer's entered billing address."
11418
  msgstr ""
11419
 
11420
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:37
 
 
 
 
 
 
 
 
 
 
 
 
11421
  msgid "If any field is left empty - it's ignored."
11422
  msgstr ""
11423
 
11424
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:60
11425
  msgid "Include Countries"
11426
  msgstr ""
11427
 
11428
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:70
11429
  msgid "Exclude Countries"
11430
  msgstr ""
11431
 
11432
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:80
11433
  msgid "Include States (Base Country)"
11434
  msgstr ""
11435
 
11436
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:90
11437
  msgid "Exclude States (Base Country)"
11438
  msgstr ""
11439
 
11440
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:100
11441
  msgid "Include Postcodes (one per line)"
11442
  msgstr ""
11443
 
11444
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:101
11445
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:111
11446
  msgid ""
11447
  "Postcodes containing wildcards (e.g. CB23*) and fully numeric ranges (e.g. "
11448
  "<code>90210...99000</code>) are also supported."
11449
  msgstr ""
11450
 
11451
- #: includes/settings/wcj-settings-payment-gateways-by-country.php:110
11452
  msgid "Exclude Postcodes (one per line)"
11453
  msgstr ""
11454
 
11455
  #: includes/settings/wcj-settings-payment-gateways-by-currency.php:16
11456
  #: includes/settings/wcj-settings-payment-gateways-by-user-role.php:16
11457
- #: includes/settings/wcj-settings-shipping-by-condition.php:20
11458
  msgid "Leave empty to disable."
11459
  msgstr ""
11460
 
@@ -11471,7 +11832,23 @@ msgstr ""
11471
  msgid "Denied Currencies"
11472
  msgstr ""
11473
 
11474
- #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:23
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11475
  msgid ""
11476
  "If payment gateway is only available for certain methods, set it up here. "
11477
  "Leave blank to enable for all methods."
@@ -11510,8 +11887,8 @@ msgid "Fee (or discount) title to show to customer."
11510
  msgstr ""
11511
 
11512
  #: includes/settings/wcj-settings-payment-gateways-fees.php:25
11513
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:36
11514
- #: includes/settings/wcj-settings-pdf-invoicing-page.php:83
11515
  #: includes/settings/wcj-settings-purchase-data.php:67
11516
  msgid "Leave blank to disable"
11517
  msgstr ""
@@ -11742,130 +12119,138 @@ msgid ""
11742
  "admin order meta box."
11743
  msgstr ""
11744
 
11745
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:15
11746
  msgid "Fonts download is disabled."
11747
  msgstr ""
11748
 
11749
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:18
11750
  msgid "Fonts are up to date."
11751
  msgstr ""
11752
 
11753
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:19
11754
  #, php-format
11755
  msgid "Latest successful download or version check was on %s."
11756
  msgstr ""
11757
 
11758
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:23
11759
  msgid ""
11760
  "Fonts are NOT up to date. Please try downloading by pressing the button "
11761
  "below."
11762
  msgstr ""
11763
 
11764
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:26
11765
  #, php-format
11766
  msgid "Latest successful downloaded version is %s."
11767
  msgstr ""
11768
 
11769
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:32
11770
  #, php-format
11771
  msgid "Latest download executed on %s."
11772
  msgstr ""
11773
 
11774
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:46
11775
  msgid "Hide Disabled Docs Settings"
11776
  msgstr ""
11777
 
11778
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:53
11779
  msgid "Replace Admin Order Search with Invoice Search"
11780
  msgstr ""
11781
 
11782
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:60
11783
  msgid "Default Images Directory"
11784
  msgstr ""
11785
 
11786
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:61
11787
  msgid "Default images directory in TCPDF library (K_PATH_IMAGES)."
11788
  msgstr ""
11789
 
11790
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:62
11791
  msgid ""
11792
  "Try changing this if you have issues displaying images in page background or "
11793
  "header."
11794
  msgstr ""
11795
 
11796
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:67
11797
  msgid "Empty"
11798
  msgstr ""
11799
 
11800
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:68
11801
  msgid "TCPDF Default"
11802
  msgstr ""
11803
 
11804
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:69
11805
  msgid "ABSPATH"
11806
  msgstr ""
11807
 
11808
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:70
11809
  msgid "DOCUMENT_ROOT"
11810
  msgstr ""
11811
 
11812
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:74
11813
  msgid "Temp Directory"
11814
  msgstr ""
11815
 
11816
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:75
11817
  msgid "Leave blank to use the default temp directory."
11818
  msgstr ""
11819
 
11820
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:86
11821
  msgid "Fonts Manager"
11822
  msgstr ""
11823
 
11824
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:95
11825
  msgid "Re-download"
11826
  msgstr ""
11827
 
11828
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:100
 
 
 
 
11829
  msgid "Disable Fonts Download"
11830
  msgstr ""
11831
 
11832
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:111
11833
  msgid "General Display Options"
11834
  msgstr ""
11835
 
11836
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:116
11837
  msgid "Add PDF Invoices Meta Box to Admin Edit Order Page"
11838
  msgstr ""
11839
 
11840
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:127
 
 
 
 
11841
  msgid "Report Tool Options"
11842
  msgstr ""
11843
 
11844
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:132
11845
  msgid "Reports Filename"
11846
  msgstr ""
11847
 
11848
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:140
11849
  msgid "Report Columns"
11850
  msgstr ""
11851
 
11852
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:141
11853
  msgid "Leave blank to show all columns."
11854
  msgstr ""
11855
 
11856
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:149
11857
  msgid "Tax Percent Precision"
11858
  msgstr ""
11859
 
11860
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:162
11861
  msgid "CSV UTF-8 BOM"
11862
  msgstr ""
11863
 
11864
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:169
11865
  msgid "Replace Periods with Commas in CSV Data"
11866
  msgstr ""
11867
 
11868
- #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:170
11869
  msgid "Replace"
11870
  msgstr ""
11871
 
@@ -11981,42 +12366,55 @@ msgstr ""
11981
  msgid "Footer Margin"
11982
  msgstr ""
11983
 
11984
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:22
11985
  msgid "Enable Header"
11986
  msgstr ""
11987
 
11988
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:29
11989
  msgid "Header Image"
11990
  msgstr ""
11991
 
11992
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:34
 
 
 
 
 
 
 
11993
  #, php-format
11994
  msgid ""
11995
- "Enter a URL to an image you want to show in the invoice's header. Upload "
11996
- "your image using the <a href=\"%s\">media uploader</a>."
 
11997
  msgstr ""
11998
 
11999
  #: includes/settings/wcj-settings-pdf-invoicing-header.php:40
12000
- msgid "Header Image Width in mm"
 
12001
  msgstr ""
12002
 
12003
  #: includes/settings/wcj-settings-pdf-invoicing-header.php:46
 
 
 
 
12004
  msgid "Header Title"
12005
  msgstr ""
12006
 
12007
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:53
12008
  msgid "Header Text"
12009
  msgstr ""
12010
 
12011
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:60
12012
  msgid "Header Text Color"
12013
  msgstr ""
12014
 
12015
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:67
12016
  msgid "Header Line Color"
12017
  msgstr ""
12018
 
12019
- #: includes/settings/wcj-settings-pdf-invoicing-header.php:74
12020
  msgid "Header Margin"
12021
  msgstr ""
12022
 
@@ -12029,19 +12427,19 @@ msgid "Counter Width"
12029
  msgstr ""
12030
 
12031
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:41
12032
- #: includes/settings/wcj-settings-sku.php:57
12033
- #: includes/settings/wcj-settings-sku.php:119
12034
  msgid "Prefix"
12035
  msgstr ""
12036
 
12037
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:47
12038
- #: includes/settings/wcj-settings-sku.php:71
12039
- #: includes/settings/wcj-settings-sku.php:128
12040
  msgid "Suffix"
12041
  msgstr ""
12042
 
12043
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:53
12044
- #: includes/settings/wcj-settings-sku.php:78
12045
  msgid "Template"
12046
  msgstr ""
12047
 
@@ -12096,6 +12494,14 @@ msgid ""
12096
  "\">media uploader</a>."
12097
  msgstr ""
12098
 
 
 
 
 
 
 
 
 
12099
  #: includes/settings/wcj-settings-pdf-invoicing-styling.php:19
12100
  #: includes/settings/wcj-settings-pdf-invoicing-styling.php:37
12101
  msgid "Font Family"
@@ -12145,7 +12551,7 @@ msgid "Create on Order Partially Refunded"
12145
  msgstr ""
12146
 
12147
  #: includes/settings/wcj-settings-pdf-invoicing.php:32
12148
- #: includes/settings/wcj-settings-product-by-country.php:63
12149
  msgid "Manually"
12150
  msgstr ""
12151
 
@@ -12411,13 +12817,22 @@ msgid "Disable Price by User Role for Products on Sale"
12411
  msgstr ""
12412
 
12413
  #: includes/settings/wcj-settings-price-by-user-role.php:104
12414
- #: includes/settings/wcj-settings-price-by-user-role.php:153
12415
  #: includes/settings/meta-box/wcj-settings-meta-box-price-by-user-role.php:99
12416
  msgid "Make Empty Price"
12417
  msgstr ""
12418
 
12419
- #: includes/settings/wcj-settings-price-by-user-role.php:124
12420
- msgid "Price by User Role by Products Categories"
 
 
 
 
 
 
 
 
 
12421
  msgstr ""
12422
 
12423
  #: includes/settings/wcj-settings-price-formats.php:20
@@ -12625,7 +13040,7 @@ msgid ""
12625
  msgstr ""
12626
 
12627
  #: includes/settings/wcj-settings-product-add-to-cart.php:40
12628
- #: includes/settings/wcj-settings-product-tabs.php:213
12629
  msgid "This will add meta boxes to each product's edit page."
12630
  msgstr ""
12631
 
@@ -12924,7 +13339,7 @@ msgid "Position Priority on Frontend"
12924
  msgstr ""
12925
 
12926
  #: includes/settings/wcj-settings-product-addons.php:199
12927
- #: includes/settings/wcj-settings-shipping-by-condition.php:84
12928
  #: includes/settings/wcj-settings-shipping-options.php:41
12929
  msgid "Set to zero to use the default priority."
12930
  msgstr ""
@@ -13110,45 +13525,50 @@ msgstr ""
13110
  msgid "This will hide selected products completely (including direct link)."
13111
  msgstr ""
13112
 
13113
- #: includes/settings/wcj-settings-product-by-country.php:47
 
 
 
 
 
13114
  msgid "User Country Selection Options"
13115
  msgstr ""
13116
 
13117
- #: includes/settings/wcj-settings-product-by-country.php:52
13118
  msgid "User Country Selection Method"
13119
  msgstr ""
13120
 
13121
- #: includes/settings/wcj-settings-product-by-country.php:53
13122
  msgid "Possible values: \"Automatically by IP\" or \"Manually\"."
13123
  msgstr ""
13124
 
13125
- #: includes/settings/wcj-settings-product-by-country.php:55
13126
  #, php-format
13127
  msgid ""
13128
  "If \"Manually\" option is selected, you can add country selection drop box "
13129
  "to frontend with \"%s\" widget or %s shortcode."
13130
  msgstr ""
13131
 
13132
- #: includes/settings/wcj-settings-product-by-country.php:62
13133
  msgid "Automatically by IP"
13134
  msgstr ""
13135
 
13136
- #: includes/settings/wcj-settings-product-by-country.php:73
13137
  msgid "Admin Options"
13138
  msgstr ""
13139
 
13140
- #: includes/settings/wcj-settings-product-by-country.php:78
13141
  msgid "Country List"
13142
  msgstr ""
13143
 
13144
- #: includes/settings/wcj-settings-product-by-country.php:79
13145
  msgid ""
13146
  "This option sets which countries will be added to list in product's edit "
13147
  "page. Possible values: \"All countries\" or \"WooCommerce selling locations"
13148
  "\"."
13149
  msgstr ""
13150
 
13151
- #: includes/settings/wcj-settings-product-by-country.php:80
13152
  #, php-format
13153
  msgid ""
13154
  "If \"WooCommerce selling locations\" option is selected, country list will "
@@ -13156,38 +13576,38 @@ msgid ""
13156
  "(s)</a>."
13157
  msgstr ""
13158
 
13159
- #: includes/settings/wcj-settings-product-by-country.php:87
13160
  msgid "WooCommerce selling locations"
13161
  msgstr ""
13162
 
13163
- #: includes/settings/wcj-settings-product-by-country.php:93
13164
  msgid "Visibility Method"
13165
  msgstr ""
13166
 
13167
- #: includes/settings/wcj-settings-product-by-country.php:94
13168
  msgid ""
13169
  "This option sets how do you want to set product's visibility. Possible "
13170
  "values: \"Set visible countries\", \"Set invisible countries\" or \"Set both"
13171
  "\"."
13172
  msgstr ""
13173
 
13174
- #: includes/settings/wcj-settings-product-by-country.php:99
13175
  msgid "Set visible countries"
13176
  msgstr ""
13177
 
13178
- #: includes/settings/wcj-settings-product-by-country.php:100
13179
  msgid "Set invisible countries"
13180
  msgstr ""
13181
 
13182
- #: includes/settings/wcj-settings-product-by-country.php:101
13183
  msgid "Set both"
13184
  msgstr ""
13185
 
13186
- #: includes/settings/wcj-settings-product-by-country.php:108
13187
  msgid "Admin Products List Column"
13188
  msgstr ""
13189
 
13190
- #: includes/settings/wcj-settings-product-by-country.php:109
13191
  msgid "This will add \"Countries\" column to the admin products list."
13192
  msgstr ""
13193
 
@@ -13223,6 +13643,9 @@ msgstr ""
13223
  #: includes/settings/wcj-settings-product-by-date.php:96
13224
  #: includes/settings/wcj-settings-product-by-time.php:72
13225
  #: includes/settings/wcj-settings-product-by-time.php:84
 
 
 
13226
  msgid "You can also use shortcodes here."
13227
  msgstr ""
13228
 
@@ -13347,20 +13770,20 @@ msgstr ""
13347
  msgid "Custom Taxonomy"
13348
  msgstr ""
13349
 
13350
- #: includes/settings/wcj-settings-product-custom-info.php:43
13351
  msgid "Single Product Pages"
13352
  msgstr ""
13353
 
13354
- #: includes/settings/wcj-settings-product-custom-info.php:43
13355
  msgid "Archives"
13356
  msgstr ""
13357
 
13358
- #: includes/settings/wcj-settings-product-custom-info.php:72
13359
  #, php-format
13360
  msgid "Block #%s"
13361
  msgstr ""
13362
 
13363
- #: includes/settings/wcj-settings-product-custom-info.php:81
13364
  #: includes/settings/wcj-settings-product-images.php:49
13365
  #: includes/settings/wcj-settings-product-images.php:58
13366
  #: includes/settings/wcj-settings-product-images.php:67
@@ -13370,72 +13793,72 @@ msgstr ""
13370
  msgid "You can use shortcodes here."
13371
  msgstr ""
13372
 
13373
- #: includes/settings/wcj-settings-product-custom-info.php:96
13374
  msgid "Before add to cart form"
13375
  msgstr ""
13376
 
13377
- #: includes/settings/wcj-settings-product-custom-info.php:97
13378
  #: includes/settings/wcj-settings-product-input-fields.php:194
13379
  msgid "Before add to cart button"
13380
  msgstr ""
13381
 
13382
- #: includes/settings/wcj-settings-product-custom-info.php:98
13383
  #: includes/settings/wcj-settings-product-input-fields.php:195
13384
  msgid "After add to cart button"
13385
  msgstr ""
13386
 
13387
- #: includes/settings/wcj-settings-product-custom-info.php:99
13388
  msgid "After add to cart form"
13389
  msgstr ""
13390
 
13391
- #: includes/settings/wcj-settings-product-custom-info.php:104
13392
  msgid "Inside product title"
13393
  msgstr ""
13394
 
13395
- #: includes/settings/wcj-settings-product-custom-info.php:117
13396
  msgid "Product Categories to Include"
13397
  msgstr ""
13398
 
13399
- #: includes/settings/wcj-settings-product-custom-info.php:118
13400
- #: includes/settings/wcj-settings-product-custom-info.php:127
13401
- #: includes/settings/wcj-settings-product-custom-info.php:136
13402
- #: includes/settings/wcj-settings-product-custom-info.php:145
13403
- #: includes/settings/wcj-settings-product-custom-info.php:155
13404
- #: includes/settings/wcj-settings-product-custom-info.php:165
13405
  msgid "Leave blank to disable the option."
13406
  msgstr ""
13407
 
13408
- #: includes/settings/wcj-settings-product-custom-info.php:126
13409
  msgid "Product Categories to Exclude"
13410
  msgstr ""
13411
 
13412
- #: includes/settings/wcj-settings-product-custom-info.php:135
13413
  msgid "Product Tags to Include"
13414
  msgstr ""
13415
 
13416
- #: includes/settings/wcj-settings-product-custom-info.php:144
13417
  msgid "Product Tags to Exclude"
13418
  msgstr ""
13419
 
13420
- #: includes/settings/wcj-settings-product-custom-info.php:154
13421
  #: includes/settings/wcj-settings-products-xml.php:140
13422
  msgid "Products to Include"
13423
  msgstr ""
13424
 
13425
- #: includes/settings/wcj-settings-product-custom-info.php:164
13426
  #: includes/settings/wcj-settings-products-xml.php:150
13427
  msgid "Products to Exclude"
13428
  msgstr ""
13429
 
13430
- #: includes/settings/wcj-settings-product-custom-info.php:185
13431
  msgid "Extra Filters"
13432
  msgstr ""
13433
 
13434
- #: includes/settings/wcj-settings-product-custom-info.php:187
13435
  msgid "You can add custom filters here (one per line, in filter|title format)."
13436
  msgstr ""
13437
 
13438
- #: includes/settings/wcj-settings-product-custom-info.php:188
13439
  #, php-format
13440
  msgid "E.g.: %s."
13441
  msgstr ""
@@ -13741,7 +14164,7 @@ msgid ""
13741
  msgstr ""
13742
 
13743
  #: includes/settings/wcj-settings-product-listings.php:57
13744
- #: includes/settings/wcj-settings-product-listings.php:103
13745
  msgid "Hide Empty"
13746
  msgstr ""
13747
 
@@ -13750,7 +14173,7 @@ msgid "Hide empty categories on shop page"
13750
  msgstr ""
13751
 
13752
  #: includes/settings/wcj-settings-product-listings.php:64
13753
- #: includes/settings/wcj-settings-product-listings.php:110
13754
  msgid "Show Products"
13755
  msgstr ""
13756
 
@@ -13758,11 +14181,21 @@ msgstr ""
13758
  msgid "Show products if no categories are displayed on shop page"
13759
  msgstr ""
13760
 
13761
- #: includes/settings/wcj-settings-product-listings.php:75
 
 
 
 
 
 
 
 
 
 
13762
  msgid "Category Display Options"
13763
  msgstr ""
13764
 
13765
- #: includes/settings/wcj-settings-product-listings.php:78
13766
  #, php-format
13767
  msgid ""
13768
  "You can control what is shown on category archives in <a href=\"%s"
@@ -13770,59 +14203,59 @@ msgid ""
13770
  "a>."
13771
  msgstr ""
13772
 
13773
- #: includes/settings/wcj-settings-product-listings.php:84
13774
  msgid "Subcategories Count"
13775
  msgstr ""
13776
 
13777
- #: includes/settings/wcj-settings-product-listings.php:85
13778
  msgid "Hide subcategories count on category pages"
13779
  msgstr ""
13780
 
13781
- #: includes/settings/wcj-settings-product-listings.php:93
13782
  msgid "Exclude Subcategories"
13783
  msgstr ""
13784
 
13785
- #: includes/settings/wcj-settings-product-listings.php:94
13786
  msgid ""
13787
  " Excludes one or more categories from the category (archive) pages. Leave "
13788
  "blank to disable."
13789
  msgstr ""
13790
 
13791
- #: includes/settings/wcj-settings-product-listings.php:104
13792
  msgid "Hide empty subcategories on category pages"
13793
  msgstr ""
13794
 
13795
- #: includes/settings/wcj-settings-product-listings.php:111
13796
  msgid "Show products if no categories are displayed on category page"
13797
  msgstr ""
13798
 
13799
- #: includes/settings/wcj-settings-product-listings.php:121
13800
- #: includes/settings/wcj-settings-product-listings.php:127
13801
  msgid "Product Shop Visibility by Price"
13802
  msgstr ""
13803
 
13804
- #: includes/settings/wcj-settings-product-listings.php:123
13805
  msgid ""
13806
  "Here you can set to hide products from shop and search results depending on "
13807
  "product's price. Products will still be accessible via direct link."
13808
  msgstr ""
13809
 
13810
- #: includes/settings/wcj-settings-product-listings.php:134
13811
  #: includes/settings/meta-box/wcj-settings-meta-box-product-open-pricing.php:31
13812
  msgid "Min Price"
13813
  msgstr ""
13814
 
13815
- #: includes/settings/wcj-settings-product-listings.php:135
13816
  msgid ""
13817
  "Products with price below this value will be hidden. Ignored if set to zero."
13818
  msgstr ""
13819
 
13820
- #: includes/settings/wcj-settings-product-listings.php:142
13821
  #: includes/settings/meta-box/wcj-settings-meta-box-product-open-pricing.php:38
13822
  msgid "Max Price"
13823
  msgstr ""
13824
 
13825
- #: includes/settings/wcj-settings-product-listings.php:143
13826
  msgid ""
13827
  "Products with price above this value will be hidden. Ignored if set to zero."
13828
  msgstr ""
@@ -13913,202 +14346,215 @@ msgstr ""
13913
  msgid "Total Params"
13914
  msgstr ""
13915
 
13916
- #: includes/settings/wcj-settings-product-tabs.php:16
13917
- #: includes/settings/wcj-settings-product-tabs.php:22
 
 
 
 
 
 
 
 
 
 
 
 
 
13918
  msgid "Custom Product Tabs - All Products"
13919
  msgstr ""
13920
 
13921
- #: includes/settings/wcj-settings-product-tabs.php:18
13922
  msgid "This section lets you add custom single product tabs."
13923
  msgstr ""
13924
 
13925
- #: includes/settings/wcj-settings-product-tabs.php:29
13926
  msgid "Custom Product Tabs Number"
13927
  msgstr ""
13928
 
13929
- #: includes/settings/wcj-settings-product-tabs.php:60
13930
- #: includes/settings/wcj-settings-product-tabs.php:259
13931
  msgid "Make sure it's unique for each tab."
13932
  msgstr ""
13933
 
13934
- #: includes/settings/wcj-settings-product-tabs.php:73
13935
- #: includes/settings/wcj-settings-product-tabs.php:272
13936
  msgid "You can use shortcodes here..."
13937
  msgstr ""
13938
 
13939
- #: includes/settings/wcj-settings-product-tabs.php:94
13940
- #: includes/settings/wcj-settings-product-tabs.php:293
13941
  msgid "PRODUCTS to HIDE this tab"
13942
  msgstr ""
13943
 
13944
- #: includes/settings/wcj-settings-product-tabs.php:95
13945
- #: includes/settings/wcj-settings-product-tabs.php:294
13946
  msgid "To hide this tab from some products, enter products here."
13947
  msgstr ""
13948
 
13949
- #: includes/settings/wcj-settings-product-tabs.php:103
13950
- #: includes/settings/wcj-settings-product-tabs.php:302
13951
  msgid "PRODUCTS to SHOW this tab"
13952
  msgstr ""
13953
 
13954
- #: includes/settings/wcj-settings-product-tabs.php:104
13955
- #: includes/settings/wcj-settings-product-tabs.php:303
13956
  msgid "To show this tab only for some products, enter products here."
13957
  msgstr ""
13958
 
13959
- #: includes/settings/wcj-settings-product-tabs.php:112
13960
- #: includes/settings/wcj-settings-product-tabs.php:311
13961
  msgid "CATEGORIES to HIDE this tab"
13962
  msgstr ""
13963
 
13964
- #: includes/settings/wcj-settings-product-tabs.php:113
13965
- #: includes/settings/wcj-settings-product-tabs.php:312
13966
  msgid "To hide this tab from some categories, enter categories here."
13967
  msgstr ""
13968
 
13969
- #: includes/settings/wcj-settings-product-tabs.php:121
13970
- #: includes/settings/wcj-settings-product-tabs.php:320
13971
  msgid "CATEGORIES to SHOW this tab"
13972
  msgstr ""
13973
 
13974
- #: includes/settings/wcj-settings-product-tabs.php:122
13975
- #: includes/settings/wcj-settings-product-tabs.php:321
13976
  msgid "To show this tab only for some categories, enter categories here."
13977
  msgstr ""
13978
 
13979
- #: includes/settings/wcj-settings-product-tabs.php:130
13980
- #: includes/settings/wcj-settings-product-tabs.php:329
13981
  msgid "TAGS to HIDE this tab"
13982
  msgstr ""
13983
 
13984
- #: includes/settings/wcj-settings-product-tabs.php:131
13985
- #: includes/settings/wcj-settings-product-tabs.php:330
13986
  msgid "To hide this tab from some tags, enter tags here."
13987
  msgstr ""
13988
 
13989
- #: includes/settings/wcj-settings-product-tabs.php:139
13990
- #: includes/settings/wcj-settings-product-tabs.php:338
13991
  msgid "TAGS to SHOW this tab"
13992
  msgstr ""
13993
 
13994
- #: includes/settings/wcj-settings-product-tabs.php:140
13995
- #: includes/settings/wcj-settings-product-tabs.php:339
13996
  msgid "To show this tab only for some tags, enter tags here."
13997
  msgstr ""
13998
 
13999
- #: includes/settings/wcj-settings-product-tabs.php:152
14000
  msgid "Comma separated PRODUCT IDs to HIDE this tab"
14001
  msgstr ""
14002
 
14003
- #: includes/settings/wcj-settings-product-tabs.php:153
14004
  msgid "To hide this tab from some products, enter product IDs here."
14005
  msgstr ""
14006
 
14007
- #: includes/settings/wcj-settings-product-tabs.php:164
14008
  msgid "Comma separated PRODUCT IDs to SHOW this tab"
14009
  msgstr ""
14010
 
14011
- #: includes/settings/wcj-settings-product-tabs.php:165
14012
  msgid "To show this tab only for some products, enter product IDs here."
14013
  msgstr ""
14014
 
14015
- #: includes/settings/wcj-settings-product-tabs.php:176
14016
  msgid "Comma separated CATEGORY IDs to HIDE this tab"
14017
  msgstr ""
14018
 
14019
- #: includes/settings/wcj-settings-product-tabs.php:177
14020
  msgid "To hide this tab from some categories, enter category IDs here."
14021
  msgstr ""
14022
 
14023
- #: includes/settings/wcj-settings-product-tabs.php:188
14024
  msgid "Comma separated CATEGORY IDs to SHOW this tab"
14025
  msgstr ""
14026
 
14027
- #: includes/settings/wcj-settings-product-tabs.php:189
14028
  msgid "To show this tab only for some categories, enter category IDs here."
14029
  msgstr ""
14030
 
14031
- #: includes/settings/wcj-settings-product-tabs.php:205
14032
  msgid "Custom Product Tabs - Per Product"
14033
  msgstr ""
14034
 
14035
- #: includes/settings/wcj-settings-product-tabs.php:207
14036
  msgid "This section lets you set defaults for per product custom tabs."
14037
  msgstr ""
14038
 
14039
- #: includes/settings/wcj-settings-product-tabs.php:211
14040
  msgid "Enable Per Product Custom Product Tabs"
14041
  msgstr ""
14042
 
14043
- #: includes/settings/wcj-settings-product-tabs.php:219
14044
  msgid "Use Visual Editor"
14045
  msgstr ""
14046
 
14047
- #: includes/settings/wcj-settings-product-tabs.php:226
14048
  msgid "Add Per Product Tabs Content to \"Yoast SEO\" plugin analysis"
14049
  msgstr ""
14050
 
14051
- #: includes/settings/wcj-settings-product-tabs.php:233
14052
  msgid "Default Per Product Custom Product Tabs Number"
14053
  msgstr ""
14054
 
14055
- #: includes/settings/wcj-settings-product-tabs.php:251
14056
  msgid "Default Title"
14057
  msgstr ""
14058
 
14059
- #: includes/settings/wcj-settings-product-tabs.php:258
14060
  msgid "Default Key"
14061
  msgstr ""
14062
 
14063
- #: includes/settings/wcj-settings-product-tabs.php:265
14064
  msgid "Default Priority (i.e. Order)"
14065
  msgstr ""
14066
 
14067
- #: includes/settings/wcj-settings-product-tabs.php:271
14068
  msgid "Default Content"
14069
  msgstr ""
14070
 
14071
- #: includes/settings/wcj-settings-product-tabs.php:279
14072
  msgid "Default Link"
14073
  msgstr ""
14074
 
14075
- #: includes/settings/wcj-settings-product-tabs.php:280
14076
  msgid "Leave blank for default behaviour."
14077
  msgstr ""
14078
 
14079
- #: includes/settings/wcj-settings-product-tabs.php:287
14080
  msgid "Default \"Link - Open in New Window\""
14081
  msgstr ""
14082
 
14083
- #: includes/settings/wcj-settings-product-tabs.php:355
14084
  msgid "WooCommerce Standard Product Tabs Options"
14085
  msgstr ""
14086
 
14087
- #: includes/settings/wcj-settings-product-tabs.php:357
14088
  msgid "This section lets you customize single product tabs."
14089
  msgstr ""
14090
 
14091
- #: includes/settings/wcj-settings-product-tabs.php:361
14092
  msgid "Description Tab"
14093
  msgstr ""
14094
 
14095
- #: includes/settings/wcj-settings-product-tabs.php:362
14096
- #: includes/settings/wcj-settings-product-tabs.php:383
14097
- #: includes/settings/wcj-settings-product-tabs.php:404
14098
  msgid "Remove tab from product page"
14099
  msgstr ""
14100
 
14101
- #: includes/settings/wcj-settings-product-tabs.php:369
14102
- #: includes/settings/wcj-settings-product-tabs.php:390
14103
- #: includes/settings/wcj-settings-product-tabs.php:411
14104
  msgid "Leave blank for WooCommerce defaults"
14105
  msgstr ""
14106
 
14107
- #: includes/settings/wcj-settings-product-tabs.php:382
14108
  msgid "Additional Information Tab"
14109
  msgstr ""
14110
 
14111
- #: includes/settings/wcj-settings-product-tabs.php:403
14112
  msgid "Reviews Tab"
14113
  msgstr ""
14114
 
@@ -14363,8 +14809,8 @@ msgid ""
14363
  msgstr ""
14364
 
14365
  #: includes/settings/wcj-settings-purchase-data.php:179
14366
- #: includes/settings/wcj-settings-sku.php:151
14367
- #: includes/settings/wcj-settings-stock.php:123
14368
  msgid "More Options"
14369
  msgstr ""
14370
 
@@ -14618,27 +15064,27 @@ msgstr ""
14618
  msgid "Per Tag"
14619
  msgstr ""
14620
 
14621
- #: includes/settings/wcj-settings-shipping-by-condition.php:18
14622
- #: includes/settings/wcj-settings-shipping-by-condition.php:24
14623
  #, php-format
14624
  msgid "Shipping Methods by %s"
14625
  msgstr ""
14626
 
14627
- #: includes/settings/wcj-settings-shipping-by-condition.php:47
14628
  #, php-format
14629
  msgid "Include %s"
14630
  msgstr ""
14631
 
14632
- #: includes/settings/wcj-settings-shipping-by-condition.php:58
14633
  #, php-format
14634
  msgid "Exclude %s"
14635
  msgstr ""
14636
 
14637
- #: includes/settings/wcj-settings-shipping-by-condition.php:83
14638
  msgid "Filter Priority"
14639
  msgstr ""
14640
 
14641
- #: includes/settings/wcj-settings-shipping-by-order-amount.php:44
14642
  msgid "Maximum order amount"
14643
  msgstr ""
14644
 
@@ -14728,13 +15174,33 @@ msgid "Only on checkout page"
14728
  msgstr ""
14729
 
14730
  #: includes/settings/wcj-settings-shipping-description.php:30
14731
- #: includes/settings/wcj-settings-shipping-icons.php:39
14732
  msgid ""
14733
  "Possible values: on both cart and checkout pages; only on cart page; only on "
14734
- "checkout page"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14735
  msgstr ""
14736
 
14737
- #: includes/settings/wcj-settings-shipping-description.php:39
14738
  msgid "Shipping Methods Descriptions"
14739
  msgstr ""
14740
 
@@ -14760,6 +15226,12 @@ msgstr ""
14760
  msgid "Icon Visibility"
14761
  msgstr ""
14762
 
 
 
 
 
 
 
14763
  #: includes/settings/wcj-settings-shipping-icons.php:44
14764
  msgid "Icon Style"
14765
  msgstr ""
@@ -14822,6 +15294,23 @@ msgstr ""
14822
  msgid "At least one product in cart must grant free shipping"
14823
  msgstr ""
14824
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14825
  #: includes/settings/wcj-settings-shipping.php:13
14826
  msgid "WooCommerce > Settings > Shipping"
14827
  msgstr ""
@@ -14861,65 +15350,74 @@ msgstr ""
14861
  msgid "Admin Title Custom Shipping"
14862
  msgstr ""
14863
 
14864
- #: includes/settings/wcj-settings-sku.php:16
14865
  msgid "SKU Format Options"
14866
  msgstr ""
14867
 
14868
- #: includes/settings/wcj-settings-sku.php:26
14869
  msgid "From product ID"
14870
  msgstr ""
14871
 
14872
- #: includes/settings/wcj-settings-sku.php:30
14873
  msgid "Number generation method."
14874
  msgstr ""
14875
 
14876
- #: includes/settings/wcj-settings-sku.php:31
14877
  msgid "Possible values: from product ID, sequential or pseudorandom."
14878
  msgstr ""
14879
 
14880
- #: includes/settings/wcj-settings-sku.php:36
14881
  msgid "Sequential Number Generation - Counter"
14882
  msgstr ""
14883
 
14884
- #: includes/settings/wcj-settings-sku.php:37
14885
  msgid ""
14886
  "If you choose to use sequential number inside SKU, you can set current "
14887
  "sequential number counter here."
14888
  msgstr ""
14889
 
14890
- #: includes/settings/wcj-settings-sku.php:48
14891
  msgid "Sequential Number Generation - By Category"
14892
  msgstr ""
14893
 
14894
- #: includes/settings/wcj-settings-sku.php:49
14895
  msgid "Enables sequential number generation by category."
14896
  msgstr ""
14897
 
14898
- #: includes/settings/wcj-settings-sku.php:58
14899
  msgid "SKU prefix."
14900
  msgstr ""
14901
 
14902
- #: includes/settings/wcj-settings-sku.php:64
14903
  msgid "Minimum Number Length"
14904
  msgstr ""
14905
 
14906
- #: includes/settings/wcj-settings-sku.php:65
14907
  msgid "Minimum length for SKU number part."
14908
  msgstr ""
14909
 
14910
- #: includes/settings/wcj-settings-sku.php:72
14911
  msgid "SKU suffix."
14912
  msgstr ""
14913
 
14914
  #: includes/settings/wcj-settings-sku.php:79
 
 
 
 
 
 
 
 
 
14915
  msgid "SKU template."
14916
  msgstr ""
14917
 
14918
- #: includes/settings/wcj-settings-sku.php:87
14919
  msgid "Variable Products Variations"
14920
  msgstr ""
14921
 
14922
- #: includes/settings/wcj-settings-sku.php:88
14923
  msgid ""
14924
  "SKU generation for variations. Please note, that if \"Generate SKU for New "
14925
  "Products Only on First Publish\" option below is not checked, then on new "
@@ -14928,110 +15426,110 @@ msgid ""
14928
  "\"Autogenerate SKUs\" tool manually."
14929
  msgstr ""
14930
 
14931
- #: includes/settings/wcj-settings-sku.php:89
14932
  msgid ""
14933
  "Possible values: SKU same as parent's product; Generate different SKU for "
14934
  "each variation; SKU same as parent's product + variation letter suffix."
14935
  msgstr ""
14936
 
14937
- #: includes/settings/wcj-settings-sku.php:94
14938
  msgid "SKU same as parent's product"
14939
  msgstr ""
14940
 
14941
- #: includes/settings/wcj-settings-sku.php:95
14942
  msgid "Generate different SKU for each variation"
14943
  msgstr ""
14944
 
14945
- #: includes/settings/wcj-settings-sku.php:96
14946
  msgid "SKU same as parent's product + variation letter suffix"
14947
  msgstr ""
14948
 
14949
- #: includes/settings/wcj-settings-sku.php:108
14950
  msgid "Categories Options"
14951
  msgstr ""
14952
 
14953
- #: includes/settings/wcj-settings-sku.php:135
14954
  msgid "Counter (Sequential)"
14955
  msgstr ""
14956
 
14957
- #: includes/settings/wcj-settings-sku.php:156
14958
  msgid "Automatically Generate SKU for New Products"
14959
  msgstr ""
14960
 
14961
- #: includes/settings/wcj-settings-sku.php:158
14962
  msgid "Alternatively you can use Autogenerate SKUs tool."
14963
  msgstr ""
14964
 
14965
- #: includes/settings/wcj-settings-sku.php:164
14966
  msgid "Generate SKU for New Products Only on First Publish"
14967
  msgstr ""
14968
 
14969
- #: includes/settings/wcj-settings-sku.php:166
14970
  msgid ""
14971
  "This is important if, for example, you are using category prefix and don't "
14972
  "want SKU generated too early, before you set the category."
14973
  msgstr ""
14974
 
14975
- #: includes/settings/wcj-settings-sku.php:172
14976
  msgid "Allow Duplicate SKUs"
14977
  msgstr ""
14978
 
14979
- #: includes/settings/wcj-settings-sku.php:174
14980
  msgid ""
14981
  "If you wish to set SKUs manually, and you need to have same SKUs for "
14982
  "different products, you can enable allow duplicate SKUs option here (which "
14983
  "is disabled in WooCommerce by default)."
14984
  msgstr ""
14985
 
14986
- #: includes/settings/wcj-settings-sku.php:180
14987
  msgid "Search by SKU"
14988
  msgstr ""
14989
 
14990
- #: includes/settings/wcj-settings-sku.php:182
14991
  msgid "Add product searching by SKU on frontend."
14992
  msgstr ""
14993
 
14994
- #: includes/settings/wcj-settings-sku.php:188
14995
  msgid "Advanced: Search by SKU Hook"
14996
  msgstr ""
14997
 
14998
- #: includes/settings/wcj-settings-sku.php:189
14999
  msgid ""
15000
  "If you are experiencing any issues with searching by SKU, try changing this "
15001
  "option."
15002
  msgstr ""
15003
 
15004
- #: includes/settings/wcj-settings-sku.php:199
15005
  msgid "Generate SKUs Only for Products with Empty SKU"
15006
  msgstr ""
15007
 
15008
- #: includes/settings/wcj-settings-sku.php:201
15009
  msgid ""
15010
  "This may help if you are going to use Autogenerate SKUs tool, but don't want "
15011
  "to change your existing SKUs."
15012
  msgstr ""
15013
 
15014
- #: includes/settings/wcj-settings-sku.php:207
15015
  msgid "Add SKU to Customer Emails"
15016
  msgstr ""
15017
 
15018
- #: includes/settings/wcj-settings-sku.php:209
15019
  msgid "Adds product SKU to customer's emails."
15020
  msgstr ""
15021
 
15022
- #: includes/settings/wcj-settings-sku.php:215
15023
  msgid "Remove SKU from Admin Emails"
15024
  msgstr ""
15025
 
15026
- #: includes/settings/wcj-settings-sku.php:217
15027
  msgid "Removes product SKU from admin's emails."
15028
  msgstr ""
15029
 
15030
- #: includes/settings/wcj-settings-sku.php:223
15031
  msgid "Disable SKUs"
15032
  msgstr ""
15033
 
15034
- #: includes/settings/wcj-settings-sku.php:225
15035
  msgid ""
15036
  "Enable this option if you are not going to use SKUs in your shop at all."
15037
  msgstr ""
@@ -15138,41 +15636,41 @@ msgstr ""
15138
  msgid "Custom \"In Stock\" HTML"
15139
  msgstr ""
15140
 
15141
- #: includes/settings/wcj-settings-stock.php:39
15142
  msgid "Custom \"In Stock\" Class"
15143
  msgstr ""
15144
 
15145
- #: includes/settings/wcj-settings-stock.php:55
15146
  msgid "Custom \"Out of Stock\" Options"
15147
  msgstr ""
15148
 
15149
- #: includes/settings/wcj-settings-stock.php:60
15150
  msgid "Custom \"Out of Stock\""
15151
  msgstr ""
15152
 
15153
- #: includes/settings/wcj-settings-stock.php:67
15154
  msgid "Custom \"Out of Stock\" HTML"
15155
  msgstr ""
15156
 
15157
- #: includes/settings/wcj-settings-stock.php:80
15158
  msgid "Custom \"Out of Stock\" Class"
15159
  msgstr ""
15160
 
15161
- #: includes/settings/wcj-settings-stock.php:96
15162
- #: includes/settings/wcj-settings-stock.php:101
15163
  msgid "Custom Stock HTML"
15164
  msgstr ""
15165
 
15166
- #: includes/settings/wcj-settings-stock.php:110
15167
  #: includes/settings/meta-box/wcj-settings-meta-box-sale-flash.php:24
15168
  msgid "HTML"
15169
  msgstr ""
15170
 
15171
- #: includes/settings/wcj-settings-stock.php:128
15172
  msgid "Remove Stock Display"
15173
  msgstr ""
15174
 
15175
- #: includes/settings/wcj-settings-stock.php:129
15176
  msgid "This will remove stock display from frontend."
15177
  msgstr ""
15178
 
@@ -15490,17 +15988,17 @@ msgstr ""
15490
  msgid "Content to replace add to cart button on category/archives."
15491
  msgstr ""
15492
 
15493
- #: includes/settings/meta-box/wcj-settings-meta-box-admin-tools.php:18
15494
  #, php-format
15495
  msgid "Product ID: %s"
15496
  msgstr ""
15497
 
15498
- #: includes/settings/meta-box/wcj-settings-meta-box-admin-tools.php:25
15499
  #: includes/settings/meta-box/wcj-settings-meta-box-price-by-country.php:45
15500
  msgid "Regular price"
15501
  msgstr ""
15502
 
15503
- #: includes/settings/meta-box/wcj-settings-meta-box-admin-tools.php:33
15504
  #: includes/settings/meta-box/wcj-settings-meta-box-price-by-country.php:54
15505
  msgid "Sale price"
15506
  msgstr ""
@@ -15530,6 +16028,17 @@ msgstr ""
15530
  msgid "PayPal Email"
15531
  msgstr ""
15532
 
 
 
 
 
 
 
 
 
 
 
 
15533
  #: includes/settings/meta-box/wcj-settings-meta-box-offer-price.php:14
15534
  msgid "Enable Offer Price"
15535
  msgstr ""
@@ -15550,6 +16059,11 @@ msgstr ""
15550
  msgid "Save order after you change this field."
15551
  msgstr ""
15552
 
 
 
 
 
 
15553
  #: includes/settings/meta-box/wcj-settings-meta-box-price-by-user-role.php:27
15554
  msgid "Per Product Settings (press Update after changing)"
15555
  msgstr ""
@@ -15803,11 +16317,11 @@ msgstr ""
15803
  msgid "Enable Custom Shipping"
15804
  msgstr ""
15805
 
15806
- #: includes/shortcodes/class-wcj-shortcodes-general.php:92
15807
  msgid "Tax toggle (incl.)"
15808
  msgstr ""
15809
 
15810
- #: includes/shortcodes/class-wcj-shortcodes-general.php:93
15811
  msgid "Tax toggle (excl.)"
15812
  msgstr ""
15813
 
@@ -15819,11 +16333,11 @@ msgstr ""
15819
  msgid "Standard"
15820
  msgstr ""
15821
 
15822
- #: includes/shortcodes/class-wcj-shortcodes-orders.php:112
15823
  msgid "Dollars"
15824
  msgstr ""
15825
 
15826
- #: includes/shortcodes/class-wcj-shortcodes-orders.php:113
15827
  msgid "Cents"
15828
  msgstr ""
15829
 
@@ -15865,16 +16379,16 @@ msgstr ""
15865
  msgid "Edit Product"
15866
  msgstr ""
15867
 
15868
- #: includes/shortcodes/class-wcj-shortcodes-products.php:318
15869
  #, php-format
15870
  msgid "%s ago"
15871
  msgstr ""
15872
 
15873
- #: includes/shortcodes/class-wcj-shortcodes-products.php:334
15874
  msgid "No sales yet."
15875
  msgstr ""
15876
 
15877
- #: includes/shortcodes/class-wcj-shortcodes-products.php:557
15878
  msgid "In stock"
15879
  msgstr ""
15880
 
113
 
114
  #: includes/class-wcj-admin-bar.php:265
115
  #: includes/class-wcj-checkout-files-upload.php:146
116
+ #: includes/class-wcj-eu-vat-number.php:129
117
+ #: includes/class-wcj-max-products-per-user.php:115
118
+ #: includes/class-wcj-orders.php:109 includes/class-wcj-orders.php:138
119
  #: includes/class-wcj-payment-gateways.php:91
120
  #: includes/class-wcj-track-users.php:117
121
  #: includes/class-wcj-track-users.php:213
211
  msgid "Customer list"
212
  msgstr ""
213
 
214
+ #: includes/class-wcj-admin-bar.php:390 includes/class-wcj-stock.php:26
215
  #: includes/reports/wcj-class-reports-stock.php:256
216
  #: includes/settings/wcj-settings-reports.php:127
217
  #: includes/settings/wcj-settings-reports.php:133
224
  msgstr ""
225
 
226
  #: includes/class-wcj-admin-bar.php:398
227
+ #: includes/shortcodes/class-wcj-shortcodes-products.php:561
228
  msgid "Out of stock"
229
  msgstr ""
230
 
262
 
263
  #: includes/class-wcj-admin-bar.php:436
264
  #: includes/class-wcj-product-bulk-price-converter.php:149
265
+ #: includes/class-wcj-sku.php:419
266
  #: includes/export/class-wcj-fields-helper.php:318
 
267
  #: includes/settings/wcj-settings-product-by-user.php:19
268
  #: includes/shortcodes/class-wcj-shortcodes-products-add-form.php:185
269
  #: includes/shortcodes/class-wcj-shortcodes-products-add-form.php:406
325
  #: includes/settings/wcj-settings-checkout-custom-fields.php:170
326
  #: includes/settings/wcj-settings-checkout-custom-info.php:56
327
  #: includes/settings/wcj-settings-empty-cart.php:59
328
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:115
329
  #: includes/settings/wcj-settings-price-by-user-role.php:46
330
  msgid "Shipping"
331
  msgstr ""
414
  msgstr ""
415
 
416
  #: includes/class-wcj-admin-orders-list.php:281
417
+ #: includes/settings/wcj-settings-product-by-country.php:93
418
  msgid "All countries"
419
  msgstr ""
420
 
443
  msgid "Customize WooCommerce admin products list."
444
  msgstr ""
445
 
446
+ #: includes/class-wcj-admin-tools.php:24 includes/class-wcj-admin-tools.php:31
447
  msgid "Admin Tools"
448
  msgstr ""
449
 
450
+ #: includes/class-wcj-admin-tools.php:25
451
  msgid "Booster for WooCommerce debug and log tools."
452
  msgstr ""
453
 
454
+ #: includes/class-wcj-admin-tools.php:32
455
  msgid "Log."
456
  msgstr ""
457
 
458
+ #: includes/class-wcj-admin-tools.php:33
459
  #: includes/settings/wcj-settings-admin-tools.php:19
460
  msgid "Log"
461
  msgstr ""
462
 
463
+ #: includes/class-wcj-admin-tools.php:44
464
  #, php-format
465
  msgid "Current PHP memory limit: %s."
466
  msgstr ""
467
 
468
+ #: includes/class-wcj-admin-tools.php:49
469
  #, php-format
470
  msgid "Current PHP time limit: %s seconds."
471
  msgstr ""
472
 
473
+ #: includes/class-wcj-admin-tools.php:103
474
  #: includes/settings/wcj-settings-export.php:157
475
  #: includes/settings/wcj-settings-export.php:236
476
  msgid "Product Meta"
477
  msgstr ""
478
 
479
+ #: includes/class-wcj-admin-tools.php:120
480
  #: includes/settings/wcj-settings-export.php:86
481
  #: includes/settings/wcj-settings-export.php:154
482
  msgid "Order Meta"
483
  msgstr ""
484
 
485
+ #: includes/class-wcj-admin-tools.php:154
486
  msgid "Order Items Meta"
487
  msgstr ""
488
 
489
+ #: includes/class-wcj-admin-tools.php:156
490
  msgid "Item Key"
491
  msgstr ""
492
 
493
+ #: includes/class-wcj-admin-tools.php:156
494
  msgid "Item Meta Key"
495
  msgstr ""
496
 
497
+ #: includes/class-wcj-admin-tools.php:156
498
  msgid "Item Meta Value"
499
  msgstr ""
500
 
501
+ #: includes/class-wcj-admin-tools.php:182
502
  msgid "Delete Log"
503
  msgstr ""
504
 
505
+ #: includes/class-wcj-admin-tools.php:185
506
  #, php-format
507
  msgid "Now: %s"
508
  msgstr ""
509
 
510
+ #: includes/class-wcj-admin-tools.php:189
511
  msgid "Log is empty."
512
  msgstr ""
513
 
514
+ #: includes/class-wcj-admin-tools.php:220
515
  msgid "NOT DEFINED"
516
  msgstr ""
517
 
676
  #: includes/class-wcj-checkout-files-upload.php:554
677
  #: includes/class-wcj-checkout-files-upload.php:555
678
  #: includes/settings/wcj-settings-checkout-files-upload.php:107
679
+ #: includes/settings/wcj-settings-sku.php:227
680
  #: includes/settings/wcj-settings-sorting.php:144
681
+ #: includes/settings/wcj-settings-stock.php:133
682
  msgid "Remove"
683
  msgstr ""
684
 
749
  msgid "Automatic currency exchange rates for WooCommerce."
750
  msgstr ""
751
 
752
+ #: includes/class-wcj-currency-exchange-rates.php:181
753
  #: includes/settings/wcj-settings-currency-exchange-rates.php:46
754
  msgid "Exchange Rates Server"
755
  msgstr ""
756
 
757
+ #: includes/class-wcj-currency-exchange-rates.php:186
758
  #, php-format
759
  msgid "Use default: %s"
760
  msgstr ""
761
 
762
+ #: includes/class-wcj-currency-exchange-rates.php:209
763
+ msgid "Exchange Rates Offset (Percent)"
764
+ msgstr ""
765
+
766
+ #: includes/class-wcj-currency-exchange-rates.php:214
767
+ #, php-format
768
+ msgid "Use default: %s%%"
769
+ msgstr ""
770
+
771
+ #: includes/class-wcj-currency-exchange-rates.php:215
772
+ msgid "Custom offset"
773
+ msgstr ""
774
+
775
+ #: includes/class-wcj-currency-exchange-rates.php:219
776
+ msgid "Custom offset (Percent)"
777
+ msgstr ""
778
+
779
+ #: includes/class-wcj-currency-exchange-rates.php:220
780
+ msgid "Used when \"Custom offset\" option is selected above."
781
+ msgstr ""
782
+
783
  #: includes/class-wcj-currency-external-products.php:23
784
  msgid "Currency for External Products"
785
  msgstr ""
796
  msgid "Display prices for WooCommerce products in different currencies."
797
  msgstr ""
798
 
799
+ #: includes/class-wcj-currency-per-product.php:169
800
  #: includes/settings/wcj-settings-currency-per-product.php:43
801
  msgid ""
802
  "Only one product can be added to the cart. Clear the cart or finish the "
803
  "order, before adding another product to the cart."
804
  msgstr ""
805
 
806
+ #: includes/class-wcj-currency-per-product.php:184
807
  #: includes/settings/wcj-settings-currency-per-product.php:50
808
  msgid ""
809
  "Only products with same currency can be added to the cart. Clear the cart or "
810
  "finish the order, before adding products with another currency to the cart."
811
  msgstr ""
812
 
813
+ #: includes/class-wcj-currency-per-product.php:230
814
  #, php-format
815
  msgctxt "Price range: from-to"
816
  msgid "%1$s&ndash;%2$s"
845
  "WooCommerce emails."
846
  msgstr ""
847
 
848
+ #: includes/class-wcj-email-options.php:109
849
  msgid "Booster: Email Forwarding Options"
850
  msgstr ""
851
 
852
+ #: includes/class-wcj-email-options.php:110
853
  msgid "Email Forwarding Options"
854
  msgstr ""
855
 
856
+ #: includes/class-wcj-email-options.php:112
857
  msgid ""
858
  "This section lets you add another email recipient(s) to all WooCommerce "
859
  "emails. Leave blank to disable."
860
  msgstr ""
861
 
862
+ #: includes/class-wcj-email-options.php:116
863
  msgid "Cc Email"
864
  msgstr ""
865
 
866
+ #: includes/class-wcj-email-options.php:117
867
  msgid "Cc to email, e.g. youremail@yourdomain.com. Leave blank to disable."
868
  msgstr ""
869
 
870
+ #: includes/class-wcj-email-options.php:123
871
  msgid "Bcc Email"
872
  msgstr ""
873
 
874
+ #: includes/class-wcj-email-options.php:124
875
  msgid "Bcc to email, e.g. youremail@yourdomain.com. Leave blank to disable."
876
  msgstr ""
877
 
878
+ #: includes/class-wcj-email-options.php:130
879
+ msgid "Orders Emails: Enable for Statuses"
880
+ msgstr ""
881
+
882
+ #: includes/class-wcj-email-options.php:132
883
+ msgid ""
884
+ "If you want to forward emails for certain orders only, set order statuses "
885
+ "here. Leave blank to send for all orders statuses."
886
+ msgstr ""
887
+
888
  #: includes/class-wcj-emails-verification.php:26
889
  msgid "Email Verification"
890
  msgstr ""
988
  msgstr ""
989
 
990
  #: includes/class-wcj-empty-cart-button.php:25
991
+ #: includes/shortcodes/class-wcj-shortcodes-general.php:380
992
  msgid "Empty Cart Button"
993
  msgstr ""
994
 
1026
 
1027
  #: includes/class-wcj-eu-vat-number.php:185 includes/class-wcj-orders.php:138
1028
  #: includes/settings/wcj-settings-orders.php:83
1029
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:27
1030
  msgid "Country by IP"
1031
  msgstr ""
1032
 
1220
  msgstr ""
1221
 
1222
  #: includes/class-wcj-general.php:197 includes/class-wcj-general.php:210
1223
+ #: includes/class-wcj-sku.php:417
1224
  #: includes/reports/wcj-class-reports-sales.php:192
1225
+ #: includes/settings/wcj-settings-order-numbers.php:150
1226
  #: includes/settings/wcj-settings-product-by-user.php:161
1227
  #: includes/settings/wcj-settings-related-products.php:30
1228
  msgid "ID"
1238
 
1239
  #: includes/class-wcj-general.php:197
1240
  #: includes/class-wcj-product-by-user.php:197
1241
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:93
1242
  #: includes/tools/class-wcj-order-statuses-tool.php:142
1243
  #: includes/tools/class-wcj-order-statuses-tool.php:214
1244
  msgid "Actions"
1249
  #: includes/class-wcj-product-bulk-meta-editor.php:367
1250
  #: includes/class-wcj-product-by-user.php:206
1251
  #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:138
1252
+ #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:309
1253
  #: includes/shortcodes/class-wcj-shortcodes-products-add-form.php:367
1254
  #: includes/tools/class-wcj-order-statuses-tool.php:157
1255
  msgid "Delete"
1264
  msgstr ""
1265
 
1266
  #: includes/class-wcj-general.php:215
1267
+ #: includes/class-wcj-shipping-by-products.php:144
1268
  #: includes/settings/wcj-settings-admin-orders-list.php:134
1269
  #: includes/settings/wcj-settings-checkout-custom-fields.php:22
1270
  #: includes/settings/wcj-settings-checkout-custom-fields.php:29
1280
  #: includes/settings/wcj-settings-order-min-amount.php:53
1281
  #: includes/settings/wcj-settings-orders.php:89
1282
  #: includes/settings/wcj-settings-orders.php:116
1283
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:118
1284
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:170
1285
+ #: includes/settings/wcj-settings-product-by-country.php:117
1286
  #: includes/settings/wcj-settings-product-by-user.php:114
1287
  #: includes/settings/wcj-settings-product-open-pricing.php:108
1288
+ #: includes/settings/wcj-settings-product-tabs.php:247
1289
  #: includes/settings/wcj-settings-purchase-data.php:134
1290
  #: includes/settings/wcj-settings-purchase-data.php:143
1291
  #: includes/settings/wcj-settings-purchase-data.php:162
1292
  #: includes/settings/wcj-settings-purchase-data.php:169
1293
+ #: includes/settings/wcj-settings-sku.php:192
1294
+ #: includes/settings/wcj-settings-sku.php:219
1295
  #: includes/shortcodes/class-wcj-shortcodes-products-add-form.php:425
1296
  #: includes/tools/class-wcj-order-statuses-tool.php:228
1297
  msgid "Add"
1300
  #: includes/class-wcj-general.php:278 includes/class-wcj-general.php:320
1301
  #: includes/class-wcj-product-bulk-meta-editor.php:339
1302
  #: includes/class-wcj-product-bulk-price-converter.php:148
1303
+ #: includes/class-wcj-sku.php:418
1304
  #: includes/reports/wcj-class-reports-sales.php:193
1305
  #: includes/reports/wcj-class-reports-stock.php:253
1306
  msgid "Product"
1335
  #: includes/class-wcj-left-to-free-shipping.php:62
1336
  #: includes/class-wcj-left-to-free-shipping.php:72
1337
  #: includes/class-wcj-left-to-free-shipping.php:82
1338
+ #: includes/functions/wcj-functions-shipping.php:273
1339
  #: includes/settings/wcj-settings-left-to-free-shipping.php:37
1340
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:68
1341
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:102
1342
  #: includes/widgets/class-wcj-widget-left-to-free-shipping.php:61
1343
  #, php-format
1344
  msgid "%left_to_free% left to free shipping"
1345
  msgstr ""
1346
 
1347
+ #: includes/class-wcj-max-products-per-user.php:28
1348
+ msgid "Maximum Products per User"
1349
+ msgstr ""
1350
+
1351
+ #: includes/class-wcj-max-products-per-user.php:29
1352
+ msgid "Limit number of items your WooCommerce customers (logged) can buy."
1353
+ msgstr ""
1354
+
1355
+ #: includes/class-wcj-max-products-per-user.php:30
1356
+ msgid ""
1357
+ "Please note, that there is no maximum quantity set for not-logged (i.e. "
1358
+ "guest) users. Product quantities are updated, when order status is changed "
1359
+ "to completed."
1360
+ msgstr ""
1361
+
1362
+ #: includes/class-wcj-max-products-per-user.php:62
1363
+ msgid "Data re-calculated."
1364
+ msgstr ""
1365
+
1366
+ #: includes/class-wcj-max-products-per-user.php:63
1367
+ #, php-format
1368
+ msgid "%s order(s) processed."
1369
+ msgstr ""
1370
+
1371
+ #: includes/class-wcj-max-products-per-user.php:115
1372
+ msgid "Maximum Products per User: Sales Data"
1373
+ msgstr ""
1374
+
1375
+ #: includes/class-wcj-max-products-per-user.php:132
1376
+ msgid "User ID"
1377
+ msgstr ""
1378
+
1379
+ #: includes/class-wcj-max-products-per-user.php:132
1380
+ msgid "User Name"
1381
+ msgstr ""
1382
+
1383
+ #: includes/class-wcj-max-products-per-user.php:132
1384
+ msgid "Qty Bought"
1385
+ msgstr ""
1386
+
1387
+ #: includes/class-wcj-max-products-per-user.php:135
1388
+ #: includes/functions/wcj-functions-users.php:136
1389
+ #: includes/functions/wcj-functions-users.php:156
1390
+ msgid "Guest"
1391
+ msgstr ""
1392
+
1393
+ #: includes/class-wcj-max-products-per-user.php:144
1394
+ msgid "No data yet."
1395
+ msgstr ""
1396
+
1397
+ #: includes/class-wcj-max-products-per-user.php:263
1398
+ #: includes/settings/wcj-settings-max-products-per-user.php:63
1399
+ msgid ""
1400
+ "You can only buy maximum %max_qty% pcs. of %product_title% (you already "
1401
+ "bought %qty_already_bought% pcs.)."
1402
+ msgstr ""
1403
+
1404
  #: includes/class-wcj-mini-cart.php:24
1405
  msgid "Mini Cart Custom Info"
1406
  msgstr ""
1429
  msgid "Enter prices for WooCommerce products in different currencies."
1430
  msgstr ""
1431
 
1432
+ #: includes/class-wcj-multicurrency.php:25
1433
  msgid "Multicurrency (Currency Switcher)"
1434
  msgstr ""
1435
 
1436
+ #: includes/class-wcj-multicurrency.php:26
1437
  msgid "Add multiple currencies (currency switcher) to WooCommerce."
1438
  msgstr ""
1439
 
1440
+ #: includes/class-wcj-multicurrency.php:28
1441
  #, php-format
1442
  msgid ""
1443
  "After setting currencies in the Currencies Options section below, use %s "
1445
  "insert switcher in your <strong>PHP code</strong>, just use %s code."
1446
  msgstr ""
1447
 
1448
+ #: includes/class-wcj-multicurrency.php:29
1449
  #: includes/widgets/class-wcj-widget-multicurrency.php:27
1450
  msgid "Booster - Multicurrency Switcher"
1451
  msgstr ""
1464
  #: includes/class-wcj-purchase-data.php:94
1465
  #: includes/class-wcj-track-users.php:296
1466
  #: includes/classes/class-wcj-module.php:613
1467
+ #: includes/functions/wcj-functions-general.php:88
1468
  #: includes/functions/wcj-functions-html.php:97
1469
  #: includes/reports/wcj-class-reports-monthly-sales.php:341
1470
  #: includes/settings/wcj-settings-empty-cart.php:80
1493
  #: includes/class-wcj-offer-price.php:113
1494
  #: includes/functions/wcj-functions-reports.php:21
1495
  #: includes/functions/wcj-functions-reports.php:24
1496
+ #: includes/settings/wcj-settings-order-numbers.php:151
1497
  #: includes/settings/wcj-settings-related-products.php:23
1498
  msgid "Date"
1499
  msgstr ""
1734
  msgid "Minimum WooCommerce order amount (optionally by user role)."
1735
  msgstr ""
1736
 
1737
+ #: includes/class-wcj-order-numbers.php:25
1738
  #: includes/settings/wcj-settings-order-numbers.php:15
1739
  msgid "Order Numbers"
1740
  msgstr ""
1741
 
1742
+ #: includes/class-wcj-order-numbers.php:26
1743
  msgid ""
1744
  "WooCommerce sequential order numbering, custom order number prefix, suffix "
1745
  "and number width."
1746
  msgstr ""
1747
 
1748
+ #: includes/class-wcj-order-numbers.php:32
1749
  msgid "Orders Renumerate"
1750
  msgstr ""
1751
 
1752
+ #: includes/class-wcj-order-numbers.php:33
1753
  msgid "Tool renumerates all orders."
1754
  msgstr ""
1755
 
1756
+ #: includes/class-wcj-order-numbers.php:202
1757
  msgid "Orders successfully renumerated!"
1758
  msgstr ""
1759
 
1760
+ #: includes/class-wcj-order-numbers.php:205
1761
  #, php-format
1762
  msgid "Sequential number generation is enabled. Next order number will be %s."
1763
  msgstr ""
1764
 
1765
+ #: includes/class-wcj-order-numbers.php:214
1766
  #, php-format
1767
  msgid ""
1768
  "Press the button below to renumerate all existing orders starting from order "
1769
  "counter settings in <a href=\"%s\">Order Numbers</a> module."
1770
  msgstr ""
1771
 
1772
+ #: includes/class-wcj-order-numbers.php:221
1773
  msgid "Renumerate orders"
1774
  msgstr ""
1775
 
1860
  msgid "Set allowed currencies for WooCommerce payment gateways to show up."
1861
  msgstr ""
1862
 
1863
+ #: includes/class-wcj-payment-gateways-by-shipping.php:26
1864
  msgid "Gateways by Shipping"
1865
  msgstr ""
1866
 
1867
+ #: includes/class-wcj-payment-gateways-by-shipping.php:27
1868
  msgid "Set \"enable for shipping methods\" for WooCommerce payment gateways."
1869
  msgstr ""
1870
 
1978
  msgid "Invoices Monthly Reports."
1979
  msgstr ""
1980
 
1981
+ #: includes/class-wcj-pdf-invoicing.php:91
 
1982
  #: includes/settings/wcj-settings-price-by-country.php:174
1983
  #: includes/settings/wcj-settings-price-by-country.php:179
1984
  #: includes/settings/wcj-settings-price-by-country.php:184
1985
  msgid "Generate"
1986
  msgstr ""
1987
 
1988
+ #: includes/class-wcj-pdf-invoicing.php:92
1989
+ msgid "Download (Zip)"
1990
+ msgstr ""
1991
+
1992
+ #: includes/class-wcj-pdf-invoicing.php:93
1993
+ msgid "Merge (Print)"
1994
  msgstr ""
1995
 
1996
+ #: includes/class-wcj-pdf-invoicing.php:126
1997
  #, php-format
1998
  msgid "Document generated."
1999
  msgid_plural "%s documents generated."
2000
  msgstr[0] ""
2001
  msgstr[1] ""
2002
 
2003
+ #: includes/class-wcj-pdf-invoicing.php:133
2004
  #: includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php:172
2005
  #, php-format
2006
  msgid ""
2008
  "hosting provider."
2009
  msgstr ""
2010
 
2011
+ #: includes/class-wcj-pdf-invoicing.php:139
2012
  msgid "Booster: ZipArchive error."
2013
  msgstr ""
2014
 
2015
+ #: includes/class-wcj-pdf-invoicing.php:434
 
 
 
 
 
 
2016
  msgid "You are not allowed to view the invoice."
2017
  msgstr ""
2018
 
2109
  #: includes/settings/wcj-settings-checkout-files-upload.php:291
2110
  #: includes/settings/wcj-settings-coupon-code-generator.php:32
2111
  #: includes/settings/wcj-settings-currency-exchange-rates.php:54
2112
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:85
2113
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:93
2114
  #: includes/settings/wcj-settings-currency-per-product.php:66
2115
  #: includes/settings/wcj-settings-currency-per-product.php:73
2116
  #: includes/settings/wcj-settings-currency-per-product.php:80
2125
  #: includes/settings/wcj-settings-general.php:151
2126
  #: includes/settings/wcj-settings-general.php:202
2127
  #: includes/settings/wcj-settings-global-discount.php:52
2128
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:28
2129
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:57
2130
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:91
2131
+ #: includes/settings/wcj-settings-max-products-per-user.php:69
2132
  #: includes/settings/wcj-settings-more-button-labels.php:28
2133
  #: includes/settings/wcj-settings-multicurrency-base-price.php:40
2134
  #: includes/settings/wcj-settings-multicurrency-base-price.php:55
2139
  #: includes/settings/wcj-settings-order-numbers.php:97
2140
  #: includes/settings/wcj-settings-order-numbers.php:105
2141
  #: includes/settings/wcj-settings-order-numbers.php:112
2142
+ #: includes/settings/wcj-settings-order-numbers.php:119
2143
  #: includes/settings/wcj-settings-order-quantities.php:53
2144
  #: includes/settings/wcj-settings-order-quantities.php:111
2145
  #: includes/settings/wcj-settings-order-quantities.php:137
2147
  #: includes/settings/wcj-settings-orders.php:25
2148
  #: includes/settings/wcj-settings-orders.php:53
2149
  #: includes/settings/wcj-settings-orders.php:72
2150
+ #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:23
2151
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:55
2152
  #: includes/settings/wcj-settings-pdf-invoicing-display.php:113
2153
  #: includes/settings/wcj-settings-pdf-invoicing-footer.php:23
2154
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:24
2155
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:23
2156
  #: includes/settings/wcj-settings-pdf-invoicing-styling.php:73
2157
  #: includes/settings/wcj-settings-price-by-country.php:69
2183
  #: includes/settings/wcj-settings-product-by-country.php:21
2184
  #: includes/settings/wcj-settings-product-by-country.php:29
2185
  #: includes/settings/wcj-settings-product-by-country.php:37
2186
+ #: includes/settings/wcj-settings-product-by-country.php:44
2187
  #: includes/settings/wcj-settings-product-by-date.php:21
2188
  #: includes/settings/wcj-settings-product-by-date.php:53
2189
  #: includes/settings/wcj-settings-product-by-time.php:21
2203
  #: includes/settings/wcj-settings-product-open-pricing.php:87
2204
  #: includes/settings/wcj-settings-product-open-pricing.php:94
2205
  #: includes/settings/wcj-settings-product-price-by-formula.php:30
2206
+ #: includes/settings/wcj-settings-product-tabs.php:43
2207
+ #: includes/settings/wcj-settings-product-tabs.php:232
2208
+ #: includes/settings/wcj-settings-product-tabs.php:240
2209
  #: includes/settings/wcj-settings-products-xml.php:73
2210
  #: includes/settings/wcj-settings-purchase-data.php:22
2211
  #: includes/settings/wcj-settings-purchase-data.php:29
2218
  #: includes/settings/wcj-settings-related-products.php:112
2219
  #: includes/settings/wcj-settings-related-products.php:119
2220
  #: includes/settings/wcj-settings-related-products.php:149
2221
+ #: includes/settings/wcj-settings-shipping-by-condition.php:25
2222
+ #: includes/settings/wcj-settings-shipping-by-order-amount.php:21
2223
  #: includes/settings/wcj-settings-shipping-calculator.php:20
2224
  #: includes/settings/wcj-settings-shipping-calculator.php:27
2225
  #: includes/settings/wcj-settings-shipping-calculator.php:34
2226
  #: includes/settings/wcj-settings-shipping-calculator.php:41
2227
  #: includes/settings/wcj-settings-shipping-options.php:63
2228
+ #: includes/settings/wcj-settings-shipping-time.php:31
2229
+ #: includes/settings/wcj-settings-shipping-time.php:40
2230
  #: includes/settings/wcj-settings-shipping.php:24
2231
+ #: includes/settings/wcj-settings-sku.php:51
2232
+ #: includes/settings/wcj-settings-sku.php:168
2233
+ #: includes/settings/wcj-settings-sku.php:176
2234
+ #: includes/settings/wcj-settings-sku.php:184
2235
+ #: includes/settings/wcj-settings-sku.php:211
2236
  #: includes/settings/wcj-settings-stock.php:27
2237
+ #: includes/settings/wcj-settings-stock.php:41
2238
+ #: includes/settings/wcj-settings-stock.php:69
2239
+ #: includes/settings/wcj-settings-stock.php:83
2240
  #: includes/settings/wcj-settings-track-users.php:47
2241
  #: includes/settings/wcj-settings-wholesale-price.php:22
2242
  #: includes/settings/wcj-settings-wholesale-price.php:29
2587
  msgstr ""
2588
 
2589
  #: includes/class-wcj-product-bulk-price-converter.php:260
2590
+ #: includes/shortcodes/class-wcj-shortcodes-products.php:351
2591
  msgid "Any"
2592
  msgstr ""
2593
 
2611
  msgid "Change Prices"
2612
  msgstr ""
2613
 
2614
+ #: includes/class-wcj-product-by-country.php:26
2615
  msgid "Product Visibility by Country"
2616
  msgstr ""
2617
 
2618
+ #: includes/class-wcj-product-by-country.php:27
2619
  msgid "Display WooCommerce products by customer's country."
2620
  msgstr ""
2621
 
2622
+ #: includes/class-wcj-product-by-country.php:29
2623
  msgid ""
2624
  "When enabled, module will add new \"Booster: Product Visibility by Country\" "
2625
  "meta box to each product's edit page."
2626
  msgstr ""
2627
 
2628
+ #: includes/class-wcj-product-by-country.php:69
2629
  #: includes/widgets/class-wcj-widget-country-switcher.php:69
2630
  #: includes/widgets/class-wcj-widget-selector.php:64
2631
  msgid "Countries"
2722
  msgstr ""
2723
 
2724
  #: includes/class-wcj-product-by-user.php:197
2725
+ #: includes/class-wcj-product-tabs.php:591
2726
  #: includes/gateways/class-wc-gateway-wcj-custom.php:66
2727
  #: includes/input-fields/wcj-product-input-fields-options.php:51
2728
  #: includes/settings/wcj-settings-export.php:75
2731
  #: includes/settings/wcj-settings-product-add-to-cart.php:300
2732
  #: includes/settings/wcj-settings-product-addons.php:92
2733
  #: includes/settings/wcj-settings-product-by-user.php:167
2734
+ #: includes/settings/wcj-settings-product-tabs.php:72
2735
+ #: includes/settings/wcj-settings-product-tabs.php:388
2736
+ #: includes/settings/wcj-settings-product-tabs.php:409
2737
+ #: includes/settings/wcj-settings-product-tabs.php:430
2738
  #: includes/settings/wcj-settings-purchase-data.php:66
2739
  #: includes/settings/wcj-settings-related-products.php:24
2740
  #: includes/settings/meta-box/wcj-settings-meta-box-product-addons.php:57
2757
 
2758
  #: includes/class-wcj-product-custom-info.php:24
2759
  #: includes/admin/class-wc-settings-jetpack.php:467
2760
+ #: includes/admin/class-wc-settings-jetpack.php:479
2761
+ #: includes/admin/class-wc-settings-jetpack.php:488
2762
+ #: includes/functions/wcj-functions-general.php:347
2763
  msgid "Product Info"
2764
  msgstr ""
2765
 
2790
  msgstr ""
2791
 
2792
  #: includes/class-wcj-product-custom-visibility.php:34
2793
+ #: includes/settings/wcj-settings-product-by-country.php:63
2794
  #: includes/widgets/class-wcj-widget-selector.php:27
2795
  msgid "Booster - Selector"
2796
  msgstr ""
2810
  #: includes/class-wcj-product-info.php:124
2811
  #: includes/settings/wcj-settings-offer-price.php:91
2812
  #: includes/settings/wcj-settings-product-add-to-cart.php:326
2813
+ #: includes/settings/wcj-settings-product-custom-info.php:114
2814
  msgid "Before product"
2815
  msgstr ""
2816
 
2817
  #: includes/class-wcj-product-info.php:125
2818
  #: includes/settings/wcj-settings-product-add-to-cart.php:327
2819
+ #: includes/settings/wcj-settings-product-custom-info.php:115
2820
  msgid "Before product title"
2821
  msgstr ""
2822
 
2823
  #: includes/class-wcj-product-info.php:126
2824
  #: includes/settings/wcj-settings-offer-price.php:92
2825
  #: includes/settings/wcj-settings-product-add-to-cart.php:328
2826
+ #: includes/settings/wcj-settings-product-custom-info.php:118
2827
  msgid "After product"
2828
  msgstr ""
2829
 
2830
  #: includes/class-wcj-product-info.php:127
2831
  #: includes/settings/wcj-settings-product-add-to-cart.php:329
2832
+ #: includes/settings/wcj-settings-product-custom-info.php:117
2833
  msgid "After product title"
2834
  msgstr ""
2835
 
2836
  #: includes/class-wcj-product-info.php:139
2837
  #: includes/settings/wcj-settings-offer-price.php:72
2838
  #: includes/settings/wcj-settings-product-add-to-cart.php:292
2839
+ #: includes/settings/wcj-settings-product-custom-info.php:105
2840
  msgid "Inside single product summary"
2841
  msgstr ""
2842
 
2843
  #: includes/class-wcj-product-info.php:140
2844
  #: includes/settings/wcj-settings-offer-price.php:71
2845
  #: includes/settings/wcj-settings-product-add-to-cart.php:291
2846
+ #: includes/settings/wcj-settings-product-custom-info.php:104
2847
  msgid "Before single product summary"
2848
  msgstr ""
2849
 
2850
  #: includes/class-wcj-product-info.php:141
2851
  #: includes/settings/wcj-settings-offer-price.php:73
2852
  #: includes/settings/wcj-settings-product-add-to-cart.php:293
2853
+ #: includes/settings/wcj-settings-product-custom-info.php:106
2854
  msgid "After single product summary"
2855
  msgstr ""
2856
 
2858
  #: includes/settings/wcj-settings-cart.php:51
2859
  #: includes/settings/wcj-settings-checkout-custom-info.php:47
2860
  #: includes/settings/wcj-settings-checkout-files-upload.php:51
2861
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:42
2862
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:73
2863
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:107
2864
  #: includes/settings/wcj-settings-mini-cart.php:46
2865
  #: includes/settings/wcj-settings-my-account.php:74
2866
  #: includes/settings/wcj-settings-product-add-to-cart.php:286
2867
  #: includes/settings/wcj-settings-product-add-to-cart.php:321
2868
+ #: includes/settings/wcj-settings-product-custom-info.php:97
2869
  #: includes/settings/wcj-settings-product-info.php:50
2870
  #: includes/settings/wcj-settings-product-info.php:83
2871
  #: includes/settings/wcj-settings-products-per-page.php:36
2876
  #: includes/settings/wcj-settings-checkout-custom-fields.php:157
2877
  #: includes/settings/wcj-settings-product-info.php:61
2878
  #: includes/settings/wcj-settings-product-info.php:94
2879
+ #: includes/settings/wcj-settings-product-tabs.php:86
2880
+ #: includes/settings/wcj-settings-product-tabs.php:398
2881
+ #: includes/settings/wcj-settings-product-tabs.php:419
2882
+ #: includes/settings/wcj-settings-product-tabs.php:440
2883
  msgid "Priority (i.e. Order)"
2884
  msgstr ""
2885
 
2902
 
2903
  #: includes/class-wcj-product-input-fields.php:24
2904
  #: includes/admin/class-wc-settings-jetpack.php:468
2905
+ #: includes/input-fields/class-wcj-product-input-fields-core.php:126
2906
  msgid "Product Input Fields"
2907
  msgstr ""
2908
 
2910
  msgid "WooCommerce product input fields."
2911
  msgstr ""
2912
 
2913
+ #: includes/class-wcj-product-listings.php:27
2914
  msgid "Product Listings"
2915
  msgstr ""
2916
 
2917
+ #: includes/class-wcj-product-listings.php:28
2918
  msgid ""
2919
  "Change WooCommerce display options for shop and category pages: show/hide "
2920
  "categories count, exclude categories, show/hide empty categories."
2995
  "remove WooCommerce default product tabs."
2996
  msgstr ""
2997
 
2998
+ #: includes/class-wcj-product-tabs.php:548
2999
  msgid "Booster: Custom Tabs"
3000
  msgstr ""
3001
 
3002
+ #: includes/class-wcj-product-tabs.php:575
3003
  msgid "Total number of custom tabs"
3004
  msgstr ""
3005
 
3006
+ #: includes/class-wcj-product-tabs.php:581
3007
+ #: includes/input-fields/class-wcj-product-input-fields-core.php:154
3008
  msgid "Click \"Update\" product after you change this number."
3009
  msgstr ""
3010
 
3011
+ #: includes/class-wcj-product-tabs.php:596
3012
  #: includes/settings/wcj-settings-checkout-custom-fields.php:108
3013
+ #: includes/settings/wcj-settings-product-tabs.php:79
3014
  msgid "Key"
3015
  msgstr ""
3016
 
3017
+ #: includes/class-wcj-product-tabs.php:601
3018
  #: includes/input-fields/wcj-product-input-fields-options.php:21
3019
  #: includes/settings/wcj-settings-related-products.php:59
3020
  #: includes/settings/wcj-settings-related-products.php:84
3021
  msgid "Order"
3022
  msgstr ""
3023
 
3024
+ #: includes/class-wcj-product-tabs.php:606
3025
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:36
3026
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:51
3027
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:100
3029
  #: includes/settings/wcj-settings-cart.php:44
3030
  #: includes/settings/wcj-settings-checkout-custom-info.php:40
3031
  #: includes/settings/wcj-settings-left-to-free-shipping.php:34
3032
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:65
3033
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:99
3034
  #: includes/settings/wcj-settings-mini-cart.php:39
3035
  #: includes/settings/wcj-settings-my-account.php:66
3036
+ #: includes/settings/wcj-settings-product-custom-info.php:89
3037
+ #: includes/settings/wcj-settings-product-tabs.php:92
3038
  #: includes/widgets/class-wcj-widget-left-to-free-shipping.php:59
3039
  msgid "Content"
3040
  msgstr ""
3041
 
3042
+ #: includes/class-wcj-product-tabs.php:611
3043
  #: includes/settings/wcj-settings-cart-customization.php:63
3044
+ #: includes/settings/wcj-settings-product-tabs.php:100
3045
  msgid "Link"
3046
  msgstr ""
3047
 
3048
+ #: includes/class-wcj-product-tabs.php:613
3049
+ #: includes/settings/wcj-settings-product-tabs.php:101
3050
  msgid ""
3051
  "If you wish to forward tab to new link, enter it here. In this case content "
3052
  "is ignored. Leave blank to show content."
3053
  msgstr ""
3054
 
3055
+ #: includes/class-wcj-product-tabs.php:617
3056
+ #: includes/settings/wcj-settings-product-tabs.php:108
3057
  msgid "Link - Open in New Window"
3058
  msgstr ""
3059
 
3060
+ #: includes/class-wcj-product-tabs.php:620
3061
  #: includes/input-fields/wcj-product-input-fields-options.php:101
3062
  #: includes/settings/wcj-settings-admin-orders-list.php:84
3063
  #: includes/settings/wcj-settings-checkout-custom-fields.php:224
3084
  msgid "No"
3085
  msgstr ""
3086
 
3087
+ #: includes/class-wcj-product-tabs.php:621
3088
  #: includes/input-fields/wcj-product-input-fields-options.php:94
3089
  #: includes/settings/wcj-settings-checkout-custom-fields.php:218
3090
  #: includes/settings/wcj-settings-eu-vat-number.php:50
3116
  msgid "Yes"
3117
  msgstr ""
3118
 
3119
+ #: includes/class-wcj-product-tabs.php:629
3120
  #: includes/settings/wcj-settings-checkout-core-fields.php:71
3121
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:142
3122
  #: includes/settings/wcj-settings-order-numbers.php:46
3123
  #: includes/settings/wcj-settings-orders.php:137
3124
  #: includes/settings/wcj-settings-product-add-to-cart.php:64
3127
  msgid "Disabled"
3128
  msgstr ""
3129
 
3130
+ #: includes/class-wcj-product-tabs.php:632
3131
+ #: includes/settings/wcj-settings-product-tabs.php:71
3132
+ #: includes/settings/wcj-settings-product-tabs.php:270
3133
  msgid "Custom Product Tab"
3134
  msgstr ""
3135
 
3157
  msgstr ""
3158
 
3159
  #: includes/class-wcj-products-xml.php:95
3160
+ #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:210
3161
  msgid "Once Weekly"
3162
  msgstr ""
3163
 
3164
  #: includes/class-wcj-products-xml.php:99
3165
+ #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:214
3166
  msgid "Once a Minute"
3167
  msgstr ""
3168
 
3331
  msgstr ""
3332
 
3333
  #: includes/class-wcj-shipping-by-order-amount.php:26
3334
+ #: includes/settings/wcj-settings-shipping-by-order-amount.php:33
3335
  msgid "Shipping Methods by Min/Max Order Amount"
3336
  msgstr ""
3337
 
3374
  msgid "Shipping methods by <strong>products tags</strong>."
3375
  msgstr ""
3376
 
3377
+ #: includes/class-wcj-shipping-by-products.php:131
3378
  msgid "\"Include\" Options"
3379
  msgstr ""
3380
 
3381
+ #: includes/class-wcj-shipping-by-products.php:132
3382
  msgid ""
3383
  "Enable this checkbox if you want all products in cart to be valid (instead "
3384
  "of at least one)."
3385
  msgstr ""
3386
 
3387
+ #: includes/class-wcj-shipping-by-products.php:133
3388
  msgid "Validate all"
3389
  msgstr ""
3390
 
3391
+ #: includes/class-wcj-shipping-by-products.php:141
3392
+ msgid "Add Products Variations"
3393
+ msgstr ""
3394
+
3395
+ #: includes/class-wcj-shipping-by-products.php:142
3396
+ msgid ""
3397
+ "Enable this checkbox if you want to add products variations to the products "
3398
+ "list."
3399
+ msgstr ""
3400
+
3401
+ #: includes/class-wcj-shipping-by-products.php:143
3402
+ #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:25
3403
+ #: includes/settings/wcj-settings-shipping-by-condition.php:27
3404
+ #: includes/settings/wcj-settings-shipping-by-order-amount.php:23
3405
+ #: includes/settings/wcj-settings-shipping-time.php:33
3406
+ #: includes/settings/wcj-settings-shipping-time.php:42
3407
+ msgid "Save changes after enabling this option."
3408
+ msgstr ""
3409
+
3410
  #: includes/class-wcj-shipping-by-user-role.php:25
3411
  msgid "Shipping Methods by Users"
3412
  msgstr ""
3460
  msgstr ""
3461
 
3462
  #: includes/class-wcj-shipping-description.php:26
3463
+ msgid "Add descriptions to WooCommerce shipping methods on frontend."
3464
  msgstr ""
3465
 
3466
  #: includes/class-wcj-shipping-icons.php:25
3468
  msgstr ""
3469
 
3470
  #: includes/class-wcj-shipping-icons.php:26
3471
+ msgid "Add icons to WooCommerce shipping methods on frontend."
3472
  msgstr ""
3473
 
3474
  #: includes/class-wcj-shipping-options.php:26
3509
  msgid "Hide \"Flat Rate\" only"
3510
  msgstr ""
3511
 
3512
+ #: includes/class-wcj-shipping-time.php:25
3513
+ msgid "Shipping Time"
3514
+ msgstr ""
3515
+
3516
+ #: includes/class-wcj-shipping-time.php:26
3517
+ #, php-format
3518
+ msgid ""
3519
+ "After you set estimated shipping time here, you can display it on frontend "
3520
+ "with %s shortcodes."
3521
+ msgstr ""
3522
+
3523
+ #: includes/class-wcj-shipping-time.php:28
3524
+ msgid "Add delivery time estimation to WooCommerce shipping methods."
3525
+ msgstr ""
3526
+
3527
  #: includes/class-wcj-shipping.php:24
3528
  #: includes/settings/wcj-settings-shipping.php:16
3529
  #: includes/settings/wcj-settings-shipping.php:23
3536
  msgid "Add multiple custom shipping methods to WooCommerce."
3537
  msgstr ""
3538
 
3539
+ #: includes/class-wcj-sku.php:23 includes/class-wcj-sku.php:420
3540
  #: includes/export/class-wcj-fields-helper.php:283
3541
  msgid "SKU"
3542
  msgstr ""
3553
  msgid "The tool generates and sets product SKUs for existing products."
3554
  msgstr ""
3555
 
3556
+ #: includes/class-wcj-sku.php:421
3557
  msgid "Old SKU"
3558
  msgstr ""
3559
 
3560
+ #: includes/class-wcj-sku.php:427
3561
  msgid "SKUs generated and set successfully!"
3562
  msgstr ""
3563
 
3564
+ #: includes/class-wcj-sku.php:437
3565
  msgid "Preview SKUs"
3566
  msgstr ""
3567
 
3568
+ #: includes/class-wcj-sku.php:439
3569
  msgid "Set SKUs"
3570
  msgstr ""
3571
 
3572
+ #: includes/class-wcj-sku.php:442
3573
+ msgid ""
3574
+ "You can optionally limit affected products by main product's ID (set option "
3575
+ "to zero to ignore):"
3576
+ msgstr ""
3577
+
3578
+ #: includes/class-wcj-sku.php:444
3579
+ msgid "Min ID"
3580
+ msgstr ""
3581
+
3582
+ #: includes/class-wcj-sku.php:447
3583
+ msgid "Max ID"
3584
+ msgstr ""
3585
+
3586
  #: includes/class-wcj-sorting.php:24
3587
  msgid "Sorting"
3588
  msgstr ""
3617
  msgid "Sort by price: high to low"
3618
  msgstr ""
3619
 
3620
+ #: includes/class-wcj-stock.php:27
3621
  msgid "WooCommerce products stock management."
3622
  msgstr ""
3623
 
3847
  msgstr ""
3848
 
3849
  #: includes/admin/class-wc-settings-jetpack.php:464
3850
+ #: includes/admin/class-wc-settings-jetpack.php:478
3851
+ #: includes/admin/class-wc-settings-jetpack.php:487
3852
  #, php-format
3853
  msgid "Supported modules: %s."
3854
  msgstr ""
3857
  msgid "Products XML"
3858
  msgstr ""
3859
 
3860
+ #: includes/admin/class-wc-settings-jetpack.php:476
3861
+ msgid ""
3862
+ "Use List Instead of Comma Separated Text for Products Categories in Settings"
3863
+ msgstr ""
3864
+
3865
+ #: includes/admin/class-wc-settings-jetpack.php:485
3866
+ msgid "Use List Instead of Comma Separated Text for Products Tags in Settings"
3867
+ msgstr ""
3868
+
3869
+ #: includes/admin/class-wc-settings-jetpack.php:512
3870
  #: includes/core/class-wcj-admin.php:97
3871
  msgid "Booster for WooCommerce"
3872
  msgstr ""
3873
 
3874
  #: includes/admin/class-wcj-settings-custom-fields.php:65
3875
  #, php-format
3876
+ msgid "Grab raw %s rate from %s."
3877
+ msgstr ""
3878
+
3879
+ #: includes/admin/class-wcj-settings-custom-fields.php:66
3880
+ msgid "Doesn't apply rounding, offset etc."
3881
  msgstr ""
3882
 
3883
+ #: includes/admin/class-wcj-settings-custom-fields.php:260
3884
  #: includes/settings/wcj-settings-wpml.php:21
3885
  msgid "To use tools, module must be enabled."
3886
  msgstr ""
3887
 
3888
+ #: includes/admin/class-wcj-settings-custom-fields.php:299
3889
  msgid "Save changes"
3890
  msgstr ""
3891
 
3984
  msgstr ""
3985
 
3986
  #: includes/admin/wcj-modules-cats.php:112
3987
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:55
3988
  #: includes/settings/wcj-settings-payment-gateways-by-currency.php:14
3989
+ #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:37
3990
  #: includes/settings/wcj-settings-payment-gateways-by-user-role.php:14
3991
  #: includes/settings/wcj-settings-payment-gateways-min-max.php:65
3992
  msgid "Payment Gateways"
4008
  "Methods and more."
4009
  msgstr ""
4010
 
4011
+ #: includes/admin/wcj-modules-cats.php:154
4012
  msgid "PDF Invoicing & Packing Slips"
4013
  msgstr ""
4014
 
4015
+ #: includes/admin/wcj-modules-cats.php:155
4016
  msgid "PDF Documents"
4017
  msgstr ""
4018
 
4019
+ #: includes/admin/wcj-modules-cats.php:171
4020
  msgid "Emails & Misc."
4021
  msgstr ""
4022
 
4023
+ #: includes/admin/wcj-modules-cats.php:172
4024
  msgid "Emails, Reports, Export, Admin Tools, General Options and more."
4025
  msgstr ""
4026
 
4057
  msgstr ""
4058
 
4059
  #: includes/classes/class-wcj-module.php:565
4060
+ #: includes/settings/wcj-settings-product-tabs.php:172
4061
+ #: includes/settings/wcj-settings-product-tabs.php:184
4062
+ #: includes/settings/wcj-settings-product-tabs.php:196
4063
+ #: includes/settings/wcj-settings-product-tabs.php:208
4064
  msgid "Deprecated"
4065
  msgstr ""
4066
 
4088
  msgid "Enable Module"
4089
  msgstr ""
4090
 
4091
+ #: includes/classes/class-wcj-pdf-invoice.php:88
4092
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:61
4093
  msgid "Company Name"
4094
  msgstr ""
4095
 
4096
+ #: includes/classes/class-wcj-pdf-invoice.php:236
4097
+ #: includes/functions/wcj-functions-general.php:44
4098
+ #: includes/pdf-invoices/class-wcj-pdf-invoicing-report-tool.php:245
4099
+ msgid "Unexpected error"
4100
+ msgstr ""
4101
+
4102
+ #: includes/classes/class-wcj-shortcodes.php:109
4103
+ #: includes/shortcodes/class-wcj-shortcodes-general.php:380
4104
  #, php-format
4105
  msgid "\"%s\" module is not enabled!"
4106
  msgstr ""
4107
 
4108
+ #: includes/classes/class-wcj-tcpdf.php:44
4109
  #: includes/settings/wcj-settings-pdf-invoicing-footer.php:31
4110
  msgid "Page %page_number% / %total_pages%"
4111
  msgstr ""
4300
  msgstr ""
4301
 
4302
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:22
4303
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:36
4304
  #: includes/settings/wcj-settings-products-xml.php:129
4305
  msgid "Update Every Minute"
4306
  msgstr ""
4307
 
4308
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:23
4309
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:37
4310
  #: includes/settings/wcj-settings-products-xml.php:130
4311
  msgid "Update Hourly"
4312
  msgstr ""
4313
 
4314
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:24
4315
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:38
4316
  #: includes/settings/wcj-settings-products-xml.php:131
4317
  msgid "Update Twice Daily"
4318
  msgstr ""
4319
 
4320
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:25
4321
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:39
4322
  #: includes/settings/wcj-settings-products-xml.php:132
4323
  msgid "Update Daily"
4324
  msgstr ""
4325
 
4326
  #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:26
4327
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:40
4328
  #: includes/settings/wcj-settings-products-xml.php:133
4329
  msgid "Update Weekly"
4330
  msgstr ""
4331
 
4332
+ #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:185
4333
  msgid "Cron job: exchange rates successfully updated"
4334
  msgstr ""
4335
 
4336
+ #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:187
4337
  msgid "Cron job: exchange rates not updated, as currency_from == currency_to"
4338
  msgstr ""
4339
 
4340
+ #: includes/exchange-rates/class-wcj-exchange-rates-crons.php:190
4341
  msgid "Cron job: exchange rates update failed"
4342
  msgstr ""
4343
 
4780
  msgid "Availability Class"
4781
  msgstr ""
4782
 
4783
+ #: includes/functions/wcj-functions-admin.php:108
4784
  #, php-format
4785
  msgid ""
4786
  "<strong>Booster for WooCommerce</strong> plugin was successfully updated to "
4787
  "version <strong>%s</strong>."
4788
  msgstr ""
4789
 
4790
+ #: includes/functions/wcj-functions-admin.php:131
4791
  msgid "Enter comma separated list of IDs."
4792
  msgstr ""
4793
 
4794
+ #: includes/functions/wcj-functions-admin.php:205
4795
  #: includes/settings/wcj-settings-emails-verification.php:59
4796
  #: includes/settings/wcj-settings-emails-verification.php:67
4797
  #: includes/settings/wcj-settings-emails-verification.php:107
4799
  msgid "Replaced value: %s"
4800
  msgstr ""
4801
 
4802
+ #: includes/functions/wcj-functions-admin.php:205
4803
  #, php-format
4804
  msgid "Replaced values: %s"
4805
  msgstr ""
4806
 
4807
+ #: includes/functions/wcj-functions-admin.php:234
4808
  msgid "Install Booster Plus to unlock all features"
4809
  msgstr ""
4810
 
4811
+ #: includes/functions/wcj-functions-admin.php:235
4812
  #, php-format
4813
  msgid ""
4814
  "Some settings fields are locked and you will need %s to modify all locked "
4815
  "fields."
4816
  msgstr ""
4817
 
4818
+ #: includes/functions/wcj-functions-admin.php:236
4819
  msgid "Buy now"
4820
  msgstr ""
4821
 
4822
+ #: includes/functions/wcj-functions-admin.php:236
4823
  msgid "Visit Booster Site"
4824
  msgstr ""
4825
 
4826
+ #: includes/functions/wcj-functions-admin.php:240
4827
  #, php-format
4828
  msgid "Get <a href=\"%s\" target=\"_blank\">Booster Plus</a> to change value."
4829
  msgstr ""
4830
 
4831
+ #: includes/functions/wcj-functions-admin.php:243
4832
  #, php-format
4833
  msgid ""
4834
  "Get <a href=\"%s\" target=\"_blank\">Booster Plus</a> to enable \"%s\" "
4835
  "option."
4836
  msgstr ""
4837
 
4838
+ #: includes/functions/wcj-functions-admin.php:246
4839
  #, php-format
4840
  msgid "Get Booster Plus to enable \"%s\" option."
4841
  msgstr ""
4842
 
4843
+ #: includes/functions/wcj-functions-admin.php:249
4844
  #, php-format
4845
  msgid ""
4846
  "Get <a href=\"%s\" target=\"_blank\">Booster Plus</a> to change values below."
4847
  msgstr ""
4848
 
4849
+ #: includes/functions/wcj-functions-admin.php:252
4850
  #, php-format
4851
  msgid ""
4852
  "Get <a href=\"%s\" target=\"_blank\">Booster Plus</a> to change values above."
4853
  msgstr ""
4854
 
4855
+ #: includes/functions/wcj-functions-admin.php:255
4856
  msgid "Get Booster Plus to change value."
4857
  msgstr ""
4858
 
4859
+ #: includes/functions/wcj-functions-country.php:148
4860
  msgid "Afghanistan"
4861
  msgstr ""
4862
 
4863
+ #: includes/functions/wcj-functions-country.php:149
4864
  msgid "&#197;land Islands"
4865
  msgstr ""
4866
 
4867
+ #: includes/functions/wcj-functions-country.php:150
4868
  msgid "Albania"
4869
  msgstr ""
4870
 
4871
+ #: includes/functions/wcj-functions-country.php:151
4872
  msgid "Algeria"
4873
  msgstr ""
4874
 
4875
+ #: includes/functions/wcj-functions-country.php:152
4876
  msgid "Andorra"
4877
  msgstr ""
4878
 
4879
+ #: includes/functions/wcj-functions-country.php:153
4880
  msgid "Angola"
4881
  msgstr ""
4882
 
4883
+ #: includes/functions/wcj-functions-country.php:154
4884
  msgid "Anguilla"
4885
  msgstr ""
4886
 
4887
+ #: includes/functions/wcj-functions-country.php:155
4888
  msgid "Antarctica"
4889
  msgstr ""
4890
 
4891
+ #: includes/functions/wcj-functions-country.php:156
4892
  msgid "Antigua and Barbuda"
4893
  msgstr ""
4894
 
4895
+ #: includes/functions/wcj-functions-country.php:157
4896
  msgid "Argentina"
4897
  msgstr ""
4898
 
4899
+ #: includes/functions/wcj-functions-country.php:158
4900
  msgid "Armenia"
4901
  msgstr ""
4902
 
4903
+ #: includes/functions/wcj-functions-country.php:159
4904
  msgid "Aruba"
4905
  msgstr ""
4906
 
4907
+ #: includes/functions/wcj-functions-country.php:160
4908
  msgid "Australia"
4909
  msgstr ""
4910
 
4911
+ #: includes/functions/wcj-functions-country.php:161
4912
  msgid "Austria"
4913
  msgstr ""
4914
 
4915
+ #: includes/functions/wcj-functions-country.php:162
4916
  msgid "Azerbaijan"
4917
  msgstr ""
4918
 
4919
+ #: includes/functions/wcj-functions-country.php:163
4920
  msgid "Bahamas"
4921
  msgstr ""
4922
 
4923
+ #: includes/functions/wcj-functions-country.php:164
4924
  msgid "Bahrain"
4925
  msgstr ""
4926
 
4927
+ #: includes/functions/wcj-functions-country.php:165
4928
  msgid "Bangladesh"
4929
  msgstr ""
4930
 
4931
+ #: includes/functions/wcj-functions-country.php:166
4932
  msgid "Barbados"
4933
  msgstr ""
4934
 
4935
+ #: includes/functions/wcj-functions-country.php:167
4936
  msgid "Belarus"
4937
  msgstr ""
4938
 
4939
+ #: includes/functions/wcj-functions-country.php:168
4940
  msgid "Belgium"
4941
  msgstr ""
4942
 
4943
+ #: includes/functions/wcj-functions-country.php:169
4944
  msgid "Belau"
4945
  msgstr ""
4946
 
4947
+ #: includes/functions/wcj-functions-country.php:170
4948
  msgid "Belize"
4949
  msgstr ""
4950
 
4951
+ #: includes/functions/wcj-functions-country.php:171
4952
  msgid "Benin"
4953
  msgstr ""
4954
 
4955
+ #: includes/functions/wcj-functions-country.php:172
4956
  msgid "Bermuda"
4957
  msgstr ""
4958
 
4959
+ #: includes/functions/wcj-functions-country.php:173
4960
  msgid "Bhutan"
4961
  msgstr ""
4962
 
4963
+ #: includes/functions/wcj-functions-country.php:174
4964
  msgid "Bolivia"
4965
  msgstr ""
4966
 
4967
+ #: includes/functions/wcj-functions-country.php:175
4968
  msgid "Bonaire, Saint Eustatius and Saba"
4969
  msgstr ""
4970
 
4971
+ #: includes/functions/wcj-functions-country.php:176
4972
  msgid "Bosnia and Herzegovina"
4973
  msgstr ""
4974
 
4975
+ #: includes/functions/wcj-functions-country.php:177
4976
  msgid "Botswana"
4977
  msgstr ""
4978
 
4979
+ #: includes/functions/wcj-functions-country.php:178
4980
  msgid "Bouvet Island"
4981
  msgstr ""
4982
 
4983
+ #: includes/functions/wcj-functions-country.php:179
4984
  msgid "Brazil"
4985
  msgstr ""
4986
 
4987
+ #: includes/functions/wcj-functions-country.php:180
4988
  msgid "British Indian Ocean Territory"
4989
  msgstr ""
4990
 
4991
+ #: includes/functions/wcj-functions-country.php:181
4992
  msgid "British Virgin Islands"
4993
  msgstr ""
4994
 
4995
+ #: includes/functions/wcj-functions-country.php:182
4996
  msgid "Brunei"
4997
  msgstr ""
4998
 
4999
+ #: includes/functions/wcj-functions-country.php:183
5000
  msgid "Bulgaria"
5001
  msgstr ""
5002
 
5003
+ #: includes/functions/wcj-functions-country.php:184
5004
  msgid "Burkina Faso"
5005
  msgstr ""
5006
 
5007
+ #: includes/functions/wcj-functions-country.php:185
5008
  msgid "Burundi"
5009
  msgstr ""
5010
 
5011
+ #: includes/functions/wcj-functions-country.php:186
5012
  msgid "Cambodia"
5013
  msgstr ""
5014
 
5015
+ #: includes/functions/wcj-functions-country.php:187
5016
  msgid "Cameroon"
5017
  msgstr ""
5018
 
5019
+ #: includes/functions/wcj-functions-country.php:188
5020
  msgid "Canada"
5021
  msgstr ""
5022
 
5023
+ #: includes/functions/wcj-functions-country.php:189
5024
  msgid "Cape Verde"
5025
  msgstr ""
5026
 
5027
+ #: includes/functions/wcj-functions-country.php:190
5028
  msgid "Cayman Islands"
5029
  msgstr ""
5030
 
5031
+ #: includes/functions/wcj-functions-country.php:191
5032
  msgid "Central African Republic"
5033
  msgstr ""
5034
 
5035
+ #: includes/functions/wcj-functions-country.php:192
5036
  msgid "Chad"
5037
  msgstr ""
5038
 
5039
+ #: includes/functions/wcj-functions-country.php:193
5040
  msgid "Chile"
5041
  msgstr ""
5042
 
5043
+ #: includes/functions/wcj-functions-country.php:194
5044
  msgid "China"
5045
  msgstr ""
5046
 
5047
+ #: includes/functions/wcj-functions-country.php:195
5048
  msgid "Christmas Island"
5049
  msgstr ""
5050
 
5051
+ #: includes/functions/wcj-functions-country.php:196
5052
  msgid "Cocos (Keeling) Islands"
5053
  msgstr ""
5054
 
5055
+ #: includes/functions/wcj-functions-country.php:197
5056
  msgid "Colombia"
5057
  msgstr ""
5058
 
5059
+ #: includes/functions/wcj-functions-country.php:198
5060
  msgid "Comoros"
5061
  msgstr ""
5062
 
5063
+ #: includes/functions/wcj-functions-country.php:199
5064
  msgid "Congo (Brazzaville)"
5065
  msgstr ""
5066
 
5067
+ #: includes/functions/wcj-functions-country.php:200
5068
  msgid "Congo (Kinshasa)"
5069
  msgstr ""
5070
 
5071
+ #: includes/functions/wcj-functions-country.php:201
5072
  msgid "Cook Islands"
5073
  msgstr ""
5074
 
5075
+ #: includes/functions/wcj-functions-country.php:202
5076
  msgid "Costa Rica"
5077
  msgstr ""
5078
 
5079
+ #: includes/functions/wcj-functions-country.php:203
5080
  msgid "Croatia"
5081
  msgstr ""
5082
 
5083
+ #: includes/functions/wcj-functions-country.php:204
5084
  msgid "Cuba"
5085
  msgstr ""
5086
 
5087
+ #: includes/functions/wcj-functions-country.php:205
5088
  msgid "Cura&Ccedil;ao"
5089
  msgstr ""
5090
 
5091
+ #: includes/functions/wcj-functions-country.php:206
5092
  msgid "Cyprus"
5093
  msgstr ""
5094
 
5095
+ #: includes/functions/wcj-functions-country.php:207
5096
  msgid "Czech Republic"
5097
  msgstr ""
5098
 
5099
+ #: includes/functions/wcj-functions-country.php:208
5100
  msgid "Denmark"
5101
  msgstr ""
5102
 
5103
+ #: includes/functions/wcj-functions-country.php:209
5104
  msgid "Djibouti"
5105
  msgstr ""
5106
 
5107
+ #: includes/functions/wcj-functions-country.php:210
5108
  msgid "Dominica"
5109
  msgstr ""
5110
 
5111
+ #: includes/functions/wcj-functions-country.php:211
5112
  msgid "Dominican Republic"
5113
  msgstr ""
5114
 
5115
+ #: includes/functions/wcj-functions-country.php:212
5116
  msgid "Ecuador"
5117
  msgstr ""
5118
 
5119
+ #: includes/functions/wcj-functions-country.php:213
5120
  msgid "Egypt"
5121
  msgstr ""
5122
 
5123
+ #: includes/functions/wcj-functions-country.php:214
5124
  msgid "El Salvador"
5125
  msgstr ""
5126
 
5127
+ #: includes/functions/wcj-functions-country.php:215
5128
  msgid "Equatorial Guinea"
5129
  msgstr ""
5130
 
5131
+ #: includes/functions/wcj-functions-country.php:216
5132
  msgid "Eritrea"
5133
  msgstr ""
5134
 
5135
+ #: includes/functions/wcj-functions-country.php:217
5136
  msgid "Estonia"
5137
  msgstr ""
5138
 
5139
+ #: includes/functions/wcj-functions-country.php:218
5140
  msgid "Ethiopia"
5141
  msgstr ""
5142
 
5143
+ #: includes/functions/wcj-functions-country.php:219
5144
  msgid "Falkland Islands"
5145
  msgstr ""
5146
 
5147
+ #: includes/functions/wcj-functions-country.php:220
5148
  msgid "Faroe Islands"
5149
  msgstr ""
5150
 
5151
+ #: includes/functions/wcj-functions-country.php:221
5152
  msgid "Fiji"
5153
  msgstr ""
5154
 
5155
+ #: includes/functions/wcj-functions-country.php:222
5156
  msgid "Finland"
5157
  msgstr ""
5158
 
5159
+ #: includes/functions/wcj-functions-country.php:223
5160
  msgid "France"
5161
  msgstr ""
5162
 
5163
+ #: includes/functions/wcj-functions-country.php:224
5164
  msgid "French Guiana"
5165
  msgstr ""
5166
 
5167
+ #: includes/functions/wcj-functions-country.php:225
5168
  msgid "French Polynesia"
5169
  msgstr ""
5170
 
5171
+ #: includes/functions/wcj-functions-country.php:226
5172
  msgid "French Southern Territories"
5173
  msgstr ""
5174
 
5175
+ #: includes/functions/wcj-functions-country.php:227
5176
  msgid "Gabon"
5177
  msgstr ""
5178
 
5179
+ #: includes/functions/wcj-functions-country.php:228
5180
  msgid "Gambia"
5181
  msgstr ""
5182
 
5183
+ #: includes/functions/wcj-functions-country.php:229
5184
  msgid "Georgia"
5185
  msgstr ""
5186
 
5187
+ #: includes/functions/wcj-functions-country.php:230
5188
  msgid "Germany"
5189
  msgstr ""
5190
 
5191
+ #: includes/functions/wcj-functions-country.php:231
5192
  msgid "Ghana"
5193
  msgstr ""
5194
 
5195
+ #: includes/functions/wcj-functions-country.php:232
5196
  msgid "Gibraltar"
5197
  msgstr ""
5198
 
5199
+ #: includes/functions/wcj-functions-country.php:233
5200
  msgid "Greece"
5201
  msgstr ""
5202
 
5203
+ #: includes/functions/wcj-functions-country.php:234
5204
  msgid "Greenland"
5205
  msgstr ""
5206
 
5207
+ #: includes/functions/wcj-functions-country.php:235
5208
  msgid "Grenada"
5209
  msgstr ""
5210
 
5211
+ #: includes/functions/wcj-functions-country.php:236
5212
  msgid "Guadeloupe"
5213
  msgstr ""
5214
 
5215
+ #: includes/functions/wcj-functions-country.php:237
5216
  msgid "Guatemala"
5217
  msgstr ""
5218
 
5219
+ #: includes/functions/wcj-functions-country.php:238
5220
  msgid "Guernsey"
5221
  msgstr ""
5222
 
5223
+ #: includes/functions/wcj-functions-country.php:239
5224
  msgid "Guinea"
5225
  msgstr ""
5226
 
5227
+ #: includes/functions/wcj-functions-country.php:240
5228
  msgid "Guinea-Bissau"
5229
  msgstr ""
5230
 
5231
+ #: includes/functions/wcj-functions-country.php:241
5232
  msgid "Guyana"
5233
  msgstr ""
5234
 
5235
+ #: includes/functions/wcj-functions-country.php:242
5236
  msgid "Haiti"
5237
  msgstr ""
5238
 
5239
+ #: includes/functions/wcj-functions-country.php:243
5240
  msgid "Heard Island and McDonald Islands"
5241
  msgstr ""
5242
 
5243
+ #: includes/functions/wcj-functions-country.php:244
5244
  msgid "Honduras"
5245
  msgstr ""
5246
 
5247
+ #: includes/functions/wcj-functions-country.php:245
5248
  msgid "Hong Kong"
5249
  msgstr ""
5250
 
5251
+ #: includes/functions/wcj-functions-country.php:246
5252
  msgid "Hungary"
5253
  msgstr ""
5254
 
5255
+ #: includes/functions/wcj-functions-country.php:247
5256
  msgid "Iceland"
5257
  msgstr ""
5258
 
5259
+ #: includes/functions/wcj-functions-country.php:248
5260
  msgid "India"
5261
  msgstr ""
5262
 
5263
+ #: includes/functions/wcj-functions-country.php:249
5264
  msgid "Indonesia"
5265
  msgstr ""
5266
 
5267
+ #: includes/functions/wcj-functions-country.php:250
5268
  msgid "Iran"
5269
  msgstr ""
5270
 
5271
+ #: includes/functions/wcj-functions-country.php:251
5272
  msgid "Iraq"
5273
  msgstr ""
5274
 
5275
+ #: includes/functions/wcj-functions-country.php:252
5276
  msgid "Republic of Ireland"
5277
  msgstr ""
5278
 
5279
+ #: includes/functions/wcj-functions-country.php:253
5280
  msgid "Isle of Man"
5281
  msgstr ""
5282
 
5283
+ #: includes/functions/wcj-functions-country.php:254
5284
  msgid "Israel"
5285
  msgstr ""
5286
 
5287
+ #: includes/functions/wcj-functions-country.php:255
5288
  msgid "Italy"
5289
  msgstr ""
5290
 
5291
+ #: includes/functions/wcj-functions-country.php:256
5292
  msgid "Ivory Coast"
5293
  msgstr ""
5294
 
5295
+ #: includes/functions/wcj-functions-country.php:257
5296
  msgid "Jamaica"
5297
  msgstr ""
5298
 
5299
+ #: includes/functions/wcj-functions-country.php:258
5300
  msgid "Japan"
5301
  msgstr ""
5302
 
5303
+ #: includes/functions/wcj-functions-country.php:259
5304
  msgid "Jersey"
5305
  msgstr ""
5306
 
5307
+ #: includes/functions/wcj-functions-country.php:260
5308
  msgid "Jordan"
5309
  msgstr ""
5310
 
5311
+ #: includes/functions/wcj-functions-country.php:261
5312
  msgid "Kazakhstan"
5313
  msgstr ""
5314
 
5315
+ #: includes/functions/wcj-functions-country.php:262
5316
  msgid "Kenya"
5317
  msgstr ""
5318
 
5319
+ #: includes/functions/wcj-functions-country.php:263
5320
  msgid "Kiribati"
5321
  msgstr ""
5322
 
5323
+ #: includes/functions/wcj-functions-country.php:264
5324
  msgid "Kuwait"
5325
  msgstr ""
5326
 
5327
+ #: includes/functions/wcj-functions-country.php:265
5328
  msgid "Kyrgyzstan"
5329
  msgstr ""
5330
 
5331
+ #: includes/functions/wcj-functions-country.php:266
5332
  msgid "Laos"
5333
  msgstr ""
5334
 
5335
+ #: includes/functions/wcj-functions-country.php:267
5336
  msgid "Latvia"
5337
  msgstr ""
5338
 
5339
+ #: includes/functions/wcj-functions-country.php:268
5340
  msgid "Lebanon"
5341
  msgstr ""
5342
 
5343
+ #: includes/functions/wcj-functions-country.php:269
5344
  msgid "Lesotho"
5345
  msgstr ""
5346
 
5347
+ #: includes/functions/wcj-functions-country.php:270
5348
  msgid "Liberia"
5349
  msgstr ""
5350
 
5351
+ #: includes/functions/wcj-functions-country.php:271
5352
  msgid "Libya"
5353
  msgstr ""
5354
 
5355
+ #: includes/functions/wcj-functions-country.php:272
5356
  msgid "Liechtenstein"
5357
  msgstr ""
5358
 
5359
+ #: includes/functions/wcj-functions-country.php:273
5360
  msgid "Lithuania"
5361
  msgstr ""
5362
 
5363
+ #: includes/functions/wcj-functions-country.php:274
5364
  msgid "Luxembourg"
5365
  msgstr ""
5366
 
5367
+ #: includes/functions/wcj-functions-country.php:275
5368
  msgid "Macao S.A.R., China"
5369
  msgstr ""
5370
 
5371
+ #: includes/functions/wcj-functions-country.php:276
5372
  msgid "Macedonia"
5373
  msgstr ""
5374
 
5375
+ #: includes/functions/wcj-functions-country.php:277
5376
  msgid "Madagascar"
5377
  msgstr ""
5378
 
5379
+ #: includes/functions/wcj-functions-country.php:278
5380
  msgid "Malawi"
5381
  msgstr ""
5382
 
5383
+ #: includes/functions/wcj-functions-country.php:279
5384
  msgid "Malaysia"
5385
  msgstr ""
5386
 
5387
+ #: includes/functions/wcj-functions-country.php:280
5388
  msgid "Maldives"
5389
  msgstr ""
5390
 
5391
+ #: includes/functions/wcj-functions-country.php:281
5392
  msgid "Mali"
5393
  msgstr ""
5394
 
5395
+ #: includes/functions/wcj-functions-country.php:282
5396
  msgid "Malta"
5397
  msgstr ""
5398
 
5399
+ #: includes/functions/wcj-functions-country.php:283
5400
  msgid "Marshall Islands"
5401
  msgstr ""
5402
 
5403
+ #: includes/functions/wcj-functions-country.php:284
5404
  msgid "Martinique"
5405
  msgstr ""
5406
 
5407
+ #: includes/functions/wcj-functions-country.php:285
5408
  msgid "Mauritania"
5409
  msgstr ""
5410
 
5411
+ #: includes/functions/wcj-functions-country.php:286
5412
  msgid "Mauritius"
5413
  msgstr ""
5414
 
5415
+ #: includes/functions/wcj-functions-country.php:287
5416
  msgid "Mayotte"
5417
  msgstr ""
5418
 
5419
+ #: includes/functions/wcj-functions-country.php:288
5420
  msgid "Mexico"
5421
  msgstr ""
5422
 
5423
+ #: includes/functions/wcj-functions-country.php:289
5424
  msgid "Micronesia"
5425
  msgstr ""
5426
 
5427
+ #: includes/functions/wcj-functions-country.php:290
5428
  msgid "Moldova"
5429
  msgstr ""
5430
 
5431
+ #: includes/functions/wcj-functions-country.php:291
5432
  msgid "Monaco"
5433
  msgstr ""
5434
 
5435
+ #: includes/functions/wcj-functions-country.php:292
5436
  msgid "Mongolia"
5437
  msgstr ""
5438
 
5439
+ #: includes/functions/wcj-functions-country.php:293
5440
  msgid "Montenegro"
5441
  msgstr ""
5442
 
5443
+ #: includes/functions/wcj-functions-country.php:294
5444
  msgid "Montserrat"
5445
  msgstr ""
5446
 
5447
+ #: includes/functions/wcj-functions-country.php:295
5448
  msgid "Morocco"
5449
  msgstr ""
5450
 
5451
+ #: includes/functions/wcj-functions-country.php:296
5452
  msgid "Mozambique"
5453
  msgstr ""
5454
 
5455
+ #: includes/functions/wcj-functions-country.php:297
5456
  msgid "Myanmar"
5457
  msgstr ""
5458
 
5459
+ #: includes/functions/wcj-functions-country.php:298
5460
  msgid "Namibia"
5461
  msgstr ""
5462
 
5463
+ #: includes/functions/wcj-functions-country.php:299
5464
  msgid "Nauru"
5465
  msgstr ""
5466
 
5467
+ #: includes/functions/wcj-functions-country.php:300
5468
  msgid "Nepal"
5469
  msgstr ""
5470
 
5471
+ #: includes/functions/wcj-functions-country.php:301
5472
  msgid "Netherlands"
5473
  msgstr ""
5474
 
5475
+ #: includes/functions/wcj-functions-country.php:302
5476
  msgid "Netherlands Antilles"
5477
  msgstr ""
5478
 
5479
+ #: includes/functions/wcj-functions-country.php:303
5480
  msgid "New Caledonia"
5481
  msgstr ""
5482
 
5483
+ #: includes/functions/wcj-functions-country.php:304
5484
  msgid "New Zealand"
5485
  msgstr ""
5486
 
5487
+ #: includes/functions/wcj-functions-country.php:305
5488
  msgid "Nicaragua"
5489
  msgstr ""
5490
 
5491
+ #: includes/functions/wcj-functions-country.php:306
5492
  msgid "Niger"
5493
  msgstr ""
5494
 
5495
+ #: includes/functions/wcj-functions-country.php:307
5496
  msgid "Nigeria"
5497
  msgstr ""
5498
 
5499
+ #: includes/functions/wcj-functions-country.php:308
5500
  msgid "Niue"
5501
  msgstr ""
5502
 
5503
+ #: includes/functions/wcj-functions-country.php:309
5504
  msgid "Norfolk Island"
5505
  msgstr ""
5506
 
5507
+ #: includes/functions/wcj-functions-country.php:310
5508
  msgid "North Korea"
5509
  msgstr ""
5510
 
5511
+ #: includes/functions/wcj-functions-country.php:311
5512
  msgid "Norway"
5513
  msgstr ""
5514
 
5515
+ #: includes/functions/wcj-functions-country.php:312
5516
  msgid "Oman"
5517
  msgstr ""
5518
 
5519
+ #: includes/functions/wcj-functions-country.php:313
5520
  msgid "Pakistan"
5521
  msgstr ""
5522
 
5523
+ #: includes/functions/wcj-functions-country.php:314
5524
  msgid "Palestinian Territory"
5525
  msgstr ""
5526
 
5527
+ #: includes/functions/wcj-functions-country.php:315
5528
  msgid "Panama"
5529
  msgstr ""
5530
 
5531
+ #: includes/functions/wcj-functions-country.php:316
5532
  msgid "Papua New Guinea"
5533
  msgstr ""
5534
 
5535
+ #: includes/functions/wcj-functions-country.php:317
5536
  msgid "Paraguay"
5537
  msgstr ""
5538
 
5539
+ #: includes/functions/wcj-functions-country.php:318
5540
  msgid "Peru"
5541
  msgstr ""
5542
 
5543
+ #: includes/functions/wcj-functions-country.php:319
5544
  msgid "Philippines"
5545
  msgstr ""
5546
 
5547
+ #: includes/functions/wcj-functions-country.php:320
5548
  msgid "Pitcairn"
5549
  msgstr ""
5550
 
5551
+ #: includes/functions/wcj-functions-country.php:321
5552
  msgid "Poland"
5553
  msgstr ""
5554
 
5555
+ #: includes/functions/wcj-functions-country.php:322
5556
  msgid "Portugal"
5557
  msgstr ""
5558
 
5559
+ #: includes/functions/wcj-functions-country.php:323
5560
  msgid "Qatar"
5561
  msgstr ""
5562
 
5563
+ #: includes/functions/wcj-functions-country.php:324
5564
  msgid "Reunion"
5565
  msgstr ""
5566
 
5567
+ #: includes/functions/wcj-functions-country.php:325
5568
  msgid "Romania"
5569
  msgstr ""
5570
 
5571
+ #: includes/functions/wcj-functions-country.php:326
5572
  msgid "Russia"
5573
  msgstr ""
5574
 
5575
+ #: includes/functions/wcj-functions-country.php:327
5576
  msgid "Rwanda"
5577
  msgstr ""
5578
 
5579
+ #: includes/functions/wcj-functions-country.php:328
5580
  msgid "Saint Barth&eacute;lemy"
5581
  msgstr ""
5582
 
5583
+ #: includes/functions/wcj-functions-country.php:329
5584
  msgid "Saint Helena"
5585
  msgstr ""
5586
 
5587
+ #: includes/functions/wcj-functions-country.php:330
5588
  msgid "Saint Kitts and Nevis"
5589
  msgstr ""
5590
 
5591
+ #: includes/functions/wcj-functions-country.php:331
5592
  msgid "Saint Lucia"
5593
  msgstr ""
5594
 
5595
+ #: includes/functions/wcj-functions-country.php:332
5596
  msgid "Saint Martin (French part)"
5597
  msgstr ""
5598
 
5599
+ #: includes/functions/wcj-functions-country.php:333
5600
  msgid "Saint Martin (Dutch part)"
5601
  msgstr ""
5602
 
5603
+ #: includes/functions/wcj-functions-country.php:334
5604
  msgid "Saint Pierre and Miquelon"
5605
  msgstr ""
5606
 
5607
+ #: includes/functions/wcj-functions-country.php:335
5608
  msgid "Saint Vincent and the Grenadines"
5609
  msgstr ""
5610
 
5611
+ #: includes/functions/wcj-functions-country.php:336
5612
  msgid "San Marino"
5613
  msgstr ""
5614
 
5615
+ #: includes/functions/wcj-functions-country.php:337
5616
  msgid "S&atilde;o Tom&eacute; and Pr&iacute;ncipe"
5617
  msgstr ""
5618
 
5619
+ #: includes/functions/wcj-functions-country.php:338
5620
  msgid "Saudi Arabia"
5621
  msgstr ""
5622
 
5623
+ #: includes/functions/wcj-functions-country.php:339
5624
  msgid "Senegal"
5625
  msgstr ""
5626
 
5627
+ #: includes/functions/wcj-functions-country.php:340
5628
  msgid "Serbia"
5629
  msgstr ""
5630
 
5631
+ #: includes/functions/wcj-functions-country.php:341
5632
  msgid "Seychelles"
5633
  msgstr ""
5634
 
5635
+ #: includes/functions/wcj-functions-country.php:342
5636
  msgid "Sierra Leone"
5637
  msgstr ""
5638
 
5639
+ #: includes/functions/wcj-functions-country.php:343
5640
  msgid "Singapore"
5641
  msgstr ""
5642
 
5643
+ #: includes/functions/wcj-functions-country.php:344
5644
  msgid "Slovakia"
5645
  msgstr ""
5646
 
5647
+ #: includes/functions/wcj-functions-country.php:345
5648
  msgid "Slovenia"
5649
  msgstr ""
5650
 
5651
+ #: includes/functions/wcj-functions-country.php:346
5652
  msgid "Solomon Islands"
5653
  msgstr ""
5654
 
5655
+ #: includes/functions/wcj-functions-country.php:347
5656
  msgid "Somalia"
5657
  msgstr ""
5658
 
5659
+ #: includes/functions/wcj-functions-country.php:348
5660
  msgid "South Africa"
5661
  msgstr ""
5662
 
5663
+ #: includes/functions/wcj-functions-country.php:349
5664
  msgid "South Georgia/Sandwich Islands"
5665
  msgstr ""
5666
 
5667
+ #: includes/functions/wcj-functions-country.php:350
5668
  msgid "South Korea"
5669
  msgstr ""
5670
 
5671
+ #: includes/functions/wcj-functions-country.php:351
5672
  msgid "South Sudan"
5673
  msgstr ""
5674
 
5675
+ #: includes/functions/wcj-functions-country.php:352
5676
  msgid "Spain"
5677
  msgstr ""
5678
 
5679
+ #: includes/functions/wcj-functions-country.php:353
5680
  msgid "Sri Lanka"
5681
  msgstr ""
5682
 
5683
+ #: includes/functions/wcj-functions-country.php:354
5684
  msgid "Sudan"
5685
  msgstr ""
5686
 
5687
+ #: includes/functions/wcj-functions-country.php:355
5688
  msgid "Suriname"
5689
  msgstr ""
5690
 
5691
+ #: includes/functions/wcj-functions-country.php:356
5692
  msgid "Svalbard and Jan Mayen"
5693
  msgstr ""
5694
 
5695
+ #: includes/functions/wcj-functions-country.php:357
5696
  msgid "Swaziland"
5697
  msgstr ""
5698
 
5699
+ #: includes/functions/wcj-functions-country.php:358
5700
  msgid "Sweden"
5701
  msgstr ""
5702
 
5703
+ #: includes/functions/wcj-functions-country.php:359
5704
  msgid "Switzerland"
5705
  msgstr ""
5706
 
5707
+ #: includes/functions/wcj-functions-country.php:360
5708
  msgid "Syria"
5709
  msgstr ""
5710
 
5711
+ #: includes/functions/wcj-functions-country.php:361
5712
  msgid "Taiwan"
5713
  msgstr ""
5714
 
5715
+ #: includes/functions/wcj-functions-country.php:362
5716
  msgid "Tajikistan"
5717
  msgstr ""
5718
 
5719
+ #: includes/functions/wcj-functions-country.php:363
5720
  msgid "Tanzania"
5721
  msgstr ""
5722
 
5723
+ #: includes/functions/wcj-functions-country.php:364
5724
  msgid "Thailand"
5725
  msgstr ""
5726
 
5727
+ #: includes/functions/wcj-functions-country.php:365
5728
  msgid "Timor-Leste"
5729
  msgstr ""
5730
 
5731
+ #: includes/functions/wcj-functions-country.php:366
5732
  msgid "Togo"
5733
  msgstr ""
5734
 
5735
+ #: includes/functions/wcj-functions-country.php:367
5736
  msgid "Tokelau"
5737
  msgstr ""
5738
 
5739
+ #: includes/functions/wcj-functions-country.php:368
5740
  msgid "Tonga"
5741
  msgstr ""
5742
 
5743
+ #: includes/functions/wcj-functions-country.php:369
5744
  msgid "Trinidad and Tobago"
5745
  msgstr ""
5746
 
5747
+ #: includes/functions/wcj-functions-country.php:370
5748
  msgid "Tunisia"
5749
  msgstr ""
5750
 
5751
+ #: includes/functions/wcj-functions-country.php:371
5752
  msgid "Turkey"
5753
  msgstr ""
5754
 
5755
+ #: includes/functions/wcj-functions-country.php:372
5756
  msgid "Turkmenistan"
5757
  msgstr ""
5758
 
5759
+ #: includes/functions/wcj-functions-country.php:373
5760
  msgid "Turks and Caicos Islands"
5761
  msgstr ""
5762
 
5763
+ #: includes/functions/wcj-functions-country.php:374
5764
  msgid "Tuvalu"
5765
  msgstr ""
5766
 
5767
+ #: includes/functions/wcj-functions-country.php:375
5768
  msgid "Uganda"
5769
  msgstr ""
5770
 
5771
+ #: includes/functions/wcj-functions-country.php:376
5772
  msgid "Ukraine"
5773
  msgstr ""
5774
 
5775
+ #: includes/functions/wcj-functions-country.php:377
5776
  msgid "United Arab Emirates"
5777
  msgstr ""
5778
 
5779
+ #: includes/functions/wcj-functions-country.php:378
5780
  msgid "United Kingdom (UK)"
5781
  msgstr ""
5782
 
5783
+ #: includes/functions/wcj-functions-country.php:379
5784
  msgid "United States (US)"
5785
  msgstr ""
5786
 
5787
+ #: includes/functions/wcj-functions-country.php:380
5788
  msgid "Uruguay"
5789
  msgstr ""
5790
 
5791
+ #: includes/functions/wcj-functions-country.php:381
5792
  msgid "Uzbekistan"
5793
  msgstr ""
5794
 
5795
+ #: includes/functions/wcj-functions-country.php:382
5796
  msgid "Vanuatu"
5797
  msgstr ""
5798
 
5799
+ #: includes/functions/wcj-functions-country.php:383
5800
  msgid "Vatican"
5801
  msgstr ""
5802
 
5803
+ #: includes/functions/wcj-functions-country.php:384
5804
  msgid "Venezuela"
5805
  msgstr ""
5806
 
5807
+ #: includes/functions/wcj-functions-country.php:385
5808
  msgid "Vietnam"
5809
  msgstr ""
5810
 
5811
+ #: includes/functions/wcj-functions-country.php:386
5812
  msgid "Wallis and Futuna"
5813
  msgstr ""
5814
 
5815
+ #: includes/functions/wcj-functions-country.php:387
5816
  msgid "Western Sahara"
5817
  msgstr ""
5818
 
5819
+ #: includes/functions/wcj-functions-country.php:388
5820
  msgid "Western Samoa"
5821
  msgstr ""
5822
 
5823
+ #: includes/functions/wcj-functions-country.php:389
5824
  msgid "Yemen"
5825
  msgstr ""
5826
 
5827
+ #: includes/functions/wcj-functions-country.php:390
5828
  msgid "Zambia"
5829
  msgstr ""
5830
 
5831
+ #: includes/functions/wcj-functions-country.php:391
5832
  msgid "Zimbabwe"
5833
  msgstr ""
5834
 
5835
+ #: includes/functions/wcj-functions-country.php:392
5836
  msgid "European Union"
5837
  msgstr ""
5838
 
5910
  msgid "Once a minute"
5911
  msgstr ""
5912
 
5913
+ #: includes/functions/wcj-functions-currencies.php:18
5914
  msgid "United Arab Emirates Dirham"
5915
  msgstr ""
5916
 
5917
+ #: includes/functions/wcj-functions-currencies.php:19
5918
  msgid "Afghan afghani"
5919
  msgstr ""
5920
 
5921
+ #: includes/functions/wcj-functions-currencies.php:20
5922
  msgid "Albanian lek"
5923
  msgstr ""
5924
 
5925
+ #: includes/functions/wcj-functions-currencies.php:21
5926
  msgid "Armenian dram"
5927
  msgstr ""
5928
 
5929
+ #: includes/functions/wcj-functions-currencies.php:22
5930
  msgid "Netherlands Antillean gulden"
5931
  msgstr ""
5932
 
5933
+ #: includes/functions/wcj-functions-currencies.php:23
5934
  msgid "Angolan kwanza"
5935
  msgstr ""
5936
 
5937
+ #: includes/functions/wcj-functions-currencies.php:24
5938
  msgid "Argentine Peso"
5939
  msgstr ""
5940
 
5941
+ #: includes/functions/wcj-functions-currencies.php:25
5942
  msgid "Australian Dollars"
5943
  msgstr ""
5944
 
5945
+ #: includes/functions/wcj-functions-currencies.php:26
5946
  msgid "Aruban florin"
5947
  msgstr ""
5948
 
5949
+ #: includes/functions/wcj-functions-currencies.php:27
5950
  msgid "Azerbaijani manat"
5951
  msgstr ""
5952
 
5953
+ #: includes/functions/wcj-functions-currencies.php:28
5954
  msgid "Bosnia and Herzegovina konvertibilna marka"
5955
  msgstr ""
5956
 
5957
+ #: includes/functions/wcj-functions-currencies.php:29
5958
  msgid "Barbadian dollar"
5959
  msgstr ""
5960
 
5961
+ #: includes/functions/wcj-functions-currencies.php:30
5962
  msgid "Bangladeshi Taka"
5963
  msgstr ""
5964
 
5965
+ #: includes/functions/wcj-functions-currencies.php:31
5966
  msgid "Bulgarian Lev"
5967
  msgstr ""
5968
 
5969
+ #: includes/functions/wcj-functions-currencies.php:32
5970
  msgid "Bahraini dinar"
5971
  msgstr ""
5972
 
5973
+ #: includes/functions/wcj-functions-currencies.php:33
5974
  msgid "Burundi franc"
5975
  msgstr ""
5976
 
5977
+ #: includes/functions/wcj-functions-currencies.php:34
5978
  msgid "Belarusian ruble"
5979
  msgstr ""
5980
 
5981
+ #: includes/functions/wcj-functions-currencies.php:35
5982
  msgid "Brunei dollar"
5983
  msgstr ""
5984
 
5985
+ #: includes/functions/wcj-functions-currencies.php:36
5986
  msgid "Bolivian boliviano"
5987
  msgstr ""
5988
 
5989
+ #: includes/functions/wcj-functions-currencies.php:37
5990
  msgid "Brazilian Real"
5991
  msgstr ""
5992
 
5993
+ #: includes/functions/wcj-functions-currencies.php:38
5994
  msgid "Bahamian dollar"
5995
  msgstr ""
5996
 
5997
+ #: includes/functions/wcj-functions-currencies.php:39
5998
  msgid "Bhutanese ngultrum"
5999
  msgstr ""
6000
 
6001
+ #: includes/functions/wcj-functions-currencies.php:40
6002
  msgid "Botswana pula"
6003
  msgstr ""
6004
 
6005
+ #: includes/functions/wcj-functions-currencies.php:41
6006
  msgid "Belize dollar"
6007
  msgstr ""
6008
 
6009
+ #: includes/functions/wcj-functions-currencies.php:42
6010
  msgid "Canadian Dollars"
6011
  msgstr ""
6012
 
6013
+ #: includes/functions/wcj-functions-currencies.php:43
6014
  msgid "Congolese franc"
6015
  msgstr ""
6016
 
6017
+ #: includes/functions/wcj-functions-currencies.php:44
6018
  msgid "Swiss Franc"
6019
  msgstr ""
6020
 
6021
+ #: includes/functions/wcj-functions-currencies.php:45
6022
  msgid "Chilean Peso"
6023
  msgstr ""
6024
 
6025
+ #: includes/functions/wcj-functions-currencies.php:46
6026
  msgid "Chinese Yuan"
6027
  msgstr ""
6028
 
6029
+ #: includes/functions/wcj-functions-currencies.php:47
6030
  msgid "Colombian Peso"
6031
  msgstr ""
6032
 
6033
+ #: includes/functions/wcj-functions-currencies.php:48
6034
  msgid "Costa Rican colon"
6035
  msgstr ""
6036
 
6037
+ #: includes/functions/wcj-functions-currencies.php:49
6038
  msgid "Cuban peso"
6039
  msgstr ""
6040
 
6041
+ #: includes/functions/wcj-functions-currencies.php:50
6042
  msgid "Cape Verdean escudo"
6043
  msgstr ""
6044
 
6045
+ #: includes/functions/wcj-functions-currencies.php:51
6046
  msgid "Czech Koruna"
6047
  msgstr ""
6048
 
6049
+ #: includes/functions/wcj-functions-currencies.php:52
6050
  msgid "Djiboutian franc"
6051
  msgstr ""
6052
 
6053
+ #: includes/functions/wcj-functions-currencies.php:53
6054
  msgid "Danish Krone"
6055
  msgstr ""
6056
 
6057
+ #: includes/functions/wcj-functions-currencies.php:54
6058
  msgid "Dominican Peso"
6059
  msgstr ""
6060
 
6061
+ #: includes/functions/wcj-functions-currencies.php:55
6062
  msgid "Algerian dinar"
6063
  msgstr ""
6064
 
6065
+ #: includes/functions/wcj-functions-currencies.php:56
6066
  msgid "Estonian kroon"
6067
  msgstr ""
6068
 
6069
+ #: includes/functions/wcj-functions-currencies.php:57
6070
  msgid "Egyptian Pound"
6071
  msgstr ""
6072
 
6073
+ #: includes/functions/wcj-functions-currencies.php:58
6074
  msgid "Eritrean nakfa"
6075
  msgstr ""
6076
 
6077
+ #: includes/functions/wcj-functions-currencies.php:59
6078
  msgid "Ethiopian birr"
6079
  msgstr ""
6080
 
6081
+ #: includes/functions/wcj-functions-currencies.php:60
6082
  msgid "Euros"
6083
  msgstr ""
6084
 
6085
+ #: includes/functions/wcj-functions-currencies.php:61
6086
  msgid "Fijian dollar"
6087
  msgstr ""
6088
 
6089
+ #: includes/functions/wcj-functions-currencies.php:62
6090
  msgid "Falkland Islands pound"
6091
  msgstr ""
6092
 
6093
+ #: includes/functions/wcj-functions-currencies.php:63
6094
  msgid "Pounds Sterling"
6095
  msgstr ""
6096
 
6097
+ #: includes/functions/wcj-functions-currencies.php:64
6098
  msgid "Georgian lari"
6099
  msgstr ""
6100
 
6101
+ #: includes/functions/wcj-functions-currencies.php:65
6102
  msgid "Ghanaian cedi"
6103
  msgstr ""
6104
 
6105
+ #: includes/functions/wcj-functions-currencies.php:66
6106
  msgid "Gibraltar pound"
6107
  msgstr ""
6108
 
6109
+ #: includes/functions/wcj-functions-currencies.php:67
6110
  msgid "Guyanese dollar"
6111
  msgstr ""
6112
 
6113
+ #: includes/functions/wcj-functions-currencies.php:68
6114
  msgid "Gambian dalasi"
6115
  msgstr ""
6116
 
6117
+ #: includes/functions/wcj-functions-currencies.php:69
6118
  msgid "Guinean franc"
6119
  msgstr ""
6120
 
6121
+ #: includes/functions/wcj-functions-currencies.php:70
6122
+ #: includes/functions/wcj-functions-currencies.php:173
6123
  msgid "Central African CFA franc"
6124
  msgstr ""
6125
 
6126
+ #: includes/functions/wcj-functions-currencies.php:71
6127
  msgid "Guatemalan quetzal"
6128
  msgstr ""
6129
 
6130
+ #: includes/functions/wcj-functions-currencies.php:72
6131
  msgid "Hong Kong Dollar"
6132
  msgstr ""
6133
 
6134
+ #: includes/functions/wcj-functions-currencies.php:73
6135
  msgid "Honduran lempira"
6136
  msgstr ""
6137
 
6138
+ #: includes/functions/wcj-functions-currencies.php:74
6139
  msgid "Croatia kuna"
6140
  msgstr ""
6141
 
6142
+ #: includes/functions/wcj-functions-currencies.php:75
6143
  msgid "Haitian gourde"
6144
  msgstr ""
6145
 
6146
+ #: includes/functions/wcj-functions-currencies.php:76
6147
  msgid "Hungarian Forint"
6148
  msgstr ""
6149
 
6150
+ #: includes/functions/wcj-functions-currencies.php:77
6151
  msgid "Indonesia Rupiah"
6152
  msgstr ""
6153
 
6154
+ #: includes/functions/wcj-functions-currencies.php:78
6155
  msgid "Israeli Shekel"
6156
  msgstr ""
6157
 
6158
+ #: includes/functions/wcj-functions-currencies.php:79
6159
  msgid "Indian Rupee"
6160
  msgstr ""
6161
 
6162
+ #: includes/functions/wcj-functions-currencies.php:80
6163
  msgid "Iraqi dinar"
6164
  msgstr ""
6165
 
6166
+ #: includes/functions/wcj-functions-currencies.php:81
6167
  msgid "Iranian rial"
6168
  msgstr ""
6169
 
6170
+ #: includes/functions/wcj-functions-currencies.php:82
6171
  msgid "Icelandic krona"
6172
  msgstr ""
6173
 
6174
+ #: includes/functions/wcj-functions-currencies.php:83
6175
  msgid "Yemeni rial"
6176
  msgstr ""
6177
 
6178
+ #: includes/functions/wcj-functions-currencies.php:84
6179
  msgid "Jamaican dollar"
6180
  msgstr ""
6181
 
6182
+ #: includes/functions/wcj-functions-currencies.php:85
6183
  msgid "Jordanian dinar"
6184
  msgstr ""
6185
 
6186
+ #: includes/functions/wcj-functions-currencies.php:86
6187
  msgid "Japanese Yen"
6188
  msgstr ""
6189
 
6190
+ #: includes/functions/wcj-functions-currencies.php:87
6191
  msgid "Kenyan shilling"
6192
  msgstr ""
6193
 
6194
+ #: includes/functions/wcj-functions-currencies.php:88
6195
  msgid "Kyrgyzstani som"
6196
  msgstr ""
6197
 
6198
+ #: includes/functions/wcj-functions-currencies.php:89
6199
  msgid "Cambodian riel"
6200
  msgstr ""
6201
 
6202
+ #: includes/functions/wcj-functions-currencies.php:90
6203
  msgid "Lao kip"
6204
  msgstr ""
6205
 
6206
+ #: includes/functions/wcj-functions-currencies.php:91
6207
  msgid "Cayman Islands dollar"
6208
  msgstr ""
6209
 
6210
+ #: includes/functions/wcj-functions-currencies.php:92
6211
  msgid "Comorian franc"
6212
  msgstr ""
6213
 
6214
+ #: includes/functions/wcj-functions-currencies.php:93
6215
  msgid "North Korean won"
6216
  msgstr ""
6217
 
6218
+ #: includes/functions/wcj-functions-currencies.php:94
6219
  msgid "South Korean Won"
6220
  msgstr ""
6221
 
6222
+ #: includes/functions/wcj-functions-currencies.php:95
6223
  msgid "Kuwaiti dinar"
6224
  msgstr ""
6225
 
6226
+ #: includes/functions/wcj-functions-currencies.php:96
6227
  msgid "Kazakhstani tenge"
6228
  msgstr ""
6229
 
6230
+ #: includes/functions/wcj-functions-currencies.php:97
6231
  msgid "Lao Kip"
6232
  msgstr ""
6233
 
6234
+ #: includes/functions/wcj-functions-currencies.php:98
6235
  msgid "Lebanese lira"
6236
  msgstr ""
6237
 
6238
+ #: includes/functions/wcj-functions-currencies.php:99
6239
  msgid "Libyan dinar"
6240
  msgstr ""
6241
 
6242
+ #: includes/functions/wcj-functions-currencies.php:100
6243
  msgid "Sri Lankan rupee"
6244
  msgstr ""
6245
 
6246
+ #: includes/functions/wcj-functions-currencies.php:101
6247
  msgid "Liberian dollar"
6248
  msgstr ""
6249
 
6250
+ #: includes/functions/wcj-functions-currencies.php:102
6251
  msgid "Lesotho loti"
6252
  msgstr ""
6253
 
6254
+ #: includes/functions/wcj-functions-currencies.php:103
6255
  msgid "Lithuanian litas"
6256
  msgstr ""
6257
 
6258
+ #: includes/functions/wcj-functions-currencies.php:104
6259
  msgid "Latvian lats"
6260
  msgstr ""
6261
 
6262
+ #: includes/functions/wcj-functions-currencies.php:105
6263
  msgid "Moroccan dirham"
6264
  msgstr ""
6265
 
6266
+ #: includes/functions/wcj-functions-currencies.php:106
6267
  msgid "Moldovan leu"
6268
  msgstr ""
6269
 
6270
+ #: includes/functions/wcj-functions-currencies.php:107
6271
  msgid "Malagasy ariary"
6272
  msgstr ""
6273
 
6274
+ #: includes/functions/wcj-functions-currencies.php:108
6275
  msgid "Malaysian ringgit"
6276
  msgstr ""
6277
 
6278
+ #: includes/functions/wcj-functions-currencies.php:109
6279
  msgid "Macedonian denar"
6280
  msgstr ""
6281
 
6282
+ #: includes/functions/wcj-functions-currencies.php:110
6283
  msgid "Myanma kyat"
6284
  msgstr ""
6285
 
6286
+ #: includes/functions/wcj-functions-currencies.php:111
6287
  msgid "Mongolian tugrik"
6288
  msgstr ""
6289
 
6290
+ #: includes/functions/wcj-functions-currencies.php:112
6291
  msgid "Macanese pataca"
6292
  msgstr ""
6293
 
6294
+ #: includes/functions/wcj-functions-currencies.php:113
6295
  msgid "Mauritanian ouguiya"
6296
  msgstr ""
6297
 
6298
+ #: includes/functions/wcj-functions-currencies.php:114
6299
  msgid "Mauritian rupee"
6300
  msgstr ""
6301
 
6302
+ #: includes/functions/wcj-functions-currencies.php:115
6303
  msgid "Maldivian rufiyaa"
6304
  msgstr ""
6305
 
6306
+ #: includes/functions/wcj-functions-currencies.php:116
6307
  msgid "Malawian kwacha"
6308
  msgstr ""
6309
 
6310
+ #: includes/functions/wcj-functions-currencies.php:117
6311
  msgid "Mexican Peso"
6312
  msgstr ""
6313
 
6314
+ #: includes/functions/wcj-functions-currencies.php:118
6315
  msgid "Malaysian Ringgits"
6316
  msgstr ""
6317
 
6318
+ #: includes/functions/wcj-functions-currencies.php:119
6319
  msgid "Mozambican metical"
6320
  msgstr ""
6321
 
6322
+ #: includes/functions/wcj-functions-currencies.php:120
6323
  msgid "Namibian dollar"
6324
  msgstr ""
6325
 
6326
+ #: includes/functions/wcj-functions-currencies.php:121
6327
  msgid "Nigerian Naira"
6328
  msgstr ""
6329
 
6330
+ #: includes/functions/wcj-functions-currencies.php:122
6331
  msgid "Nicaraguan cordoba"
6332
  msgstr ""
6333
 
6334
+ #: includes/functions/wcj-functions-currencies.php:123
6335
  msgid "Norwegian Krone"
6336
  msgstr ""
6337
 
6338
+ #: includes/functions/wcj-functions-currencies.php:124
6339
  msgid "Nepali Rupee"
6340
  msgstr ""
6341
 
6342
+ #: includes/functions/wcj-functions-currencies.php:125
6343
  msgid "New Zealand Dollar"
6344
  msgstr ""
6345
 
6346
+ #: includes/functions/wcj-functions-currencies.php:126
6347
  msgid "Omani rial"
6348
  msgstr ""
6349
 
6350
+ #: includes/functions/wcj-functions-currencies.php:127
6351
  msgid "Panamanian balboa"
6352
  msgstr ""
6353
 
6354
+ #: includes/functions/wcj-functions-currencies.php:128
6355
  msgid "Peruvian nuevo sol"
6356
  msgstr ""
6357
 
6358
+ #: includes/functions/wcj-functions-currencies.php:129
6359
  msgid "Papua New Guinean kina"
6360
  msgstr ""
6361
 
6362
+ #: includes/functions/wcj-functions-currencies.php:130
6363
  msgid "Philippine Pesos"
6364
  msgstr ""
6365
 
6366
+ #: includes/functions/wcj-functions-currencies.php:131
6367
  msgid "Paraguayan guarani"
6368
  msgstr ""
6369
 
6370
+ #: includes/functions/wcj-functions-currencies.php:132
6371
  msgid "Pakistani Rupee"
6372
  msgstr ""
6373
 
6374
+ #: includes/functions/wcj-functions-currencies.php:133
6375
  msgid "Polish Zloty"
6376
  msgstr ""
6377
 
6378
+ #: includes/functions/wcj-functions-currencies.php:134
6379
  msgid "Paraguayan Guaran"
6380
  msgstr ""
6381
 
6382
+ #: includes/functions/wcj-functions-currencies.php:135
6383
  msgid "Qatari riyal"
6384
  msgstr ""
6385
 
6386
+ #: includes/functions/wcj-functions-currencies.php:136
6387
  msgid "Chinese renminbi"
6388
  msgstr ""
6389
 
6390
+ #: includes/functions/wcj-functions-currencies.php:137
6391
  msgid "Romanian Leu"
6392
  msgstr ""
6393
 
6394
+ #: includes/functions/wcj-functions-currencies.php:138
6395
  msgid "Serbian dinar"
6396
  msgstr ""
6397
 
6398
+ #: includes/functions/wcj-functions-currencies.php:139
6399
  msgid "Russian Ruble"
6400
  msgstr ""
6401
 
6402
+ #: includes/functions/wcj-functions-currencies.php:140
6403
  msgid "Rwandan franc"
6404
  msgstr ""
6405
 
6406
+ #: includes/functions/wcj-functions-currencies.php:141
6407
  msgid "Saudi Riyal"
6408
  msgstr ""
6409
 
6410
+ #: includes/functions/wcj-functions-currencies.php:142
6411
  msgid "Solomon Islands dollar"
6412
  msgstr ""
6413
 
6414
+ #: includes/functions/wcj-functions-currencies.php:143
6415
  msgid "Seychellois rupee"
6416
  msgstr ""
6417
 
6418
+ #: includes/functions/wcj-functions-currencies.php:144
6419
  msgid "Sudanese pound"
6420
  msgstr ""
6421
 
6422
+ #: includes/functions/wcj-functions-currencies.php:145
6423
  msgid "Swedish Krona"
6424
  msgstr ""
6425
 
6426
+ #: includes/functions/wcj-functions-currencies.php:146
6427
  msgid "Singapore Dollar"
6428
  msgstr ""
6429
 
6430
+ #: includes/functions/wcj-functions-currencies.php:147
6431
  msgid "Saint Helena pound"
6432
  msgstr ""
6433
 
6434
+ #: includes/functions/wcj-functions-currencies.php:148
6435
  msgid "Syrian pound"
6436
  msgstr ""
6437
 
6438
+ #: includes/functions/wcj-functions-currencies.php:149
6439
  msgid "Slovak koruna"
6440
  msgstr ""
6441
 
6442
+ #: includes/functions/wcj-functions-currencies.php:150
6443
  msgid "Sierra Leonean leone"
6444
  msgstr ""
6445
 
6446
+ #: includes/functions/wcj-functions-currencies.php:151
6447
  msgid "Somali shilling"
6448
  msgstr ""
6449
 
6450
+ #: includes/functions/wcj-functions-currencies.php:152
6451
  msgid "Surinamese dollar"
6452
  msgstr ""
6453
 
6454
+ #: includes/functions/wcj-functions-currencies.php:153
6455
  msgid "Sao Tome and Principe dobra"
6456
  msgstr ""
6457
 
6458
+ #: includes/functions/wcj-functions-currencies.php:154
6459
  msgid "Swazi lilangeni"
6460
  msgstr ""
6461
 
6462
+ #: includes/functions/wcj-functions-currencies.php:155
6463
  msgid "Thai Baht"
6464
  msgstr ""
6465
 
6466
+ #: includes/functions/wcj-functions-currencies.php:156
6467
  msgid "Tajikistani somoni"
6468
  msgstr ""
6469
 
6470
+ #: includes/functions/wcj-functions-currencies.php:157
6471
  msgid "Turkmen manat"
6472
  msgstr ""
6473
 
6474
+ #: includes/functions/wcj-functions-currencies.php:158
6475
  msgid "Tunisian dinar"
6476
  msgstr ""
6477
 
6478
+ #: includes/functions/wcj-functions-currencies.php:159
6479
  msgid "Paanga"
6480
  msgstr ""
6481
 
6482
+ #: includes/functions/wcj-functions-currencies.php:160
6483
  msgid "Turkish Lira"
6484
  msgstr ""
6485
 
6486
+ #: includes/functions/wcj-functions-currencies.php:161
6487
  msgid "Trinidad and Tobago dollar"
6488
  msgstr ""
6489
 
6490
+ #: includes/functions/wcj-functions-currencies.php:162
6491
  msgid "Taiwan New Dollars"
6492
  msgstr ""
6493
 
6494
+ #: includes/functions/wcj-functions-currencies.php:163
6495
  msgid "Tanzanian shilling"
6496
  msgstr ""
6497
 
6498
+ #: includes/functions/wcj-functions-currencies.php:164
6499
  msgid "Ukrainian Hryvnia"
6500
  msgstr ""
6501
 
6502
+ #: includes/functions/wcj-functions-currencies.php:165
6503
  msgid "Ugandan shilling"
6504
  msgstr ""
6505
 
6506
+ #: includes/functions/wcj-functions-currencies.php:166
6507
  msgid "Uruguayan peso"
6508
  msgstr ""
6509
 
6510
+ #: includes/functions/wcj-functions-currencies.php:167
6511
  msgid "US Dollars"
6512
  msgstr ""
6513
 
6514
+ #: includes/functions/wcj-functions-currencies.php:168
6515
  msgid "Uzbekistani som"
6516
  msgstr ""
6517
 
6518
+ #: includes/functions/wcj-functions-currencies.php:169
6519
  msgid "Venezuelan bolivar"
6520
  msgstr ""
6521
 
6522
+ #: includes/functions/wcj-functions-currencies.php:170
6523
  msgid "Vietnamese Dong"
6524
  msgstr ""
6525
 
6526
+ #: includes/functions/wcj-functions-currencies.php:171
6527
  msgid "Vanuatu vatu"
6528
  msgstr ""
6529
 
6530
+ #: includes/functions/wcj-functions-currencies.php:172
6531
  msgid "Samoan tala"
6532
  msgstr ""
6533
 
6534
+ #: includes/functions/wcj-functions-currencies.php:174
6535
  msgid "East Caribbean dollar"
6536
  msgstr ""
6537
 
6538
+ #: includes/functions/wcj-functions-currencies.php:175
6539
  msgid "Special Drawing Rights"
6540
  msgstr ""
6541
 
6542
+ #: includes/functions/wcj-functions-currencies.php:176
6543
  msgid "West African CFA franc"
6544
  msgstr ""
6545
 
6546
+ #: includes/functions/wcj-functions-currencies.php:177
6547
  msgid "CFP franc"
6548
  msgstr ""
6549
 
6550
+ #: includes/functions/wcj-functions-currencies.php:178
6551
  msgid "South African rand"
6552
  msgstr ""
6553
 
6554
+ #: includes/functions/wcj-functions-currencies.php:179
6555
  msgid "Zambian kwacha"
6556
  msgstr ""
6557
 
6558
+ #: includes/functions/wcj-functions-currencies.php:180
6559
  msgid "Zimbabwean dollar"
6560
  msgstr ""
6561
 
6562
+ #: includes/functions/wcj-functions-currencies.php:182
6563
  msgid "Auroracoin"
6564
  msgstr ""
6565
 
6566
+ #: includes/functions/wcj-functions-currencies.php:183
6567
  msgid "BitConnect"
6568
  msgstr ""
6569
 
6570
+ #: includes/functions/wcj-functions-currencies.php:184
6571
  msgid "Bitcoin Cash"
6572
  msgstr ""
6573
 
6574
+ #: includes/functions/wcj-functions-currencies.php:185
6575
  msgid "Bitcoin"
6576
  msgstr ""
6577
 
6578
+ #: includes/functions/wcj-functions-currencies.php:186
6579
  msgid "Coinye"
6580
  msgstr ""
6581
 
6582
+ #: includes/functions/wcj-functions-currencies.php:187
6583
  msgid "DigitalNote"
6584
  msgstr ""
6585
 
6586
+ #: includes/functions/wcj-functions-currencies.php:188
6587
  msgid "Emercoin"
6588
  msgstr ""
6589
 
6590
+ #: includes/functions/wcj-functions-currencies.php:189
6591
  msgid "Ethereum Classic"
6592
  msgstr ""
6593
 
6594
+ #: includes/functions/wcj-functions-currencies.php:190
6595
  msgid "Ethereum"
6596
  msgstr ""
6597
 
6598
+ #: includes/functions/wcj-functions-currencies.php:191
6599
  msgid "Freemasoncoin"
6600
  msgstr ""
6601
 
6602
+ #: includes/functions/wcj-functions-currencies.php:192
6603
  msgid "Gridcoin"
6604
  msgstr ""
6605
 
6606
+ #: includes/functions/wcj-functions-currencies.php:193
6607
  msgid "IOTA"
6608
  msgstr ""
6609
 
6610
+ #: includes/functions/wcj-functions-currencies.php:194
6611
  msgid "Litecoin"
6612
  msgstr ""
6613
 
6614
+ #: includes/functions/wcj-functions-currencies.php:195
6615
  msgid "MazaCoin"
6616
  msgstr ""
6617
 
6618
+ #: includes/functions/wcj-functions-currencies.php:196
6619
  msgid "Monero"
6620
  msgstr ""
6621
 
6622
+ #: includes/functions/wcj-functions-currencies.php:197
6623
  msgid "Namecoin"
6624
  msgstr ""
6625
 
6626
+ #: includes/functions/wcj-functions-currencies.php:198
6627
  msgid "NEM"
6628
  msgstr ""
6629
 
6630
+ #: includes/functions/wcj-functions-currencies.php:199
6631
  msgid "Nxt"
6632
  msgstr ""
6633
 
6634
+ #: includes/functions/wcj-functions-currencies.php:200
6635
  msgid "Omni"
6636
  msgstr ""
6637
 
6638
+ #: includes/functions/wcj-functions-currencies.php:201
6639
  msgid "Peercoin"
6640
  msgstr ""
6641
 
6642
+ #: includes/functions/wcj-functions-currencies.php:202
6643
  msgid "PotCoin"
6644
  msgstr ""
6645
 
6646
+ #: includes/functions/wcj-functions-currencies.php:203
6647
  msgid "Primecoin"
6648
  msgstr ""
6649
 
6650
+ #: includes/functions/wcj-functions-currencies.php:204
6651
  msgid "Ripple"
6652
  msgstr ""
6653
 
6654
+ #: includes/functions/wcj-functions-currencies.php:205
6655
  msgid "SixEleven"
6656
  msgstr ""
6657
 
6658
+ #: includes/functions/wcj-functions-currencies.php:206
6659
  msgid "Synereo AMP"
6660
  msgstr ""
6661
 
6662
+ #: includes/functions/wcj-functions-currencies.php:207
6663
  msgid "Titcoin"
6664
  msgstr ""
6665
 
6666
+ #: includes/functions/wcj-functions-currencies.php:208
6667
  msgid "Ubiq"
6668
  msgstr ""
6669
 
6670
+ #: includes/functions/wcj-functions-currencies.php:209
6671
  msgid "Vertcoin"
6672
  msgstr ""
6673
 
6674
+ #: includes/functions/wcj-functions-currencies.php:210
6675
  msgid "Zcash"
6676
  msgstr ""
6677
 
6678
+ #: includes/functions/wcj-functions-currencies.php:212
6679
  msgid "myCred"
6680
  msgstr ""
6681
 
6687
  msgid "European Central Bank (ECB)"
6688
  msgstr ""
6689
 
6690
+ #: includes/functions/wcj-functions-exchange-rates.php:70
6691
+ msgid "recommended"
6692
+ msgstr ""
6693
+
6694
  #: includes/functions/wcj-functions-exchange-rates.php:71
6695
  msgid "TCMB"
6696
  msgstr ""
6707
  msgid "CoinMarketCap"
6708
  msgstr ""
6709
 
6710
+ #: includes/functions/wcj-functions-exchange-rates.php:75
6711
+ msgid "Google"
6712
+ msgstr ""
6713
+
6714
+ #: includes/functions/wcj-functions-exchange-rates.php:76
6715
+ msgid "Bank of England (BOE)"
6716
  msgstr ""
6717
 
6718
+ #: includes/functions/wcj-functions-general.php:550
6719
  msgid "Before cart"
6720
  msgstr ""
6721
 
6722
+ #: includes/functions/wcj-functions-general.php:551
6723
  msgid "Before cart table"
6724
  msgstr ""
6725
 
6726
+ #: includes/functions/wcj-functions-general.php:552
6727
  msgid "Before cart contents"
6728
  msgstr ""
6729
 
6730
+ #: includes/functions/wcj-functions-general.php:553
6731
  msgid "Cart contents"
6732
  msgstr ""
6733
 
6734
+ #: includes/functions/wcj-functions-general.php:554
6735
  msgid "Cart coupon"
6736
  msgstr ""
6737
 
6738
+ #: includes/functions/wcj-functions-general.php:555
6739
  msgid "Cart actions"
6740
  msgstr ""
6741
 
6742
+ #: includes/functions/wcj-functions-general.php:556
6743
  msgid "After cart contents"
6744
  msgstr ""
6745
 
6746
+ #: includes/functions/wcj-functions-general.php:557
6747
  msgid "After cart table"
6748
  msgstr ""
6749
 
6750
+ #: includes/functions/wcj-functions-general.php:558
6751
  msgid "Cart collaterals"
6752
  msgstr ""
6753
 
6754
+ #: includes/functions/wcj-functions-general.php:559
6755
  msgid "After cart"
6756
  msgstr ""
6757
 
6758
+ #: includes/functions/wcj-functions-general.php:561
6759
  msgid "Before cart totals"
6760
  msgstr ""
6761
 
6762
+ #: includes/functions/wcj-functions-general.php:562
6763
  msgid "Cart totals: Before shipping"
6764
  msgstr ""
6765
 
6766
+ #: includes/functions/wcj-functions-general.php:563
6767
  msgid "Cart totals: After shipping"
6768
  msgstr ""
6769
 
6770
+ #: includes/functions/wcj-functions-general.php:564
6771
  msgid "Cart totals: Before order total"
6772
  msgstr ""
6773
 
6774
+ #: includes/functions/wcj-functions-general.php:565
6775
  msgid "Cart totals: After order total"
6776
  msgstr ""
6777
 
6778
+ #: includes/functions/wcj-functions-general.php:566
6779
  msgid "Proceed to checkout"
6780
  msgstr ""
6781
 
6782
+ #: includes/functions/wcj-functions-general.php:567
6783
  msgid "After cart totals"
6784
  msgstr ""
6785
 
6786
+ #: includes/functions/wcj-functions-general.php:569
6787
  msgid "Before shipping calculator"
6788
  msgstr ""
6789
 
6790
+ #: includes/functions/wcj-functions-general.php:570
6791
  msgid "After shipping calculator"
6792
  msgstr ""
6793
 
6794
+ #: includes/functions/wcj-functions-general.php:572
6795
  msgid "If cart is empty"
6796
  msgstr ""
6797
 
6798
+ #: includes/functions/wcj-functions-invoicing.php:33
6799
+ #, php-format
6800
+ msgid "Current image path: %s."
6801
+ msgstr ""
6802
+
6803
+ #: includes/functions/wcj-functions-invoicing.php:266
6804
  msgid "Invoice"
6805
  msgstr ""
6806
 
6807
+ #: includes/functions/wcj-functions-invoicing.php:272
6808
  msgid "Proforma Invoice"
6809
  msgstr ""
6810
 
6811
+ #: includes/functions/wcj-functions-invoicing.php:278
6812
  msgid "Packing Slip"
6813
  msgstr ""
6814
 
6815
+ #: includes/functions/wcj-functions-invoicing.php:284
6816
  msgid "Credit Note"
6817
  msgstr ""
6818
 
6819
+ #: includes/functions/wcj-functions-invoicing.php:294
6820
  msgid "Custom Document"
6821
  msgstr ""
6822
 
6854
  msgid "Last Sale Order Status"
6855
  msgstr ""
6856
 
6857
+ #: includes/functions/wcj-functions-reports.php:83
6858
  msgid "Last 14 days"
6859
  msgstr ""
6860
 
6861
+ #: includes/functions/wcj-functions-reports.php:88
6862
  msgid "Last 30 days"
6863
  msgstr ""
6864
 
6865
+ #: includes/functions/wcj-functions-reports.php:93
6866
  msgid "Last 3 months"
6867
  msgstr ""
6868
 
6869
+ #: includes/functions/wcj-functions-reports.php:98
6870
  msgid "Last 6 months"
6871
  msgstr ""
6872
 
6873
+ #: includes/functions/wcj-functions-reports.php:103
6874
  msgid "Last 12 months"
6875
  msgstr ""
6876
 
6877
+ #: includes/functions/wcj-functions-reports.php:108
6878
  msgid "Last 24 months"
6879
  msgstr ""
6880
 
6881
+ #: includes/functions/wcj-functions-reports.php:113
6882
  msgid "Last 36 months"
6883
  msgstr ""
6884
 
6885
+ #: includes/functions/wcj-functions-reports.php:118
6886
  msgid "Same days last month"
6887
  msgstr ""
6888
 
6889
+ #: includes/functions/wcj-functions-reports.php:123
6890
  msgid "Same days last year"
6891
  msgstr ""
6892
 
6893
+ #: includes/functions/wcj-functions-reports.php:128
6894
  msgid "Last year"
6895
  msgstr ""
6896
 
6897
+ #: includes/functions/wcj-functions-reports.php:133
6898
  msgid "Yesterday"
6899
  msgstr ""
6900
 
6901
+ #: includes/functions/wcj-functions-reports.php:138
6902
  msgid "Today"
6903
  msgstr ""
6904
 
6905
+ #: includes/functions/wcj-functions-shipping.php:38
6906
+ #, php-format
6907
+ msgid "%s day(s)"
6908
+ msgstr ""
6909
+
6910
+ #: includes/functions/wcj-functions-shipping.php:108
6911
+ msgid "No shipping class"
6912
+ msgstr ""
6913
+
6914
+ #: includes/functions/wcj-functions-shipping.php:216
6915
+ #: includes/functions/wcj-functions-shipping.php:267
6916
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:134
6917
+ msgid "You have Free delivery"
6918
  msgstr ""
6919
 
6920
  #: includes/gateways/class-wc-gateway-wcj-custom.php:61
6971
  msgstr ""
6972
 
6973
  #: includes/gateways/class-wc-gateway-wcj-custom.php:108
6974
+ #: includes/settings/wcj-settings-shipping-by-order-amount.php:57
6975
  msgid "Minimum order amount"
6976
  msgstr ""
6977
 
6982
  msgstr ""
6983
 
6984
  #: includes/gateways/class-wc-gateway-wcj-custom.php:117
6985
+ #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:59
6986
  msgid "Enable for shipping methods"
6987
  msgstr ""
6988
 
6993
  msgstr ""
6994
 
6995
  #: includes/gateways/class-wc-gateway-wcj-custom.php:125
6996
+ #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:66
6997
  msgid "Select shipping methods"
6998
  msgstr ""
6999
 
7053
  msgid "Booster for WooCommerce: Custom Payment Gateway"
7054
  msgstr ""
7055
 
7056
+ #: includes/input-fields/class-wcj-product-input-fields-core.php:109
7057
  msgid "Booster: Product Input Fields"
7058
  msgstr ""
7059
 
7060
+ #: includes/input-fields/class-wcj-product-input-fields-core.php:148
7061
  msgid "Total number of "
7062
  msgstr ""
7063
 
7064
+ #: includes/input-fields/class-wcj-product-input-fields-core.php:164
7065
+ #: includes/input-fields/class-wcj-product-input-fields-core.php:319
7066
  #: includes/settings/wcj-settings-product-input-fields.php:83
7067
  msgid "Product Input Field"
7068
  msgstr ""
7069
 
7070
+ #: includes/input-fields/class-wcj-product-input-fields-core.php:404
7071
  msgid "Wrong file type!"
7072
  msgstr ""
7073
 
7074
+ #: includes/input-fields/class-wcj-product-input-fields-core.php:412
7075
  msgid "File is too big!"
7076
  msgstr ""
7077
 
7078
+ #: includes/input-fields/class-wcj-product-input-fields-core.php:625
7079
  msgid "Select a country&hellip;"
7080
  msgstr ""
7081
 
7120
 
7121
  #: includes/input-fields/wcj-product-input-fields-options.php:34
7122
  #: includes/settings/wcj-settings-checkout-custom-fields.php:122
7123
+ #: includes/settings/meta-box/wcj-settings-meta-box-order-numbers.php:14
7124
  msgid "Number"
7125
  msgstr ""
7126
 
7523
 
7524
  #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-advanced.php:25
7525
  #: includes/settings/wcj-settings-order-min-amount.php:69
7526
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:61
7527
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:75
7528
  msgid "Advanced"
7529
  msgstr ""
7530
 
7602
  msgstr ""
7603
 
7604
  #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:129
7605
+ #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:302
7606
  msgid "View"
7607
  msgstr ""
7608
 
7609
  #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:148
7610
+ #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:326
7611
  msgid "Create"
7612
  msgstr ""
7613
 
7614
+ #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:268
7615
  msgid "Booster: PDF Invoices"
7616
  msgstr ""
7617
 
7618
+ #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:288
7619
  msgid "You have no document types enabled."
7620
  msgstr ""
7621
 
7622
+ #: includes/pdf-invoices/submodules/class-wcj-pdf-invoicing-display.php:332
7623
  msgid ""
7624
  "In case of partial refund, you need to reload the page to see created "
7625
  "document in this meta box."
7649
  msgid "Templates"
7650
  msgstr ""
7651
 
7652
+ #: includes/plus/class-wcj-plus-site-key-manager.php:79
7653
+ #, php-format
7654
+ msgid "Status last checked at %s."
7655
+ msgstr ""
7656
+
7657
+ #: includes/plus/class-wcj-plus-site-key-manager.php:80
7658
+ #, php-format
7659
+ msgid "Cron scheduled at %s."
7660
+ msgstr ""
7661
+
7662
+ #: includes/plus/class-wcj-plus-site-key-manager.php:81
7663
+ #, php-format
7664
+ msgid "Cron last run at %s."
7665
+ msgstr ""
7666
+
7667
+ #: includes/plus/class-wcj-plus-site-key-manager.php:122
7668
+ msgid "No key set."
7669
+ msgstr ""
7670
+
7671
+ #: includes/plus/class-wcj-plus-site-key-manager.php:123
7672
+ #, php-format
7673
+ msgid ""
7674
+ "To get the key, please visit <a target=\"_blank\" href=\"%s\">your account "
7675
+ "page at %s</a>."
7676
+ msgstr ""
7677
+
7678
+ #: includes/plus/class-wcj-plus-site-key-manager.php:126
7679
+ #, php-format
7680
+ msgid "No response from server. Please <a href=\"%s\">try again</a> later."
7681
+ msgstr ""
7682
+
7683
+ #: includes/plus/class-wcj-plus-site-key-manager.php:128
7684
+ #, php-format
7685
+ msgid "Server error. Please <a href=\"%s\">try again</a> later."
7686
+ msgstr ""
7687
+
7688
+ #: includes/plus/class-wcj-plus-site-key-section.php:46
7689
+ msgid "Manage site key"
7690
+ msgstr ""
7691
+
7692
+ #: includes/plus/class-wcj-plus-site-key-section.php:59
7693
+ #: includes/plus/class-wcj-plus-site-key-section.php:73
7694
+ #: includes/plus/class-wcj-plus-site-key-section.php:81
7695
+ msgid "Site Key"
7696
+ msgstr ""
7697
+
7698
+ #: includes/plus/class-wcj-plus-site-key-section.php:74
7699
+ msgid ""
7700
+ "This section lets you manage site key for paid Booster Plus for WooCommerce "
7701
+ "plugin."
7702
+ msgstr ""
7703
+
7704
+ #: includes/plus/class-wcj-plus-site-key-section.php:75
7705
+ #, php-format
7706
+ msgid ""
7707
+ "To get the key, please go to <a target=\"_blank\" href=\"%s\">your account "
7708
+ "page at %s</a>."
7709
+ msgstr ""
7710
+
7711
+ #: includes/plus/class-wcj-plus-site-key-section.php:78
7712
+ msgid "Check site key now"
7713
+ msgstr ""
7714
+
7715
+ #: includes/plus/class-wcj-plus-site-key-section.php:82
7716
+ #, php-format
7717
+ msgid "Site URL: %s"
7718
+ msgstr ""
7719
+
7720
+ #: includes/plus/lib/plugin-update-checker/github-checker.php:119
7721
+ msgid "There is no changelog available."
7722
+ msgstr ""
7723
+
7724
+ #: includes/plus/lib/plugin-update-checker/plugin-update-checker.php:763
7725
+ msgid "Check for updates"
7726
+ msgstr ""
7727
+
7728
+ #: includes/plus/lib/plugin-update-checker/plugin-update-checker.php:807
7729
+ msgid "This plugin is up to date."
7730
+ msgstr ""
7731
+
7732
+ #: includes/plus/lib/plugin-update-checker/plugin-update-checker.php:809
7733
+ msgid "A new version of this plugin is available."
7734
+ msgstr ""
7735
+
7736
+ #: includes/plus/lib/plugin-update-checker/plugin-update-checker.php:811
7737
+ #, php-format
7738
+ msgid "Unknown update checker status \"%s\""
7739
+ msgstr ""
7740
+
7741
  #: includes/price-by-country/class-wcj-price-by-country-group-generator.php:75
7742
  msgid "Create All Country Groups Failed."
7743
  msgstr ""
8062
 
8063
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:17
8064
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:22
8065
+ #: includes/settings/wcj-settings-max-products-per-user.php:14
8066
+ #: includes/settings/wcj-settings-max-products-per-user.php:19
8067
  #: includes/settings/wcj-settings-product-add-to-cart.php:24
8068
  #: includes/settings/wcj-settings-product-by-date.php:20
8069
  msgid "All Products"
8077
  #: includes/settings/wcj-settings-admin-orders-list.php:150
8078
  #: includes/settings/wcj-settings-admin-products-list.php:20
8079
  #: includes/settings/wcj-settings-admin-products-list.php:76
8080
+ #: includes/settings/wcj-settings-max-products-per-user.php:20
8081
+ #: includes/settings/wcj-settings-max-products-per-user.php:43
8082
  #: includes/settings/wcj-settings-my-account.php:40
8083
  #: includes/settings/wcj-settings-order-quantities.php:21
8084
  #: includes/settings/wcj-settings-order-quantities.php:79
8085
  #: includes/settings/wcj-settings-orders.php:107
8086
  #: includes/settings/wcj-settings-price-formats.php:37
8087
  #: includes/settings/wcj-settings-product-add-to-cart.php:273
8088
+ #: includes/settings/wcj-settings-product-listings.php:138
8089
  #: includes/settings/wcj-settings-sale-flash.php:20
8090
  #: includes/settings/wcj-settings-sale-flash.php:65
8091
  #: includes/settings/wcj-settings-sale-flash.php:90
8092
+ #: includes/settings/wcj-settings-shipping-by-condition.php:47
8093
  #: includes/settings/wcj-settings-shipping-options.php:21
8094
  #: includes/settings/wcj-settings-stock.php:20
8095
+ #: includes/settings/wcj-settings-stock.php:62
8096
+ #: includes/settings/wcj-settings-stock.php:104
8097
  #: includes/settings/wcj-settings-tax-display.php:27
8098
  #: includes/settings/wcj-settings-tax-display.php:44
8099
  #: includes/settings/wcj-settings-tax-display.php:101
8113
  #: includes/settings/wcj-settings-general.php:121
8114
  #: includes/settings/wcj-settings-general.php:128
8115
  #: includes/settings/wcj-settings-general.php:135
8116
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:102
8117
  #: includes/settings/wcj-settings-price-by-user-role.php:56
8118
  #: includes/settings/wcj-settings-price-by-user-role.php:88
8119
  #: includes/settings/wcj-settings-product-add-to-cart.php:131
8120
  #: includes/settings/wcj-settings-product-open-pricing.php:80
8121
+ #: includes/settings/wcj-settings-sku.php:235
8122
  #: includes/settings/meta-box/wcj-settings-meta-box-product-add-to-cart.php:67
8123
  msgid "Disable"
8124
  msgstr ""
8144
 
8145
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:63
8146
  #: includes/settings/wcj-settings-add-to-cart-button-visibility.php:68
8147
+ #: includes/settings/wcj-settings-max-products-per-user.php:37
8148
+ #: includes/settings/wcj-settings-max-products-per-user.php:42
8149
  #: includes/settings/wcj-settings-price-labels.php:22
8150
  #: includes/settings/wcj-settings-product-add-to-cart.php:39
8151
  #: includes/settings/wcj-settings-product-by-date.php:52
8196
  msgstr ""
8197
 
8198
  #: includes/settings/wcj-settings-add-to-cart.php:29
8199
+ #: includes/settings/wcj-settings-product-tabs.php:50
8200
  msgid "Click \"Save changes\" after you change this number."
8201
  msgstr ""
8202
 
8290
  #: includes/settings/wcj-settings-add-to-cart.php:165
8291
  #: includes/settings/wcj-settings-add-to-cart.php:209
8292
  #: includes/settings/wcj-settings-add-to-cart.php:220
8293
+ #: includes/settings/wcj-settings-product-custom-info.php:190
8294
  msgid "Leave blank to disable."
8295
  msgstr ""
8296
 
8511
  #: includes/settings/wcj-settings-checkout-customization.php:68
8512
  #: includes/settings/wcj-settings-currency.php:21
8513
  #: includes/settings/wcj-settings-order-custom-statuses.php:63
8514
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:48
8515
  #: includes/settings/wcj-settings-product-bookings.php:92
8516
  #: includes/settings/wcj-settings-product-images.php:20
8517
  #: includes/settings/wcj-settings-product-images.php:27
8544
  msgstr ""
8545
 
8546
  #: includes/settings/wcj-settings-admin-products-list.php:27
8547
+ #: includes/settings/wcj-settings-price-by-user-role.php:147
8548
  #: includes/settings/wcj-settings-shipping.php:51
8549
  msgid ""
8550
  "Save module's settings after changing this option to see new settings fields."
8728
  #: includes/settings/wcj-settings-checkout-custom-info.php:19
8729
  #: includes/settings/wcj-settings-mini-cart.php:19
8730
  #: includes/settings/wcj-settings-my-account.php:46
8731
+ #: includes/settings/wcj-settings-product-custom-info.php:53
8732
  msgid "Total Blocks"
8733
  msgstr ""
8734
 
8743
  #: includes/settings/wcj-settings-checkout-custom-info.php:84
8744
  #: includes/settings/wcj-settings-mini-cart.php:58
8745
  #: includes/settings/wcj-settings-my-account.php:119
8746
+ #: includes/settings/wcj-settings-product-custom-info.php:123
8747
  msgid "Position Order (i.e. Priority)"
8748
  msgstr ""
8749
 
8763
  #: includes/settings/wcj-settings-checkout-core-fields.php:16
8764
  #: includes/settings/wcj-settings-currency-exchange-rates.php:26
8765
  #: includes/settings/wcj-settings-emails-verification.php:14
8766
+ #: includes/settings/wcj-settings-max-products-per-user.php:55
8767
  #: includes/settings/wcj-settings-multicurrency.php:17
8768
  #: includes/settings/wcj-settings-offer-price.php:14
8769
  #: includes/settings/wcj-settings-order-quantities.php:131
8770
  #: includes/settings/wcj-settings-payment-gateways-by-country.php:15
8771
+ #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:17
8772
  #: includes/settings/wcj-settings-payment-gateways-min-max.php:15
8773
  #: includes/settings/wcj-settings-price-formats.php:15
8774
+ #: includes/settings/wcj-settings-product-tabs.php:15
8775
+ #: includes/settings/wcj-settings-shipping-by-condition.php:19
8776
+ #: includes/settings/wcj-settings-shipping-by-order-amount.php:15
8777
+ #: includes/settings/wcj-settings-shipping-time.php:25
8778
  msgid "General Options"
8779
  msgstr ""
8780
 
8949
  #: includes/settings/wcj-settings-checkout-custom-fields.php:169
8950
  #: includes/settings/wcj-settings-checkout-custom-info.php:55
8951
  #: includes/settings/wcj-settings-empty-cart.php:58
8952
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:114
8953
  msgid "Billing"
8954
  msgstr ""
8955
 
9128
  #: includes/settings/wcj-settings-checkout-custom-info.php:53
9129
  #: includes/settings/wcj-settings-checkout-files-upload.php:55
9130
  #: includes/settings/wcj-settings-empty-cart.php:56
9131
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:112
9132
  msgid "Before checkout form"
9133
  msgstr ""
9134
 
9135
  #: includes/settings/wcj-settings-checkout-custom-info.php:54
9136
  #: includes/settings/wcj-settings-empty-cart.php:57
9137
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:113
9138
  msgid "Before customer details"
9139
  msgstr ""
9140
 
9141
  #: includes/settings/wcj-settings-checkout-custom-info.php:57
9142
  #: includes/settings/wcj-settings-empty-cart.php:60
9143
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:116
9144
  msgid "After customer details"
9145
  msgstr ""
9146
 
9147
  #: includes/settings/wcj-settings-checkout-custom-info.php:58
9148
  #: includes/settings/wcj-settings-empty-cart.php:61
9149
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:117
9150
  msgid "Before order review"
9151
  msgstr ""
9152
 
9153
  #: includes/settings/wcj-settings-checkout-custom-info.php:59
9154
  #: includes/settings/wcj-settings-empty-cart.php:62
9155
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:118
9156
  msgid "Order review"
9157
  msgstr ""
9158
 
9159
  #: includes/settings/wcj-settings-checkout-custom-info.php:60
9160
  #: includes/settings/wcj-settings-empty-cart.php:63
9161
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:119
9162
  msgid "After order review"
9163
  msgstr ""
9164
 
9165
  #: includes/settings/wcj-settings-checkout-custom-info.php:61
9166
  #: includes/settings/wcj-settings-checkout-files-upload.php:56
9167
  #: includes/settings/wcj-settings-empty-cart.php:64
9168
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:120
9169
  msgid "After checkout form"
9170
  msgstr ""
9171
 
9259
  msgstr ""
9260
 
9261
  #: includes/settings/wcj-settings-checkout-customization.php:96
9262
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:36
9263
  msgid "Billing state"
9264
  msgstr ""
9265
 
9266
  #: includes/settings/wcj-settings-checkout-customization.php:97
9267
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:46
9268
  msgid "Billing postcode"
9269
  msgstr ""
9270
 
9301
  msgstr ""
9302
 
9303
  #: includes/settings/wcj-settings-checkout-customization.php:107
9304
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:37
9305
  msgid "Shipping state"
9306
  msgstr ""
9307
 
9308
  #: includes/settings/wcj-settings-checkout-customization.php:108
9309
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:47
9310
  msgid "Shipping postcode"
9311
  msgstr ""
9312
 
9536
  #: includes/settings/wcj-settings-eu-vat-number.php:203
9537
  #: includes/settings/wcj-settings-general.php:77
9538
  #: includes/settings/wcj-settings-payment-gateways.php:49
9539
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:43
9540
+ #: includes/settings/wcj-settings-product-custom-info.php:184
9541
+ #: includes/settings/wcj-settings-shipping-by-condition.php:101
9542
  msgid "Advanced Options"
9543
  msgstr ""
9544
 
9618
  msgid "%s seconds till next update."
9619
  msgstr ""
9620
 
9621
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:31
 
 
 
 
 
 
 
9622
  #: includes/settings/wcj-settings-currency-per-product.php:102
9623
  #: includes/settings/wcj-settings-multicurrency-base-price.php:24
9624
  #: includes/settings/wcj-settings-multicurrency.php:22
9627
  msgid "Exchange Rates Updates"
9628
  msgstr ""
9629
 
9630
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:43
9631
+ msgid "Update all rates now"
9632
+ msgstr ""
9633
+
9634
  #: includes/settings/wcj-settings-currency-exchange-rates.php:53
9635
  msgid "Exchange Rates Rounding"
9636
  msgstr ""
9641
  msgid "Rounding Precision"
9642
  msgstr ""
9643
 
9644
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:61
9645
+ msgid "Rounding precision sets number of decimal digits to round to."
9646
  msgstr ""
9647
 
9648
  #: includes/settings/wcj-settings-currency-exchange-rates.php:68
9649
+ msgid "Exchange Rates Offset - Percent"
9650
+ msgstr ""
9651
+
9652
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:69
9653
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:77
9654
  msgid ""
9655
  "If both percent and fixed offsets are set - percent offset is applied first "
9656
  "and fixed offset after that."
9657
  msgstr ""
9658
 
9659
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:76
9660
  msgid "Exchange Rates Offset - Fixed"
9661
  msgstr ""
9662
 
9663
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:84
9664
  msgid "Calculate with Inversion"
9665
  msgstr ""
9666
 
9667
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:86
9668
  msgid ""
9669
  "If your currency pair have very small exchange rate, you may want to invert "
9670
  "currencies before calculating the rate."
9671
  msgstr ""
9672
 
9673
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:92
9674
  msgid "Always Use cURL"
9675
  msgstr ""
9676
 
9677
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:94
9678
  msgid ""
9679
  "If for some reason currency exchange rates are not updating, try enabling "
9680
  "this option."
9681
  msgstr ""
9682
 
9683
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:113
9684
  msgid "Custom Currencies Options"
9685
  msgstr ""
9686
 
9687
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:115
9688
  #, php-format
9689
  msgid ""
9690
  "You can add more currencies in this section. E.g. this can be used to "
9691
  "display exchange rates with %s shortcodes."
9692
  msgstr ""
9693
 
9694
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:126
9695
  #: includes/settings/wcj-settings-currency.php:59
9696
  msgid "Total Custom Currencies"
9697
  msgstr ""
9698
 
9699
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:138
9700
  #: includes/settings/wcj-settings-currency.php:71
9701
  msgid "Custom Currency"
9702
  msgstr ""
9703
 
9704
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:157
9705
  #: includes/settings/wcj-settings-price-by-country.php:265
9706
  msgid "Exchange Rates"
9707
  msgstr ""
9708
 
9709
+ #: includes/settings/wcj-settings-currency-exchange-rates.php:159
9710
+ msgid ""
9711
+ "All currencies from all <strong>enabled</strong> modules (with \"Exchange "
9712
+ "Rates Updates\" set to \"Automatically via Currency Exchange Rates module\") "
9713
+ "will be automatically added to the list."
9714
+ msgstr ""
9715
+
9716
  #: includes/settings/wcj-settings-currency-external-products.php:14
9717
  msgid "Currency for External Products Options"
9718
  msgstr ""
10205
  msgstr ""
10206
 
10207
  #: includes/settings/wcj-settings-export.php:20
10208
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:163
10209
  msgid "CSV Separator"
10210
  msgstr ""
10211
 
10454
  msgstr ""
10455
 
10456
  #: includes/settings/wcj-settings-general.php:152
10457
+ #: includes/settings/wcj-settings-max-products-per-user.php:44
10458
  #: includes/settings/wcj-settings-product-by-date.php:54
10459
  #: includes/settings/wcj-settings-product-by-time.php:54
10460
  msgid "This will add new meta box to each product's edit page."
10640
 
10641
  #: includes/settings/wcj-settings-left-to-free-shipping.php:20
10642
  #, php-format
10643
+ msgid "In content replaced values are: %s, %s and %s."
10644
  msgstr ""
10645
 
10646
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:27
10647
  msgid "Info on Cart"
10648
  msgstr ""
10649
 
10650
  #: includes/settings/wcj-settings-left-to-free-shipping.php:35
10651
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:66
10652
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:100
10653
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:131
10654
  msgid "You can use HTML and/or shortcodes (e.g. [wcj_wpml]) here."
10655
  msgstr ""
10656
 
10657
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:43
10658
+ msgid ""
10659
+ "Please note, that depending on the \"Position\" you select, your customer "
10660
+ "may have to reload the cart page to see the updated left to free shipping "
10661
+ "value. For example, if you select \"After cart totals\" position, then left "
10662
+ "to free shipping value will be updated as soon as customer updates the cart. "
10663
+ "However if you select \"After cart\" position instead message will not be "
10664
+ "updated, and customer will have to reload the page. In other words, message "
10665
+ "position should be inside that page part that is automatically updated on "
10666
+ "cart update."
10667
+ msgstr ""
10668
+
10669
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:50
10670
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:84
10671
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:124
10672
  msgid "Position Order (Priority)"
10673
  msgstr ""
10674
 
10675
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:56
10676
  msgid "Info on Mini Cart"
10677
  msgstr ""
10678
 
10679
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:78
10680
  #: includes/settings/wcj-settings-mini-cart.php:51
10681
  msgid "Before mini cart"
10682
  msgstr ""
10683
 
10684
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:79
10685
  #: includes/settings/wcj-settings-mini-cart.php:52
10686
  msgid "Before buttons"
10687
  msgstr ""
10688
 
10689
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:80
10690
  #: includes/settings/wcj-settings-mini-cart.php:53
10691
  msgid "After mini cart"
10692
  msgstr ""
10693
 
10694
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:90
10695
  msgid "Info on Checkout"
10696
  msgstr ""
10697
 
10698
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:130
10699
  msgid "Message on Free Shipping Reached"
10700
  msgstr ""
10701
 
10702
+ #: includes/settings/wcj-settings-left-to-free-shipping.php:132
10703
  msgid "Set empty to disable."
10704
  msgstr ""
10705
 
10706
+ #: includes/settings/wcj-settings-max-products-per-user.php:26
10707
+ msgid "Maximum Allowed Each Product's Quantity per User"
10708
+ msgstr ""
10709
+
10710
+ #: includes/settings/wcj-settings-max-products-per-user.php:60
10711
+ #: includes/settings/wcj-settings-offer-price.php:170
10712
+ msgid "Customer Message"
10713
+ msgstr ""
10714
+
10715
+ #: includes/settings/wcj-settings-max-products-per-user.php:68
10716
+ msgid "Block Checkout Page"
10717
+ msgstr ""
10718
+
10719
+ #: includes/settings/wcj-settings-max-products-per-user.php:70
10720
+ msgid ""
10721
+ "This will stop customer from accessing the checkout page on exceeded "
10722
+ "quantities. Customer will be redirected to the cart page."
10723
+ msgstr ""
10724
+
10725
+ #: includes/settings/wcj-settings-max-products-per-user.php:76
10726
+ #: includes/settings/wcj-settings-max-products-per-user.php:82
10727
+ msgid "Calculate Data"
10728
+ msgstr ""
10729
+
10730
  #: includes/settings/wcj-settings-mini-cart.php:14
10731
  msgid "Mini Cart Custom Info Blocks"
10732
  msgstr ""
11106
  msgstr ""
11107
 
11108
  #: includes/settings/wcj-settings-offer-price.php:70
11109
+ #: includes/settings/wcj-settings-product-custom-info.php:103
11110
  msgid "Before single product"
11111
  msgstr ""
11112
 
11113
  #: includes/settings/wcj-settings-offer-price.php:74
11114
+ #: includes/settings/wcj-settings-product-custom-info.php:107
11115
  msgid "After single product"
11116
  msgstr ""
11117
 
11168
  msgid "Customer Email"
11169
  msgstr ""
11170
 
 
 
 
 
11171
  #: includes/settings/wcj-settings-offer-price.php:178
11172
  msgid "Send a Copy to Customer Checkbox"
11173
  msgstr ""
11386
  msgstr ""
11387
 
11388
  #: includes/settings/wcj-settings-order-numbers.php:21
11389
+ #: includes/settings/wcj-settings-sku.php:22
11390
  msgid "Number Generation"
11391
  msgstr ""
11392
 
11393
  #: includes/settings/wcj-settings-order-numbers.php:26
11394
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:22
11395
+ #: includes/settings/wcj-settings-sku.php:28
11396
  msgid "Sequential"
11397
  msgstr ""
11398
 
11399
  #: includes/settings/wcj-settings-order-numbers.php:28
11400
+ #: includes/settings/wcj-settings-sku.php:29
11401
  msgid "Pseudorandom - Hash (max 10 digits)"
11402
  msgstr ""
11403
 
11510
  msgid "Enable Order Admin Search by Custom Number"
11511
  msgstr ""
11512
 
11513
+ #: includes/settings/wcj-settings-order-numbers.php:118
11514
+ msgid "Enable Editable Order Number Meta Box"
11515
  msgstr ""
11516
 
11517
  #: includes/settings/wcj-settings-order-numbers.php:127
11518
+ msgid "Minimal Order ID"
11519
+ msgstr ""
11520
+
11521
+ #: includes/settings/wcj-settings-order-numbers.php:128
11522
+ msgid ""
11523
+ "If you wish to disable order numbering for some (older) orders, you can set "
11524
+ "order ID to start here."
11525
+ msgstr ""
11526
+
11527
+ #: includes/settings/wcj-settings-order-numbers.php:129
11528
+ msgid "Set to zero to enable numbering for all orders."
11529
+ msgstr ""
11530
+
11531
+ #: includes/settings/wcj-settings-order-numbers.php:140
11532
+ msgid "Orders Renumerate Tool Options"
11533
+ msgstr ""
11534
+
11535
+ #: includes/settings/wcj-settings-order-numbers.php:145
11536
  msgid "Sort by"
11537
  msgstr ""
11538
 
11539
+ #: includes/settings/wcj-settings-order-numbers.php:152
11540
  msgid "Last modified date"
11541
  msgstr ""
11542
 
11543
+ #: includes/settings/wcj-settings-order-numbers.php:153
11544
  #: includes/settings/wcj-settings-related-products.php:22
11545
  msgid "Random"
11546
  msgstr ""
11547
 
11548
+ #: includes/settings/wcj-settings-order-numbers.php:157
11549
  msgid "Sort Ascending or Descending"
11550
  msgstr ""
11551
 
11552
+ #: includes/settings/wcj-settings-order-numbers.php:162
11553
  #: includes/settings/wcj-settings-related-products.php:90
11554
  msgid "Ascending"
11555
  msgstr ""
11556
 
11557
+ #: includes/settings/wcj-settings-order-numbers.php:163
11558
  #: includes/settings/wcj-settings-related-products.php:91
11559
  msgid "Descending"
11560
  msgstr ""
11577
  #: includes/settings/wcj-settings-order-quantities.php:44
11578
  #: includes/settings/wcj-settings-order-quantities.php:86
11579
  #: includes/settings/wcj-settings-order-quantities.php:102
11580
+ #: includes/settings/wcj-settings-shipping-by-order-amount.php:35
11581
  msgid "Set to zero to disable."
11582
  msgstr ""
11583
 
11627
  msgstr ""
11628
 
11629
  #: includes/settings/wcj-settings-order-quantities.php:157
11630
+ #: includes/settings/wcj-settings-product-tabs.php:27
11631
  msgid "Do nothing"
11632
  msgstr ""
11633
 
11759
  msgstr ""
11760
 
11761
  #: includes/settings/wcj-settings-payment-gateways-by-country.php:20
11762
+ msgid "Detect Country by"
11763
  msgstr ""
11764
 
11765
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:25
11766
+ msgid "Billing country"
11767
  msgstr ""
11768
 
11769
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:26
11770
+ msgid "Shipping country"
11771
+ msgstr ""
11772
+
11773
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:31
11774
+ msgid "Detect State by"
11775
+ msgstr ""
11776
+
11777
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:41
11778
+ msgid "Detect Postcode by"
11779
+ msgstr ""
11780
+
11781
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:57
11782
  msgid "If any field is left empty - it's ignored."
11783
  msgstr ""
11784
 
11785
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:80
11786
  msgid "Include Countries"
11787
  msgstr ""
11788
 
11789
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:90
11790
  msgid "Exclude Countries"
11791
  msgstr ""
11792
 
11793
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:100
11794
  msgid "Include States (Base Country)"
11795
  msgstr ""
11796
 
11797
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:110
11798
  msgid "Exclude States (Base Country)"
11799
  msgstr ""
11800
 
11801
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:120
11802
  msgid "Include Postcodes (one per line)"
11803
  msgstr ""
11804
 
11805
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:121
11806
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:131
11807
  msgid ""
11808
  "Postcodes containing wildcards (e.g. CB23*) and fully numeric ranges (e.g. "
11809
  "<code>90210...99000</code>) are also supported."
11810
  msgstr ""
11811
 
11812
+ #: includes/settings/wcj-settings-payment-gateways-by-country.php:130
11813
  msgid "Exclude Postcodes (one per line)"
11814
  msgstr ""
11815
 
11816
  #: includes/settings/wcj-settings-payment-gateways-by-currency.php:16
11817
  #: includes/settings/wcj-settings-payment-gateways-by-user-role.php:16
11818
+ #: includes/settings/wcj-settings-shipping-by-condition.php:42
11819
  msgid "Leave empty to disable."
11820
  msgstr ""
11821
 
11832
  msgid "Denied Currencies"
11833
  msgstr ""
11834
 
11835
+ #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:22
11836
+ #: includes/settings/wcj-settings-shipping-by-condition.php:24
11837
+ #: includes/settings/wcj-settings-shipping-by-order-amount.php:20
11838
+ #: includes/settings/wcj-settings-shipping-time.php:30
11839
+ msgid "Use Shipping Instances"
11840
+ msgstr ""
11841
+
11842
+ #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:24
11843
+ #: includes/settings/wcj-settings-shipping-by-condition.php:26
11844
+ #: includes/settings/wcj-settings-shipping-by-order-amount.php:22
11845
+ #: includes/settings/wcj-settings-shipping-time.php:32
11846
+ msgid ""
11847
+ "Enable this if you want to use shipping methods instances instead of "
11848
+ "shipping methods."
11849
+ msgstr ""
11850
+
11851
+ #: includes/settings/wcj-settings-payment-gateways-by-shipping.php:39
11852
  msgid ""
11853
  "If payment gateway is only available for certain methods, set it up here. "
11854
  "Leave blank to enable for all methods."
11887
  msgstr ""
11888
 
11889
  #: includes/settings/wcj-settings-payment-gateways-fees.php:25
11890
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:42
11891
+ #: includes/settings/wcj-settings-pdf-invoicing-page.php:88
11892
  #: includes/settings/wcj-settings-purchase-data.php:67
11893
  msgid "Leave blank to disable"
11894
  msgstr ""
12119
  "admin order meta box."
12120
  msgstr ""
12121
 
12122
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:16
12123
  msgid "Fonts download is disabled."
12124
  msgstr ""
12125
 
12126
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:19
12127
  msgid "Fonts are up to date."
12128
  msgstr ""
12129
 
12130
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:20
12131
  #, php-format
12132
  msgid "Latest successful download or version check was on %s."
12133
  msgstr ""
12134
 
12135
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:24
12136
  msgid ""
12137
  "Fonts are NOT up to date. Please try downloading by pressing the button "
12138
  "below."
12139
  msgstr ""
12140
 
12141
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:27
12142
  #, php-format
12143
  msgid "Latest successful downloaded version is %s."
12144
  msgstr ""
12145
 
12146
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:33
12147
  #, php-format
12148
  msgid "Latest download executed on %s."
12149
  msgstr ""
12150
 
12151
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:47
12152
  msgid "Hide Disabled Docs Settings"
12153
  msgstr ""
12154
 
12155
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:54
12156
  msgid "Replace Admin Order Search with Invoice Search"
12157
  msgstr ""
12158
 
12159
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:61
12160
  msgid "Default Images Directory"
12161
  msgstr ""
12162
 
12163
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:62
12164
  msgid "Default images directory in TCPDF library (K_PATH_IMAGES)."
12165
  msgstr ""
12166
 
12167
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:63
12168
  msgid ""
12169
  "Try changing this if you have issues displaying images in page background or "
12170
  "header."
12171
  msgstr ""
12172
 
12173
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:68
12174
  msgid "Empty"
12175
  msgstr ""
12176
 
12177
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:69
12178
  msgid "TCPDF Default"
12179
  msgstr ""
12180
 
12181
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:70
12182
  msgid "ABSPATH"
12183
  msgstr ""
12184
 
12185
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:71
12186
  msgid "DOCUMENT_ROOT"
12187
  msgstr ""
12188
 
12189
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:75
12190
  msgid "Temp Directory"
12191
  msgstr ""
12192
 
12193
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:76
12194
  msgid "Leave blank to use the default temp directory."
12195
  msgstr ""
12196
 
12197
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:87
12198
  msgid "Fonts Manager"
12199
  msgstr ""
12200
 
12201
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:96
12202
  msgid "Re-download"
12203
  msgstr ""
12204
 
12205
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:96
12206
+ msgid "Download"
12207
+ msgstr ""
12208
+
12209
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:101
12210
  msgid "Disable Fonts Download"
12211
  msgstr ""
12212
 
12213
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:112
12214
  msgid "General Display Options"
12215
  msgstr ""
12216
 
12217
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:117
12218
  msgid "Add PDF Invoices Meta Box to Admin Edit Order Page"
12219
  msgstr ""
12220
 
12221
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:124
12222
+ msgid "Add editable numbers"
12223
+ msgstr ""
12224
+
12225
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:134
12226
  msgid "Report Tool Options"
12227
  msgstr ""
12228
 
12229
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:139
12230
  msgid "Reports Filename"
12231
  msgstr ""
12232
 
12233
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:147
12234
  msgid "Report Columns"
12235
  msgstr ""
12236
 
12237
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:148
12238
  msgid "Leave blank to show all columns."
12239
  msgstr ""
12240
 
12241
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:156
12242
  msgid "Tax Percent Precision"
12243
  msgstr ""
12244
 
12245
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:169
12246
  msgid "CSV UTF-8 BOM"
12247
  msgstr ""
12248
 
12249
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:176
12250
  msgid "Replace Periods with Commas in CSV Data"
12251
  msgstr ""
12252
 
12253
+ #: includes/settings/wcj-settings-pdf-invoicing-advanced.php:177
12254
  msgid "Replace"
12255
  msgstr ""
12256
 
12366
  msgid "Footer Margin"
12367
  msgstr ""
12368
 
12369
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:23
12370
  msgid "Enable Header"
12371
  msgstr ""
12372
 
12373
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:30
12374
  msgid "Header Image"
12375
  msgstr ""
12376
 
12377
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:35
12378
+ #, php-format
12379
+ msgid ""
12380
+ "Enter a local URL to an image you want to show in the invoice's header. "
12381
+ "Upload your image using the <a href=\"%s\">media uploader</a>."
12382
+ msgstr ""
12383
+
12384
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:38
12385
  #, php-format
12386
  msgid ""
12387
+ "If you are experiencing issues with displaying header image, please try "
12388
+ "setting different values for the \"Advanced: Default Images Directory\" "
12389
+ "option in %s."
12390
  msgstr ""
12391
 
12392
  #: includes/settings/wcj-settings-pdf-invoicing-header.php:40
12393
+ #: includes/settings/wcj-settings-pdf-invoicing-page.php:86
12394
+ msgid "PDF Invoicing & Packing Slips > Advanced"
12395
  msgstr ""
12396
 
12397
  #: includes/settings/wcj-settings-pdf-invoicing-header.php:46
12398
+ msgid "Header Image Width in mm"
12399
+ msgstr ""
12400
+
12401
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:52
12402
  msgid "Header Title"
12403
  msgstr ""
12404
 
12405
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:59
12406
  msgid "Header Text"
12407
  msgstr ""
12408
 
12409
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:66
12410
  msgid "Header Text Color"
12411
  msgstr ""
12412
 
12413
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:73
12414
  msgid "Header Line Color"
12415
  msgstr ""
12416
 
12417
+ #: includes/settings/wcj-settings-pdf-invoicing-header.php:80
12418
  msgid "Header Margin"
12419
  msgstr ""
12420
 
12427
  msgstr ""
12428
 
12429
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:41
12430
+ #: includes/settings/wcj-settings-sku.php:58
12431
+ #: includes/settings/wcj-settings-sku.php:130
12432
  msgid "Prefix"
12433
  msgstr ""
12434
 
12435
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:47
12436
+ #: includes/settings/wcj-settings-sku.php:72
12437
+ #: includes/settings/wcj-settings-sku.php:139
12438
  msgid "Suffix"
12439
  msgstr ""
12440
 
12441
  #: includes/settings/wcj-settings-pdf-invoicing-numbering.php:53
12442
+ #: includes/settings/wcj-settings-sku.php:89
12443
  msgid "Template"
12444
  msgstr ""
12445
 
12494
  "\">media uploader</a>."
12495
  msgstr ""
12496
 
12497
+ #: includes/settings/wcj-settings-pdf-invoicing-page.php:84
12498
+ #, php-format
12499
+ msgid ""
12500
+ "If you are experiencing issues with displaying background image, please try "
12501
+ "setting different values for the \"Advanced: Default Images Directory\" "
12502
+ "option in %s."
12503
+ msgstr ""
12504
+
12505
  #: includes/settings/wcj-settings-pdf-invoicing-styling.php:19
12506
  #: includes/settings/wcj-settings-pdf-invoicing-styling.php:37
12507
  msgid "Font Family"
12551
  msgstr ""
12552
 
12553
  #: includes/settings/wcj-settings-pdf-invoicing.php:32
12554
+ #: includes/settings/wcj-settings-product-by-country.php:70
12555
  msgid "Manually"
12556
  msgstr ""
12557
 
12817
  msgstr ""
12818
 
12819
  #: includes/settings/wcj-settings-price-by-user-role.php:104
12820
+ #: includes/settings/wcj-settings-price-by-user-role.php:170
12821
  #: includes/settings/meta-box/wcj-settings-meta-box-price-by-user-role.php:99
12822
  msgid "Make Empty Price"
12823
  msgstr ""
12824
 
12825
+ #: includes/settings/wcj-settings-price-by-user-role.php:119
12826
+ msgid "Products Categories"
12827
+ msgstr ""
12828
+
12829
+ #: includes/settings/wcj-settings-price-by-user-role.php:125
12830
+ msgid "Products Tags"
12831
+ msgstr ""
12832
+
12833
+ #: includes/settings/wcj-settings-price-by-user-role.php:141
12834
+ #, php-format
12835
+ msgid "Price by User Role by %s"
12836
  msgstr ""
12837
 
12838
  #: includes/settings/wcj-settings-price-formats.php:20
13040
  msgstr ""
13041
 
13042
  #: includes/settings/wcj-settings-product-add-to-cart.php:40
13043
+ #: includes/settings/wcj-settings-product-tabs.php:233
13044
  msgid "This will add meta boxes to each product's edit page."
13045
  msgstr ""
13046
 
13339
  msgstr ""
13340
 
13341
  #: includes/settings/wcj-settings-product-addons.php:199
13342
+ #: includes/settings/wcj-settings-shipping-by-condition.php:107
13343
  #: includes/settings/wcj-settings-shipping-options.php:41
13344
  msgid "Set to zero to use the default priority."
13345
  msgstr ""
13525
  msgid "This will hide selected products completely (including direct link)."
13526
  msgstr ""
13527
 
13528
+ #: includes/settings/wcj-settings-product-by-country.php:43
13529
+ msgid ""
13530
+ "Enable this if you are still seeing hidden products in \"Products\" widgets."
13531
+ msgstr ""
13532
+
13533
+ #: includes/settings/wcj-settings-product-by-country.php:54
13534
  msgid "User Country Selection Options"
13535
  msgstr ""
13536
 
13537
+ #: includes/settings/wcj-settings-product-by-country.php:59
13538
  msgid "User Country Selection Method"
13539
  msgstr ""
13540
 
13541
+ #: includes/settings/wcj-settings-product-by-country.php:60
13542
  msgid "Possible values: \"Automatically by IP\" or \"Manually\"."
13543
  msgstr ""
13544
 
13545
+ #: includes/settings/wcj-settings-product-by-country.php:62
13546
  #, php-format
13547
  msgid ""
13548
  "If \"Manually\" option is selected, you can add country selection drop box "
13549
  "to frontend with \"%s\" widget or %s shortcode."
13550
  msgstr ""
13551
 
13552
+ #: includes/settings/wcj-settings-product-by-country.php:69
13553
  msgid "Automatically by IP"
13554
  msgstr ""
13555
 
13556
+ #: includes/settings/wcj-settings-product-by-country.php:80
13557
  msgid "Admin Options"
13558
  msgstr ""
13559
 
13560
+ #: includes/settings/wcj-settings-product-by-country.php:85
13561
  msgid "Country List"
13562
  msgstr ""
13563
 
13564
+ #: includes/settings/wcj-settings-product-by-country.php:86
13565
  msgid ""
13566
  "This option sets which countries will be added to list in product's edit "
13567
  "page. Possible values: \"All countries\" or \"WooCommerce selling locations"
13568
  "\"."
13569
  msgstr ""
13570
 
13571
+ #: includes/settings/wcj-settings-product-by-country.php:87
13572
  #, php-format
13573
  msgid ""
13574
  "If \"WooCommerce selling locations\" option is selected, country list will "
13576
  "(s)</a>."
13577
  msgstr ""
13578
 
13579
+ #: includes/settings/wcj-settings-product-by-country.php:94
13580
  msgid "WooCommerce selling locations"
13581
  msgstr ""
13582
 
13583
+ #: includes/settings/wcj-settings-product-by-country.php:100
13584
  msgid "Visibility Method"
13585
  msgstr ""
13586
 
13587
+ #: includes/settings/wcj-settings-product-by-country.php:101
13588
  msgid ""
13589
  "This option sets how do you want to set product's visibility. Possible "
13590
  "values: \"Set visible countries\", \"Set invisible countries\" or \"Set both"
13591
  "\"."
13592
  msgstr ""
13593
 
13594
+ #: includes/settings/wcj-settings-product-by-country.php:106
13595
  msgid "Set visible countries"
13596
  msgstr ""
13597
 
13598
+ #: includes/settings/wcj-settings-product-by-country.php:107
13599
  msgid "Set invisible countries"
13600
  msgstr ""
13601
 
13602
+ #: includes/settings/wcj-settings-product-by-country.php:108
13603
  msgid "Set both"
13604
  msgstr ""
13605
 
13606
+ #: includes/settings/wcj-settings-product-by-country.php:115
13607
  msgid "Admin Products List Column"
13608
  msgstr ""
13609
 
13610
+ #: includes/settings/wcj-settings-product-by-country.php:116
13611
  msgid "This will add \"Countries\" column to the admin products list."
13612
  msgstr ""
13613
 
13643
  #: includes/settings/wcj-settings-product-by-date.php:96
13644
  #: includes/settings/wcj-settings-product-by-time.php:72
13645
  #: includes/settings/wcj-settings-product-by-time.php:84
13646
+ #: includes/settings/wcj-settings-stock.php:33
13647
+ #: includes/settings/wcj-settings-stock.php:75
13648
+ #: includes/settings/wcj-settings-stock.php:113
13649
  msgid "You can also use shortcodes here."
13650
  msgstr ""
13651
 
13770
  msgid "Custom Taxonomy"
13771
  msgstr ""
13772
 
13773
+ #: includes/settings/wcj-settings-product-custom-info.php:45
13774
  msgid "Single Product Pages"
13775
  msgstr ""
13776
 
13777
+ #: includes/settings/wcj-settings-product-custom-info.php:45
13778
  msgid "Archives"
13779
  msgstr ""
13780
 
13781
+ #: includes/settings/wcj-settings-product-custom-info.php:84
13782
  #, php-format
13783
  msgid "Block #%s"
13784
  msgstr ""
13785
 
13786
+ #: includes/settings/wcj-settings-product-custom-info.php:93
13787
  #: includes/settings/wcj-settings-product-images.php:49
13788
  #: includes/settings/wcj-settings-product-images.php:58
13789
  #: includes/settings/wcj-settings-product-images.php:67
13793
  msgid "You can use shortcodes here."
13794
  msgstr ""
13795
 
13796
+ #: includes/settings/wcj-settings-product-custom-info.php:108
13797
  msgid "Before add to cart form"
13798
  msgstr ""
13799
 
13800
+ #: includes/settings/wcj-settings-product-custom-info.php:109
13801
  #: includes/settings/wcj-settings-product-input-fields.php:194
13802
  msgid "Before add to cart button"
13803
  msgstr ""
13804
 
13805
+ #: includes/settings/wcj-settings-product-custom-info.php:110
13806
  #: includes/settings/wcj-settings-product-input-fields.php:195
13807
  msgid "After add to cart button"
13808
  msgstr ""
13809
 
13810
+ #: includes/settings/wcj-settings-product-custom-info.php:111
13811
  msgid "After add to cart form"
13812
  msgstr ""
13813
 
13814
+ #: includes/settings/wcj-settings-product-custom-info.php:116
13815
  msgid "Inside product title"
13816
  msgstr ""
13817
 
13818
+ #: includes/settings/wcj-settings-product-custom-info.php:129
13819
  msgid "Product Categories to Include"
13820
  msgstr ""
13821
 
13822
+ #: includes/settings/wcj-settings-product-custom-info.php:130
13823
+ #: includes/settings/wcj-settings-product-custom-info.php:138
13824
+ #: includes/settings/wcj-settings-product-custom-info.php:146
13825
+ #: includes/settings/wcj-settings-product-custom-info.php:154
13826
+ #: includes/settings/wcj-settings-product-custom-info.php:162
13827
+ #: includes/settings/wcj-settings-product-custom-info.php:170
13828
  msgid "Leave blank to disable the option."
13829
  msgstr ""
13830
 
13831
+ #: includes/settings/wcj-settings-product-custom-info.php:137
13832
  msgid "Product Categories to Exclude"
13833
  msgstr ""
13834
 
13835
+ #: includes/settings/wcj-settings-product-custom-info.php:145
13836
  msgid "Product Tags to Include"
13837
  msgstr ""
13838
 
13839
+ #: includes/settings/wcj-settings-product-custom-info.php:153
13840
  msgid "Product Tags to Exclude"
13841
  msgstr ""
13842
 
13843
+ #: includes/settings/wcj-settings-product-custom-info.php:161
13844
  #: includes/settings/wcj-settings-products-xml.php:140
13845
  msgid "Products to Include"
13846
  msgstr ""
13847
 
13848
+ #: includes/settings/wcj-settings-product-custom-info.php:169
13849
  #: includes/settings/wcj-settings-products-xml.php:150
13850
  msgid "Products to Exclude"
13851
  msgstr ""
13852
 
13853
+ #: includes/settings/wcj-settings-product-custom-info.php:189
13854
  msgid "Extra Filters"
13855
  msgstr ""
13856
 
13857
+ #: includes/settings/wcj-settings-product-custom-info.php:191
13858
  msgid "You can add custom filters here (one per line, in filter|title format)."
13859
  msgstr ""
13860
 
13861
+ #: includes/settings/wcj-settings-product-custom-info.php:192
13862
  #, php-format
13863
  msgid "E.g.: %s."
13864
  msgstr ""
14164
  msgstr ""
14165
 
14166
  #: includes/settings/wcj-settings-product-listings.php:57
14167
+ #: includes/settings/wcj-settings-product-listings.php:113
14168
  msgid "Hide Empty"
14169
  msgstr ""
14170
 
14173
  msgstr ""
14174
 
14175
  #: includes/settings/wcj-settings-product-listings.php:64
14176
+ #: includes/settings/wcj-settings-product-listings.php:120
14177
  msgid "Show Products"
14178
  msgstr ""
14179
 
14181
  msgid "Show products if no categories are displayed on shop page"
14182
  msgstr ""
14183
 
14184
+ #: includes/settings/wcj-settings-product-listings.php:71
14185
+ msgid "Exclude Categories Products"
14186
+ msgstr ""
14187
+
14188
+ #: includes/settings/wcj-settings-product-listings.php:72
14189
+ msgid ""
14190
+ " Excludes one or more categories products from the shop page. Leave blank to "
14191
+ "disable."
14192
+ msgstr ""
14193
+
14194
+ #: includes/settings/wcj-settings-product-listings.php:85
14195
  msgid "Category Display Options"
14196
  msgstr ""
14197
 
14198
+ #: includes/settings/wcj-settings-product-listings.php:88
14199
  #, php-format
14200
  msgid ""
14201
  "You can control what is shown on category archives in <a href=\"%s"
14203
  "a>."
14204
  msgstr ""
14205
 
14206
+ #: includes/settings/wcj-settings-product-listings.php:94
14207
  msgid "Subcategories Count"
14208
  msgstr ""
14209
 
14210
+ #: includes/settings/wcj-settings-product-listings.php:95
14211
  msgid "Hide subcategories count on category pages"
14212
  msgstr ""
14213
 
14214
+ #: includes/settings/wcj-settings-product-listings.php:103
14215
  msgid "Exclude Subcategories"
14216
  msgstr ""
14217
 
14218
+ #: includes/settings/wcj-settings-product-listings.php:104
14219
  msgid ""
14220
  " Excludes one or more categories from the category (archive) pages. Leave "
14221
  "blank to disable."
14222
  msgstr ""
14223
 
14224
+ #: includes/settings/wcj-settings-product-listings.php:114
14225
  msgid "Hide empty subcategories on category pages"
14226
  msgstr ""
14227
 
14228
+ #: includes/settings/wcj-settings-product-listings.php:121
14229
  msgid "Show products if no categories are displayed on category page"
14230
  msgstr ""
14231
 
14232
+ #: includes/settings/wcj-settings-product-listings.php:131
14233
+ #: includes/settings/wcj-settings-product-listings.php:137
14234
  msgid "Product Shop Visibility by Price"
14235
  msgstr ""
14236
 
14237
+ #: includes/settings/wcj-settings-product-listings.php:133
14238
  msgid ""
14239
  "Here you can set to hide products from shop and search results depending on "
14240
  "product's price. Products will still be accessible via direct link."
14241
  msgstr ""
14242
 
14243
+ #: includes/settings/wcj-settings-product-listings.php:144
14244
  #: includes/settings/meta-box/wcj-settings-meta-box-product-open-pricing.php:31
14245
  msgid "Min Price"
14246
  msgstr ""
14247
 
14248
+ #: includes/settings/wcj-settings-product-listings.php:145
14249
  msgid ""
14250
  "Products with price below this value will be hidden. Ignored if set to zero."
14251
  msgstr ""
14252
 
14253
+ #: includes/settings/wcj-settings-product-listings.php:152
14254
  #: includes/settings/meta-box/wcj-settings-meta-box-product-open-pricing.php:38
14255
  msgid "Max Price"
14256
  msgstr ""
14257
 
14258
+ #: includes/settings/wcj-settings-product-listings.php:153
14259
  msgid ""
14260
  "Products with price above this value will be hidden. Ignored if set to zero."
14261
  msgstr ""
14346
  msgid "Total Params"
14347
  msgstr ""
14348
 
14349
+ #: includes/settings/wcj-settings-product-tabs.php:20
14350
+ msgid "Content Processing"
14351
+ msgstr ""
14352
+
14353
+ #: includes/settings/wcj-settings-product-tabs.php:25
14354
+ #, php-format
14355
+ msgid "Apply %s filter"
14356
+ msgstr ""
14357
+
14358
+ #: includes/settings/wcj-settings-product-tabs.php:26
14359
+ msgid "Only process shortcodes"
14360
+ msgstr ""
14361
+
14362
+ #: includes/settings/wcj-settings-product-tabs.php:36
14363
+ #: includes/settings/wcj-settings-product-tabs.php:42
14364
  msgid "Custom Product Tabs - All Products"
14365
  msgstr ""
14366
 
14367
+ #: includes/settings/wcj-settings-product-tabs.php:38
14368
  msgid "This section lets you add custom single product tabs."
14369
  msgstr ""
14370
 
14371
+ #: includes/settings/wcj-settings-product-tabs.php:49
14372
  msgid "Custom Product Tabs Number"
14373
  msgstr ""
14374
 
14375
+ #: includes/settings/wcj-settings-product-tabs.php:80
14376
+ #: includes/settings/wcj-settings-product-tabs.php:279
14377
  msgid "Make sure it's unique for each tab."
14378
  msgstr ""
14379
 
14380
+ #: includes/settings/wcj-settings-product-tabs.php:93
14381
+ #: includes/settings/wcj-settings-product-tabs.php:292
14382
  msgid "You can use shortcodes here..."
14383
  msgstr ""
14384
 
14385
+ #: includes/settings/wcj-settings-product-tabs.php:114
14386
+ #: includes/settings/wcj-settings-product-tabs.php:313
14387
  msgid "PRODUCTS to HIDE this tab"
14388
  msgstr ""
14389
 
14390
+ #: includes/settings/wcj-settings-product-tabs.php:115
14391
+ #: includes/settings/wcj-settings-product-tabs.php:314
14392
  msgid "To hide this tab from some products, enter products here."
14393
  msgstr ""
14394
 
14395
+ #: includes/settings/wcj-settings-product-tabs.php:123
14396
+ #: includes/settings/wcj-settings-product-tabs.php:322
14397
  msgid "PRODUCTS to SHOW this tab"
14398
  msgstr ""
14399
 
14400
+ #: includes/settings/wcj-settings-product-tabs.php:124
14401
+ #: includes/settings/wcj-settings-product-tabs.php:323
14402
  msgid "To show this tab only for some products, enter products here."
14403
  msgstr ""
14404
 
14405
+ #: includes/settings/wcj-settings-product-tabs.php:132
14406
+ #: includes/settings/wcj-settings-product-tabs.php:331
14407
  msgid "CATEGORIES to HIDE this tab"
14408
  msgstr ""
14409
 
14410
+ #: includes/settings/wcj-settings-product-tabs.php:133
14411
+ #: includes/settings/wcj-settings-product-tabs.php:332
14412
  msgid "To hide this tab from some categories, enter categories here."
14413
  msgstr ""
14414
 
14415
+ #: includes/settings/wcj-settings-product-tabs.php:141
14416
+ #: includes/settings/wcj-settings-product-tabs.php:340
14417
  msgid "CATEGORIES to SHOW this tab"
14418
  msgstr ""
14419
 
14420
+ #: includes/settings/wcj-settings-product-tabs.php:142
14421
+ #: includes/settings/wcj-settings-product-tabs.php:341
14422
  msgid "To show this tab only for some categories, enter categories here."
14423
  msgstr ""
14424
 
14425
+ #: includes/settings/wcj-settings-product-tabs.php:150
14426
+ #: includes/settings/wcj-settings-product-tabs.php:349
14427
  msgid "TAGS to HIDE this tab"
14428
  msgstr ""
14429
 
14430
+ #: includes/settings/wcj-settings-product-tabs.php:151
14431
+ #: includes/settings/wcj-settings-product-tabs.php:350
14432
  msgid "To hide this tab from some tags, enter tags here."
14433
  msgstr ""
14434
 
14435
+ #: includes/settings/wcj-settings-product-tabs.php:159
14436
+ #: includes/settings/wcj-settings-product-tabs.php:358
14437
  msgid "TAGS to SHOW this tab"
14438
  msgstr ""
14439
 
14440
+ #: includes/settings/wcj-settings-product-tabs.php:160
14441
+ #: includes/settings/wcj-settings-product-tabs.php:359
14442
  msgid "To show this tab only for some tags, enter tags here."
14443
  msgstr ""
14444
 
14445
+ #: includes/settings/wcj-settings-product-tabs.php:172
14446
  msgid "Comma separated PRODUCT IDs to HIDE this tab"
14447
  msgstr ""
14448
 
14449
+ #: includes/settings/wcj-settings-product-tabs.php:173
14450
  msgid "To hide this tab from some products, enter product IDs here."
14451
  msgstr ""
14452
 
14453
+ #: includes/settings/wcj-settings-product-tabs.php:184
14454
  msgid "Comma separated PRODUCT IDs to SHOW this tab"
14455
  msgstr ""
14456
 
14457
+ #: includes/settings/wcj-settings-product-tabs.php:185
14458
  msgid "To show this tab only for some products, enter product IDs here."
14459
  msgstr ""
14460
 
14461
+ #: includes/settings/wcj-settings-product-tabs.php:196
14462
  msgid "Comma separated CATEGORY IDs to HIDE this tab"
14463
  msgstr ""
14464
 
14465
+ #: includes/settings/wcj-settings-product-tabs.php:197
14466
  msgid "To hide this tab from some categories, enter category IDs here."
14467
  msgstr ""
14468
 
14469
+ #: includes/settings/wcj-settings-product-tabs.php:208
14470
  msgid "Comma separated CATEGORY IDs to SHOW this tab"
14471
  msgstr ""
14472
 
14473
+ #: includes/settings/wcj-settings-product-tabs.php:209
14474
  msgid "To show this tab only for some categories, enter category IDs here."
14475
  msgstr ""
14476
 
14477
+ #: includes/settings/wcj-settings-product-tabs.php:225
14478
  msgid "Custom Product Tabs - Per Product"
14479
  msgstr ""
14480
 
14481
+ #: includes/settings/wcj-settings-product-tabs.php:227
14482
  msgid "This section lets you set defaults for per product custom tabs."
14483
  msgstr ""
14484
 
14485
+ #: includes/settings/wcj-settings-product-tabs.php:231
14486
  msgid "Enable Per Product Custom Product Tabs"
14487
  msgstr ""
14488
 
14489
+ #: includes/settings/wcj-settings-product-tabs.php:239
14490
  msgid "Use Visual Editor"
14491
  msgstr ""
14492
 
14493
+ #: includes/settings/wcj-settings-product-tabs.php:246
14494
  msgid "Add Per Product Tabs Content to \"Yoast SEO\" plugin analysis"
14495
  msgstr ""
14496
 
14497
+ #: includes/settings/wcj-settings-product-tabs.php:253
14498
  msgid "Default Per Product Custom Product Tabs Number"
14499
  msgstr ""
14500
 
14501
+ #: includes/settings/wcj-settings-product-tabs.php:271
14502
  msgid "Default Title"
14503
  msgstr ""
14504
 
14505
+ #: includes/settings/wcj-settings-product-tabs.php:278
14506
  msgid "Default Key"
14507
  msgstr ""
14508
 
14509
+ #: includes/settings/wcj-settings-product-tabs.php:285
14510
  msgid "Default Priority (i.e. Order)"
14511
  msgstr ""
14512
 
14513
+ #: includes/settings/wcj-settings-product-tabs.php:291
14514
  msgid "Default Content"
14515
  msgstr ""
14516
 
14517
+ #: includes/settings/wcj-settings-product-tabs.php:299
14518
  msgid "Default Link"
14519
  msgstr ""
14520
 
14521
+ #: includes/settings/wcj-settings-product-tabs.php:300
14522
  msgid "Leave blank for default behaviour."
14523
  msgstr ""
14524
 
14525
+ #: includes/settings/wcj-settings-product-tabs.php:307
14526
  msgid "Default \"Link - Open in New Window\""
14527
  msgstr ""
14528
 
14529
+ #: includes/settings/wcj-settings-product-tabs.php:375
14530
  msgid "WooCommerce Standard Product Tabs Options"
14531
  msgstr ""
14532
 
14533
+ #: includes/settings/wcj-settings-product-tabs.php:377
14534
  msgid "This section lets you customize single product tabs."
14535
  msgstr ""
14536
 
14537
+ #: includes/settings/wcj-settings-product-tabs.php:381
14538
  msgid "Description Tab"
14539
  msgstr ""
14540
 
14541
+ #: includes/settings/wcj-settings-product-tabs.php:382
14542
+ #: includes/settings/wcj-settings-product-tabs.php:403
14543
+ #: includes/settings/wcj-settings-product-tabs.php:424
14544
  msgid "Remove tab from product page"
14545
  msgstr ""
14546
 
14547
+ #: includes/settings/wcj-settings-product-tabs.php:389
14548
+ #: includes/settings/wcj-settings-product-tabs.php:410
14549
+ #: includes/settings/wcj-settings-product-tabs.php:431
14550
  msgid "Leave blank for WooCommerce defaults"
14551
  msgstr ""
14552
 
14553
+ #: includes/settings/wcj-settings-product-tabs.php:402
14554
  msgid "Additional Information Tab"
14555
  msgstr ""
14556
 
14557
+ #: includes/settings/wcj-settings-product-tabs.php:423
14558
  msgid "Reviews Tab"
14559
  msgstr ""
14560
 
14809
  msgstr ""
14810
 
14811
  #: includes/settings/wcj-settings-purchase-data.php:179
14812
+ #: includes/settings/wcj-settings-sku.php:162
14813
+ #: includes/settings/wcj-settings-stock.php:126
14814
  msgid "More Options"
14815
  msgstr ""
14816
 
15064
  msgid "Per Tag"
15065
  msgstr ""
15066
 
15067
+ #: includes/settings/wcj-settings-shipping-by-condition.php:40
15068
+ #: includes/settings/wcj-settings-shipping-by-condition.php:46
15069
  #, php-format
15070
  msgid "Shipping Methods by %s"
15071
  msgstr ""
15072
 
15073
+ #: includes/settings/wcj-settings-shipping-by-condition.php:70
15074
  #, php-format
15075
  msgid "Include %s"
15076
  msgstr ""
15077
 
15078
+ #: includes/settings/wcj-settings-shipping-by-condition.php:81
15079
  #, php-format
15080
  msgid "Exclude %s"
15081
  msgstr ""
15082
 
15083
+ #: includes/settings/wcj-settings-shipping-by-condition.php:106
15084
  msgid "Filter Priority"
15085
  msgstr ""
15086
 
15087
+ #: includes/settings/wcj-settings-shipping-by-order-amount.php:65
15088
  msgid "Maximum order amount"
15089
  msgstr ""
15090
 
15174
  msgstr ""
15175
 
15176
  #: includes/settings/wcj-settings-shipping-description.php:30
 
15177
  msgid ""
15178
  "Possible values: on both cart and checkout pages; only on cart page; only on "
15179
+ "checkout page."
15180
+ msgstr ""
15181
+
15182
+ #: includes/settings/wcj-settings-shipping-description.php:35
15183
+ msgid "Description Position"
15184
+ msgstr ""
15185
+
15186
+ #: includes/settings/wcj-settings-shipping-description.php:40
15187
+ msgid "After the label"
15188
+ msgstr ""
15189
+
15190
+ #: includes/settings/wcj-settings-shipping-description.php:41
15191
+ msgid "Before the label"
15192
+ msgstr ""
15193
+
15194
+ #: includes/settings/wcj-settings-shipping-description.php:42
15195
+ msgid "Instead of the label"
15196
+ msgstr ""
15197
+
15198
+ #: includes/settings/wcj-settings-shipping-description.php:44
15199
+ msgid ""
15200
+ "Possible values: after the label; before the label; instead of the label."
15201
  msgstr ""
15202
 
15203
+ #: includes/settings/wcj-settings-shipping-description.php:53
15204
  msgid "Shipping Methods Descriptions"
15205
  msgstr ""
15206
 
15226
  msgid "Icon Visibility"
15227
  msgstr ""
15228
 
15229
+ #: includes/settings/wcj-settings-shipping-icons.php:39
15230
+ msgid ""
15231
+ "Possible values: on both cart and checkout pages; only on cart page; only on "
15232
+ "checkout page"
15233
+ msgstr ""
15234
+
15235
  #: includes/settings/wcj-settings-shipping-icons.php:44
15236
  msgid "Icon Style"
15237
  msgstr ""
15294
  msgid "At least one product in cart must grant free shipping"
15295
  msgstr ""
15296
 
15297
+ #: includes/settings/wcj-settings-shipping-time.php:39
15298
+ msgid "Use Shipping Classes"
15299
+ msgstr ""
15300
+
15301
+ #: includes/settings/wcj-settings-shipping-time.php:41
15302
+ msgid ""
15303
+ "Enable this if you want to set options for each shipping class separately."
15304
+ msgstr ""
15305
+
15306
+ #: includes/settings/wcj-settings-shipping-time.php:55
15307
+ msgid "Shipping Time Options"
15308
+ msgstr ""
15309
+
15310
+ #: includes/settings/wcj-settings-shipping-time.php:56
15311
+ msgid "Set estimated shipping time in <strong>days</strong>."
15312
+ msgstr ""
15313
+
15314
  #: includes/settings/wcj-settings-shipping.php:13
15315
  msgid "WooCommerce > Settings > Shipping"
15316
  msgstr ""
15350
  msgid "Admin Title Custom Shipping"
15351
  msgstr ""
15352
 
15353
+ #: includes/settings/wcj-settings-sku.php:17
15354
  msgid "SKU Format Options"
15355
  msgstr ""
15356
 
15357
+ #: includes/settings/wcj-settings-sku.php:27
15358
  msgid "From product ID"
15359
  msgstr ""
15360
 
15361
+ #: includes/settings/wcj-settings-sku.php:31
15362
  msgid "Number generation method."
15363
  msgstr ""
15364
 
15365
+ #: includes/settings/wcj-settings-sku.php:32
15366
  msgid "Possible values: from product ID, sequential or pseudorandom."
15367
  msgstr ""
15368
 
15369
+ #: includes/settings/wcj-settings-sku.php:37
15370
  msgid "Sequential Number Generation - Counter"
15371
  msgstr ""
15372
 
15373
+ #: includes/settings/wcj-settings-sku.php:38
15374
  msgid ""
15375
  "If you choose to use sequential number inside SKU, you can set current "
15376
  "sequential number counter here."
15377
  msgstr ""
15378
 
15379
+ #: includes/settings/wcj-settings-sku.php:49
15380
  msgid "Sequential Number Generation - By Category"
15381
  msgstr ""
15382
 
15383
+ #: includes/settings/wcj-settings-sku.php:50
15384
  msgid "Enables sequential number generation by category."
15385
  msgstr ""
15386
 
15387
+ #: includes/settings/wcj-settings-sku.php:59
15388
  msgid "SKU prefix."
15389
  msgstr ""
15390
 
15391
+ #: includes/settings/wcj-settings-sku.php:65
15392
  msgid "Minimum Number Length"
15393
  msgstr ""
15394
 
15395
+ #: includes/settings/wcj-settings-sku.php:66
15396
  msgid "Minimum length for SKU number part."
15397
  msgstr ""
15398
 
15399
+ #: includes/settings/wcj-settings-sku.php:73
15400
  msgid "SKU suffix."
15401
  msgstr ""
15402
 
15403
  #: includes/settings/wcj-settings-sku.php:79
15404
+ msgid "Attributes Separator"
15405
+ msgstr ""
15406
+
15407
+ #: includes/settings/wcj-settings-sku.php:80
15408
+ #, php-format
15409
+ msgid "Used in %s."
15410
+ msgstr ""
15411
+
15412
+ #: includes/settings/wcj-settings-sku.php:90
15413
  msgid "SKU template."
15414
  msgstr ""
15415
 
15416
+ #: includes/settings/wcj-settings-sku.php:98
15417
  msgid "Variable Products Variations"
15418
  msgstr ""
15419
 
15420
+ #: includes/settings/wcj-settings-sku.php:99
15421
  msgid ""
15422
  "SKU generation for variations. Please note, that if \"Generate SKU for New "
15423
  "Products Only on First Publish\" option below is not checked, then on new "
15426
  "\"Autogenerate SKUs\" tool manually."
15427
  msgstr ""
15428
 
15429
+ #: includes/settings/wcj-settings-sku.php:100
15430
  msgid ""
15431
  "Possible values: SKU same as parent's product; Generate different SKU for "
15432
  "each variation; SKU same as parent's product + variation letter suffix."
15433
  msgstr ""
15434
 
15435
+ #: includes/settings/wcj-settings-sku.php:105
15436
  msgid "SKU same as parent's product"
15437
  msgstr ""
15438
 
15439
+ #: includes/settings/wcj-settings-sku.php:106
15440
  msgid "Generate different SKU for each variation"
15441
  msgstr ""
15442
 
15443
+ #: includes/settings/wcj-settings-sku.php:107
15444
  msgid "SKU same as parent's product + variation letter suffix"
15445
  msgstr ""
15446
 
15447
+ #: includes/settings/wcj-settings-sku.php:119
15448
  msgid "Categories Options"
15449
  msgstr ""
15450
 
15451
+ #: includes/settings/wcj-settings-sku.php:146
15452
  msgid "Counter (Sequential)"
15453
  msgstr ""
15454
 
15455
+ #: includes/settings/wcj-settings-sku.php:167
15456
  msgid "Automatically Generate SKU for New Products"
15457
  msgstr ""
15458
 
15459
+ #: includes/settings/wcj-settings-sku.php:169
15460
  msgid "Alternatively you can use Autogenerate SKUs tool."
15461
  msgstr ""
15462
 
15463
+ #: includes/settings/wcj-settings-sku.php:175
15464
  msgid "Generate SKU for New Products Only on First Publish"
15465
  msgstr ""
15466
 
15467
+ #: includes/settings/wcj-settings-sku.php:177
15468
  msgid ""
15469
  "This is important if, for example, you are using category prefix and don't "
15470
  "want SKU generated too early, before you set the category."
15471
  msgstr ""
15472
 
15473
+ #: includes/settings/wcj-settings-sku.php:183
15474
  msgid "Allow Duplicate SKUs"
15475
  msgstr ""
15476
 
15477
+ #: includes/settings/wcj-settings-sku.php:185
15478
  msgid ""
15479
  "If you wish to set SKUs manually, and you need to have same SKUs for "
15480
  "different products, you can enable allow duplicate SKUs option here (which "
15481
  "is disabled in WooCommerce by default)."
15482
  msgstr ""
15483
 
15484
+ #: includes/settings/wcj-settings-sku.php:191
15485
  msgid "Search by SKU"
15486
  msgstr ""
15487
 
15488
+ #: includes/settings/wcj-settings-sku.php:193
15489
  msgid "Add product searching by SKU on frontend."
15490
  msgstr ""
15491
 
15492
+ #: includes/settings/wcj-settings-sku.php:199
15493
  msgid "Advanced: Search by SKU Hook"
15494
  msgstr ""
15495
 
15496
+ #: includes/settings/wcj-settings-sku.php:200
15497
  msgid ""
15498
  "If you are experiencing any issues with searching by SKU, try changing this "
15499
  "option."
15500
  msgstr ""
15501
 
15502
+ #: includes/settings/wcj-settings-sku.php:210
15503
  msgid "Generate SKUs Only for Products with Empty SKU"
15504
  msgstr ""
15505
 
15506
+ #: includes/settings/wcj-settings-sku.php:212
15507
  msgid ""
15508
  "This may help if you are going to use Autogenerate SKUs tool, but don't want "
15509
  "to change your existing SKUs."
15510
  msgstr ""
15511
 
15512
+ #: includes/settings/wcj-settings-sku.php:218
15513
  msgid "Add SKU to Customer Emails"
15514
  msgstr ""
15515
 
15516
+ #: includes/settings/wcj-settings-sku.php:220
15517
  msgid "Adds product SKU to customer's emails."
15518
  msgstr ""
15519
 
15520
+ #: includes/settings/wcj-settings-sku.php:226
15521
  msgid "Remove SKU from Admin Emails"
15522
  msgstr ""
15523
 
15524
+ #: includes/settings/wcj-settings-sku.php:228
15525
  msgid "Removes product SKU from admin's emails."
15526
  msgstr ""
15527
 
15528
+ #: includes/settings/wcj-settings-sku.php:234
15529
  msgid "Disable SKUs"
15530
  msgstr ""
15531
 
15532
+ #: includes/settings/wcj-settings-sku.php:236
15533
  msgid ""
15534
  "Enable this option if you are not going to use SKUs in your shop at all."
15535
  msgstr ""
15636
  msgid "Custom \"In Stock\" HTML"
15637
  msgstr ""
15638
 
15639
+ #: includes/settings/wcj-settings-stock.php:40
15640
  msgid "Custom \"In Stock\" Class"
15641
  msgstr ""
15642
 
15643
+ #: includes/settings/wcj-settings-stock.php:56
15644
  msgid "Custom \"Out of Stock\" Options"
15645
  msgstr ""
15646
 
15647
+ #: includes/settings/wcj-settings-stock.php:61
15648
  msgid "Custom \"Out of Stock\""
15649
  msgstr ""
15650
 
15651
+ #: includes/settings/wcj-settings-stock.php:68
15652
  msgid "Custom \"Out of Stock\" HTML"
15653
  msgstr ""
15654
 
15655
+ #: includes/settings/wcj-settings-stock.php:82
15656
  msgid "Custom \"Out of Stock\" Class"
15657
  msgstr ""
15658
 
15659
+ #: includes/settings/wcj-settings-stock.php:98
15660
+ #: includes/settings/wcj-settings-stock.php:103
15661
  msgid "Custom Stock HTML"
15662
  msgstr ""
15663
 
15664
+ #: includes/settings/wcj-settings-stock.php:112
15665
  #: includes/settings/meta-box/wcj-settings-meta-box-sale-flash.php:24
15666
  msgid "HTML"
15667
  msgstr ""
15668
 
15669
+ #: includes/settings/wcj-settings-stock.php:131
15670
  msgid "Remove Stock Display"
15671
  msgstr ""
15672
 
15673
+ #: includes/settings/wcj-settings-stock.php:132
15674
  msgid "This will remove stock display from frontend."
15675
  msgstr ""
15676
 
15988
  msgid "Content to replace add to cart button on category/archives."
15989
  msgstr ""
15990
 
15991
+ #: includes/settings/meta-box/wcj-settings-meta-box-admin-tools.php:19
15992
  #, php-format
15993
  msgid "Product ID: %s"
15994
  msgstr ""
15995
 
15996
+ #: includes/settings/meta-box/wcj-settings-meta-box-admin-tools.php:26
15997
  #: includes/settings/meta-box/wcj-settings-meta-box-price-by-country.php:45
15998
  msgid "Regular price"
15999
  msgstr ""
16000
 
16001
+ #: includes/settings/meta-box/wcj-settings-meta-box-admin-tools.php:34
16002
  #: includes/settings/meta-box/wcj-settings-meta-box-price-by-country.php:54
16003
  msgid "Sale price"
16004
  msgstr ""
16028
  msgid "PayPal Email"
16029
  msgstr ""
16030
 
16031
+ #: includes/settings/meta-box/wcj-settings-meta-box-max-products-per-user.php:14
16032
+ msgid "Max Qty"
16033
+ msgstr ""
16034
+
16035
+ #: includes/settings/meta-box/wcj-settings-meta-box-max-products-per-user.php:18
16036
+ msgid ""
16037
+ "If set to zero, and \"All Products\" section is enabled - global maximum "
16038
+ "quantity will be used; in case if \"All Products\" section is disabled - no "
16039
+ "maximum quantity will be used."
16040
+ msgstr ""
16041
+
16042
  #: includes/settings/meta-box/wcj-settings-meta-box-offer-price.php:14
16043
  msgid "Enable Offer Price"
16044
  msgstr ""
16059
  msgid "Save order after you change this field."
16060
  msgstr ""
16061
 
16062
+ #: includes/settings/meta-box/wcj-settings-meta-box-pdf-invoicing.php:24
16063
+ #, php-format
16064
+ msgid "%s number"
16065
+ msgstr ""
16066
+
16067
  #: includes/settings/meta-box/wcj-settings-meta-box-price-by-user-role.php:27
16068
  msgid "Per Product Settings (press Update after changing)"
16069
  msgstr ""
16317
  msgid "Enable Custom Shipping"
16318
  msgstr ""
16319
 
16320
+ #: includes/shortcodes/class-wcj-shortcodes-general.php:93
16321
  msgid "Tax toggle (incl.)"
16322
  msgstr ""
16323
 
16324
+ #: includes/shortcodes/class-wcj-shortcodes-general.php:94
16325
  msgid "Tax toggle (excl.)"
16326
  msgstr ""
16327
 
16333
  msgid "Standard"
16334
  msgstr ""
16335
 
16336
+ #: includes/shortcodes/class-wcj-shortcodes-orders.php:113
16337
  msgid "Dollars"
16338
  msgstr ""
16339
 
16340
+ #: includes/shortcodes/class-wcj-shortcodes-orders.php:114
16341
  msgid "Cents"
16342
  msgstr ""
16343
 
16379
  msgid "Edit Product"
16380
  msgstr ""
16381
 
16382
+ #: includes/shortcodes/class-wcj-shortcodes-products.php:319
16383
  #, php-format
16384
  msgid "%s ago"
16385
  msgstr ""
16386
 
16387
+ #: includes/shortcodes/class-wcj-shortcodes-products.php:335
16388
  msgid "No sales yet."
16389
  msgstr ""
16390
 
16391
+ #: includes/shortcodes/class-wcj-shortcodes-products.php:558
16392
  msgid "In stock"
16393
  msgstr ""
16394
 
readme.txt CHANGED
@@ -3,7 +3,7 @@ Contributors: algoritmika, anbinder
3
  Tags: woocommerce, booster for woocommerce, woocommerce jetpack
4
  Requires at least: 4.4
5
  Tested up to: 4.9
6
- Stable tag: 3.4.5
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
@@ -105,6 +105,7 @@ Booster for WooCommerce is a WordPress plugin that supercharges your site with a
105
  * *Admin Orders List* - Customize WooCommerce admin orders list: add custom columns; add multiple status filtering.
106
  * *Custom Shipping* - Add multiple custom shipping methods to WooCommerce.
107
  * *Left to Free Shipping* - Display "left to free shipping" info in WooCommerce.
 
108
  * *Order Custom Statuses* - Custom statuses for WooCommerce orders.
109
  * *Order Min/Max Quantities* - Set min/max product quantities in WooCommerce order.
110
  * *Order Minimum Amount* - Minimum WooCommerce order amount (optionally by user role).
@@ -117,6 +118,7 @@ Booster for WooCommerce is a WordPress plugin that supercharges your site with a
117
  * *Shipping Methods by Products* - Set products, product categories or tags to include/exclude for WooCommerce shipping methods to show up.
118
  * *Shipping Methods by Users* - Set user roles, users or membership plans to include/exclude for WooCommerce shipping methods to show up.
119
  * *Shipping Options* - Hide WooCommerce shipping when free is available. Grant free shipping on per product basis.
 
120
 
121
  **PDF Invoicing & Packing Slips**
122
 
@@ -180,6 +182,67 @@ You can see the differences between versions in this [table](https://booster.io/
180
 
181
  == Changelog ==
182
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
183
  = 3.4.5 - 19/02/2018 =
184
  * Fix - PRICES & CURRENCIES - Currency Exchange Rates - Crons - "Undefined index..." notices in log fixed.
185
  * Dev - PRICES & CURRENCIES - Currency Exchange Rates - "Exchange Rates Offset (Percent)" options added for each currency pair.
3
  Tags: woocommerce, booster for woocommerce, woocommerce jetpack
4
  Requires at least: 4.4
5
  Tested up to: 4.9
6
+ Stable tag: 3.5.0
7
  License: GNU General Public License v3.0
8
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
9
 
105
  * *Admin Orders List* - Customize WooCommerce admin orders list: add custom columns; add multiple status filtering.
106
  * *Custom Shipping* - Add multiple custom shipping methods to WooCommerce.
107
  * *Left to Free Shipping* - Display "left to free shipping" info in WooCommerce.
108
+ * *Maximum Products per User* - Limit number of items your WooCommerce customers (logged) can buy.
109
  * *Order Custom Statuses* - Custom statuses for WooCommerce orders.
110
  * *Order Min/Max Quantities* - Set min/max product quantities in WooCommerce order.
111
  * *Order Minimum Amount* - Minimum WooCommerce order amount (optionally by user role).
118
  * *Shipping Methods by Products* - Set products, product categories or tags to include/exclude for WooCommerce shipping methods to show up.
119
  * *Shipping Methods by Users* - Set user roles, users or membership plans to include/exclude for WooCommerce shipping methods to show up.
120
  * *Shipping Options* - Hide WooCommerce shipping when free is available. Grant free shipping on per product basis.
121
+ * *Shipping Time* - Add delivery time estimation to WooCommerce shipping methods.
122
 
123
  **PDF Invoicing & Packing Slips**
124
 
182
 
183
  == Changelog ==
184
 
185
+ = 3.5.0 - 04/04/2018 =
186
+ * Dev - PRICES & CURRENCIES - Currency Exchange Rates - Exchange Rates Server - "Bank of England (BOE)" server added.
187
+ * Dev - PRICES & CURRENCIES - Currency Exchange Rates - Exchange Rates Server - "Google" server added.
188
+ * Dev - PRICES & CURRENCIES - Currency Exchange Rates - Exchange Rates Server - ECB option set as fallback; marked as "recommended".
189
+ * Fix - PRICES & CURRENCIES - Multicurrency (Currency Switcher) - Missing options (rounding) added to variation prices hash and hash array restructured.
190
+ * Fix - PRICES & CURRENCIES - Multicurrency Product Base Price - Missing options (rounding etc.) added to variation prices hash and hash array restructured.
191
+ * Dev - PRICES & CURRENCIES - Multicurrency Product Base Price - Minor code refactoring.
192
+ * Dev - PRICES & CURRENCIES - Price Formats - `wc_get_price_decimals` filter added.
193
+ * Dev - PRICES & CURRENCIES - Price by User Role - "Price by User Role by Products Tags" section added.
194
+ * Dev - PRICES & CURRENCIES - Prices and Currencies by Country - "Booster - Selector" (country) widget now overrides "Booster - Country Switcher" widget (in case if both widgets are enabled).
195
+ * Dev - PRODUCTS - Product Input Fields - Local input fields are saved as array now in product's meta.
196
+ * Dev - PRODUCTS - Product Listings - Shop Page Display Options - "Exclude Categories Products" option added.
197
+ * Dev - PRODUCTS - Product Visibility by Country - Modify Query - "Widgets" option added.
198
+ * Dev - PRODUCTS - SKU - Autogenerate SKUs tool - Optional "Min ID" and "Max ID" options added (to generate SKUs only for selected products).
199
+ * Dev - PRODUCTS - SKU - `{product_slug}`, `{parent_product_slug}`, `{variation_attributes}`, `{parent_sku}` replaced values added.
200
+ * Dev - PRODUCTS - Stock - Now shortcodes are processed in all "HTML" options.
201
+ * Dev - PAYMENT GATEWAYS - Gateways by Country, State or Postcode - General Options - "Detect Country by" (billing / shipping / by IP) and "Detect State by" (billing / shipping) options added.
202
+ * Dev - PAYMENT GATEWAYS - Gateways by Shipping - "Use Shipping Instances" option added.
203
+ * Dev - PAYMENT GATEWAYS - Gateways by Shipping - Code refactoring (`wcj_get_shipping_methods()`).
204
+ * Fix - SHIPPING & ORDERS - Left to Free Shipping - Calculating cart total exactly as in `WC_Shipping_Free_Shipping` class.
205
+ * Dev - SHIPPING & ORDERS - Left to Free Shipping - Admin settings - Descriptions updated.
206
+ * Dev - SHIPPING & ORDERS - Left to Free Shipping - `%cart_total%` replaced value added.
207
+ * Dev - SHIPPING & ORDERS - Maximum Products per User - Initial module release.
208
+ * Dev - SHIPPING & ORDERS - Order Numbers - "Enable Editable Order Number Meta Box" option added.
209
+ * Dev - SHIPPING & ORDERS - Order Numbers - "Minimal Order ID" option added.
210
+ * Dev - SHIPPING & ORDERS - Order Numbers - `%order_items_skus%` replaced value added.
211
+ * Dev - SHIPPING & ORDERS - Shipping Descriptions - "Description Position" option added.
212
+ * Dev - SHIPPING & ORDERS - Shipping Methods by Min/Max Order Amount - "Use Shipping Instances" option added.
213
+ * Dev - SHIPPING & ORDERS - Shipping Methods by Products - "Products" section - "Add Products Variations" option added.
214
+ * Dev - SHIPPING & ORDERS - Shipping Time - Initial module release.
215
+ * Dev - SHIPPING & ORDERS - `WCJ_Module_Shipping_By_Condition` (Shipping Methods by Products / Users) - "Use Shipping Instances" option added.
216
+ * Fix - PDF INVOICING & PACKING SLIPS - Advanced - Temp Directory - Option now used in "Invoices Report" tool and in orders "Bulk Actions".
217
+ * Dev - PDF INVOICING & PACKING SLIPS - Advanced - General Display Options - Meta Box - Editable invoice numbers added.
218
+ * Fix - PDF INVOICING & PACKING SLIPS - Invoices Report Tool - "Download all monthly documents PDFs in single ZIP file" - `check_user_roles()` fixed.
219
+ * Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - "Merge (Print)" bulk action added.
220
+ * Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - Code refactoring.
221
+ * Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - Download - Code refactoring (`wcj_send_file()` function added).
222
+ * Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - Download - Site URL and min/max orders IDs added to zip filename.
223
+ * Dev - PDF INVOICING & PACKING SLIPS - Bulk Actions - Download - `ZIPARCHIVE::OVERWRITE` added when creating zip file.
224
+ * Dev - EMAILS & MISC. - Admin Tools - Show Variable Product Pricing Table - Displaying all variations (instead of only available variations).
225
+ * Dev - EMAILS & MISC. - Email Options - Email Forwarding - "Orders Emails: Enable for Statuses" option added.
226
+ * Dev - Shortcodes - General - `[wcj_cart_total]` - `multiply_by` attribute added.
227
+ * Dev - Shortcodes - General - `[wcj_shipping_time_table]` shortcode added.
228
+ * Dev - Shortcodes - Orders - `[wcj_order_customer_data]` shortcode added.
229
+ * Dev - Shortcodes - Orders - `[wcj_order_items]` - Special `_sku` value added for the `field` attribute.
230
+ * Dev - Shortcodes - Orders - `[wcj_order_notes]` - `limit` attribute added.
231
+ * Dev - Shortcodes - Products - `[wcj_product_price]` - `multiply_by_attribute` attribute added.
232
+ * Dev - Shortcodes - Products - `[wcj_product_shipping_time_table]` shortcode added.
233
+ * Dev - Shortcodes - `multiply` common attribute added.
234
+ * Dev - Shortcodes - `site_visibility` common attribute - `front_page` option added.
235
+ * Dev - Functions - Debug - `error_reporting( E_ALL )` moved to `wcj-loader.php`.
236
+ * Dev - Functions - Debug - `wcj_log()` - `$do_var_dump` param added.
237
+ * Dev - Functions - Price and Currency - `wcj_get_currency_exchange_rate_product_base_currency()` - Minor code refactoring.
238
+ * Dev - Functions - Products - `wcj_get_products()` - Product's ID info added.
239
+ * Dev - Functions - Products - `wcj_product_has_terms()` - Function now also accepts product id as param.
240
+ * Dev - Functions - Shipping - `wcj-functions-shipping.php` added.
241
+ * Fix - Classes - `WCJ_Invoice` - `get_file_name()` - Empty file name fallback fixed.
242
+ * Dev - Classes - Shortcodes - Minor code refactoring.
243
+ * Dev - Classes - `WCJ_PDF_Invoice` - Minor code refactoring.
244
+ * Dev - Manage Settings - "Use List Instead of Comma Separated Text for Products Categories/Tags in Settings" options added (Supported modules: Product Info).
245
+
246
  = 3.4.5 - 19/02/2018 =
247
  * Fix - PRICES & CURRENCIES - Currency Exchange Rates - Crons - "Undefined index..." notices in log fixed.
248
  * Dev - PRICES & CURRENCIES - Currency Exchange Rates - "Exchange Rates Offset (Percent)" options added for each currency pair.
woocommerce-jetpack.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: https://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
- Version: 3.4.5
7
  Author: Algoritmika Ltd
8
  Author URI: https://booster.io
9
  Text Domain: woocommerce-jetpack
@@ -57,7 +57,7 @@ final class WC_Jetpack {
57
  * @var string
58
  * @since 2.4.7
59
  */
60
- public $version = '3.4.5';
61
 
62
  /**
63
  * @var WC_Jetpack The single instance of the class
3
  Plugin Name: Booster for WooCommerce
4
  Plugin URI: https://booster.io
5
  Description: Supercharge your WooCommerce site with these awesome powerful features.
6
+ Version: 3.5.0
7
  Author: Algoritmika Ltd
8
  Author URI: https://booster.io
9
  Text Domain: woocommerce-jetpack
57
  * @var string
58
  * @since 2.4.7
59
  */
60
+ public $version = '3.5.0';
61
 
62
  /**
63
  * @var WC_Jetpack The single instance of the class