WooCommerce Payments – Fully Integrated Solution Built and Supported by Woo - Version 2.7.1

Version Description

  • 2021-07-26 =
  • Fix - Ensure test mode setting value is correctly saved.
  • Fix - Onboarding redirection occasionally not finalizing account connection.
Download this release

Release Info

Developer automattic
Plugin Icon 128x128 WooCommerce Payments – Fully Integrated Solution Built and Supported by Woo
Version 2.7.1
Comparing to
See all releases

Code changes from version 2.7.0 to 2.7.1

Files changed (38) hide show
  1. changelog.txt +4 -0
  2. includes/admin/class-wc-payments-admin.php +4 -1
  3. includes/admin/class-wc-rest-payments-settings-controller.php +1 -1
  4. includes/class-wc-payments-account.php +1 -1
  5. includes/compat/subscriptions/class-wc-payment-gateway-wcpay-subscriptions-compat.php +0 -567
  6. includes/constants/class-digital-wallets-locations.php +0 -23
  7. includes/multi-currency/class-country-flags.php +0 -290
  8. includes/multi-currency/class-currency-switcher-widget.php +0 -197
  9. includes/multi-currency/class-currency.php +0 -227
  10. includes/multi-currency/class-frontend-currencies.php +0 -171
  11. includes/multi-currency/class-frontend-prices.php +0 -234
  12. includes/multi-currency/class-multi-currency.php +0 -526
  13. includes/multi-currency/class-settings.php +0 -429
  14. includes/multi-currency/class-user-settings.php +0 -77
  15. includes/multi-currency/class-wc-rest-controller.php +0 -70
  16. includes/multi-currency/notes/NoteMultiCurrencyAvailable.php +0 -54
  17. includes/multi-currency/notes/class-note-multi-currency-available.php +0 -54
  18. languages/woocommerce-payments.pot +2 -2
  19. readme.txt +5 -1
  20. vendor/autoload.php +1 -1
  21. vendor/autoload_packages.php +1 -1
  22. vendor/composer/InstalledVersions.php +2 -2
  23. vendor/composer/autoload_real.php +7 -7
  24. vendor/composer/autoload_static.php +4 -4
  25. vendor/composer/installed.php +2 -2
  26. vendor/jetpack-autoloader/class-autoloader-handler.php +1 -1
  27. vendor/jetpack-autoloader/class-autoloader-locator.php +1 -1
  28. vendor/jetpack-autoloader/class-autoloader.php +1 -1
  29. vendor/jetpack-autoloader/class-container.php +1 -1
  30. vendor/jetpack-autoloader/class-hook-manager.php +1 -1
  31. vendor/jetpack-autoloader/class-latest-autoloader-guard.php +1 -1
  32. vendor/jetpack-autoloader/class-manifest-reader.php +1 -1
  33. vendor/jetpack-autoloader/class-path-processor.php +1 -1
  34. vendor/jetpack-autoloader/class-plugin-locator.php +1 -1
  35. vendor/jetpack-autoloader/class-plugins-handler.php +1 -1
  36. vendor/jetpack-autoloader/class-version-loader.php +1 -1
  37. vendor/jetpack-autoloader/class-version-selector.php +1 -1
  38. woocommerce-payments.php +1 -1
changelog.txt CHANGED
@@ -1,5 +1,9 @@
1
  *** WooCommerce Payments Changelog ***
2
 
 
 
 
 
3
  = 2.7.0 - 2021-07-14 =
4
  * Add - Add a link to the snackbar notice that appears after submitting or saving evidence for a dispute challenge.
5
  * Add - Support saving new cards and paying with previously saved cards in the WooCommerce Checkout Block.
1
  *** WooCommerce Payments Changelog ***
2
 
3
+ = 2.7.1 - 2021-07-26 =
4
+ * Fix - Ensure test mode setting value is correctly saved.
5
+ * Fix - Onboarding redirection occasionally not finalizing account connection.
6
+
7
  = 2.7.0 - 2021-07-14 =
8
  * Add - Add a link to the snackbar notice that appears after submitting or saving evidence for a dispute challenge.
9
  * Add - Support saving new cards and paying with previously saved cards in the WooCommerce Checkout Block.
includes/admin/class-wc-payments-admin.php CHANGED
@@ -65,7 +65,7 @@ class WC_Payments_Admin {
65
 
66
  // Add menu items.
67
  add_action( 'admin_menu', [ $this, 'add_payments_menu' ], 0 );
68
- add_action( 'admin_menu', [ $this, 'maybe_redirect_to_onboarding' ], 1 );
69
  add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_payments_scripts' ] );
70
  add_action( 'woocommerce_admin_field_payment_gateways', [ $this, 'payment_gateways_container' ] );
71
 
@@ -615,6 +615,9 @@ class WC_Payments_Admin {
615
  * if it is not and the user is attempting to view a WCPay admin page.
616
  */
617
  public function maybe_redirect_to_onboarding() {
 
 
 
618
  $url_params = wp_unslash( $_GET ); // phpcs:ignore WordPress.Security.NonceVerification
619
 
620
  if ( empty( $url_params['page'] ) || 'wc-admin' !== $url_params['page'] ) {
65
 
66
  // Add menu items.
67
  add_action( 'admin_menu', [ $this, 'add_payments_menu' ], 0 );
68
+ add_action( 'admin_init', [ $this, 'maybe_redirect_to_onboarding' ], 11 ); // Run this after the WC setup wizard and onboarding redirection logic.
69
  add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_payments_scripts' ] );
70
  add_action( 'woocommerce_admin_field_payment_gateways', [ $this, 'payment_gateways_container' ] );
71
 
615
  * if it is not and the user is attempting to view a WCPay admin page.
616
  */
617
  public function maybe_redirect_to_onboarding() {
618
+ if ( wp_doing_ajax() ) {
619
+ return false;
620
+ }
621
  $url_params = wp_unslash( $_GET ); // phpcs:ignore WordPress.Security.NonceVerification
622
 
623
  if ( empty( $url_params['page'] ) || 'wc-admin' !== $url_params['page'] ) {
includes/admin/class-wc-rest-payments-settings-controller.php CHANGED
@@ -177,7 +177,7 @@ class WC_REST_Payments_Settings_Controller extends WC_Payments_REST_Controller {
177
  'available_payment_method_ids' => $this->wcpay_gateway->get_upe_available_payment_methods(),
178
  'is_wcpay_enabled' => $this->wcpay_gateway->is_enabled(),
179
  'is_manual_capture_enabled' => 'yes' === $this->wcpay_gateway->get_option( 'manual_capture' ),
180
- 'is_test_mode_enabled' => 'yes' === $this->wcpay_gateway->is_in_test_mode(),
181
  'is_dev_mode_enabled' => $this->wcpay_gateway->is_in_dev_mode(),
182
  'account_statement_descriptor' => $this->wcpay_gateway->get_option( 'account_statement_descriptor' ),
183
  'is_payment_request_enabled' => 'yes' === $this->wcpay_gateway->get_option( 'payment_request' ),
177
  'available_payment_method_ids' => $this->wcpay_gateway->get_upe_available_payment_methods(),
178
  'is_wcpay_enabled' => $this->wcpay_gateway->is_enabled(),
179
  'is_manual_capture_enabled' => 'yes' === $this->wcpay_gateway->get_option( 'manual_capture' ),
180
+ 'is_test_mode_enabled' => $this->wcpay_gateway->is_in_test_mode(),
181
  'is_dev_mode_enabled' => $this->wcpay_gateway->is_in_dev_mode(),
182
  'account_statement_descriptor' => $this->wcpay_gateway->get_option( 'account_statement_descriptor' ),
183
  'is_payment_request_enabled' => 'yes' === $this->wcpay_gateway->get_option( 'payment_request' ),
includes/class-wc-payments-account.php CHANGED
@@ -41,7 +41,7 @@ class WC_Payments_Account {
41
  $this->payments_api_client = $payments_api_client;
42
 
43
  add_action( 'admin_init', [ $this, 'maybe_handle_oauth' ] );
44
- add_action( 'admin_init', [ $this, 'maybe_redirect_to_onboarding' ], 11 ); // Run this after the WC setup wizard redirection logic.
45
  add_action( 'woocommerce_payments_account_refreshed', [ $this, 'handle_instant_deposits_inbox_note' ] );
46
  add_action( 'wcpay_instant_deposit_reminder', [ $this, 'handle_instant_deposits_inbox_reminder' ] );
47
  add_filter( 'allowed_redirect_hosts', [ $this, 'allowed_redirect_hosts' ] );
41
  $this->payments_api_client = $payments_api_client;
42
 
43
  add_action( 'admin_init', [ $this, 'maybe_handle_oauth' ] );
44
+ add_action( 'admin_init', [ $this, 'maybe_redirect_to_onboarding' ], 11 ); // Run this after the WC setup wizard and onboarding redirection logic.
45
  add_action( 'woocommerce_payments_account_refreshed', [ $this, 'handle_instant_deposits_inbox_note' ] );
46
  add_action( 'wcpay_instant_deposit_reminder', [ $this, 'handle_instant_deposits_inbox_reminder' ] );
47
  add_filter( 'allowed_redirect_hosts', [ $this, 'allowed_redirect_hosts' ] );
includes/compat/subscriptions/class-wc-payment-gateway-wcpay-subscriptions-compat.php DELETED
@@ -1,567 +0,0 @@
1
- <?php
2
- /**
3
- * Class WC_Payment_Gateway_WCPay_Subscriptions_Compat
4
- *
5
- * @package WooCommerce\Payments
6
- */
7
-
8
- if ( ! defined( 'ABSPATH' ) ) {
9
- exit; // Exit if accessed directly.
10
- }
11
-
12
- use WCPay\Exceptions\API_Exception;
13
- use WCPay\Exceptions\Invalid_Payment_Method_Exception;
14
- use WCPay\Logger;
15
- use WCPay\Payment_Information;
16
- use WCPay\Constants\Payment_Type;
17
- use WCPay\Constants\Payment_Initiated_By;
18
-
19
- /**
20
- * Gateway class for WooCommerce Payments, with added compatibility with WooCommerce Subscriptions.
21
- */
22
- class WC_Payment_Gateway_WCPay_Subscriptions_Compat extends WC_Payment_Gateway_WCPay {
23
-
24
- const PAYMENT_METHOD_META_TABLE = 'wc_order_tokens';
25
- const PAYMENT_METHOD_META_KEY = 'token';
26
-
27
- /**
28
- * WC_Payment_Gateway_WCPay_Subscriptions_Compat constructor.
29
- *
30
- * @param array ...$args Arguments passed to the main gateway's constructor.
31
- */
32
- public function __construct( ...$args ) {
33
- parent::__construct( ...$args );
34
-
35
- $this->supports = array_merge(
36
- $this->supports,
37
- [
38
- 'subscriptions',
39
- 'subscription_cancellation',
40
- 'subscription_suspension',
41
- 'subscription_reactivation',
42
- 'subscription_amount_changes',
43
- 'subscription_date_changes',
44
- 'subscription_payment_method_change',
45
- 'subscription_payment_method_change_customer',
46
- 'subscription_payment_method_change_admin',
47
- 'multiple_subscriptions',
48
- ]
49
- );
50
-
51
- add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, [ $this, 'scheduled_subscription_payment' ], 10, 2 );
52
- add_action( 'woocommerce_subscription_failing_payment_method_updated_' . $this->id, [ $this, 'update_failing_payment_method' ], 10, 2 );
53
- add_filter( 'wc_payments_display_save_payment_method_checkbox', [ $this, 'display_save_payment_method_checkbox' ], 10 );
54
-
55
- // Display the credit card used for a subscription in the "My Subscriptions" table.
56
- add_filter( 'woocommerce_my_subscriptions_payment_method', [ $this, 'maybe_render_subscription_payment_method' ], 10, 2 );
57
-
58
- // Used to filter out unwanted metadata on new renewal orders.
59
- add_filter( 'wcs_renewal_order_meta_query', [ $this, 'update_renewal_meta_data' ], 10, 3 );
60
-
61
- // Allow store managers to manually set Stripe as the payment method on a subscription.
62
- add_filter( 'woocommerce_subscription_payment_meta', [ $this, 'add_subscription_payment_meta' ], 10, 2 );
63
- add_filter( 'woocommerce_subscription_validate_payment_meta', [ $this, 'validate_subscription_payment_meta' ], 10, 3 );
64
- add_action( 'wcs_save_other_payment_meta', [ $this, 'save_meta_in_order_tokens' ], 10, 4 );
65
-
66
- add_filter( 'woocommerce_subscription_note_old_payment_method_title', [ $this, 'get_specific_old_payment_method_title' ], 10, 3 );
67
- add_filter( 'woocommerce_subscription_note_new_payment_method_title', [ $this, 'get_specific_new_payment_method_title' ], 10, 3 );
68
-
69
- // Enqueue JS hack when Subscriptions does not provide the meta input filter.
70
- if ( version_compare( WC_Subscriptions::$version, '3.0.7', '<=' ) ) {
71
- add_action( 'woocommerce_admin_order_data_after_billing_address', [ $this, 'add_payment_method_select_to_subscription_edit' ] );
72
- }
73
- }
74
-
75
- /**
76
- * Returns whether this user is changing the payment method for a subscription.
77
- *
78
- * @return bool
79
- */
80
- private function is_changing_payment_method_for_subscription() {
81
- if ( isset( $_GET['change_payment_method'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
82
- return wcs_is_subscription( wc_clean( wp_unslash( $_GET['change_payment_method'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
83
- }
84
- return false;
85
- }
86
-
87
- /**
88
- * Prepares the payment information object.
89
- *
90
- * @param WC_Order $order The order whose payment will be processed.
91
- * @return Payment_Information An object, which describes the payment.
92
- */
93
- protected function prepare_payment_information( $order ) {
94
- $is_changing_payment = $this->is_changing_payment_method_for_subscription();
95
- if ( ! $is_changing_payment && ! wcs_order_contains_subscription( $order->get_id() ) ) {
96
- return parent::prepare_payment_information( $order );
97
- }
98
-
99
- // Subs-specific behavior starts here.
100
-
101
- $payment_information = parent::prepare_payment_information( $order );
102
- $payment_information->set_payment_type( Payment_Type::RECURRING() );
103
- // The payment method is always saved for subscriptions.
104
- $payment_information->must_save_payment_method();
105
- $payment_information->set_is_changing_payment_method_for_subscription( $is_changing_payment );
106
-
107
- return $payment_information;
108
- }
109
-
110
- /**
111
- * Returns a boolean value indicating whether the save payment checkbox should be
112
- * displayed during checkout.
113
- *
114
- * Returns `false` if the cart currently has a subscriptions or if the request has a
115
- * `change_payment_method` GET parameter. Returns the value in `$display` otherwise.
116
- *
117
- * @param bool $display Bool indicating whether to show the save payment checkbox in the absence of subscriptions.
118
- *
119
- * @return bool Indicates whether the save payment method checkbox should be displayed or not.
120
- */
121
- public function display_save_payment_method_checkbox( $display ) {
122
- if ( WC_Subscriptions_Cart::cart_contains_subscription() || $this->is_changing_payment_method_for_subscription() ) {
123
- return false;
124
- }
125
- // Only render the "Save payment method" checkbox if there are no subscription products in the cart.
126
- return $display;
127
- }
128
-
129
- /**
130
- * Process a scheduled subscription payment.
131
- *
132
- * @param float $amount The amount to charge.
133
- * @param WC_Order $renewal_order A WC_Order object created to record the renewal payment.
134
- */
135
- public function scheduled_subscription_payment( $amount, $renewal_order ) {
136
- $token = $this->get_payment_token( $renewal_order );
137
- if ( is_null( $token ) && ! WC_Payments::is_network_saved_cards_enabled() ) {
138
- Logger::error( 'There is no saved payment token for order #' . $renewal_order->get_id() );
139
- $renewal_order->update_status( 'failed' );
140
- return;
141
- }
142
-
143
- try {
144
- $payment_information = new Payment_Information( '', $renewal_order, Payment_Type::RECURRING(), $token, Payment_Initiated_By::MERCHANT() );
145
- $this->process_payment_for_order( null, $payment_information );
146
- } catch ( API_Exception $e ) {
147
- Logger::error( 'Error processing subscription renewal: ' . $e->getMessage() );
148
-
149
- $renewal_order->update_status( 'failed' );
150
-
151
- if ( ! empty( $payment_information ) ) {
152
- $note = sprintf(
153
- WC_Payments_Utils::esc_interpolated_html(
154
- /* translators: %1: the failed payment amount, %2: error message */
155
- __(
156
- 'A payment of %1$s <strong>failed</strong> to complete with the following message: <code>%2$s</code>.',
157
- 'woocommerce-payments'
158
- ),
159
- [
160
- 'strong' => '<strong>',
161
- 'code' => '<code>',
162
- ]
163
- ),
164
- wc_price( $amount, [ 'currency' => WC_Payments_Utils::get_order_intent_currency( $renewal_order ) ] ),
165
- esc_html( rtrim( $e->getMessage(), '.' ) )
166
- );
167
- $renewal_order->add_order_note( $note );
168
- }
169
- }
170
- }
171
-
172
- /**
173
- * Adds the payment token from a failed renewal order to the provided subscription.
174
- *
175
- * @param WC_Subscription $subscription The subscription to be updated.
176
- * @param WC_Order $renewal_order The failed renewal order.
177
- */
178
- public function update_failing_payment_method( $subscription, $renewal_order ) {
179
- $renewal_token = $this->get_payment_token( $renewal_order );
180
- if ( is_null( $renewal_token ) ) {
181
- Logger::error( 'Failing subscription could not be updated: there is no saved payment token for order #' . $renewal_order->get_id() );
182
- return;
183
- }
184
- $this->add_token_to_order( $subscription, $renewal_token );
185
- }
186
-
187
- /**
188
- * Include the payment meta data required to process automatic recurring payments so that store managers can
189
- * manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
190
- *
191
- * @param array $payment_meta Associative array of meta data required for automatic payments.
192
- * @param WC_Subscription $subscription The subscription order.
193
- * @return array
194
- */
195
- public function add_subscription_payment_meta( $payment_meta, $subscription ) {
196
- $active_token = $this->get_payment_token( $subscription );
197
-
198
- $payment_meta[ $this->id ] = [
199
- self::PAYMENT_METHOD_META_TABLE => [
200
- self::PAYMENT_METHOD_META_KEY => [
201
- 'label' => __( 'Saved payment method', 'woocommerce-payments' ),
202
- 'value' => empty( $active_token ) ? '' : (string) $active_token->get_id(),
203
- ],
204
- ],
205
- ];
206
-
207
- // Display select element on newer Subscriptions versions.
208
- add_action(
209
- sprintf(
210
- 'woocommerce_subscription_payment_meta_input_%s_%s_%s',
211
- WC_Payment_Gateway_WCPay::GATEWAY_ID,
212
- self::PAYMENT_METHOD_META_TABLE,
213
- self::PAYMENT_METHOD_META_KEY
214
- ),
215
- [ $this, 'render_custom_payment_meta_input' ],
216
- 10,
217
- 3
218
- );
219
-
220
- return $payment_meta;
221
- }
222
-
223
- /**
224
- * Validate the payment meta data required to process automatic recurring payments so that store managers can
225
- * manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
226
- *
227
- * @param string $payment_gateway_id The ID of the payment gateway to validate.
228
- * @param array $payment_meta Associative array of meta data required for automatic payments.
229
- * @param WC_Subscription $subscription The subscription order.
230
- *
231
- * @throws Invalid_Payment_Method_Exception When $payment_meta is not valid.
232
- */
233
- public function validate_subscription_payment_meta( $payment_gateway_id, $payment_meta, $subscription ) {
234
- if ( $this->id !== $payment_gateway_id ) {
235
- return;
236
- }
237
-
238
- if ( empty( $payment_meta[ self::PAYMENT_METHOD_META_TABLE ][ self::PAYMENT_METHOD_META_KEY ]['value'] ) ) {
239
- throw new Invalid_Payment_Method_Exception(
240
- __( 'A customer saved payment method was not selected for this order.', 'woocommerce-payments' ),
241
- 'payment_method_not_selected'
242
- );
243
- }
244
-
245
- $token = WC_Payment_Tokens::get( $payment_meta[ self::PAYMENT_METHOD_META_TABLE ][ self::PAYMENT_METHOD_META_KEY ]['value'] );
246
-
247
- if ( empty( $token ) ) {
248
- throw new Invalid_Payment_Method_Exception(
249
- __( 'The saved payment method selected is invalid or does not exist.', 'woocommerce-payments' ),
250
- 'payment_method_token_not_found'
251
- );
252
- }
253
-
254
- if ( $subscription->get_user_id() !== $token->get_user_id() ) {
255
- throw new Invalid_Payment_Method_Exception(
256
- __( 'The saved payment method selected does not belong to this order\'s customer.', 'woocommerce-payments' ),
257
- 'payment_method_token_not_owned'
258
- );
259
- }
260
- }
261
-
262
- /**
263
- * Save subscriptions payment_method metadata to the order tokens when its type is wc_order_tokens.
264
- *
265
- * @param WC_Subscription $subscription The subscription to be updated.
266
- * @param string $table Where to store and retrieve the metadata.
267
- * @param string $meta_key Meta key to be updated.
268
- * @param string $meta_value Meta value to be updated.
269
- */
270
- public function save_meta_in_order_tokens( $subscription, $table, $meta_key, $meta_value ) {
271
- if ( self::PAYMENT_METHOD_META_TABLE !== $table || self::PAYMENT_METHOD_META_KEY !== $meta_key ) {
272
- return;
273
- }
274
-
275
- $token = WC_Payment_Tokens::get( $meta_value );
276
-
277
- if ( empty( $token ) ) {
278
- return;
279
- }
280
-
281
- $this->add_token_to_order( $subscription, $token );
282
- }
283
-
284
- /**
285
- * Loads the subscription edit page script with user cards to hijack the payment method input and
286
- * transform it into a select element.
287
- *
288
- * @param WC_Order $order The WC Order.
289
- */
290
- public function add_payment_method_select_to_subscription_edit( $order ) {
291
- // Do not load the script if the order is not a subscription.
292
- if ( ! wcs_is_subscription( $order ) ) {
293
- return;
294
- }
295
-
296
- $script_src_url = plugins_url( 'dist/subscription-edit-page.js', WCPAY_PLUGIN_FILE );
297
- $script_asset_path = WCPAY_ABSPATH . 'dist/subscription-edit-page.asset.php';
298
- $script_asset = file_exists( $script_asset_path ) ? require_once $script_asset_path : [ 'dependencies' => [] ];
299
-
300
- wp_register_script(
301
- 'WCPAY_SUBSCRIPTION_EDIT_PAGE',
302
- $script_src_url,
303
- $script_asset['dependencies'],
304
- WC_Payments::get_file_version( 'dist/subscription-edit-page.js' ),
305
- true
306
- );
307
-
308
- wp_localize_script(
309
- 'WCPAY_SUBSCRIPTION_EDIT_PAGE',
310
- 'wcpaySubscriptionEdit',
311
- [
312
- 'gateway' => $this->id,
313
- 'table' => self::PAYMENT_METHOD_META_TABLE,
314
- 'metaKey' => self::PAYMENT_METHOD_META_KEY,
315
- 'tokens' => $this->get_user_formatted_tokens_array( $order->get_user_id() ),
316
- 'defaultOptionText' => __( 'Please select a payment method', 'woocommerce-payments' ),
317
- ]
318
- );
319
-
320
- wp_set_script_translations( 'WCPAY_SUBSCRIPTION_EDIT_PAGE', 'woocommerce-payments' );
321
-
322
- wp_enqueue_script( 'WCPAY_SUBSCRIPTION_EDIT_PAGE' );
323
- }
324
-
325
- /**
326
- * Saves the payment token to the order.
327
- *
328
- * @param WC_Order $order The order.
329
- * @param WC_Payment_Token $token The token to save.
330
- */
331
- public function add_token_to_order( $order, $token ) {
332
- parent::add_token_to_order( $order, $token );
333
-
334
- // Set payment token for subscriptions, so it can be used for renewals.
335
- $subscriptions = wcs_get_subscriptions_for_order( $order->get_id() );
336
- foreach ( $subscriptions as $subscription ) {
337
- parent::add_token_to_order( $subscription, $token );
338
- }
339
- }
340
-
341
- /**
342
- * Render the payment method used for a subscription in My Account pages
343
- *
344
- * @param string $payment_method_to_display Default payment method to display.
345
- * @param WC_Subscription $subscription Subscription object.
346
- *
347
- * @return string Payment method string to display in UI.
348
- */
349
- public function maybe_render_subscription_payment_method( $payment_method_to_display, $subscription ) {
350
- try {
351
- if ( $subscription->get_payment_method() !== $this->id ) {
352
- return $payment_method_to_display;
353
- }
354
-
355
- $token = $this->get_payment_token( $subscription );
356
-
357
- if ( is_null( $token ) ) {
358
- Logger::info( 'There is no saved payment token for subscription #' . $subscription->get_id() );
359
- return $payment_method_to_display;
360
- }
361
- return $token->get_display_name();
362
- } catch ( \Exception $e ) {
363
- Logger::error( 'Failed to get payment method for subscription #' . $subscription->get_id() . ' ' . $e );
364
- return $payment_method_to_display;
365
- }
366
- }
367
-
368
- /**
369
- * Outputs a select element to be used for the Subscriptions payment meta token selection.
370
- *
371
- * @param WC_Subscription $subscription The subscription object.
372
- * @param string $field_id The field_id to add to the select element.
373
- * @param string $field_value The field_value to be selected by default.
374
- */
375
- public function render_custom_payment_meta_input( $subscription, $field_id, $field_value ) {
376
- $tokens = $this->get_user_formatted_tokens_array( $subscription->get_user_id() );
377
- $is_valid_value = false;
378
-
379
- foreach ( $tokens as $token ) {
380
- $is_valid_value = $is_valid_value || (int) $field_value === $token['tokenId'];
381
- }
382
-
383
- echo '<select name="' . esc_attr( $field_id ) . '" id="' . esc_attr( $field_id ) . '">';
384
- // If no token matches the selected ID, add a default option.
385
- if ( ! $is_valid_value ) {
386
- echo '<option value="" selected disabled>' . esc_html__( 'Please select a payment method', 'woocommerce-payments' ) . '</option>';
387
- }
388
- foreach ( $tokens as $token ) {
389
- $is_selected = (int) $field_value === $token['tokenId'] ? 'selected' : '';
390
- echo '<option value="' . esc_attr( $token['tokenId'] ) . '" ' . esc_attr( $is_selected ) . '>' . esc_html( $token['displayName'] ) . '</option>';
391
- }
392
- echo '</select>';
393
- }
394
-
395
- /**
396
- * Add specific data like last 4 digit of wcpay payment gateway
397
- *
398
- * @param string $old_payment_method_title Payment method title, eg: Credit card.
399
- * @param string $old_payment_method Payment gateway id.
400
- * @param WC_Subscription $subscription The subscription order.
401
- * @return string
402
- */
403
- public function get_specific_old_payment_method_title( $old_payment_method_title, $old_payment_method, $subscription ) {
404
- // make sure payment method is wcpay's.
405
- if ( WC_Payment_Gateway_WCPay::GATEWAY_ID !== $old_payment_method ) {
406
- return $old_payment_method_title;
407
- }
408
-
409
- if ( $this->is_changing_payment_method_for_subscription() ) {
410
- $token_ids = $subscription->get_payment_tokens();
411
- // since old payment must be the second to last saved payment...
412
- if ( count( $token_ids ) < 2 ) {
413
- return $old_payment_method_title;
414
- }
415
-
416
- $second_to_last_token_id = $token_ids[ count( $token_ids ) - 2 ];
417
- $token = WC_Payment_Tokens::get( $second_to_last_token_id );
418
- if ( $token && $token instanceof WC_Payment_Token_CC ) {
419
- // translators: 1: payment method likely credit card, 2: last 4 digit.
420
- return sprintf( __( '%1$s ending in %2$s', 'woocommerce-payments' ), $old_payment_method_title, $token->get_last4() );
421
- }
422
- } else {
423
- $last_order_id = $subscription->get_last_order();
424
- if ( ! $last_order_id ) {
425
- return $old_payment_method_title;
426
- }
427
-
428
- $last_order = wc_get_order( $last_order_id );
429
- $token_ids = $last_order->get_payment_tokens();
430
- // since old payment must be the second to last saved payment...
431
- if ( count( $token_ids ) < 2 ) {
432
- return $old_payment_method_title;
433
- }
434
-
435
- $second_to_last_token_id = $token_ids[ count( $token_ids ) - 2 ];
436
- $token = WC_Payment_Tokens::get( $second_to_last_token_id );
437
- if ( $token && $token instanceof WC_Payment_Token_CC ) {
438
- // translators: 1: payment method likely credit card, 2: last 4 digit.
439
- return sprintf( __( '%1$s ending in %2$s', 'woocommerce-payments' ), $old_payment_method_title, $token->get_last4() );
440
- }
441
- }
442
-
443
- return $old_payment_method_title;
444
- }
445
-
446
- /**
447
- * Add specific data like last 4 digit of wcpay payment gateway
448
- *
449
- * @param string $new_payment_method_title Payment method title, eg: Credit card.
450
- * @param string $new_payment_method Payment gateway id.
451
- * @param WC_Subscription $subscription The subscription order.
452
- * @return string
453
- */
454
- public function get_specific_new_payment_method_title( $new_payment_method_title, $new_payment_method, $subscription ) {
455
- // make sure payment method is wcpay's.
456
- if ( WC_Payment_Gateway_WCPay::GATEWAY_ID !== $new_payment_method ) {
457
- return $new_payment_method_title;
458
- }
459
-
460
- if ( $this->is_changing_payment_method_for_subscription() ) {
461
- $order = $subscription;
462
- } else {
463
- $last_order_id = $subscription->get_last_order();
464
- if ( ! $last_order_id ) {
465
- return $new_payment_method_title;
466
- }
467
- $order = wc_get_order( $last_order_id );
468
- }
469
-
470
- try {
471
- $payment_information = $this->prepare_payment_information( $order );
472
- } catch ( Exception $e ) {
473
- return $new_payment_method_title;
474
- }
475
-
476
- if ( $payment_information->is_using_saved_payment_method() ) {
477
- $token = $payment_information->get_payment_token();
478
- if ( $token && $token instanceof WC_Payment_Token_CC ) {
479
- // translators: 1: payment method likely credit card, 2: last 4 digit.
480
- return sprintf( __( '%1$s ending in %2$s', 'woocommerce-payments' ), $new_payment_method_title, $token->get_last4() );
481
- }
482
- } else {
483
- try {
484
- $payment_method_id = $payment_information->get_payment_method();
485
- $payment_method = $this->payments_api_client->get_payment_method( $payment_method_id );
486
- if ( ! empty( $payment_method['card']['last4'] ) ) {
487
- // translators: 1: payment method likely credit card, 2: last 4 digit.
488
- return sprintf( __( '%1$s ending in %2$s', 'woocommerce-payments' ), $new_payment_method_title, $payment_method['card']['last4'] );
489
- }
490
- } catch ( Exception $e ) {
491
- Logger::error( $e );
492
- }
493
- }
494
-
495
- return $new_payment_method_title;
496
- }
497
-
498
- /**
499
- * When an order is created/updated, we want to add an ActionScheduler job to send this data to
500
- * the payment server.
501
- *
502
- * @param int $order_id The ID of the order that has been created.
503
- * @param WC_Order|null $order The order that has been created.
504
- */
505
- public function schedule_order_tracking( $order_id, $order = null ) {
506
- $save_meta_data = false;
507
-
508
- if ( is_null( $order ) ) {
509
- $order = wc_get_order( $order_id );
510
- }
511
-
512
- $payment_token = $this->get_payment_token( $order );
513
-
514
- // If we can't get the payment token for this order, then we check if we already have a payment token
515
- // set in the order metadata. If we don't, then we try and get the parent order's token from the metadata.
516
- if ( is_null( $payment_token ) ) {
517
- if ( empty( $order->get_meta( '_payment_method_id' ) ) ) {
518
- $parent_order = wc_get_order( $order->get_parent_id() );
519
-
520
- // If there is no parent order, or the parent order doesn't have the metadata set, then we cannot track this order.
521
- if ( empty( $parent_order ) || empty( $parent_order->get_meta( '_payment_method_id' ) ) ) {
522
- return;
523
- }
524
-
525
- $order->update_meta_data( '_payment_method_id', $parent_order->get_meta( '_payment_method_id' ) );
526
- $save_meta_data = true;
527
- }
528
- } elseif ( $order->get_meta( '_payment_method_id' ) !== $payment_token->get_token() ) {
529
- // If the payment token stored in the metadata already doesn't reflect the latest token, update it.
530
- $order->update_meta_data( '_payment_method_id', $payment_token->get_token() );
531
- $save_meta_data = true;
532
- }
533
-
534
- // If the stripe customer ID metadata isn't set for this order, try and get this data from the metadata of the parent order.
535
- if ( empty( $order->get_meta( '_stripe_customer_id' ) ) ) {
536
- $parent_order = wc_get_order( $order->get_parent_id() );
537
- if ( ! empty( $parent_order ) && ! empty( $parent_order->get_meta( '_stripe_customer_id' ) ) ) {
538
- $order->update_meta_data( '_stripe_customer_id', $parent_order->get_meta( '_stripe_customer_id' ) );
539
- $save_meta_data = true;
540
- }
541
- }
542
-
543
- // If we need to, save our changes to the metadata for this order.
544
- if ( $save_meta_data ) {
545
- $order->save_meta_data();
546
- }
547
-
548
- // Call the parent logic to schedule the order tracking.
549
- parent::schedule_order_tracking( $order_id, $order );
550
- }
551
-
552
- /**
553
- * Action called when a renewal order is created, allowing us to strip metadata that we do not
554
- * want it to inherit from the parent order.
555
- *
556
- * @param string $order_meta_query The metadata query (a valid SQL query).
557
- * @param int $to_order The renewal order.
558
- * @param int $from_order The source (parent) order.
559
- *
560
- * @return string
561
- */
562
- public function update_renewal_meta_data( $order_meta_query, $to_order, $from_order ) {
563
- $order_meta_query .= " AND `meta_key` NOT IN ('_new_order_tracking_complete')";
564
-
565
- return $order_meta_query;
566
- }
567
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/constants/class-digital-wallets-locations.php DELETED
@@ -1,23 +0,0 @@
1
- <?php
2
- /**
3
- * Class Digital_Wallets_Locations
4
- *
5
- * @package WooCommerce\Payments
6
- */
7
-
8
- namespace WCPay\Constants;
9
-
10
- if ( ! defined( 'ABSPATH' ) ) {
11
- exit; // Exit if accessed directly.
12
- }
13
-
14
- use MyCLabs\Enum\Enum;
15
-
16
- /**
17
- * Possible locations for digital wallets to show on.
18
- */
19
- class Digital_Wallets_Locations extends Enum {
20
- const CART = 'cart';
21
- const CHECKOUT = 'checkout';
22
- const PRODUCT_PAGE = 'product';
23
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/class-country-flags.php DELETED
@@ -1,290 +0,0 @@
1
- <?php
2
- /**
3
- * Class Country_Flags
4
- *
5
- * @package WooCommerce\Payments
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- defined( 'ABSPATH' ) || exit;
11
-
12
- /**
13
- * Class that bring flags per country/currency.
14
- */
15
- class Country_Flags {
16
-
17
- const EMOJI_COUNTRIES_FLAGS = [
18
- 'AD' => '🇦🇩',
19
- 'AE' => '🇦🇪',
20
- 'AF' => '🇦🇫',
21
- 'AG' => '🇦🇬',
22
- 'AI' => '🇦🇮',
23
- 'AL' => '🇦🇱',
24
- 'AM' => '🇦🇲',
25
- 'AO' => '🇦🇴',
26
- 'AQ' => '🇦🇶',
27
- 'AR' => '🇦🇷',
28
- 'AS' => '🇦🇸',
29
- 'AT' => '🇦🇹',
30
- 'AU' => '🇦🇺',
31
- 'AW' => '🇦🇼',
32
- 'AX' => '🇦🇽',
33
- 'AZ' => '🇦🇿',
34
- 'BA' => '🇧🇦',
35
- 'BB' => '🇧🇧',
36
- 'BD' => '🇧🇩',
37
- 'BE' => '🇧🇪',
38
- 'BF' => '🇧🇫',
39
- 'BG' => '🇧🇬',
40
- 'BH' => '🇧🇭',
41
- 'BI' => '🇧🇮',
42
- 'BJ' => '🇧🇯',
43
- 'BL' => '🇧🇱',
44
- 'BM' => '🇧🇲',
45
- 'BN' => '🇧🇳',
46
- 'BO' => '🇧🇴',
47
- 'BQ' => '🇧🇶',
48
- 'BR' => '🇧🇷',
49
- 'BS' => '🇧🇸',
50
- 'BT' => '🇧🇹',
51
- 'BV' => '🇧🇻',
52
- 'BW' => '🇧🇼',
53
- 'BY' => '🇧🇾',
54
- 'BZ' => '🇧🇿',
55
- 'CA' => '🇨🇦',
56
- 'CC' => '🇨🇨',
57
- 'CD' => '🇨🇩',
58
- 'CF' => '🇨🇫',
59
- 'CG' => '🇨🇬',
60
- 'CH' => '🇨🇭',
61
- 'CI' => '🇨🇮',
62
- 'CK' => '🇨🇰',
63
- 'CL' => '🇨🇱',
64
- 'CM' => '🇨🇲',
65
- 'CN' => '🇨🇳',
66
- 'CO' => '🇨🇴',
67
- 'CR' => '🇨🇷',
68
- 'CU' => '🇨🇺',
69
- 'CV' => '🇨🇻',
70
- 'CW' => '🇨🇼',
71
- 'CX' => '🇨🇽',
72
- 'CY' => '🇨🇾',
73
- 'CZ' => '🇨🇿',
74
- 'DE' => '🇩🇪',
75
- 'DJ' => '🇩🇯',
76
- 'DK' => '🇩🇰',
77
- 'DM' => '🇩🇲',
78
- 'DO' => '🇩🇴',
79
- 'DZ' => '🇩🇿',
80
- 'EC' => '🇪🇨',
81
- 'EE' => '🇪🇪',
82
- 'EG' => '🇪🇬',
83
- 'EH' => '🇪🇭',
84
- 'ER' => '🇪🇷',
85
- 'ES' => '🇪🇸',
86
- 'ET' => '🇪🇹',
87
- 'EU' => '🇪🇺',
88
- 'FI' => '🇫🇮',
89
- 'FJ' => '🇫🇯',
90
- 'FK' => '🇫🇰',
91
- 'FM' => '🇫🇲',
92
- 'FO' => '🇫🇴',
93
- 'FR' => '🇫🇷',
94
- 'GA' => '🇬🇦',
95
- 'GB' => '🇬🇧',
96
- 'GD' => '🇬🇩',
97
- 'GE' => '🇬🇪',
98
- 'GF' => '🇬🇫',
99
- 'GG' => '🇬🇬',
100
- 'GH' => '🇬🇭',
101
- 'GI' => '🇬🇮',
102
- 'GL' => '🇬🇱',
103
- 'GM' => '🇬🇲',
104
- 'GN' => '🇬🇳',
105
- 'GP' => '🇬🇵',
106
- 'GQ' => '🇬🇶',
107
- 'GR' => '🇬🇷',
108
- 'GS' => '🇬🇸',
109
- 'GT' => '🇬🇹',
110
- 'GU' => '🇬🇺',
111
- 'GW' => '🇬🇼',
112
- 'GY' => '🇬🇾',
113
- 'HK' => '🇭🇰',
114
- 'HM' => '🇭🇲',
115
- 'HN' => '🇭🇳',
116
- 'HR' => '🇭🇷',
117
- 'HT' => '🇭🇹',
118
- 'HU' => '🇭🇺',
119
- 'ID' => '🇮🇩',
120
- 'IE' => '🇮🇪',
121
- 'IL' => '🇮🇱',
122
- 'IM' => '🇮🇲',
123
- 'IN' => '🇮🇳',
124
- 'IO' => '🇮🇴',
125
- 'IQ' => '🇮🇶',
126
- 'IR' => '🇮🇷',
127
- 'IS' => '🇮🇸',
128
- 'IT' => '🇮🇹',
129
- 'JE' => '🇯🇪',
130
- 'JM' => '🇯🇲',
131
- 'JO' => '🇯🇴',
132
- 'JP' => '🇯🇵',
133
- 'KE' => '🇰🇪',
134
- 'KG' => '🇰🇬',
135
- 'KH' => '🇰🇭',
136
- 'KI' => '🇰🇮',
137
- 'KM' => '🇰🇲',
138
- 'KN' => '🇰🇳',
139
- 'KP' => '🇰🇵',
140
- 'KR' => '🇰🇷',
141
- 'KW' => '🇰🇼',
142
- 'KY' => '🇰🇾',
143
- 'KZ' => '🇰🇿',
144
- 'LA' => '🇱🇦',
145
- 'LB' => '🇱🇧',
146
- 'LC' => '🇱🇨',
147
- 'LI' => '🇱🇮',
148
- 'LK' => '🇱🇰',
149
- 'LR' => '🇱🇷',
150
- 'LS' => '🇱🇸',
151
- 'LT' => '🇱🇹',
152
- 'LU' => '🇱🇺',
153
- 'LV' => '🇱🇻',
154
- 'LY' => '🇱🇾',
155
- 'MA' => '🇲🇦',
156
- 'MC' => '🇲🇨',
157
- 'MD' => '🇲🇩',
158
- 'ME' => '🇲🇪',
159
- 'MF' => '🇲🇫',
160
- 'MG' => '🇲🇬',
161
- 'MH' => '🇲🇭',
162
- 'MK' => '🇲🇰',
163
- 'ML' => '🇲🇱',
164
- 'MM' => '🇲🇲',
165
- 'MN' => '🇲🇳',
166
- 'MO' => '🇲🇴',
167
- 'MP' => '🇲🇵',
168
- 'MQ' => '🇲🇶',
169
- 'MR' => '🇲🇷',
170
- 'MS' => '🇲🇸',
171
- 'MT' => '🇲🇹',
172
- 'MU' => '🇲🇺',
173
- 'MV' => '🇲🇻',
174
- 'MW' => '🇲🇼',
175
- 'MX' => '🇲🇽',
176
- 'MY' => '🇲🇾',
177
- 'MZ' => '🇲🇿',
178
- 'NA' => '🇳🇦',
179
- 'NC' => '🇳🇨',
180
- 'NE' => '🇳🇪',
181
- 'NF' => '🇳🇫',
182
- 'NG' => '🇳🇬',
183
- 'NI' => '🇳🇮',
184
- 'NL' => '🇳🇱',
185
- 'NO' => '🇳🇴',
186
- 'NP' => '🇳🇵',
187
- 'NR' => '🇳🇷',
188
- 'NU' => '🇳🇺',
189
- 'NZ' => '🇳🇿',
190
- 'OM' => '🇴🇲',
191
- 'PA' => '🇵🇦',
192
- 'PE' => '🇵🇪',
193
- 'PF' => '🇵🇫',
194
- 'PG' => '🇵🇬',
195
- 'PH' => '🇵🇭',
196
- 'PK' => '🇵🇰',
197
- 'PL' => '🇵🇱',
198
- 'PM' => '🇵🇲',
199
- 'PN' => '🇵🇳',
200
- 'PR' => '🇵🇷',
201
- 'PS' => '🇵🇸',
202
- 'PT' => '🇵🇹',
203
- 'PW' => '🇵🇼',
204
- 'PY' => '🇵🇾',
205
- 'QA' => '🇶🇦',
206
- 'RE' => '🇷🇪',
207
- 'RO' => '🇷🇴',
208
- 'RS' => '🇷🇸',
209
- 'RU' => '🇷🇺',
210
- 'RW' => '🇷🇼',
211
- 'SA' => '🇸🇦',
212
- 'SB' => '🇸🇧',
213
- 'SC' => '🇸🇨',
214
- 'SD' => '🇸🇩',
215
- 'SE' => '🇸🇪',
216
- 'SG' => '🇸🇬',
217
- 'SH' => '🇸🇭',
218
- 'SI' => '🇸🇮',
219
- 'SJ' => '🇸🇯',
220
- 'SK' => '🇸🇰',
221
- 'SL' => '🇸🇱',
222
- 'SM' => '🇸🇲',
223
- 'SN' => '🇸🇳',
224
- 'SO' => '🇸🇴',
225
- 'SR' => '🇸🇷',
226
- 'SS' => '🇸🇸',
227
- 'ST' => '🇸🇹',
228
- 'SV' => '🇸🇻',
229
- 'SX' => '🇸🇽',
230
- 'SY' => '🇸🇾',
231
- 'SZ' => '🇸🇿',
232
- 'TC' => '🇹🇨',
233
- 'TD' => '🇹🇩',
234
- 'TF' => '🇹🇫',
235
- 'TG' => '🇹🇬',
236
- 'TH' => '🇹🇭',
237
- 'TJ' => '🇹🇯',
238
- 'TK' => '🇹🇰',
239
- 'TL' => '🇹🇱',
240
- 'TM' => '🇹🇲',
241
- 'TN' => '🇹🇳',
242
- 'TO' => '🇹🇴',
243
- 'TR' => '🇹🇷',
244
- 'TT' => '🇹🇹',
245
- 'TV' => '🇹🇻',
246
- 'TW' => '🇹🇼',
247
- 'TZ' => '🇹🇿',
248
- 'UA' => '🇺🇦',
249
- 'UG' => '🇺🇬',
250
- 'UM' => '🇺🇲',
251
- 'US' => '🇺🇸',
252
- 'UY' => '🇺🇾',
253
- 'UZ' => '🇺🇿',
254
- 'VA' => '🇻🇦',
255
- 'VC' => '🇻🇨',
256
- 'VE' => '🇻🇪',
257
- 'VG' => '🇻🇬',
258
- 'VI' => '🇻🇮',
259
- 'VN' => '🇻🇳',
260
- 'VU' => '🇻🇺',
261
- 'WF' => '🇼🇫',
262
- 'WS' => '🇼🇸',
263
- 'XK' => '🇽🇰',
264
- 'YE' => '🇾🇪',
265
- 'YT' => '🇾🇹',
266
- 'ZA' => '🇿🇦',
267
- 'ZM' => '🇿🇲',
268
- 'ZW' => '🇿🇼',
269
- ];
270
-
271
- /**
272
- * Retrieves a flag by country code.
273
- *
274
- * @param string $country country alpha-2 code (ISO 3166) like US.
275
- * @return string
276
- */
277
- public static function get_by_country( string $country ): string {
278
- return self::EMOJI_COUNTRIES_FLAGS[ $country ] ?? '';
279
- }
280
-
281
- /**
282
- * Retrieves a flag by currency code.
283
- *
284
- * @param string $currency currency code (ISO 4217) like USD.
285
- * @return string
286
- */
287
- public static function get_by_currency( string $currency ): string {
288
- return self::get_by_country( substr( $currency, 0, -1 ) );
289
- }
290
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/class-currency-switcher-widget.php DELETED
@@ -1,197 +0,0 @@
1
- <?php
2
- /**
3
- * WooCommerce Payments Currency Switcher Widget
4
- *
5
- * @package WooCommerce\Payments
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- use WP_Widget;
11
-
12
- defined( 'ABSPATH' ) || exit;
13
-
14
- /**
15
- * Currency Switcher Widget Class
16
- */
17
- class Currency_Switcher_Widget extends WP_Widget {
18
-
19
- const DEFAULT_SETTINGS = [
20
- 'title' => '',
21
- 'symbol' => true,
22
- 'flag' => false,
23
- ];
24
-
25
- /**
26
- * Multi-Currency instance.
27
- *
28
- * @var Multi_Currency
29
- */
30
- protected $multi_currency;
31
-
32
- /**
33
- * Register widget with WordPress.
34
- *
35
- * @param Multi_Currency $multi_currency The Multi_Currency instance.
36
- */
37
- public function __construct( Multi_Currency $multi_currency ) {
38
- $this->multi_currency = $multi_currency;
39
-
40
- parent::__construct(
41
- 'currency_switcher_widget',
42
- __( 'Currency Switcher', 'woocommerce-payments' ),
43
- [ 'description' => __( 'Let your customers switch between your enabled currencies', 'woocommerce-payments' ) ]
44
- );
45
- }
46
-
47
- /**
48
- * Front-end display of widget.
49
- *
50
- * @param array $args Widget arguments.
51
- * @param array $instance Saved values from database.
52
- */
53
- public function widget( $args, $instance ) {
54
- $instance = wp_parse_args(
55
- $instance,
56
- self::DEFAULT_SETTINGS
57
- );
58
-
59
- $title = apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base );
60
-
61
- echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput
62
- if ( ! empty( $title ) ) {
63
- echo $args['before_title'] . $title . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput
64
- }
65
-
66
- ?>
67
- <form>
68
- <?php $this->output_get_params(); ?>
69
- <select
70
- name="currency"
71
- aria-label="<?php echo esc_attr( $title ); ?>"
72
- onchange="this.form.submit()"
73
- >
74
- <?php
75
- foreach ( $this->multi_currency->get_enabled_currencies() as $currency ) {
76
- $this->display_currency_option( $currency, $instance['symbol'], $instance['flag'] );
77
- }
78
- ?>
79
- </select>
80
- </form>
81
- <?php
82
-
83
- echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput
84
- }
85
-
86
- /**
87
- * Back-end widget form.
88
- *
89
- * @param array $instance Previously saved values from database.
90
- */
91
- public function form( $instance ) {
92
- $instance = wp_parse_args(
93
- $instance,
94
- self::DEFAULT_SETTINGS
95
- );
96
- ?>
97
- <p>
98
- <label for="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>">
99
- <?php esc_html_e( 'Title:', 'woocommerce-payments' ); ?>
100
- </label>
101
- <input
102
- class="widefat"
103
- id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"
104
- name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>"
105
- type="text"
106
- value="<?php echo esc_attr( $instance['title'] ); ?>"
107
- />
108
- </p>
109
- <p>
110
- <input
111
- class="checkbox"
112
- id="<?php echo esc_attr( $this->get_field_id( 'symbol' ) ); ?>"
113
- name="<?php echo esc_attr( $this->get_field_name( 'symbol' ) ); ?>"
114
- type="checkbox"<?php checked( $instance['symbol'] ); ?>
115
- />
116
- <label for="<?php echo esc_attr( $this->get_field_id( 'symbol' ) ); ?>">
117
- <?php esc_html_e( 'Display currency symbols', 'woocommerce-payments' ); ?>
118
- </label>
119
- <br/>
120
- <input
121
- class="checkbox"
122
- id="<?php echo esc_attr( $this->get_field_id( 'flag' ) ); ?>"
123
- name="<?php echo esc_attr( $this->get_field_name( 'flag' ) ); ?>"
124
- type="checkbox"<?php checked( $instance['flag'] ); ?>
125
- />
126
- <label for="<?php echo esc_attr( $this->get_field_id( 'flag' ) ); ?>">
127
- <?php esc_html_e( 'Display flags', 'woocommerce-payments' ); ?>
128
- </label>
129
- </p>
130
- <?php
131
- }
132
-
133
- /**
134
- * Sanitize widget form values as they are saved.
135
- *
136
- * @param array $new_instance Values just sent to be saved.
137
- * @param array $old_instance Previously saved values from database.
138
- *
139
- * @return array Updated safe values to be saved.
140
- */
141
- public function update( $new_instance, $old_instance ) {
142
- $instance = [
143
- 'title' => sanitize_text_field( $new_instance['title'] ),
144
- 'symbol' => isset( $new_instance['symbol'] ) ? 1 : 0,
145
- 'flag' => isset( $new_instance['flag'] ) ? 1 : 0,
146
- ];
147
-
148
- return $instance;
149
- }
150
-
151
- /**
152
- * Create an <option> element with provided currency. With symbol and flag if requested.
153
- *
154
- * @param Currency $currency Currency to use for <option> element.
155
- * @param boolean $with_symbol Whether to show the currency symbol.
156
- * @param boolean $with_flag Whether to show the currency flag.
157
- * @return void Displays HTML of currency <option>
158
- */
159
- private function display_currency_option( Currency $currency, bool $with_symbol, bool $with_flag ) {
160
- $code = $currency->get_code();
161
- $text = $code;
162
- $selected = $this->multi_currency->get_selected_currency()->code === $code ? ' selected' : '';
163
-
164
- if ( $with_symbol ) {
165
- $text = $currency->get_symbol() . ' ' . $text;
166
- }
167
- if ( $with_flag ) {
168
- $text = $currency->get_flag() . ' ' . $text;
169
- }
170
-
171
- echo "<option value=\"$code\"$selected>$text</option>"; // phpcs:ignore WordPress.Security.EscapeOutput
172
- }
173
-
174
- /**
175
- * Output hidden inputs for every $_GET param.
176
- * This prevent the switcher form to remove them on submit.
177
- *
178
- * @return void
179
- */
180
- private function output_get_params() {
181
- // phpcs:disable WordPress.Security.NonceVerification
182
- if ( empty( $_GET ) ) {
183
- return;
184
- }
185
- $params = explode( '&', urldecode( http_build_query( $_GET ) ) );
186
- foreach ( $params as $param ) {
187
- $name_value = explode( '=', $param );
188
- $name = $name_value[0];
189
- $value = $name_value[1];
190
- if ( 'currency' === $name ) {
191
- continue;
192
- }
193
- echo '<input type="hidden" name="' . esc_attr( $name ) . '" value="' . esc_attr( $value ) . '" />';
194
- }
195
- // phpcs:enable WordPress.Security.NonceVerification
196
- }
197
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/class-currency.php DELETED
@@ -1,227 +0,0 @@
1
- <?php
2
- /**
3
- * Class Currency
4
- *
5
- * @package WooCommerce\Payments
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- use WC_Payments_Utils;
11
-
12
- defined( 'ABSPATH' ) || exit;
13
-
14
- /**
15
- * Multi Currency Currency object.
16
- */
17
- class Currency implements \JsonSerializable {
18
-
19
- /**
20
- * Three letter currency code.
21
- *
22
- * @var string
23
- */
24
- public $code;
25
-
26
- /**
27
- * Currency conversion rate.
28
- *
29
- * @var float
30
- */
31
- public $rate;
32
-
33
- /**
34
- * Currency charm rate after conversion and rounding.
35
- *
36
- * @var float|null
37
- */
38
- private $charm;
39
-
40
- /**
41
- * Is currency default for store?
42
- *
43
- * @var bool|null
44
- */
45
- private $is_default = false;
46
-
47
- /**
48
- * Currency rounding rate after conversion.
49
- *
50
- * @var float|null
51
- */
52
- private $rounding;
53
-
54
- /**
55
- * Is currency zero decimal?
56
- *
57
- * @var bool|null
58
- */
59
- private $is_zero_decimal = false;
60
-
61
-
62
- /**
63
- * Constructor.
64
- *
65
- * @param string $code Three letter currency code.
66
- * @param float $rate The conversion rate.
67
- */
68
- public function __construct( $code = '', $rate = 1.0 ) {
69
- $this->code = $code;
70
- $this->rate = $rate;
71
-
72
- if ( get_woocommerce_currency() === $code ) {
73
- $this->is_default = true;
74
- }
75
-
76
- if ( in_array( strtolower( $code ), WC_Payments_Utils::zero_decimal_currencies(), true ) ) {
77
- $this->is_zero_decimal = true;
78
- }
79
- }
80
-
81
- /**
82
- * Retrieves the currency's translated name from WooCommerce core.
83
- *
84
- * @param string $code The currency code.
85
- */
86
- public function get_currency_name_from_code( $code ): string {
87
- $wc_currencies = get_woocommerce_currencies();
88
- return $wc_currencies[ $code ];
89
- }
90
-
91
- /**
92
- * Retrieves the currency's code.
93
- *
94
- * @return string Three letter currency code.
95
- */
96
- public function get_code(): string {
97
- return $this->code;
98
- }
99
-
100
- /**
101
- * Retrieves the currency's charm rate.
102
- *
103
- * @return float Charm rate.
104
- */
105
- public function get_charm(): float {
106
- return is_null( $this->charm ) ? 0.00 : $this->charm;
107
- }
108
-
109
- /**
110
- * Retrieves the currency's flag.
111
- *
112
- * @return string Currency flag.
113
- */
114
- public function get_flag(): string {
115
- // Maybe add param img/emoji to return which you want?
116
- return Country_Flags::get_by_currency( $this->code );
117
- }
118
-
119
- /**
120
- * Retrieves the currency code lowercased.
121
- *
122
- * @return string Currency code lowercased.
123
- */
124
- public function get_id(): string {
125
- return strtolower( $this->code );
126
- }
127
-
128
- /**
129
- * Retrieves if the currency is default for the store.
130
- *
131
- * @return bool
132
- */
133
- public function get_is_default(): bool {
134
- return $this->is_default;
135
- }
136
-
137
- /**
138
- * Retrieves the currency's name from WooCommerce core.
139
- *
140
- * @return string Currency name.
141
- */
142
- public function get_name(): string {
143
- $wc_currencies = get_woocommerce_currencies();
144
- return $wc_currencies[ $this->code ];
145
- }
146
-
147
- /**
148
- * Retrieves the currency's conversion rate.
149
- *
150
- * @return float The conversion rate.
151
- */
152
- public function get_rate(): float {
153
- return $this->rate;
154
- }
155
-
156
- /**
157
- * Retrieves the currency's rounding rate.
158
- *
159
- * @return string Rounding rate.
160
- */
161
- public function get_rounding(): string {
162
- return is_null( $this->rounding ) ? 'none' : $this->rounding;
163
- }
164
-
165
- /**
166
- * Retrieves the currency's symbol from WooCommerce core.
167
- *
168
- * @return string Currency symbol.
169
- */
170
- public function get_symbol(): string {
171
- return get_woocommerce_currency_symbol( $this->code );
172
- }
173
-
174
- /**
175
- * Retrieves if the currency is zero decimal.
176
- *
177
- * @return bool
178
- */
179
- public function get_is_zero_decimal(): bool {
180
- return $this->is_zero_decimal;
181
- }
182
-
183
- /**
184
- * Sets the currency's charm rate.
185
- *
186
- * @param float $charm Charm rate.
187
- */
188
- public function set_charm( $charm ) {
189
- $this->charm = $charm;
190
- }
191
-
192
- /**
193
- * Sets the currency's conversion rate.
194
- *
195
- * @param float $rate Conversion rate.
196
- */
197
- public function set_rate( $rate ) {
198
- $this->rate = $rate;
199
- }
200
-
201
- /**
202
- * Sets the currency's rounding rate.
203
- *
204
- * @param string $rounding Rounding rate.
205
- */
206
- public function set_rounding( $rounding ) {
207
- $this->rounding = $rounding;
208
- }
209
-
210
- /**
211
- * Specify the data that should be serialized to JSON.
212
- *
213
- * @return array Serialized Currency object.
214
- */
215
- public function jsonSerialize(): array {
216
- return [
217
- 'code' => $this->code,
218
- 'rate' => $this->get_rate(),
219
- 'name' => html_entity_decode( $this->get_name() ),
220
- 'id' => $this->get_id(),
221
- 'is_default' => $this->get_is_default(),
222
- 'flag' => $this->get_flag(),
223
- 'symbol' => html_entity_decode( $this->get_symbol() ),
224
- 'is_zero_decimal' => $this->get_is_zero_decimal(),
225
- ];
226
- }
227
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/class-frontend-currencies.php DELETED
@@ -1,171 +0,0 @@
1
- <?php
2
- /**
3
- * WooCommerce Payments Multi Currency Frontend Currencies
4
- *
5
- * @package WooCommerce\Payments
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- defined( 'ABSPATH' ) || exit;
11
-
12
- /**
13
- * Class that formats Multi Currency currencies on the frontend.
14
- */
15
- class Frontend_Currencies {
16
- /**
17
- * Multi-Currency instance.
18
- *
19
- * @var Multi_Currency
20
- */
21
- protected $multi_currency;
22
-
23
- /**
24
- * Multi-Currency currency formatting map.
25
- *
26
- * @var array
27
- */
28
- protected $currency_format = [];
29
-
30
- /**
31
- * Constructor.
32
- *
33
- * @param Multi_Currency $multi_currency The Multi_Currency instance.
34
- */
35
- public function __construct( Multi_Currency $multi_currency ) {
36
- $this->multi_currency = $multi_currency;
37
-
38
- $this->load_locale_data();
39
-
40
- if ( ! is_admin() && ! defined( 'DOING_CRON' ) ) {
41
- // Currency hooks.
42
- add_filter( 'woocommerce_currency', [ $this, 'get_woocommerce_currency' ], 50 );
43
- add_filter( 'wc_get_price_decimals', [ $this, 'get_price_decimals' ], 50 );
44
- add_filter( 'wc_get_price_decimal_separator', [ $this, 'get_price_decimal_separator' ], 50 );
45
- add_filter( 'wc_get_price_thousand_separator', [ $this, 'get_price_thousand_separator' ], 50 );
46
- add_filter( 'woocommerce_price_format', [ $this, 'get_woocommerce_price_format' ], 50 );
47
- }
48
-
49
- add_filter( 'woocommerce_cart_hash', [ $this, 'add_currency_to_cart_hash' ], 50 );
50
- }
51
-
52
- /**
53
- * Returns the currency code to be used by WooCommerce.
54
- *
55
- * @return string The code of the currency to be used.
56
- */
57
- public function get_woocommerce_currency() {
58
- return $this->multi_currency->get_selected_currency()->get_code();
59
- }
60
-
61
- /**
62
- * Returns the number of decimals to be used by WooCommerce.
63
- *
64
- * @return int The number of decimals.
65
- */
66
- public function get_price_decimals() {
67
- $currency_code = $this->multi_currency->get_selected_currency()->get_code();
68
- return $this->get_currency_format( $currency_code )['num_decimals'];
69
- }
70
-
71
- /**
72
- * Returns the decimal separator to be used by WooCommerce.
73
- *
74
- * @return int The decimal separator.
75
- */
76
- public function get_price_decimal_separator() {
77
- $currency_code = $this->multi_currency->get_selected_currency()->get_code();
78
- return $this->get_currency_format( $currency_code )['decimal_sep'];
79
- }
80
-
81
- /**
82
- * Returns the thousand separator to be used by WooCommerce.
83
- *
84
- * @return int The thousand separator.
85
- */
86
- public function get_price_thousand_separator() {
87
- $currency_code = $this->multi_currency->get_selected_currency()->get_code();
88
- return $this->get_currency_format( $currency_code )['thousand_sep'];
89
- }
90
-
91
- /**
92
- * Returns the currency format to be used by WooCommerce.
93
- *
94
- * @return int The currency format.
95
- */
96
- public function get_woocommerce_price_format() {
97
- $currency_code = $this->multi_currency->get_selected_currency()->get_code();
98
- $currency_pos = $this->get_currency_format( $currency_code )['currency_pos'];
99
-
100
- switch ( $currency_pos ) {
101
- case 'left':
102
- return '%1$s%2$s';
103
- case 'right':
104
- return '%2$s%1$s';
105
- case 'left_space':
106
- return '%1$s&nbsp;%2$s';
107
- case 'right_space':
108
- return '%2$s&nbsp;%1$s';
109
- default:
110
- return '%1$s%2$s';
111
- }
112
- }
113
-
114
- /**
115
- * Adds the currency and exchange rate to the cart hash so it's recalculated properly.
116
- *
117
- * @param string $hash The cart hash.
118
- *
119
- * @return string The adjusted cart hash.
120
- */
121
- public function add_currency_to_cart_hash( $hash ) {
122
- $currency = $this->multi_currency->get_selected_currency();
123
- return md5( $hash . $currency->get_code() . $currency->get_rate() );
124
- }
125
-
126
- /**
127
- * Retrieves the currency's format from mapped data.
128
- *
129
- * @param string $currency_code The currency code.
130
- *
131
- * @return array The currency's format.
132
- */
133
- private function get_currency_format( $currency_code ) {
134
- // Default to USD settings if mapping not found.
135
- $currency_format = $this->currency_format[ $currency_code ] ?? [
136
- 'currency_pos' => 'left',
137
- 'thousand_sep' => ',',
138
- 'decimal_sep' => '.',
139
- 'num_decimals' => 2,
140
- ];
141
-
142
- return apply_filters( 'wcpay_multi_currency_' . strtolower( $currency_code ) . '_format', $currency_format );
143
- }
144
-
145
- /**
146
- * Loads locale data from WooCommerce core (/i18n/locale-info.php) and maps it
147
- * to be used by currency.
148
- */
149
- private function load_locale_data() {
150
- $locale_info = include WC()->plugin_path() . '/i18n/locale-info.php';
151
-
152
- // Extract the currency formatting options from the locale info.
153
- foreach ( $locale_info as $locale ) {
154
- $currency_code = $locale['currency_code'];
155
-
156
- // Convert Norwegian Krone symbol to its ISO 4217 currency code.
157
- if ( 'Kr' === $currency_code ) {
158
- $currency_code = 'NOK';
159
- }
160
-
161
- if ( empty( $this->currency_format[ $currency_code ] ) ) {
162
- $this->currency_format[ $currency_code ] = [
163
- 'currency_pos' => $locale['currency_pos'],
164
- 'thousand_sep' => $locale['thousand_sep'],
165
- 'decimal_sep' => $locale['decimal_sep'],
166
- 'num_decimals' => $locale['num_decimals'],
167
- ];
168
- }
169
- }
170
- }
171
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/class-frontend-prices.php DELETED
@@ -1,234 +0,0 @@
1
- <?php
2
- /**
3
- * WooCommerce Payments Multi Currency Frontend Prices
4
- *
5
- * @package WooCommerce\Payments
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- defined( 'ABSPATH' ) || exit;
11
-
12
- /**
13
- * Class that applies Multi Currency prices on the frontend.
14
- */
15
- class Frontend_Prices {
16
- /**
17
- * Multi-Currency instance.
18
- *
19
- * @var Multi_Currency
20
- */
21
- protected $multi_currency;
22
-
23
- /**
24
- * Constructor.
25
- *
26
- * @param Multi_Currency $multi_currency The Multi_Currency instance.
27
- */
28
- public function __construct( Multi_Currency $multi_currency ) {
29
- $this->multi_currency = $multi_currency;
30
-
31
- if ( ! is_admin() && ! defined( 'DOING_CRON' ) ) {
32
- // Simple product price hooks.
33
- add_filter( 'woocommerce_product_get_price', [ $this, 'get_product_price' ], 50 );
34
- add_filter( 'woocommerce_product_get_regular_price', [ $this, 'get_product_price' ], 50 );
35
- add_filter( 'woocommerce_product_get_sale_price', [ $this, 'get_product_price' ], 50 );
36
-
37
- // Variation price hooks.
38
- add_filter( 'woocommerce_product_variation_get_price', [ $this, 'get_product_price' ], 50 );
39
- add_filter( 'woocommerce_product_variation_get_regular_price', [ $this, 'get_product_price' ], 50 );
40
- add_filter( 'woocommerce_product_variation_get_sale_price', [ $this, 'get_product_price' ], 50 );
41
-
42
- // Variation price range hooks.
43
- add_filter( 'woocommerce_variation_prices', [ $this, 'get_variation_price_range' ], 50 );
44
- add_filter( 'woocommerce_get_variation_prices_hash', [ $this, 'add_exchange_rate_to_variation_prices_hash' ], 50 );
45
-
46
- // Shipping methods hooks.
47
- add_filter( 'woocommerce_package_rates', [ $this, 'convert_package_rates_prices' ], 50 );
48
- add_action( 'init', [ $this, 'register_free_shipping_filters' ], 50 );
49
-
50
- // Coupon hooks.
51
- add_filter( 'woocommerce_coupon_get_amount', [ $this, 'get_coupon_amount' ], 50, 2 );
52
- add_filter( 'woocommerce_coupon_get_minimum_amount', [ $this, 'get_coupon_min_max_amount' ], 50 );
53
- add_filter( 'woocommerce_coupon_get_maximum_amount', [ $this, 'get_coupon_min_max_amount' ], 50 );
54
-
55
- // Order hooks.
56
- add_filter( 'woocommerce_new_order', [ $this, 'add_order_meta' ], 50, 2 );
57
-
58
- // Subscription product hooks.
59
- add_filter( 'woocommerce_subscriptions_product_price', [ $this, 'get_product_price' ], 50, 2 );
60
- add_filter( 'woocommerce_subscriptions_product_sign_up_fee', [ $this, 'get_product_price' ], 50, 2 );
61
- }
62
- }
63
-
64
- /**
65
- * Returns the price for a product.
66
- *
67
- * @param mixed $price The product's price.
68
- *
69
- * @return mixed The converted product's price.
70
- */
71
- public function get_product_price( $price ) {
72
- if ( ! $price ) {
73
- return $price;
74
- }
75
-
76
- return $this->multi_currency->get_price( $price, 'product' );
77
- }
78
-
79
- /**
80
- * Returns the price range for a variation.
81
- *
82
- * @param array $variation_prices The variation's prices.
83
- *
84
- * @return array The converted variation's prices.
85
- */
86
- public function get_variation_price_range( $variation_prices ) {
87
- foreach ( $variation_prices as $price_type => $prices ) {
88
- foreach ( $prices as $variation_id => $price ) {
89
- $variation_prices[ $price_type ][ $variation_id ] = $this->get_product_price( $price );
90
- }
91
- }
92
-
93
- return $variation_prices;
94
- }
95
-
96
- /**
97
- * Add the exchange rate into account for the variation prices hash.
98
- * This is used to recalculate the variation price range when the exchange
99
- * rate changes, otherwise the old prices will be cached.
100
- *
101
- * @param array $prices_hash The variation prices hash.
102
- *
103
- * @return array The variation prices hash with the current exchange rate.
104
- */
105
- public function add_exchange_rate_to_variation_prices_hash( $prices_hash ) {
106
- $prices_hash[] = $this->get_product_price( 1 );
107
- return $prices_hash;
108
- }
109
-
110
- /**
111
- * Returns the shipping rates with their prices converted.
112
- * Creates new rate objects to avoid issues with extensions that cache
113
- * them before this hook is called.
114
- *
115
- * @param array $rates Shipping rates.
116
- *
117
- * @return array Shipping rates with converted costs.
118
- */
119
- public function convert_package_rates_prices( $rates ) {
120
- return array_map(
121
- function ( $rate ) {
122
- $rate = clone $rate;
123
- if ( $rate->cost ) {
124
- $rate->cost = $this->multi_currency->get_price( $rate->cost, 'shipping' );
125
- }
126
- if ( $rate->taxes ) {
127
- $rate->taxes = array_map(
128
- function ( $tax ) {
129
- return $this->multi_currency->get_price( $tax, 'tax' );
130
- },
131
- $rate->taxes
132
- );
133
- }
134
- return $rate;
135
- },
136
- $rates
137
- );
138
- }
139
-
140
- /**
141
- * Returns the amount for a coupon.
142
- *
143
- * @param mixed $amount The coupon's amount.
144
- * @param object $coupon The coupon object.
145
- *
146
- * @return mixed The converted coupon's amount.
147
- */
148
- public function get_coupon_amount( $amount, $coupon ) {
149
- $percent_coupon_types = [ 'percent' ];
150
-
151
- if ( ! $amount || $coupon->is_type( $percent_coupon_types ) ) {
152
- return $amount;
153
- }
154
-
155
- return $this->multi_currency->get_price( $amount, 'coupon' );
156
- }
157
-
158
- /**
159
- * Returns the min or max amount for a coupon.
160
- *
161
- * @param mixed $amount The coupon's min or max amount.
162
- *
163
- * @return mixed The converted coupon's min or max amount.
164
- */
165
- public function get_coupon_min_max_amount( $amount ) {
166
- if ( ! $amount ) {
167
- return $amount;
168
- }
169
-
170
- // Coupon mix/max prices are treated as products to avoid inconsistencies with charm pricing
171
- // making a coupon invalid when the coupon min/max amount is the same as the product's price.
172
- return $this->multi_currency->get_price( $amount, 'product' );
173
- }
174
-
175
- /**
176
- * Returns the free shipping zone settings with converted min_amount.
177
- *
178
- * @param array $data The shipping zone settings.
179
- *
180
- * @return array The shipping zone settings with converted min_amount.
181
- */
182
- public function get_free_shipping_min_amount( $data ) {
183
- if ( ! isset( $data['min_amount'] ) || ! $data['min_amount'] ) {
184
- return $data;
185
- }
186
-
187
- // Free shipping min amount is treated as products to avoid inconsistencies with charm pricing
188
- // making a method invalid when its min amount is the same as the product's price.
189
- $data['min_amount'] = $this->multi_currency->get_price( $data['min_amount'], 'product' );
190
- return $data;
191
- }
192
-
193
- /**
194
- * Register the hooks to set the min amount for free shipping methods.
195
- */
196
- public function register_free_shipping_filters() {
197
- $shipping_zones = \WC_Shipping_Zones::get_zones();
198
-
199
- $default_zone = \WC_Shipping_Zones::get_zone( 0 );
200
- if ( $default_zone ) {
201
- $shipping_zones[] = [ 'shipping_methods' => $default_zone->get_shipping_methods() ];
202
- }
203
-
204
- foreach ( $shipping_zones as $shipping_zone ) {
205
- foreach ( $shipping_zone['shipping_methods'] as $shipping_method ) {
206
- if ( 'free_shipping' === $shipping_method->id ) {
207
- $option_name = 'option_woocommerce_' . trim( $shipping_method->id ) . '_' . intval( $shipping_method->instance_id ) . '_settings';
208
- add_filter( $option_name, [ $this, 'get_free_shipping_min_amount' ], 50 );
209
- }
210
- }
211
- }
212
- }
213
-
214
- /**
215
- * Adds the exchange rate and default currency to the order's meta if prices have been converted.
216
- *
217
- * @param int $order_id The order ID.
218
- * @param WC_Order $order The order object.
219
- */
220
- public function add_order_meta( $order_id, $order ) {
221
- $default_currency = $this->multi_currency->get_default_currency();
222
-
223
- // Do not add exchange rate if order was made in the store's default currency.
224
- if ( $default_currency->get_code() === $order->get_currency() ) {
225
- return;
226
- }
227
-
228
- $exchange_rate = $this->multi_currency->get_price( 1, 'exchange_rate' );
229
-
230
- $order->update_meta_data( '_wcpay_multi_currency_order_exchange_rate', $exchange_rate );
231
- $order->update_meta_data( '_wcpay_multi_currency_order_default_currency', $default_currency->get_code() );
232
- $order->save_meta_data();
233
- }
234
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/class-multi-currency.php DELETED
@@ -1,526 +0,0 @@
1
- <?php
2
- /**
3
- * Class Multi_Currency
4
- *
5
- * @package WooCommerce\Payments\Multi_Currency
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- defined( 'ABSPATH' ) || exit;
11
-
12
- /**
13
- * Class that controls Multi Currency functionality.
14
- */
15
- class Multi_Currency {
16
-
17
- const CURRENCY_SESSION_KEY = 'wcpay_currency';
18
- const CURRENCY_META_KEY = 'wcpay_currency';
19
-
20
- /**
21
- * The plugin's ID.
22
- *
23
- * @var string
24
- */
25
- public $id = 'wcpay_multi_currency';
26
-
27
- /**
28
- * The single instance of the class.
29
- *
30
- * @var Multi_Currency
31
- */
32
- protected static $instance = null;
33
-
34
- /**
35
- * Frontend_Prices instance.
36
- *
37
- * @var Frontend_Prices
38
- */
39
- protected $frontend_prices;
40
-
41
- /**
42
- * Frontend_Currencies instance.
43
- *
44
- * @var Frontend_Currencies
45
- */
46
- protected $frontend_currencies;
47
-
48
- /**
49
- * The available currencies.
50
- *
51
- * @var array
52
- */
53
- protected $available_currencies;
54
-
55
- /**
56
- * The default currency.
57
- *
58
- * @var object
59
- */
60
- protected $default_currency;
61
-
62
- /**
63
- * The enabled currencies.
64
- *
65
- * @var array
66
- */
67
- protected $enabled_currencies;
68
-
69
- /**
70
- * Main Multi_Currency Instance.
71
- *
72
- * Ensures only one instance of Multi_Currency is loaded or can be loaded.
73
- *
74
- * @static
75
- * @return Multi_Currency - Main instance.
76
- */
77
- public static function instance() {
78
- if ( is_null( self::$instance ) ) {
79
- self::$instance = new self();
80
- }
81
- return self::$instance;
82
- }
83
-
84
- /**
85
- * Constructor.
86
- */
87
- private function __construct() {
88
- $this->includes();
89
- $this->init();
90
- }
91
-
92
- /**
93
- * Init.
94
- */
95
- public function init() {
96
- $this->initialize_available_currencies();
97
- $this->set_default_currency();
98
- $this->initialize_enabled_currencies();
99
-
100
- add_action( 'rest_api_init', [ $this, 'init_rest_api' ] );
101
- add_action( 'widgets_init', [ $this, 'init_widgets' ] );
102
-
103
- new User_Settings( $this );
104
-
105
- $this->frontend_prices = new Frontend_Prices( $this );
106
- $this->frontend_currencies = new Frontend_Currencies( $this );
107
-
108
- $is_frontend_request = ! is_admin() && ! defined( 'DOING_CRON' ) && ! WC()->is_rest_api_request();
109
-
110
- if ( $is_frontend_request ) {
111
- add_action( 'init', [ $this, 'update_selected_currency_by_url' ] );
112
- }
113
-
114
- add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
115
-
116
- if ( is_admin() ) {
117
- add_filter( 'woocommerce_get_settings_pages', [ $this, 'init_settings_pages' ] );
118
- add_action( 'admin_init', [ __CLASS__, 'add_woo_admin_notes' ] );
119
- }
120
- }
121
-
122
- /**
123
- * Initialize the REST API controller.
124
- */
125
- public function init_rest_api() {
126
- include_once WCPAY_ABSPATH . 'includes/multi-currency/class-wc-rest-controller.php';
127
-
128
- $api_controller = new WC_REST_Controller( \WC_Payments::create_api_client() );
129
- $api_controller->register_routes();
130
- }
131
-
132
- /**
133
- * Initialize the Widgets.
134
- */
135
- public function init_widgets() {
136
- register_widget( new Currency_Switcher_Widget( $this ) );
137
- }
138
-
139
- /**
140
- * Initialize the Settings Pages.
141
- *
142
- * @param array $settings_pages The settings pages.
143
- *
144
- * @return array The new settings pages.
145
- */
146
- public function init_settings_pages( $settings_pages ) {
147
- include_once WCPAY_ABSPATH . 'includes/multi-currency/class-settings.php';
148
-
149
- $settings_pages[] = new Settings( $this );
150
- return $settings_pages;
151
- }
152
-
153
- /**
154
- * Register the CSS and JS scripts.
155
- */
156
- public function register_scripts() {
157
- $script_src_url = plugins_url( 'dist/multi-currency.js', WCPAY_PLUGIN_FILE );
158
- $script_asset_path = WCPAY_ABSPATH . 'dist/multi-currency.asset.php';
159
- $script_asset = file_exists( $script_asset_path ) ? require_once $script_asset_path : [ 'dependencies' => [] ];
160
- wp_register_script(
161
- 'WCPAY_MULTI_CURRENCY_SETTINGS',
162
- $script_src_url,
163
- $script_asset['dependencies'],
164
- \WC_Payments::get_file_version( 'dist/multi-currency.js' ),
165
- true
166
- );
167
-
168
- wp_register_style(
169
- 'WCPAY_MULTI_CURRENCY_SETTINGS',
170
- plugins_url( 'dist/multi-currency.css', WCPAY_PLUGIN_FILE ),
171
- [ 'wc-components' ],
172
- \WC_Payments::get_file_version( 'dist/multi-currency.css' )
173
- );
174
- }
175
-
176
- /**
177
- * Load the assets.
178
- */
179
- public function enqueue_scripts() {
180
- global $current_tab, $current_section;
181
-
182
- $this->register_scripts();
183
-
184
- // TODO: Set this to only display when needed.
185
- // Output the settings JS and CSS only on the settings page.
186
- wp_enqueue_script( 'WCPAY_MULTI_CURRENCY_SETTINGS' );
187
- wp_enqueue_style( 'WCPAY_MULTI_CURRENCY_SETTINGS' );
188
- }
189
-
190
- /**
191
- * Gets the mock available.
192
- *
193
- * @return array Array of currencies.
194
- */
195
- public function get_mock_currencies() {
196
- return [
197
- [ 'CAD', 1.206823 ],
198
- [ 'GBP', 0.708099 ],
199
- [ 'EUR', 0.826381 ],
200
- [ 'AED', 3.6732 ],
201
- [ 'CDF', 2000 ],
202
- [ 'NZD', 1.387163 ],
203
- [ 'DKK', 6.144615 ],
204
- [ 'BIF', 1974 ], // Zero decimal currency.
205
- [ 'CLP', 706.8 ], // Zero decimal currency.
206
- ];
207
- }
208
-
209
- /**
210
- * Returns the Frontend_Prices instance.
211
- *
212
- * @return Frontend_Prices
213
- */
214
- public function get_frontend_prices() {
215
- return $this->frontend_prices;
216
- }
217
-
218
- /**
219
- * Returns the Frontend_Currencies instance.
220
- *
221
- * @return Frontend_Currencies
222
- */
223
- public function get_frontend_currencies() {
224
- return $this->frontend_currencies;
225
- }
226
-
227
- /**
228
- * Gets the currencies stored in the db.
229
- *
230
- * @return array Multi-dimensional array of currencies and rates.
231
- */
232
- private function get_stored_currencies(): array {
233
- $stored_currencies = get_option( $this->id . '_stored_currencies', false );
234
- if ( ! $stored_currencies ) {
235
- $stored_currencies = $this->get_mock_currencies();
236
- }
237
- return $stored_currencies;
238
- }
239
-
240
- /**
241
- * Sets up the available currencies, which are alphabetical by name.
242
- */
243
- private function initialize_available_currencies() {
244
- // Add default store currency with a rate of 1.0.
245
- $woocommerce_currency = get_woocommerce_currency();
246
- $this->available_currencies[ $woocommerce_currency ] = new Currency( $woocommerce_currency, 1.0 );
247
-
248
- $currencies = $this->get_stored_currencies();
249
- foreach ( $currencies as $currency ) {
250
- $new_currency = new Currency( $currency[0], $currency[1] );
251
- $available_currencies[ $new_currency->get_name() ] = $new_currency;
252
- }
253
-
254
- ksort( $available_currencies );
255
-
256
- foreach ( $available_currencies as $currency ) {
257
- $this->available_currencies[ $currency->get_code() ] = $currency;
258
- }
259
- }
260
-
261
- /**
262
- * Sets up the enabled currencies.
263
- */
264
- private function initialize_enabled_currencies() {
265
- $available_currencies = $this->get_available_currencies();
266
- $enabled_currency_codes = get_option( $this->id . '_enabled_currencies', [] );
267
- $default_code = $this->get_default_currency()->get_code();
268
- $enabled_currency_codes[] = $default_code;
269
-
270
- // This allows to keep the alphabetical sorting by name.
271
- $enabled_currencies = array_filter(
272
- $available_currencies,
273
- function( $currency ) use ( $enabled_currency_codes ) {
274
- return in_array( $currency->get_code(), $enabled_currency_codes, true );
275
- }
276
- );
277
-
278
- $this->enabled_currencies = [];
279
-
280
- foreach ( $enabled_currencies as $enabled_currency ) {
281
- // Get the charm and rounding for each enabled currency and add the currencies to the object property.
282
- $currency = clone $enabled_currency;
283
- $charm = get_option( $this->id . '_price_charm_' . $currency->get_id(), 0.00 );
284
- $rounding = get_option( $this->id . '_price_rounding_' . $currency->get_id(), 'none' );
285
- $currency->set_charm( $charm );
286
- $currency->set_rounding( $rounding );
287
-
288
- // If the currency is set to be manual, set the rate to the stored manual rate.
289
- $type = get_option( $this->id . '_exchange_rate_' . $currency->get_id(), 'automatic' );
290
- if ( 'manual' === $type ) {
291
- $manual_rate = get_option( $this->id . '_manual_rate_' . $currency->get_id(), $currency->get_rate() );
292
- $currency->set_rate( $manual_rate );
293
- }
294
-
295
- $this->enabled_currencies[ $currency->get_code() ] = $currency;
296
- }
297
-
298
- // Set default currency to the top of the list.
299
- $default[ $default_code ] = $this->enabled_currencies[ $default_code ];
300
- unset( $this->enabled_currencies[ $default_code ] );
301
- $this->enabled_currencies = array_merge( $default, $this->enabled_currencies );
302
- }
303
-
304
- /**
305
- * Sets the default currency.
306
- */
307
- private function set_default_currency() {
308
- $this->default_currency = $this->available_currencies[ get_woocommerce_currency() ] ?? null;
309
- }
310
-
311
- /**
312
- * Gets the currencies available.
313
- *
314
- * @return array Array of Currency objects.
315
- */
316
- public function get_available_currencies(): array {
317
- return $this->available_currencies;
318
- }
319
-
320
- /**
321
- * Gets the store base currency.
322
- *
323
- * @return Currency The store base currency.
324
- */
325
- public function get_default_currency(): Currency {
326
- return $this->default_currency;
327
- }
328
-
329
- /**
330
- * Gets the currently enabled currencies.
331
- *
332
- * @return array Array of Currency objects.
333
- */
334
- public function get_enabled_currencies(): array {
335
- return $this->enabled_currencies;
336
- }
337
-
338
- /**
339
- * Sets the enabled currencies for the store.
340
- *
341
- * @param array $currencies Array of currency codes to be enabled.
342
- */
343
- public function set_enabled_currencies( $currencies = [] ) {
344
- if ( 0 < count( $currencies ) ) {
345
- update_option( $this->id . '_enabled_currencies', $currencies );
346
- $this->initialize_enabled_currencies();
347
- }
348
- }
349
-
350
- /**
351
- * Gets the user selected currency, or `$default_currency` if is not set.
352
- *
353
- * @return Currency
354
- */
355
- public function get_selected_currency(): Currency {
356
- $user_id = get_current_user_id();
357
- $code = null;
358
-
359
- if ( 0 === $user_id && WC()->session ) {
360
- $code = WC()->session->get( self::CURRENCY_SESSION_KEY );
361
- } elseif ( $user_id ) {
362
- $code = get_user_meta( $user_id, self::CURRENCY_META_KEY, true );
363
- }
364
-
365
- return $this->get_enabled_currencies()[ $code ] ?? $this->default_currency;
366
- }
367
-
368
- /**
369
- * Update the selected currency from a currency code.
370
- *
371
- * @param string $currency_code Three letter currency code.
372
- * @return void
373
- */
374
- public function update_selected_currency( string $currency_code ) {
375
- $code = strtoupper( $currency_code );
376
- $user_id = get_current_user_id();
377
- $currency = $this->get_enabled_currencies()[ $code ] ?? null;
378
-
379
- if ( null === $currency ) {
380
- return;
381
- }
382
-
383
- if ( 0 === $user_id && WC()->session ) {
384
- WC()->session->set( self::CURRENCY_SESSION_KEY, $currency->get_code() );
385
- // Set the session cookie if is not yet to persist the selected currency.
386
- if ( ! WC()->session->has_session() && ! headers_sent() ) {
387
- WC()->session->set_customer_session_cookie( true );
388
- }
389
- } elseif ( $user_id ) {
390
- update_user_meta( $user_id, self::CURRENCY_META_KEY, $currency->get_code() );
391
- }
392
-
393
- // Recalculate cart when currency changes.
394
- if ( did_action( 'wp_loaded' ) ) {
395
- $this->recalculate_cart();
396
- } else {
397
- add_action( 'wp_loaded', [ $this, 'recalculate_cart' ] );
398
- }
399
- }
400
-
401
- /**
402
- * Update the selected currency from url param `currency`.
403
- *
404
- * @return void
405
- */
406
- public function update_selected_currency_by_url() {
407
- if ( ! isset( $_GET['currency'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
408
- return;
409
- }
410
-
411
- $this->update_selected_currency( sanitize_text_field( wp_unslash( $_GET['currency'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification
412
- }
413
-
414
- /**
415
- * Recalculates WooCommerce cart totals.
416
- */
417
- public function recalculate_cart() {
418
- WC()->cart->calculate_totals();
419
- }
420
-
421
- /**
422
- * Gets the configured value for apply charm pricing only to products.
423
- *
424
- * @return bool The configured value.
425
- */
426
- public function get_apply_charm_only_to_products() {
427
- return apply_filters( 'wcpay_multi_currency_apply_charm_only_to_products', true );
428
- }
429
-
430
- /**
431
- * Gets the converted price using the current currency with the rounding and charm pricing settings.
432
- *
433
- * @param mixed $price The price to be converted.
434
- * @param bool $type The type of price being converted. One of 'product', 'shipping', 'tax', 'coupon', or 'exchange_rate'.
435
- *
436
- * @return float The converted price.
437
- */
438
- public function get_price( $price, $type ): float {
439
- $supported_types = [ 'product', 'shipping', 'tax', 'coupon', 'exchange_rate' ];
440
- $currency = $this->get_selected_currency();
441
-
442
- if ( ! in_array( $type, $supported_types, true ) || $currency->get_is_default() ) {
443
- return (float) $price;
444
- }
445
-
446
- $converted_price = ( (float) $price ) * $currency->get_rate();
447
-
448
- if ( 'tax' === $type || 'coupon' === $type || 'exchange_rate' === $type ) {
449
- return $converted_price;
450
- }
451
-
452
- $charm_compatible_types = [ 'product', 'shipping' ];
453
- $apply_charm_pricing = $this->get_apply_charm_only_to_products()
454
- ? 'product' === $type
455
- : in_array( $type, $charm_compatible_types, true );
456
-
457
- return $this->get_adjusted_price( $converted_price, $apply_charm_pricing, $currency );
458
- }
459
-
460
- /**
461
- * Gets the price after adjusting it with the rounding and charm settings.
462
- *
463
- * @param float $price The price to be adjusted.
464
- * @param bool $apply_charm_pricing Whether charm pricing should be applied.
465
- * @param Currency $currency The currency to be used when adjusting.
466
- *
467
- * @return float The adjusted price.
468
- */
469
- protected function get_adjusted_price( $price, $apply_charm_pricing, $currency ): float {
470
- if ( 'none' !== $currency->get_rounding() ) {
471
- $price = $this->ceil_price( $price, intval( $currency->get_rounding() ) );
472
- }
473
-
474
- if ( $apply_charm_pricing ) {
475
- $price += floatval( $currency->get_charm() );
476
- }
477
-
478
- // Do not return negative prices (possible because of $currency->get_charm()).
479
- return max( 0, $price );
480
- }
481
-
482
- /**
483
- * Ceils the price to the next number based on the precision.
484
- *
485
- * @param float $price The price to be ceiled.
486
- * @param int $precision The precision to be used.
487
- *
488
- * @return float The ceiled price.
489
- */
490
- protected function ceil_price( $price, $precision ) {
491
- $precision_modifier = pow( 10, $precision );
492
- return ceil( $price * $precision_modifier ) / $precision_modifier;
493
- }
494
-
495
- /**
496
- * Include required core files used in admin and on the frontend.
497
- */
498
- protected function includes() {
499
- include_once WCPAY_ABSPATH . 'includes/multi-currency/class-currency.php';
500
- include_once WCPAY_ABSPATH . 'includes/multi-currency/class-currency-switcher-widget.php';
501
- include_once WCPAY_ABSPATH . 'includes/multi-currency/class-country-flags.php';
502
- include_once WCPAY_ABSPATH . 'includes/multi-currency/class-frontend-prices.php';
503
- include_once WCPAY_ABSPATH . 'includes/multi-currency/class-frontend-currencies.php';
504
- include_once WCPAY_ABSPATH . 'includes/multi-currency/class-user-settings.php';
505
- }
506
-
507
- /**
508
- * Adds Multi-Currency notes to the WC-Admin inbox.
509
- */
510
- public static function add_woo_admin_notes() {
511
- if ( defined( 'WC_VERSION' ) && version_compare( WC_VERSION, '4.4.0', '>=' ) ) {
512
- require_once WCPAY_ABSPATH . 'includes/multi-currency/notes/class-note-multi-currency-available.php';
513
- Note_Multi_Currency_Available::possibly_add_note();
514
- }
515
- }
516
-
517
- /**
518
- * Removes Multi-Currency notes from the WC-Admin inbox.
519
- */
520
- public static function remove_woo_admin_notes() {
521
- if ( defined( 'WC_VERSION' ) && version_compare( WC_VERSION, '4.4.0', '>=' ) ) {
522
- require_once WCPAY_ABSPATH . 'includes/multi-currency/notes/class-note-multi-currency-available.php';
523
- Note_Multi_Currency_Available::possibly_delete_note();
524
- }
525
- }
526
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/class-settings.php DELETED
@@ -1,429 +0,0 @@
1
- <?php
2
- /**
3
- * WooCommerce Payments Multi-currency Settings
4
- *
5
- * @package WooCommerce\Admin
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- use WCPay\Multi_Currency\Currency;
11
-
12
- defined( 'ABSPATH' ) || exit;
13
-
14
- /**
15
- * Settings.
16
- */
17
- class Settings extends \WC_Settings_Page {
18
-
19
- /**
20
- * The id of the plugin.
21
- *
22
- * @var string
23
- */
24
- public $id;
25
-
26
- /**
27
- * The tab label.
28
- *
29
- * @var string
30
- */
31
- public $label;
32
-
33
- /**
34
- * Instance of Multi_Currency class.
35
- *
36
- * @var Multi_Currency
37
- */
38
- protected $multi_currency;
39
-
40
- /**
41
- * Constructor.
42
- *
43
- * @param Multi_Currency $multi_currency The Multi_Currency instance.
44
- */
45
- public function __construct( Multi_Currency $multi_currency ) {
46
- $this->multi_currency = $multi_currency;
47
- $this->id = $this->multi_currency->id;
48
- $this->label = _x( 'Multi-currency', 'Settings tab label', 'woocommerce-payments' );
49
-
50
- add_action( 'woocommerce_admin_field_wcpay_enabled_currencies_list', [ $this, 'enabled_currencies_list' ] );
51
- add_action( 'woocommerce_admin_field_wcpay_currencies_settings_section_start', [ $this, 'currencies_settings_section_start' ] );
52
- add_action( 'woocommerce_admin_field_wcpay_currencies_settings_section_end', [ $this, 'currencies_settings_section_end' ] );
53
-
54
- add_action( 'woocommerce_admin_field_wcpay_single_currency_preview_helper', [ $this, 'single_currency_preview_helper' ] );
55
- parent::__construct();
56
- }
57
-
58
- /**
59
- * Get sections.
60
- *
61
- * @return array
62
- */
63
- public function get_sections() {
64
- return apply_filters(
65
- 'woocommerce_get_sections_' . $this->id,
66
- [
67
- '' => __( 'Currencies', 'woocommerce-payments' ),
68
- ]
69
- );
70
- }
71
-
72
- /**
73
- * Get settings array.
74
- *
75
- * @param string $current_section Section being shown.
76
- * @return array
77
- */
78
- public function get_settings( $current_section = '' ) {
79
- $settings = [];
80
-
81
- if ( '' === $current_section ) {
82
- $settings = apply_filters(
83
- $this->id . '_enabled_currencies_settings',
84
- [
85
- [
86
- 'title' => __( 'Enabled currencies', 'woocommerce-payments' ),
87
- // TODO: Learn more link needed.
88
- 'desc' => sprintf(
89
- /* translators: %s: url to documentation. */
90
- __( 'Accept payments in multiple currencies. Prices are converted based on exchange rates and rounding rules, and include conversion fees. <a href="%s">Learn more</a>', 'woocommerce-payments' ),
91
- ''
92
- ),
93
- 'type' => 'title',
94
- 'id' => $this->id . '_enabled_currencies',
95
- ],
96
-
97
- [
98
- 'type' => 'wcpay_enabled_currencies_list',
99
- ],
100
-
101
- [
102
- 'type' => 'sectionend',
103
- 'id' => $this->id . '_enabled_currencies',
104
- ],
105
-
106
- [
107
- 'type' => 'wcpay_currencies_settings_section_start',
108
- ],
109
-
110
- [
111
- 'title' => __( 'Store settings', 'woocommerce-payments' ),
112
- // TODO: Learn more documentation link, to be done on #1780.
113
- 'desc' => sprintf(
114
- /* translators: %s: url to documentation. */
115
- __( 'Store settings allow your customers to choose which currency they would like to use when shopping at your store. <a href="%s">Learn more</a>', 'woocommerce-payments' ),
116
- ''
117
- ),
118
- 'type' => 'title',
119
- 'id' => $this->id . '_store_settings',
120
- 'class' => $this->id . '_store_settings_input',
121
- ],
122
-
123
- [
124
- 'title' => __( 'Store settings', 'woocommerce-payments' ),
125
- 'desc' => __( 'Automatically switch customers to the local currency if it is enabled above.', 'woocommerce-payments' ),
126
- // TODO: Preview link, to be done on #2258.
127
- 'desc_tip' => sprintf(
128
- /* translators: %s: url to a preview of alert banner */
129
- __( 'Customers will be notified via store alert banner. <a href="%s">Preview</a>', 'woocommerce-payments' ),
130
- ''
131
- ),
132
- 'id' => $this->id . '_enable_auto_currency',
133
- 'default' => 'yes',
134
- 'type' => 'checkbox',
135
- 'checkboxgroup' => 'start',
136
- ],
137
-
138
- [
139
- 'desc' => __( 'Add a currency switcher to the cart widget', 'woocommerce-payments' ),
140
- 'desc_tip' => sprintf(
141
- /* translators: %s: url to the widgets page */
142
- __( 'A currency switcher is also available in your widgets. <a href="%s">Configure now</a>', 'woocommerce-payments' ),
143
- 'widgets.php'
144
- ),
145
- 'id' => $this->id . '_enable_cart_switcher',
146
- 'default' => 'yes',
147
- 'type' => 'checkbox',
148
- 'checkboxgroup' => 'end',
149
- ],
150
-
151
- [
152
- 'type' => 'sectionend',
153
- 'id' => $this->id . 'store_settings',
154
- ],
155
-
156
- [
157
- 'type' => 'wcpay_currencies_settings_section_end',
158
- ],
159
- ]
160
- );
161
- } else {
162
- $settings = $this->get_currency_setting( $this->multi_currency->get_enabled_currencies()[ strtoupper( $current_section ) ] );
163
- }
164
-
165
- return apply_filters( 'woocommerce_get_settings_' . $this->id, $settings, $current_section );
166
- }
167
-
168
- /**
169
- * Output the settings.
170
- */
171
- public function output() {
172
- global $current_section;
173
-
174
- $settings = $this->get_settings( $current_section );
175
- \WC_Admin_Settings::output_fields( $settings );
176
- }
177
-
178
- /**
179
- * Output container for enabled currencies list.
180
- */
181
- public function enabled_currencies_list() {
182
- ?>
183
- <tr valign="top">
184
- <td class="wcpay_enabled_currencies_wrapper">
185
- <div id="wcpay_enabled_currencies_list" aria-describedby="wcpay_enabled_currencies-description"></div>
186
- </td>
187
- </tr>
188
- <?php
189
- }
190
-
191
- /**
192
- * Output section start for store settings.
193
- */
194
- public function currencies_settings_section_start() {
195
- ?>
196
- <div id="wcpay_currencies_settings_section" style="display: none;">
197
- <?php
198
- }
199
-
200
- /**
201
- * Output section end for store settings.
202
- */
203
- public function currencies_settings_section_end() {
204
- ?>
205
- </div>
206
- <?php
207
- }
208
-
209
- /**
210
- * Output hidden fields for preview.
211
- */
212
- public function single_currency_preview_helper() {
213
- global $current_section;
214
- $available_currencies = $this->multi_currency->get_available_currencies();
215
- $currency = $available_currencies[ strtoupper( $current_section ) ];
216
- $default_currency = $this->multi_currency->get_default_currency();
217
-
218
- ?>
219
- <tr valign="top">
220
- <th scope="row" class="titledesc">
221
- <label for="wcpay_multi_currency_preview_default"><?php echo esc_html( $default_currency->get_name() ); ?></label>
222
- </th>
223
- <td class="forminp forminp-text">
224
- <span style="line-height:30px"><?php echo esc_html( $default_currency->get_symbol() ); ?></span>
225
- <input name="wcpay_multi_currency_preview_default" id="wcpay_multi_currency_preview_default" type="text" value="20.00" placeholder="20.00">
226
- </td>
227
- </tr>
228
- <tr valign="top">
229
- <th scope="row" class="titledesc">
230
- <label for="wcpay_multi_currency_preview_converted"><?php echo esc_html( $currency->get_name() ); ?></label>
231
- </th>
232
- <td>
233
- <div id="wcpay_multi_currency_preview_converted">
234
- <?php echo esc_html( $currency->get_symbol() ); ?>
235
- <span style="display:inline-block;"></span>
236
- </div>
237
- <input type="hidden"
238
- name="<?php echo esc_attr( $this->id . '_automatic_exchange_rate' ); ?>"
239
- value="<?php echo esc_attr( $available_currencies[ $currency->get_code() ]->get_rate() ); ?>"
240
- />
241
- </td>
242
- </tr>
243
- <?php
244
- }
245
-
246
-
247
-
248
- /**
249
- * Returns the settings for the single currency.
250
- *
251
- * @param Currency $currency The currency object we're getting settings for.
252
- *
253
- * @return array Array of settings.
254
- */
255
- public function get_currency_setting( $currency ) {
256
- $available_currencies = $this->multi_currency->get_available_currencies();
257
- $default_currency = $this->multi_currency->get_default_currency();
258
- $page_id = $this->id . '_single_currency';
259
-
260
- $exchange_rate_options = [
261
- 'automatic' => sprintf(
262
- /* translators: %1$s: default currency rate, %2$s: new currency exchange rate, %3$s: time rates were last updated. */
263
- __( 'Fetch rate automatically. Current rate: %1$s = %2$s (Last updated %3$s)', 'woocommerce-payments' ),
264
- '1 ' . $default_currency->get_code(),
265
- $available_currencies[ $currency->get_code() ]->get_rate() . ' ' . $currency->get_code(),
266
- // TODO: Proper timestamp needed from API data.
267
- '12:00 UTC'
268
- ),
269
- 'manual' => __( 'Manual rate. Enter your own fixed rate of exchange.', 'woocommerce-payments' ),
270
- ];
271
-
272
- $rounding_desc = sprintf(
273
- /* translators: %1$s currency being converted to, %2$s url to documentation. */
274
- __( 'Make your %1$s prices consistent by rounding them up after they are converted. <a href="%2$s">Learn more</a>', 'woocommerce-payments' ),
275
- $currency->get_code(),
276
- // TODO: Url to documentation needed.
277
- ''
278
- );
279
-
280
- $rounding_options = apply_filters(
281
- $this->id . '_price_rounding_options',
282
- [
283
- 'none' => __( 'None', 'woocommerce-payments' ),
284
- '-1' => '10.00',
285
- '0' => '1.00 (recommended)',
286
- '1' => '0.10',
287
- ]
288
- );
289
-
290
- $charm_desc = sprintf(
291
- /* translators: %s: url to documentation.*/
292
- __( 'Reduce the converted price by a specific amount. <a href="%s">Learn more</a>', 'woocommerce-payments' ),
293
- // TODO: Url to documentation needed.
294
- ''
295
- );
296
-
297
- $charm_options = apply_filters(
298
- $this->id . '_charm_options',
299
- [
300
- '0.00' => __( 'None', 'woocommerce-payments' ),
301
- '-0.01' => __( '-0.01 (recommended)', 'woocommerce-payments' ),
302
- '-0.05' => '-0.05',
303
- ]
304
- );
305
-
306
- $preview_desc = sprintf(
307
- /* translators: %1$s: default currency of the store, %2$s currency being converted to. */
308
- __( 'Enter a price in your default currency of %1$s to see it converted into %2$s using the excange rate and formatting rules above.', 'woocommerce-payments' ),
309
- $default_currency->get_code(),
310
- $currency->get_code()
311
- );
312
-
313
- // Output breadcrumbs.
314
- ?>
315
- <h2>
316
- <a href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings&tab=wcpay_multi_currency' ) ); ?>"><?php esc_html_e( 'Currencies', 'woocommerce-payments' ); ?></a> &gt; <?php echo esc_html( "{$currency->get_name()} ({$currency->get_code()}) {$currency->get_flag()}" ); ?>
317
- </h2>
318
- <?php
319
-
320
- return apply_filters(
321
- $this->id . '_single_settings',
322
- [
323
- [
324
- 'type' => 'title',
325
- 'id' => $page_id,
326
- ],
327
-
328
- [
329
- 'title' => __( 'Exchange rate', 'woocommerce-payments' ),
330
- 'id' => $this->id . '_exchange_rate_' . $currency->get_id(),
331
- 'class' => 'exchange-rate-selector',
332
- 'default' => 'automatic',
333
- 'type' => 'radio',
334
- 'options' => $exchange_rate_options,
335
- ],
336
-
337
- [
338
- 'title' => __( 'Manual rate', 'woocommerce-payments' ),
339
- 'type' => 'text',
340
- 'id' => $this->id . '_manual_rate_' . $currency->get_id(),
341
- 'class' => 'input-text regular-input',
342
- 'default' => $currency->get_rate(),
343
- 'desc' => __( 'Enter the manual rate you would like to use. Must be a positive number.', 'woocommerce-payments' ),
344
- 'desc_tip' => true,
345
- 'custom_attributes' => [
346
- 'pattern' => '[0-9]*(\.[0-9]+)?',
347
- ],
348
- ],
349
-
350
- [
351
- 'type' => 'sectionend',
352
- 'id' => $page_id,
353
- ],
354
-
355
- [
356
- 'title' => __( 'Formatting rules', 'woocommerce-payments' ),
357
- 'type' => 'title',
358
- 'id' => $page_id . '_formatting_rules',
359
- ],
360
-
361
- [
362
- 'title' => __( 'Price rounding', 'woocommerce-payments' ),
363
- 'desc' => $rounding_desc,
364
- 'id' => $this->id . '_price_rounding_' . $currency->get_id(),
365
- 'default' => 'none',
366
- 'type' => 'select',
367
- 'options' => $rounding_options,
368
- 'desc_tip' => __( 'Conversion rates at the bank may differ from current conversion rates. Rounding up to the nearest whole number helps prevent losses on sales.', 'woocommerce-payments' ),
369
- ],
370
-
371
- [
372
- 'title' => __( 'Charm pricing', 'woocommerce-payments' ),
373
- 'desc' => $charm_desc,
374
- 'id' => $this->id . '_price_charm_' . $currency->get_id(),
375
- 'default' => '0.00',
376
- 'type' => 'select',
377
- 'options' => $charm_options,
378
- 'desc_tip' => __( 'A value of -0.01 would reduce 20.00 to 19.99.', 'woocommerce-payments' ),
379
- ],
380
-
381
- [
382
- 'type' => 'sectionend',
383
- 'id' => $page_id . '_formatting_rules',
384
- ],
385
-
386
- [
387
- 'name' => __( 'Preview', 'woocommerce-payments' ),
388
- 'type' => 'title',
389
- 'desc' => $preview_desc,
390
- 'id' => $page_id . '_preview',
391
- ],
392
-
393
- [
394
- 'type' => 'wcpay_single_currency_preview_helper',
395
- ],
396
-
397
- [
398
- 'type' => 'sectionend',
399
- 'id' => $page_id . '_preview',
400
- ],
401
- ]
402
- );
403
- }
404
-
405
- /**
406
- * Save settings.
407
- */
408
- public function save() {
409
- global $current_section;
410
-
411
- // Save all settings through the settings API.
412
- \WC_Admin_Settings::save_fields( $this->get_settings( $current_section ) );
413
-
414
- // If we are saving the settings for an individual currency, we have some additional logic.
415
- if ( '' !== $current_section ) {
416
- // If the manual rate was blank, or zero, we set it to the automatic rate.
417
- $manual_rate = get_option( $this->id . '_manual_rate_' . $current_section, false );
418
- if ( ! $manual_rate || 0 >= $manual_rate || '' === $manual_rate ) {
419
- $available_currencies = $this->multi_currency->get_available_currencies();
420
- $selected_currency = strtoupper( $current_section );
421
- if ( isset( $available_currencies[ $selected_currency ] ) ) {
422
- update_option( $this->id . '_manual_rate_' . $current_section, $available_currencies[ $selected_currency ]->get_rate() );
423
- }
424
- }
425
- }
426
-
427
- do_action( 'woocommerce_update_options_' . $this->id );
428
- }
429
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/class-user-settings.php DELETED
@@ -1,77 +0,0 @@
1
- <?php
2
- /**
3
- * WooCommerce Payments Multi Currency User Settings
4
- *
5
- * @package WooCommerce\Payments
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- defined( 'ABSPATH' ) || exit;
11
-
12
- /**
13
- * Class that add Multi Currency settings to user my account page.
14
- */
15
- class User_Settings {
16
-
17
- /**
18
- * Multi-Currency instance.
19
- *
20
- * @var Multi_Currency
21
- */
22
- protected $multi_currency;
23
-
24
- /**
25
- * Constructor.
26
- *
27
- * @param Multi_Currency $multi_currency The Multi_Currency instance.
28
- */
29
- public function __construct( Multi_Currency $multi_currency ) {
30
- $this->multi_currency = $multi_currency;
31
-
32
- add_action( 'woocommerce_edit_account_form', [ $this, 'add_presentment_currency_switch' ] );
33
- add_action( 'woocommerce_save_account_details', [ $this, 'save_presentment_currency' ] );
34
- }
35
-
36
- /**
37
- * Add a select to allow user choose default currency in `my account > account details`.
38
- *
39
- * @return void
40
- */
41
- public function add_presentment_currency_switch() {
42
- ?>
43
- <p class="woocommerce-form-row woocommerce-form-row--first form-row form-row-first">
44
- <label for="wcpay_selected_currency"><?php esc_html_e( 'Default currency', 'woocommerce-payments' ); ?></label>
45
- <select
46
- name="wcpay_selected_currency"
47
- id="wcpay_selected_currency"
48
- >
49
- <?php
50
- foreach ( $this->multi_currency->get_enabled_currencies() as $currency ) {
51
- $code = $currency->get_code();
52
- $symbol = $currency->get_symbol();
53
- $selected = $this->multi_currency->get_selected_currency()->code === $code ? ' selected' : '';
54
-
55
- echo "<option value=\"$code\"$selected>$symbol $code</option>"; // phpcs:ignore WordPress.Security.EscapeOutput
56
- }
57
- ?>
58
- </select>
59
- <span><em><?php esc_html_e( 'Select your preferred currency for shopping and payments.', 'woocommerce-payments' ); ?></em></span>
60
- </p>
61
- <div class="clear"></div>
62
- <?php
63
- }
64
-
65
- /**
66
- * Hook into save account details to capture the new value `wcpay_selected_currency` and persist it.
67
- *
68
- * @return void
69
- */
70
- public function save_presentment_currency() {
71
- if ( isset( $_POST['wcpay_selected_currency'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
72
- $currency_code = wc_clean( wp_unslash( $_POST['wcpay_selected_currency'] ) ); // phpcs:ignore WordPress.Security.NonceVerification
73
- $this->multi_currency->update_selected_currency( $currency_code );
74
- }
75
- }
76
-
77
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/class-wc-rest-controller.php DELETED
@@ -1,70 +0,0 @@
1
- <?php
2
- /**
3
- * Class WC_REST_Controller
4
- *
5
- * @package WooCommerce\Payments\Multi_Currency
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- defined( 'ABSPATH' ) || exit;
11
-
12
- /**
13
- * REST controller for multi-currency.
14
- */
15
- class WC_REST_Controller extends \WC_Payments_REST_Controller {
16
-
17
- /**
18
- * Endpoint path.
19
- *
20
- * @var string
21
- */
22
- protected $rest_base = 'payments/multi-currency';
23
-
24
- /**
25
- * Configure REST API routes.
26
- */
27
- public function register_routes() {
28
- register_rest_route(
29
- $this->namespace,
30
- '/' . $this->rest_base . '/currencies',
31
- [
32
- 'methods' => \WP_REST_Server::READABLE,
33
- 'callback' => [ $this, 'get_store_currencies' ],
34
- 'permission_callback' => [ $this, 'check_permission' ],
35
- ]
36
- );
37
-
38
- register_rest_route(
39
- $this->namespace,
40
- '/' . $this->rest_base . '/update-enabled-currencies',
41
- [
42
- 'methods' => \WP_REST_Server::CREATABLE,
43
- 'callback' => [ $this, 'update_enabled_currencies' ],
44
- 'permission_callback' => [ $this, 'check_permission' ],
45
- ]
46
- );
47
- }
48
-
49
- /**
50
- * Retrieve currencies for the store.
51
- */
52
- public function get_store_currencies() {
53
- return [
54
- 'available' => WC_Payments_Multi_Currency()->get_available_currencies(),
55
- 'enabled' => WC_Payments_Multi_Currency()->get_enabled_currencies(),
56
- 'default' => WC_Payments_Multi_Currency()->get_default_currency(),
57
- ];
58
- }
59
-
60
- /**
61
- * Update enabled currencies based on posted data.
62
- *
63
- * @param WP_REST_Request $request Full data about the request.
64
- */
65
- public function update_enabled_currencies( $request ) {
66
- $params = $request->get_params();
67
- WC_Payments_Multi_Currency()->set_enabled_currencies( $params['enabled'] );
68
- return $this->get_store_currencies();
69
- }
70
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/notes/NoteMultiCurrencyAvailable.php DELETED
@@ -1,54 +0,0 @@
1
- <?php
2
- /**
3
- * Notify merchant that Multi-Currency is available.
4
- *
5
- * @package WooCommerce\Payments\MultiCurrency
6
- */
7
-
8
- namespace WCPay\MultiCurrency\Notes;
9
-
10
- use Automattic\WooCommerce\Admin\Notes\NoteTraits;
11
-
12
- defined( 'ABSPATH' ) || exit;
13
-
14
- /**
15
- * Class NoteMultiCurrencyAvailable
16
- */
17
- class NoteMultiCurrencyAvailable {
18
- use NoteTraits;
19
-
20
- /**
21
- * Name of the note for use in the database.
22
- */
23
- const NOTE_NAME = 'wc-payments-notes-multi-currency-available';
24
-
25
- /**
26
- * Url to start the setup process.
27
- */
28
- // TODO: Proper url needed for setup process.
29
- const NOTE_SETUP_URL = 'admin.php?page=wc-settings&tab=wcpay_multi_currency';
30
-
31
- /**
32
- * Get the note.
33
- */
34
- public static function get_note() {
35
- $note_class = \WC_Payment_Woo_Compat_Utils::get_note_class();
36
- $note = new $note_class();
37
-
38
- $note->set_title( __( 'Sell worldwide in multiple currencies', 'woocommerce-payments' ) );
39
- $note->set_content( __( 'Boost your international sales by allowing your customers to shop and pay in their local currency.', 'woocommerce-payments' ) );
40
- $note->set_content_data( (object) [] );
41
- $note->set_type( $note_class::E_WC_ADMIN_NOTE_INFORMATIONAL );
42
- $note->set_name( self::NOTE_NAME );
43
- $note->set_source( 'woocommerce-payments' );
44
- $note->add_action(
45
- self::NOTE_NAME,
46
- __( 'Set up now', 'woocommerce-payments' ),
47
- self::NOTE_SETUP_URL,
48
- 'unactioned',
49
- true
50
- );
51
-
52
- return $note;
53
- }
54
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
includes/multi-currency/notes/class-note-multi-currency-available.php DELETED
@@ -1,54 +0,0 @@
1
- <?php
2
- /**
3
- * Notify merchant that Multi-Currency is available.
4
- *
5
- * @package WooCommerce\Payments\Multi_Currency
6
- */
7
-
8
- namespace WCPay\Multi_Currency;
9
-
10
- use Automattic\WooCommerce\Admin\Notes\NoteTraits;
11
-
12
- defined( 'ABSPATH' ) || exit;
13
-
14
- /**
15
- * Class Note_Multi_Currency_Available
16
- */
17
- class Note_Multi_Currency_Available {
18
- use NoteTraits;
19
-
20
- /**
21
- * Name of the note for use in the database.
22
- */
23
- const NOTE_NAME = 'wc-payments-notes-multi-currency-available';
24
-
25
- /**
26
- * Url to start the setup process.
27
- */
28
- // TODO: Proper url needed for setup process.
29
- const NOTE_SETUP_URL = 'admin.php?page=wc-settings&tab=wcpay_multi_currency';
30
-
31
- /**
32
- * Get the note.
33
- */
34
- public static function get_note() {
35
- $note_class = \WC_Payment_Woo_Compat_Utils::get_note_class();
36
- $note = new $note_class();
37
-
38
- $note->set_title( __( 'Sell worldwide in multiple currencies', 'woocommerce-payments' ) );
39
- $note->set_content( __( 'Boost your international sales by allowing your customers to shop and pay in their local currency.', 'woocommerce-payments' ) );
40
- $note->set_content_data( (object) [] );
41
- $note->set_type( $note_class::E_WC_ADMIN_NOTE_INFORMATIONAL );
42
- $note->set_name( self::NOTE_NAME );
43
- $note->set_source( 'woocommerce-payments' );
44
- $note->add_action(
45
- self::NOTE_NAME,
46
- __( 'Set up now', 'woocommerce-payments' ),
47
- self::NOTE_SETUP_URL,
48
- 'unactioned',
49
- true
50
- );
51
-
52
- return $note;
53
- }
54
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
languages/woocommerce-payments.pot CHANGED
@@ -2,10 +2,10 @@
2
  # This file is distributed under the same license as the WooCommerce Payments package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: WooCommerce Payments 2.7.0\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/woocommerce-payments\n"
8
- "POT-Creation-Date: 2021-07-14 14:11:24+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
2
  # This file is distributed under the same license as the WooCommerce Payments package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: WooCommerce Payments 2.7.1\n"
6
  "Report-Msgid-Bugs-To: "
7
  "https://wordpress.org/support/plugin/woocommerce-payments\n"
8
+ "POT-Creation-Date: 2021-07-26 18:26:34+00:00\n"
9
  "MIME-Version: 1.0\n"
10
  "Content-Type: text/plain; charset=utf-8\n"
11
  "Content-Transfer-Encoding: 8bit\n"
readme.txt CHANGED
@@ -4,7 +4,7 @@ Tags: woocommerce, payment, payment request, credit card, automattic
4
  Requires at least: 5.5
5
  Tested up to: 5.7
6
  Requires PHP: 7.0
7
- Stable tag: 2.7.0
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
@@ -101,6 +101,10 @@ Please note that our support for the checkout block is still experimental and th
101
 
102
  == Changelog ==
103
 
 
 
 
 
104
  = 2.7.0 - 2021-07-14 =
105
  * Add - Add a link to the snackbar notice that appears after submitting or saving evidence for a dispute challenge.
106
  * Add - Support saving new cards and paying with previously saved cards in the WooCommerce Checkout Block.
4
  Requires at least: 5.5
5
  Tested up to: 5.7
6
  Requires PHP: 7.0
7
+ Stable tag: 2.7.1
8
  License: GPLv2 or later
9
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
10
 
101
 
102
  == Changelog ==
103
 
104
+ = 2.7.1 - 2021-07-26 =
105
+ * Fix - Ensure test mode setting value is correctly saved.
106
+ * Fix - Onboarding redirection occasionally not finalizing account connection.
107
+
108
  = 2.7.0 - 2021-07-14 =
109
  * Add - Add a link to the snackbar notice that appears after submitting or saving evidence for a dispute challenge.
110
  * Add - Support saving new cards and paying with previously saved cards in the WooCommerce Checkout Block.
vendor/autoload.php CHANGED
@@ -4,4 +4,4 @@
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
- return ComposerAutoloaderInit2c751694e0f0d8de65372ae58e93d526::getLoader();
4
 
5
  require_once __DIR__ . '/composer/autoload_real.php';
6
 
7
+ return ComposerAutoloaderInit974fe5222c9810d6a67ef89f12533413::getLoader();
vendor/autoload_packages.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/composer/InstalledVersions.php CHANGED
@@ -30,7 +30,7 @@ private static $installed = array (
30
  'aliases' =>
31
  array (
32
  ),
33
- 'reference' => 'ca0d60fdabdc9501c165fc8b423b23bc629043dd',
34
  'name' => 'woocommerce/payments',
35
  ),
36
  'versions' =>
@@ -150,7 +150,7 @@ private static $installed = array (
150
  'aliases' =>
151
  array (
152
  ),
153
- 'reference' => 'ca0d60fdabdc9501c165fc8b423b23bc629043dd',
154
  ),
155
  ),
156
  );
30
  'aliases' =>
31
  array (
32
  ),
33
+ 'reference' => '8b3f219f61219ca117cd1363a2c714ec93729aee',
34
  'name' => 'woocommerce/payments',
35
  ),
36
  'versions' =>
150
  'aliases' =>
151
  array (
152
  ),
153
+ 'reference' => '8b3f219f61219ca117cd1363a2c714ec93729aee',
154
  ),
155
  ),
156
  );
vendor/composer/autoload_real.php CHANGED
@@ -2,7 +2,7 @@
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
- class ComposerAutoloaderInit2c751694e0f0d8de65372ae58e93d526
6
  {
7
  private static $loader;
8
 
@@ -24,15 +24,15 @@ class ComposerAutoloaderInit2c751694e0f0d8de65372ae58e93d526
24
 
25
  require __DIR__ . '/platform_check.php';
26
 
27
- spl_autoload_register(array('ComposerAutoloaderInit2c751694e0f0d8de65372ae58e93d526', 'loadClassLoader'), true, true);
28
  self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
29
- spl_autoload_unregister(array('ComposerAutoloaderInit2c751694e0f0d8de65372ae58e93d526', 'loadClassLoader'));
30
 
31
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
32
  if ($useStaticLoader) {
33
  require __DIR__ . '/autoload_static.php';
34
 
35
- call_user_func(\Composer\Autoload\ComposerStaticInit2c751694e0f0d8de65372ae58e93d526::getInitializer($loader));
36
  } else {
37
  $map = require __DIR__ . '/autoload_namespaces.php';
38
  foreach ($map as $namespace => $path) {
@@ -53,19 +53,19 @@ class ComposerAutoloaderInit2c751694e0f0d8de65372ae58e93d526
53
  $loader->register(true);
54
 
55
  if ($useStaticLoader) {
56
- $includeFiles = Composer\Autoload\ComposerStaticInit2c751694e0f0d8de65372ae58e93d526::$files;
57
  } else {
58
  $includeFiles = require __DIR__ . '/autoload_files.php';
59
  }
60
  foreach ($includeFiles as $fileIdentifier => $file) {
61
- composerRequire2c751694e0f0d8de65372ae58e93d526($fileIdentifier, $file);
62
  }
63
 
64
  return $loader;
65
  }
66
  }
67
 
68
- function composerRequire2c751694e0f0d8de65372ae58e93d526($fileIdentifier, $file)
69
  {
70
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
71
  require $file;
2
 
3
  // autoload_real.php @generated by Composer
4
 
5
+ class ComposerAutoloaderInit974fe5222c9810d6a67ef89f12533413
6
  {
7
  private static $loader;
8
 
24
 
25
  require __DIR__ . '/platform_check.php';
26
 
27
+ spl_autoload_register(array('ComposerAutoloaderInit974fe5222c9810d6a67ef89f12533413', 'loadClassLoader'), true, true);
28
  self::$loader = $loader = new \Composer\Autoload\ClassLoader(\dirname(\dirname(__FILE__)));
29
+ spl_autoload_unregister(array('ComposerAutoloaderInit974fe5222c9810d6a67ef89f12533413', 'loadClassLoader'));
30
 
31
  $useStaticLoader = PHP_VERSION_ID >= 50600 && !defined('HHVM_VERSION') && (!function_exists('zend_loader_file_encoded') || !zend_loader_file_encoded());
32
  if ($useStaticLoader) {
33
  require __DIR__ . '/autoload_static.php';
34
 
35
+ call_user_func(\Composer\Autoload\ComposerStaticInit974fe5222c9810d6a67ef89f12533413::getInitializer($loader));
36
  } else {
37
  $map = require __DIR__ . '/autoload_namespaces.php';
38
  foreach ($map as $namespace => $path) {
53
  $loader->register(true);
54
 
55
  if ($useStaticLoader) {
56
+ $includeFiles = Composer\Autoload\ComposerStaticInit974fe5222c9810d6a67ef89f12533413::$files;
57
  } else {
58
  $includeFiles = require __DIR__ . '/autoload_files.php';
59
  }
60
  foreach ($includeFiles as $fileIdentifier => $file) {
61
+ composerRequire974fe5222c9810d6a67ef89f12533413($fileIdentifier, $file);
62
  }
63
 
64
  return $loader;
65
  }
66
  }
67
 
68
+ function composerRequire974fe5222c9810d6a67ef89f12533413($fileIdentifier, $file)
69
  {
70
  if (empty($GLOBALS['__composer_autoload_files'][$fileIdentifier])) {
71
  require $file;
vendor/composer/autoload_static.php CHANGED
@@ -4,7 +4,7 @@
4
 
5
  namespace Composer\Autoload;
6
 
7
- class ComposerStaticInit2c751694e0f0d8de65372ae58e93d526
8
  {
9
  public static $files = array (
10
  'bce4ecd6aabb2a2948e06d0e2c4ea9a6' => __DIR__ . '/..' . '/automattic/jetpack-connection/legacy/load-ixr.php',
@@ -93,9 +93,9 @@ class ComposerStaticInit2c751694e0f0d8de65372ae58e93d526
93
  public static function getInitializer(ClassLoader $loader)
94
  {
95
  return \Closure::bind(function () use ($loader) {
96
- $loader->prefixLengthsPsr4 = ComposerStaticInit2c751694e0f0d8de65372ae58e93d526::$prefixLengthsPsr4;
97
- $loader->prefixDirsPsr4 = ComposerStaticInit2c751694e0f0d8de65372ae58e93d526::$prefixDirsPsr4;
98
- $loader->classMap = ComposerStaticInit2c751694e0f0d8de65372ae58e93d526::$classMap;
99
 
100
  }, null, ClassLoader::class);
101
  }
4
 
5
  namespace Composer\Autoload;
6
 
7
+ class ComposerStaticInit974fe5222c9810d6a67ef89f12533413
8
  {
9
  public static $files = array (
10
  'bce4ecd6aabb2a2948e06d0e2c4ea9a6' => __DIR__ . '/..' . '/automattic/jetpack-connection/legacy/load-ixr.php',
93
  public static function getInitializer(ClassLoader $loader)
94
  {
95
  return \Closure::bind(function () use ($loader) {
96
+ $loader->prefixLengthsPsr4 = ComposerStaticInit974fe5222c9810d6a67ef89f12533413::$prefixLengthsPsr4;
97
+ $loader->prefixDirsPsr4 = ComposerStaticInit974fe5222c9810d6a67ef89f12533413::$prefixDirsPsr4;
98
+ $loader->classMap = ComposerStaticInit974fe5222c9810d6a67ef89f12533413::$classMap;
99
 
100
  }, null, ClassLoader::class);
101
  }
vendor/composer/installed.php CHANGED
@@ -6,7 +6,7 @@
6
  'aliases' =>
7
  array (
8
  ),
9
- 'reference' => 'ca0d60fdabdc9501c165fc8b423b23bc629043dd',
10
  'name' => 'woocommerce/payments',
11
  ),
12
  'versions' =>
@@ -126,7 +126,7 @@
126
  'aliases' =>
127
  array (
128
  ),
129
- 'reference' => 'ca0d60fdabdc9501c165fc8b423b23bc629043dd',
130
  ),
131
  ),
132
  );
6
  'aliases' =>
7
  array (
8
  ),
9
+ 'reference' => '8b3f219f61219ca117cd1363a2c714ec93729aee',
10
  'name' => 'woocommerce/payments',
11
  ),
12
  'versions' =>
126
  'aliases' =>
127
  array (
128
  ),
129
+ 'reference' => '8b3f219f61219ca117cd1363a2c714ec93729aee',
130
  ),
131
  ),
132
  );
vendor/jetpack-autoloader/class-autoloader-handler.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-autoloader-locator.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-autoloader.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-container.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-hook-manager.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-latest-autoloader-guard.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-manifest-reader.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-path-processor.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-plugin-locator.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-plugins-handler.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-version-loader.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
vendor/jetpack-autoloader/class-version-selector.php CHANGED
@@ -5,7 +5,7 @@
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
- namespace Automattic\Jetpack\Autoloader\jp2c751694e0f0d8de65372ae58e93d526;
9
 
10
  // phpcs:ignore
11
 
5
  * @package automattic/jetpack-autoloader
6
  */
7
 
8
+ namespace Automattic\Jetpack\Autoloader\jp974fe5222c9810d6a67ef89f12533413;
9
 
10
  // phpcs:ignore
11
 
woocommerce-payments.php CHANGED
@@ -11,7 +11,7 @@
11
  * WC requires at least: 4.0
12
  * WC tested up to: 5.4
13
  * Requires WP: 5.5
14
- * Version: 2.7.0
15
  *
16
  * @package WooCommerce\Payments
17
  */
11
  * WC requires at least: 4.0
12
  * WC tested up to: 5.4
13
  * Requires WP: 5.5
14
+ * Version: 2.7.1
15
  *
16
  * @package WooCommerce\Payments
17
  */