From 3912a4f1cd7caed62834c6635d9fa594dc7af9f6 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 19 Dec 2022 19:17:46 +0400 Subject: [PATCH 01/46] Get mapped locale to send to PayPal --- modules/ppcp-wc-gateway/services.php | 44 +++++++++++++++++++ .../Fields/paypal-smart-button-fields.php | 11 +++++ 2 files changed, 55 insertions(+) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 8bfaa5f0b..0fded5d67 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1355,4 +1355,48 @@ return array( $container->get( 'wcgateway.is-fraudnet-enabled' ) ); }, + 'wcgateway.wp-paypal-locales-map' => static function( ContainerInterface $container ): array { + return array( + 'ar' => 'ar_EG', + 'arq' => 'ar_EG', + 'ary' => 'ar_EG', + 'de_AT' => 'de_DE', + 'de_CH' => 'de_DE', + 'de_CH_informal' => 'de_DE', + 'de_DE_formal' => 'de_DE', + 'el' => 'el_GR', + 'es_AR' => 'es_ES', + 'es_CL' => 'es_ES', + 'es_CO' => 'es_ES', + 'es_CR' => 'es_ES', + 'es_DO' => 'es_ES', + 'es_GT' => 'es_ES', + 'es_HN' => 'es_ES', + 'es_MX' => 'es_ES', + 'es_PE' => 'es_ES', + 'es_PR' => 'es_ES', + 'es_ES' => 'es_ES', + 'es_UY' => 'es_ES', + 'es_VE' => 'es_ES', + 'fi' => 'fi_FI', + 'fr_BE' => 'fr_FR', + 'ja' => 'ja_JP', + 'nb_NO' => 'no_NO', + 'nn_NO' => 'no_NO', + 'nl_BE' => 'nl_NL', + 'nl_NL_formal' => 'nl_NL', + 'pt_AO' => 'pt_PT', + 'pt_PT_ao90' => 'pt_PT', + 'th' => 'th_TH', + 'zh_SG' => 'zh_CN', + ); + }, + 'wcgateway.current-paypal-locale' => static function( ContainerInterface $container ): string { + $locale = get_user_locale(); + $wp_paypal_locale_map = $container->get( 'wcgateway.wp-paypal-locales-map' ); + + $locale = $wp_paypal_locale_map[ $locale ] ?: $locale; + + return apply_filters( 'woocommerce_paypal_payments_button_locale_override', $locale ); + }, ); diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php index 97bf6d285..03a3ecc0a 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php @@ -71,6 +71,17 @@ return function ( ContainerInterface $container, array $fields ): array { 'requirements' => array(), 'gateway' => 'paypal', ), + 'smart_button_use_wp_locale' => array( + 'title' => __( 'PayPal Buttons Locale', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'Display localized PayPal smart buttons by passing the WordPress locale.', 'woocommerce-paypal-payments' ), + 'desc_tip' => true, + 'description' => __( 'Determine the display language for the PayPal smart buttons and interface.', 'woocommerce-paypal-payments' ), + 'default' => false, + 'screens' => array( State::STATE_START, State::STATE_ONBOARDED ), + 'requirements' => array(), + 'gateway' => 'paypal', + ), 'smart_button_enable_styling_per_location' => array( 'title' => __( 'Customize Smart Buttons Per Location', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', From 90b82f41ca52197cf8a7d27d2893df212af21201 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 19 Dec 2022 19:20:18 +0400 Subject: [PATCH 02/46] Change the override locale setting name --- .../src/Settings/Fields/paypal-smart-button-fields.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php index 03a3ecc0a..162dc04c7 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php @@ -71,7 +71,7 @@ return function ( ContainerInterface $container, array $fields ): array { 'requirements' => array(), 'gateway' => 'paypal', ), - 'smart_button_use_wp_locale' => array( + 'smart_button_locale_override' => array( 'title' => __( 'PayPal Buttons Locale', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Display localized PayPal smart buttons by passing the WordPress locale.', 'woocommerce-paypal-payments' ), From b8719e1c9e90cab7915a0afac9df548be38a22d1 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 19 Dec 2022 19:20:49 +0400 Subject: [PATCH 03/46] Fix phpcs --- .../src/Settings/Fields/paypal-smart-button-fields.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php index 162dc04c7..21ff9a5a2 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php @@ -71,7 +71,7 @@ return function ( ContainerInterface $container, array $fields ): array { 'requirements' => array(), 'gateway' => 'paypal', ), - 'smart_button_locale_override' => array( + 'smart_button_locale_override' => array( 'title' => __( 'PayPal Buttons Locale', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', 'label' => __( 'Display localized PayPal smart buttons by passing the WordPress locale.', 'woocommerce-paypal-payments' ), From 19b189401d2dc9689a6dcfb0f2bf52edfd274ee8 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 19 Dec 2022 19:27:39 +0400 Subject: [PATCH 04/46] Send the locale if appropriate setting is selected --- modules/ppcp-button/services.php | 3 ++- modules/ppcp-button/src/Assets/SmartButton.php | 16 +++++++++++++++- modules/ppcp-wc-gateway/services.php | 2 +- 3 files changed, 18 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-button/services.php b/modules/ppcp-button/services.php index 0e826fab9..e3ff25cd5 100644 --- a/modules/ppcp-button/services.php +++ b/modules/ppcp-button/services.php @@ -104,7 +104,8 @@ return array( $currency, $container->get( 'wcgateway.all-funding-sources' ), $container->get( 'button.basic-checkout-validation-enabled' ), - $container->get( 'woocommerce.logger.woocommerce' ) + $container->get( 'woocommerce.logger.woocommerce' ), + $container->get( 'wcgateway.paypal-locale' ) ); }, 'button.url' => static function ( ContainerInterface $container ): string { diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 265178906..71d21b6fe 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -168,6 +168,13 @@ class SmartButton implements SmartButtonInterface { */ private $payment_tokens = null; + /** + * The locale. + * + * @var string + */ + protected $locale; + /** * SmartButton constructor. * @@ -188,6 +195,7 @@ class SmartButton implements SmartButtonInterface { * @param array $all_funding_sources All existing funding sources. * @param bool $basic_checkout_validation_enabled Whether the basic JS validation of the form iss enabled. * @param LoggerInterface $logger The logger. + * @param string $locale The locale. */ public function __construct( string $module_url, @@ -206,7 +214,8 @@ class SmartButton implements SmartButtonInterface { string $currency, array $all_funding_sources, bool $basic_checkout_validation_enabled, - LoggerInterface $logger + LoggerInterface $logger, + string $locale ) { $this->module_url = $module_url; @@ -226,6 +235,7 @@ class SmartButton implements SmartButtonInterface { $this->all_funding_sources = $all_funding_sources; $this->basic_checkout_validation_enabled = $basic_checkout_validation_enabled; $this->logger = $logger; + $this->locale = $locale; } /** @@ -971,6 +981,10 @@ class SmartButton implements SmartButtonInterface { $params['enable-funding'] = implode( ',', array_unique( $enable_funding ) ); } + if ( $this->settings->has( 'smart_button_locale_override' ) && $this->settings->get( 'smart_button_locale_override' ) ) { + $params['lc'] = $this->locale; + } + $smart_button_url = add_query_arg( $params, 'https://www.paypal.com/sdk/js' ); return $smart_button_url; } diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 0fded5d67..65684da3a 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1391,7 +1391,7 @@ return array( 'zh_SG' => 'zh_CN', ); }, - 'wcgateway.current-paypal-locale' => static function( ContainerInterface $container ): string { + 'wcgateway.paypal-locale' => static function( ContainerInterface $container ): string { $locale = get_user_locale(); $wp_paypal_locale_map = $container->get( 'wcgateway.wp-paypal-locales-map' ); From d6b6ed3ed0a183780fc03f5a9b1b94e28196be61 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 19 Dec 2022 19:49:16 +0400 Subject: [PATCH 05/46] Send the locale if appropriate setting is selected --- modules/ppcp-button/src/Assets/SmartButton.php | 2 +- modules/ppcp-wc-gateway/services.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 71d21b6fe..1953bbb2d 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -982,7 +982,7 @@ class SmartButton implements SmartButtonInterface { } if ( $this->settings->has( 'smart_button_locale_override' ) && $this->settings->get( 'smart_button_locale_override' ) ) { - $params['lc'] = $this->locale; + $params['locale'] = $this->locale; } $smart_button_url = add_query_arg( $params, 'https://www.paypal.com/sdk/js' ); diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 65684da3a..6554842a5 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1395,7 +1395,7 @@ return array( $locale = get_user_locale(); $wp_paypal_locale_map = $container->get( 'wcgateway.wp-paypal-locales-map' ); - $locale = $wp_paypal_locale_map[ $locale ] ?: $locale; + $locale = $wp_paypal_locale_map[ $locale ] ?? $locale; return apply_filters( 'woocommerce_paypal_payments_button_locale_override', $locale ); }, From 8a67585976e116d75e5cb1e200ee9e0423f081a7 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 16 Oct 2023 14:43:41 +0400 Subject: [PATCH 06/46] Create an interface for all integration controllers --- modules/ppcp-compat/src/Integration.php | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 modules/ppcp-compat/src/Integration.php diff --git a/modules/ppcp-compat/src/Integration.php b/modules/ppcp-compat/src/Integration.php new file mode 100644 index 000000000..4bb314581 --- /dev/null +++ b/modules/ppcp-compat/src/Integration.php @@ -0,0 +1,18 @@ + Date: Mon, 16 Oct 2023 14:47:46 +0400 Subject: [PATCH 07/46] Fix the package name. --- modules/ppcp-compat/src/Integration.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-compat/src/Integration.php b/modules/ppcp-compat/src/Integration.php index 4bb314581..62055c915 100644 --- a/modules/ppcp-compat/src/Integration.php +++ b/modules/ppcp-compat/src/Integration.php @@ -2,7 +2,7 @@ /** * Interface for all integration controllers. * - * @package WooCommerce\PayPalCommerce\OrderTracking\Shipment + * @package WooCommerce\PayPalCommerce\Compat */ declare(strict_types=1); From 347c412c407d725da3b77f540080c8028dfe98c6 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 16 Oct 2023 15:19:28 +0400 Subject: [PATCH 08/46] Create tracking integration for Germanized --- modules/ppcp-compat/src/Integration.php | 12 +- .../GermanizedShipmentIntegration.php | 123 ++++++++++++++++++ 2 files changed, 129 insertions(+), 6 deletions(-) create mode 100644 modules/ppcp-order-tracking/src/Integration/GermanizedShipmentIntegration.php diff --git a/modules/ppcp-compat/src/Integration.php b/modules/ppcp-compat/src/Integration.php index 62055c915..f8aaf8bc6 100644 --- a/modules/ppcp-compat/src/Integration.php +++ b/modules/ppcp-compat/src/Integration.php @@ -9,10 +9,10 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Compat; -interface Integration -{ - /** - * Integrates some (possibly external) service with PayPal Payments. - */ - public function integrate(): void; +interface Integration { + + /** + * Integrates some (possibly external) service with PayPal Payments. + */ + public function integrate(): void; } diff --git a/modules/ppcp-order-tracking/src/Integration/GermanizedShipmentIntegration.php b/modules/ppcp-order-tracking/src/Integration/GermanizedShipmentIntegration.php new file mode 100644 index 000000000..7e44fd765 --- /dev/null +++ b/modules/ppcp-order-tracking/src/Integration/GermanizedShipmentIntegration.php @@ -0,0 +1,123 @@ +shipment_factory = $shipment_factory; + $this->logger = $logger; + $this->endpoint = $endpoint; + } + + /** + * {@inheritDoc} + */ + public function integrate(): void { + + add_action( + 'woocommerce_gzd_shipment_status_shipped', + function( int $shipment_id, Shipment $shipment ) { + if ( ! apply_filters( 'woocommerce_paypal_payments_sync_gzd_tracking', true ) ) { + return; + } + + $wc_order = $shipment->get_order(); + + if ( ! is_a( $wc_order, WC_Order::class ) ) { + return; + } + + $wc_order_id = $wc_order->get_id(); + $transaction_id = $wc_order->get_transaction_id(); + $tracking_number = $shipment->get_tracking_id(); + $carrier = $shipment->get_shipping_provider(); + + $items = array_map( + function ( ShipmentItem $item ): int { + return $item->get_order_item_id(); + }, + $shipment->get_items() + ); + + if ( ! $tracking_number || ! $carrier || ! $transaction_id ) { + return; + } + + try { + $ppcp_shipment = $this->shipment_factory->create_shipment( + $wc_order_id, + $transaction_id, + $tracking_number, + 'SHIPPED', + 'OTHER', + $carrier, + $items + ); + + $tracking_information = $this->endpoint->get_tracking_information( $wc_order_id, $tracking_number ); + + $tracking_information + ? $this->endpoint->update_tracking_information( $ppcp_shipment, $wc_order_id ) + : $this->endpoint->add_tracking_information( $ppcp_shipment, $wc_order_id ); + + } catch ( Exception $exception ) { + $this->logger->error( "Couldn't sync tracking information: " . $exception->getMessage() ); + } + }, + 500, + 2 + ); + } +} From b1780ab15305c024d2ae0bf06b96bfa909a3b749 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 16 Oct 2023 15:29:37 +0400 Subject: [PATCH 09/46] Create tracking integration for Shipment Tracking plugin --- .../ShipmentTrackingIntegration.php | 174 ++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 modules/ppcp-order-tracking/src/Integration/ShipmentTrackingIntegration.php diff --git a/modules/ppcp-order-tracking/src/Integration/ShipmentTrackingIntegration.php b/modules/ppcp-order-tracking/src/Integration/ShipmentTrackingIntegration.php new file mode 100644 index 000000000..6c506a5e8 --- /dev/null +++ b/modules/ppcp-order-tracking/src/Integration/ShipmentTrackingIntegration.php @@ -0,0 +1,174 @@ +shipment_factory = $shipment_factory; + $this->logger = $logger; + $this->endpoint = $endpoint; + } + + /** + * {@inheritDoc} + */ + public function integrate(): void { + + add_action( + 'wp_ajax_wc_shipment_tracking_save_form', + function() { + check_ajax_referer( 'create-tracking-item', 'security', true ); + + if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) ) { + return; + } + + $order_id = (int) wc_clean( wp_unslash( $_POST['order_id'] ?? '' ) ); + $wc_order = wc_get_order( $order_id ); + if ( ! is_a( $wc_order, WC_Order::class ) ) { + return; + } + + $transaction_id = $wc_order->get_transaction_id(); + $tracking_number = wc_clean( wp_unslash( $_POST['tracking_number'] ?? '' ) ); + $carrier = wc_clean( wp_unslash( $_POST['tracking_provider'] ?? '' ) ); + $carrier_other = wc_clean( wp_unslash( $_POST['custom_tracking_provider'] ?? '' ) ); + $carrier = $carrier ?: $carrier_other ?: ''; + + if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $transaction_id ) { + return; + } + + $this->sync_tracking( $order_id, $transaction_id, $tracking_number, $carrier ); + } + ); + + /** + * Support the case when tracking is added via REST. + */ + add_filter( + 'woocommerce_rest_prepare_order_shipment_tracking', + function( WP_REST_Response $response, array $tracking_item, WP_REST_Request $request ): WP_REST_Response { + if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) ) { + return $response; + } + + $callback = $request->get_attributes()['callback']['1'] ?? ''; + if ( $callback !== 'create_item' ) { + return $response; + } + + $order_id = $tracking_item['order_id'] ?? 0; + $wc_order = wc_get_order( $order_id ); + if ( ! is_a( $wc_order, WC_Order::class ) ) { + return $response; + } + + $transaction_id = $wc_order->get_transaction_id(); + $tracking_number = $tracking_item['tracking_number'] ?? ''; + $carrier = $tracking_item['tracking_provider'] ?? ''; + $carrier_other = $tracking_item['custom_tracking_provider'] ?? ''; + $carrier = $carrier ?: $carrier_other ?: ''; + + if ( ! $tracking_number || ! $carrier || ! $transaction_id ) { + return $response; + } + + $this->sync_tracking( $order_id, $transaction_id, $tracking_number, $carrier ); + + return $response; + }, + 10, + 3 + ); + } + + /** + * Syncs (add | update) the PayPal tracking with given info. + * + * @param int $wc_order_id The WC order ID. + * @param string $transaction_id The transaction ID. + * @param string $tracking_number The tracking number. + * @param string $carrier The shipment carrier. + * @return void + */ + protected function sync_tracking( + int $wc_order_id, + string $transaction_id, + string $tracking_number, + string $carrier + ) { + try { + $ppcp_shipment = $this->shipment_factory->create_shipment( + $wc_order_id, + $transaction_id, + $tracking_number, + 'SHIPPED', + 'OTHER', + $carrier, + array() + ); + + $tracking_information = $this->endpoint->get_tracking_information( $wc_order_id, $tracking_number ); + + $tracking_information + ? $this->endpoint->update_tracking_information( $ppcp_shipment, $wc_order_id ) + : $this->endpoint->add_tracking_information( $ppcp_shipment, $wc_order_id ); + + } catch ( Exception $exception ) { + $this->logger->error( "Couldn't sync tracking information: " . $exception->getMessage() ); + } + } +} From bd11a246ccbadb8cd546c2fa7dd0579783f2f6fa Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 16 Oct 2023 15:34:29 +0400 Subject: [PATCH 10/46] Create tracking integration for YITH WooCommerce Order & Shipment Tracking plugin --- .../Integration/YithShipmentIntegration.php | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 modules/ppcp-order-tracking/src/Integration/YithShipmentIntegration.php diff --git a/modules/ppcp-order-tracking/src/Integration/YithShipmentIntegration.php b/modules/ppcp-order-tracking/src/Integration/YithShipmentIntegration.php new file mode 100644 index 000000000..57a36babf --- /dev/null +++ b/modules/ppcp-order-tracking/src/Integration/YithShipmentIntegration.php @@ -0,0 +1,114 @@ +shipment_factory = $shipment_factory; + $this->logger = $logger; + $this->endpoint = $endpoint; + } + + /** + * {@inheritDoc} + */ + public function integrate(): void { + + add_action( + 'woocommerce_process_shop_order_meta', + function( int $order_id ) { + if ( ! apply_filters( 'woocommerce_paypal_payments_sync_ywot_tracking', true ) ) { + return; + } + + $wc_order = wc_get_order( $order_id ); + if ( ! is_a( $wc_order, WC_Order::class ) ) { + return; + } + + $transaction_id = $wc_order->get_transaction_id(); + // phpcs:ignore WordPress.Security.NonceVerification.Missing + $tracking_number = wc_clean( wp_unslash( $_POST['ywot_tracking_code'] ?? '' ) ); + // phpcs:ignore WordPress.Security.NonceVerification.Missing + $carrier = wc_clean( wp_unslash( $_POST['ywot_carrier_name'] ?? '' ) ); + + if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $transaction_id ) { + return; + } + + try { + $ppcp_shipment = $this->shipment_factory->create_shipment( + $order_id, + $transaction_id, + $tracking_number, + 'SHIPPED', + 'OTHER', + $carrier, + array() + ); + + $tracking_information = $this->endpoint->get_tracking_information( $order_id, $tracking_number ); + + $tracking_information + ? $this->endpoint->update_tracking_information( $ppcp_shipment, $order_id ) + : $this->endpoint->add_tracking_information( $ppcp_shipment, $order_id ); + + } catch ( Exception $exception ) { + $this->logger->error( "Couldn't sync tracking information: " . $exception->getMessage() ); + } + }, + 500, + 1 + ); + } +} From e4534d64cdaf11bd2d763415dc9dc9b6ab0718e9 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 16 Oct 2023 15:41:53 +0400 Subject: [PATCH 11/46] Create configuration fol list of tracking integrations. --- modules/ppcp-order-tracking/services.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-order-tracking/services.php b/modules/ppcp-order-tracking/services.php index 144460571..df4b6bf71 100644 --- a/modules/ppcp-order-tracking/services.php +++ b/modules/ppcp-order-tracking/services.php @@ -9,15 +9,14 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\OrderTracking; -use WC_Order; -use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; -use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\OrderTracking\Integration\GermanizedShipmentIntegration; +use WooCommerce\PayPalCommerce\OrderTracking\Integration\ShipmentTrackingIntegration; +use WooCommerce\PayPalCommerce\OrderTracking\Integration\YithShipmentIntegration; use WooCommerce\PayPalCommerce\OrderTracking\Shipment\ShipmentFactoryInterface; use WooCommerce\PayPalCommerce\OrderTracking\Shipment\ShipmentFactory; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\OrderTracking\Assets\OrderEditPageAssets; use WooCommerce\PayPalCommerce\OrderTracking\Endpoint\OrderTrackingEndpoint; -use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; return array( 'order-tracking.assets' => function( ContainerInterface $container ) : OrderEditPageAssets { @@ -92,4 +91,15 @@ return array( 'order-tracking.is-merchant-country-us' => static function ( ContainerInterface $container ): bool { return $container->get( 'api.shop.country' ) === 'US'; }, + 'order-tracking.integrations' => static function ( ContainerInterface $container ): array { + $shipment_factory = $container->get( 'order-tracking.shipment.factory' ); + $logger = $container->get( 'woocommerce.logger.woocommerce' ); + $endpoint = $container->get( 'order-tracking.endpoint.controller' ); + + return array( + new GermanizedShipmentIntegration( $shipment_factory, $logger, $endpoint ), + new ShipmentTrackingIntegration( $shipment_factory, $logger, $endpoint ), + new YithShipmentIntegration( $shipment_factory, $logger, $endpoint ), + ); + }, ); From fedcc8f79ab064efcb92e38fcad545a59f2914ef Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 16 Oct 2023 15:56:45 +0400 Subject: [PATCH 12/46] Check if 3rd parties are active before integration init. --- modules/ppcp-compat/services.php | 12 ------------ modules/ppcp-order-tracking/services.php | 20 +++++++++++++++----- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index cb21e195b..c1bab8b74 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -54,18 +54,6 @@ return array( ); }, - 'compat.gzd.is_supported_plugin_version_active' => function (): bool { - return function_exists( 'wc_gzd_get_shipments_by_order' ); // 3.0+ - }, - - 'compat.wc_shipment_tracking.is_supported_plugin_version_active' => function (): bool { - return class_exists( 'WC_Shipment_Tracking' ); - }, - - 'compat.ywot.is_supported_plugin_version_active' => function (): bool { - return function_exists( 'yith_ywot_init' ); - }, - 'compat.module.url' => static function ( ContainerInterface $container ): string { /** * The path cannot be false. diff --git a/modules/ppcp-order-tracking/services.php b/modules/ppcp-order-tracking/services.php index df4b6bf71..5d938645b 100644 --- a/modules/ppcp-order-tracking/services.php +++ b/modules/ppcp-order-tracking/services.php @@ -96,10 +96,20 @@ return array( $logger = $container->get( 'woocommerce.logger.woocommerce' ); $endpoint = $container->get( 'order-tracking.endpoint.controller' ); - return array( - new GermanizedShipmentIntegration( $shipment_factory, $logger, $endpoint ), - new ShipmentTrackingIntegration( $shipment_factory, $logger, $endpoint ), - new YithShipmentIntegration( $shipment_factory, $logger, $endpoint ), - ); + $integrations = array(); + + if ( function_exists( 'wc_gzd_get_shipments_by_order' ) ) { + $integrations[] = new GermanizedShipmentIntegration( $shipment_factory, $logger, $endpoint ); + } + + if ( class_exists( 'WC_Shipment_Tracking' ) ) { + $integrations[] = new ShipmentTrackingIntegration( $shipment_factory, $logger, $endpoint ); + } + + if ( function_exists( 'yith_ywot_init' ) ) { + $integrations[] = new YithShipmentIntegration( $shipment_factory, $logger, $endpoint ); + } + + return $integrations; }, ); From 7ea6b37a459fd000b5d9f8bcc8fba835d8ccbe4f Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 16 Oct 2023 16:00:59 +0400 Subject: [PATCH 13/46] Add tracking integrations within the compat module. --- modules/ppcp-compat/src/CompatModule.php | 227 +---------------------- 1 file changed, 4 insertions(+), 223 deletions(-) diff --git a/modules/ppcp-compat/src/CompatModule.php b/modules/ppcp-compat/src/CompatModule.php index 790c3edb0..9939a2541 100644 --- a/modules/ppcp-compat/src/CompatModule.php +++ b/modules/ppcp-compat/src/CompatModule.php @@ -124,230 +124,11 @@ class CompatModule implements ModuleInterface { * @return void */ protected function initialize_tracking_compat_layer( ContainerInterface $c ): void { - $is_gzd_active = $c->get( 'compat.gzd.is_supported_plugin_version_active' ); - $is_wc_shipment_tracking_active = $c->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' ); - $is_ywot_active = $c->get( 'compat.ywot.is_supported_plugin_version_active' ); + $order_tracking_integrations = $c->get( 'order-tracking.integrations' ); - if ( $is_gzd_active ) { - $this->initialize_gzd_compat_layer( $c ); - } - - if ( $is_wc_shipment_tracking_active ) { - $this->initialize_wc_shipment_tracking_compat_layer( $c ); - } - - if ( $is_ywot_active ) { - $this->initialize_ywot_compat_layer( $c ); - } - } - - /** - * Sets up the Germanized for WooCommerce - * plugin compatibility layer. - * - * @link https://wordpress.org/plugins/woocommerce-germanized/ - * - * @param ContainerInterface $c The Container. - * @return void - */ - protected function initialize_gzd_compat_layer( ContainerInterface $c ): void { - add_action( - 'woocommerce_gzd_shipment_status_shipped', - function( int $shipment_id, Shipment $shipment ) use ( $c ) { - if ( ! apply_filters( 'woocommerce_paypal_payments_sync_gzd_tracking', true ) ) { - return; - } - - $wc_order = $shipment->get_order(); - - if ( ! is_a( $wc_order, WC_Order::class ) ) { - return; - } - - $order_id = $wc_order->get_id(); - $transaction_id = $wc_order->get_transaction_id(); - $tracking_number = $shipment->get_tracking_id(); - $carrier = $shipment->get_shipping_provider(); - $items = array_map( - function ( ShipmentItem $item ): int { - return $item->get_order_item_id(); - }, - $shipment->get_items() - ); - - if ( ! $tracking_number || ! $carrier || ! $transaction_id ) { - return; - } - - $this->create_tracking( $c, $order_id, $transaction_id, $tracking_number, $carrier, $items ); - }, - 500, - 2 - ); - } - - /** - * Sets up the Shipment Tracking - * plugin compatibility layer. - * - * @link https://woocommerce.com/document/shipment-tracking/ - * - * @param ContainerInterface $c The Container. - * @return void - */ - protected function initialize_wc_shipment_tracking_compat_layer( ContainerInterface $c ): void { - add_action( - 'wp_ajax_wc_shipment_tracking_save_form', - function() use ( $c ) { - check_ajax_referer( 'create-tracking-item', 'security', true ); - - if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) ) { - return; - } - - $order_id = (int) wc_clean( wp_unslash( $_POST['order_id'] ?? '' ) ); - $wc_order = wc_get_order( $order_id ); - if ( ! is_a( $wc_order, WC_Order::class ) ) { - return; - } - - $transaction_id = $wc_order->get_transaction_id(); - $tracking_number = wc_clean( wp_unslash( $_POST['tracking_number'] ?? '' ) ); - $carrier = wc_clean( wp_unslash( $_POST['tracking_provider'] ?? '' ) ); - $carrier_other = wc_clean( wp_unslash( $_POST['custom_tracking_provider'] ?? '' ) ); - $carrier = $carrier ?: $carrier_other ?: ''; - - if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $transaction_id ) { - return; - } - - $this->create_tracking( $c, $order_id, $transaction_id, $tracking_number, $carrier, array() ); - } - ); - - add_filter( - 'woocommerce_rest_prepare_order_shipment_tracking', - function( WP_REST_Response $response, array $tracking_item, WP_REST_Request $request ) use ( $c ): WP_REST_Response { - if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) ) { - return $response; - } - - $callback = $request->get_attributes()['callback']['1'] ?? ''; - if ( $callback !== 'create_item' ) { - return $response; - } - - $order_id = $tracking_item['order_id'] ?? 0; - $wc_order = wc_get_order( $order_id ); - if ( ! is_a( $wc_order, WC_Order::class ) ) { - return $response; - } - - $transaction_id = $wc_order->get_transaction_id(); - $tracking_number = $tracking_item['tracking_number'] ?? ''; - $carrier = $tracking_item['tracking_provider'] ?? ''; - $carrier_other = $tracking_item['custom_tracking_provider'] ?? ''; - $carrier = $carrier ?: $carrier_other ?: ''; - - if ( ! $tracking_number || ! $carrier || ! $transaction_id ) { - return $response; - } - - $this->create_tracking( $c, $order_id, $transaction_id, $tracking_number, $carrier, array() ); - - return $response; - }, - 10, - 3 - ); - } - - /** - * Sets up the YITH WooCommerce Order & Shipment Tracking - * plugin compatibility layer. - * - * @link https://wordpress.org/plugins/yith-woocommerce-order-tracking/ - * - * @param ContainerInterface $c The Container. - * @return void - */ - protected function initialize_ywot_compat_layer( ContainerInterface $c ): void { - add_action( - 'woocommerce_process_shop_order_meta', - function( int $order_id ) use ( $c ) { - if ( ! apply_filters( 'woocommerce_paypal_payments_sync_ywot_tracking', true ) ) { - return; - } - - $wc_order = wc_get_order( $order_id ); - if ( ! is_a( $wc_order, WC_Order::class ) ) { - return; - } - - $transaction_id = $wc_order->get_transaction_id(); - // phpcs:ignore WordPress.Security.NonceVerification.Missing - $tracking_number = wc_clean( wp_unslash( $_POST['ywot_tracking_code'] ?? '' ) ); - // phpcs:ignore WordPress.Security.NonceVerification.Missing - $carrier = wc_clean( wp_unslash( $_POST['ywot_carrier_name'] ?? '' ) ); - - if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $transaction_id ) { - return; - } - - $this->create_tracking( $c, $order_id, $transaction_id, $tracking_number, $carrier, array() ); - }, - 500, - 1 - ); - } - - /** - * Creates PayPal tracking. - * - * @param ContainerInterface $c The Container. - * @param int $wc_order_id The WC order ID. - * @param string $transaction_id The transaction ID. - * @param string $tracking_number The tracking number. - * @param string $carrier The shipment carrier. - * @param int[] $line_items The list of shipment line item IDs. - * @return void - */ - protected function create_tracking( - ContainerInterface $c, - int $wc_order_id, - string $transaction_id, - string $tracking_number, - string $carrier, - array $line_items - ) { - $endpoint = $c->get( 'order-tracking.endpoint.controller' ); - assert( $endpoint instanceof OrderTrackingEndpoint ); - - $logger = $c->get( 'woocommerce.logger.woocommerce' ); - assert( $logger instanceof LoggerInterface ); - - $shipment_factory = $c->get( 'order-tracking.shipment.factory' ); - assert( $shipment_factory instanceof ShipmentFactoryInterface ); - - try { - $ppcp_shipment = $shipment_factory->create_shipment( - $wc_order_id, - $transaction_id, - $tracking_number, - 'SHIPPED', - 'OTHER', - $carrier, - $line_items - ); - - $tracking_information = $endpoint->get_tracking_information( $wc_order_id, $tracking_number ); - - $tracking_information - ? $endpoint->update_tracking_information( $ppcp_shipment, $wc_order_id ) - : $endpoint->add_tracking_information( $ppcp_shipment, $wc_order_id ); - - } catch ( Exception $exception ) { - $logger->error( "Couldn't sync tracking information: " . $exception->getMessage() ); + foreach ( $order_tracking_integrations as $integration ) { + assert( $integration instanceof Integration ); + $integration->integrate(); } } From 8c8cbc6153af4fdfc0f7abd7830d74c3e12a69a7 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 16 Oct 2023 16:09:36 +0400 Subject: [PATCH 14/46] Fix the coding styles --- modules/ppcp-compat/services.php | 12 ++++++------ modules/ppcp-compat/src/CompatModule.php | 9 --------- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index c1bab8b74..99b8612b6 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -14,7 +14,7 @@ use WooCommerce\PayPalCommerce\Compat\Assets\CompatAssets; return array( - 'compat.ppec.mock-gateway' => static function( $container ) { + 'compat.ppec.mock-gateway' => static function( $container ) { $settings = $container->get( 'wcgateway.settings' ); $title = $settings->has( 'title' ) ? $settings->get( 'title' ) : __( 'PayPal', 'woocommerce-paypal-payments' ); $title = sprintf( @@ -26,20 +26,20 @@ return array( return new PPEC\MockGateway( $title ); }, - 'compat.ppec.subscriptions-handler' => static function ( ContainerInterface $container ) { + 'compat.ppec.subscriptions-handler' => static function ( ContainerInterface $container ) { $ppcp_renewal_handler = $container->get( 'subscription.renewal-handler' ); $gateway = $container->get( 'compat.ppec.mock-gateway' ); return new PPEC\SubscriptionsHandler( $ppcp_renewal_handler, $gateway ); }, - 'compat.ppec.settings_importer' => static function( ContainerInterface $container ) : PPEC\SettingsImporter { + 'compat.ppec.settings_importer' => static function( ContainerInterface $container ) : PPEC\SettingsImporter { $settings = $container->get( 'wcgateway.settings' ); return new PPEC\SettingsImporter( $settings ); }, - 'compat.plugin-script-names' => static function( ContainerInterface $container ) : array { + 'compat.plugin-script-names' => static function( ContainerInterface $container ) : array { return array( 'ppcp-smart-button', 'ppcp-oxxo', @@ -54,7 +54,7 @@ return array( ); }, - 'compat.module.url' => static function ( ContainerInterface $container ): string { + 'compat.module.url' => static function ( ContainerInterface $container ): string { /** * The path cannot be false. * @@ -66,7 +66,7 @@ return array( ); }, - 'compat.assets' => function( ContainerInterface $container ) : CompatAssets { + 'compat.assets' => function( ContainerInterface $container ) : CompatAssets { return new CompatAssets( $container->get( 'compat.module.url' ), $container->get( 'ppcp.asset-version' ), diff --git a/modules/ppcp-compat/src/CompatModule.php b/modules/ppcp-compat/src/CompatModule.php index 9939a2541..edb4f0e67 100644 --- a/modules/ppcp-compat/src/CompatModule.php +++ b/modules/ppcp-compat/src/CompatModule.php @@ -9,22 +9,13 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Compat; -use Vendidero\Germanized\Shipments\ShipmentItem; -use WooCommerce\PayPalCommerce\OrderTracking\Shipment\ShipmentFactoryInterface; use WooCommerce\PayPalCommerce\Vendor\Dhii\Container\ServiceProvider; use WooCommerce\PayPalCommerce\Vendor\Dhii\Modular\Module\ModuleInterface; -use Exception; use WooCommerce\PayPalCommerce\Vendor\Interop\Container\ServiceProviderInterface; use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface; -use Psr\Log\LoggerInterface; -use Vendidero\Germanized\Shipments\Shipment; -use WC_Order; use WooCommerce\PayPalCommerce\Compat\Assets\CompatAssets; -use WooCommerce\PayPalCommerce\OrderTracking\Endpoint\OrderTrackingEndpoint; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; -use WP_REST_Request; -use WP_REST_Response; /** * Class CompatModule From 4bfde190eca17b30d2cf465fb47774f0ad55251f Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 16 Oct 2023 16:32:09 +0400 Subject: [PATCH 15/46] services to check if supported 3rd party is active. --- modules/ppcp-compat/services.php | 24 ++++++++++++++++++------ modules/ppcp-order-tracking/services.php | 10 +++++++--- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index 99b8612b6..cb21e195b 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -14,7 +14,7 @@ use WooCommerce\PayPalCommerce\Compat\Assets\CompatAssets; return array( - 'compat.ppec.mock-gateway' => static function( $container ) { + 'compat.ppec.mock-gateway' => static function( $container ) { $settings = $container->get( 'wcgateway.settings' ); $title = $settings->has( 'title' ) ? $settings->get( 'title' ) : __( 'PayPal', 'woocommerce-paypal-payments' ); $title = sprintf( @@ -26,20 +26,20 @@ return array( return new PPEC\MockGateway( $title ); }, - 'compat.ppec.subscriptions-handler' => static function ( ContainerInterface $container ) { + 'compat.ppec.subscriptions-handler' => static function ( ContainerInterface $container ) { $ppcp_renewal_handler = $container->get( 'subscription.renewal-handler' ); $gateway = $container->get( 'compat.ppec.mock-gateway' ); return new PPEC\SubscriptionsHandler( $ppcp_renewal_handler, $gateway ); }, - 'compat.ppec.settings_importer' => static function( ContainerInterface $container ) : PPEC\SettingsImporter { + 'compat.ppec.settings_importer' => static function( ContainerInterface $container ) : PPEC\SettingsImporter { $settings = $container->get( 'wcgateway.settings' ); return new PPEC\SettingsImporter( $settings ); }, - 'compat.plugin-script-names' => static function( ContainerInterface $container ) : array { + 'compat.plugin-script-names' => static function( ContainerInterface $container ) : array { return array( 'ppcp-smart-button', 'ppcp-oxxo', @@ -54,7 +54,19 @@ return array( ); }, - 'compat.module.url' => static function ( ContainerInterface $container ): string { + 'compat.gzd.is_supported_plugin_version_active' => function (): bool { + return function_exists( 'wc_gzd_get_shipments_by_order' ); // 3.0+ + }, + + 'compat.wc_shipment_tracking.is_supported_plugin_version_active' => function (): bool { + return class_exists( 'WC_Shipment_Tracking' ); + }, + + 'compat.ywot.is_supported_plugin_version_active' => function (): bool { + return function_exists( 'yith_ywot_init' ); + }, + + 'compat.module.url' => static function ( ContainerInterface $container ): string { /** * The path cannot be false. * @@ -66,7 +78,7 @@ return array( ); }, - 'compat.assets' => function( ContainerInterface $container ) : CompatAssets { + 'compat.assets' => function( ContainerInterface $container ) : CompatAssets { return new CompatAssets( $container->get( 'compat.module.url' ), $container->get( 'ppcp.asset-version' ), diff --git a/modules/ppcp-order-tracking/services.php b/modules/ppcp-order-tracking/services.php index 5d938645b..4b8e91005 100644 --- a/modules/ppcp-order-tracking/services.php +++ b/modules/ppcp-order-tracking/services.php @@ -96,17 +96,21 @@ return array( $logger = $container->get( 'woocommerce.logger.woocommerce' ); $endpoint = $container->get( 'order-tracking.endpoint.controller' ); + $is_gzd_active = $container->get( 'compat.gzd.is_supported_plugin_version_active' ); + $is_wc_shipment_active = $container->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' ); + $is_yith_ywot_active = $container->get( 'compat.ywot.is_supported_plugin_version_active' ); + $integrations = array(); - if ( function_exists( 'wc_gzd_get_shipments_by_order' ) ) { + if ( $is_gzd_active ) { $integrations[] = new GermanizedShipmentIntegration( $shipment_factory, $logger, $endpoint ); } - if ( class_exists( 'WC_Shipment_Tracking' ) ) { + if ( $is_wc_shipment_active ) { $integrations[] = new ShipmentTrackingIntegration( $shipment_factory, $logger, $endpoint ); } - if ( function_exists( 'yith_ywot_init' ) ) { + if ( $is_yith_ywot_active ) { $integrations[] = new YithShipmentIntegration( $shipment_factory, $logger, $endpoint ); } From e6d43f1110200922f9f451194cc2a0e66ab7ccc7 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 17 Oct 2023 16:30:38 +0400 Subject: [PATCH 16/46] Add ShipStation integration for tracking --- modules/ppcp-compat/services.php | 3 + modules/ppcp-order-tracking/services.php | 12 +- .../Integration/ShipStationIntegration.php | 112 ++++++++++++++++++ 3 files changed, 124 insertions(+), 3 deletions(-) create mode 100644 modules/ppcp-order-tracking/src/Integration/ShipStationIntegration.php diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index cb21e195b..767c8b14d 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -65,6 +65,9 @@ return array( 'compat.ywot.is_supported_plugin_version_active' => function (): bool { return function_exists( 'yith_ywot_init' ); }, + 'compat.shipstation.is_supported_plugin_version_active' => function (): bool { + return function_exists( 'woocommerce_shipstation_init' ); + }, 'compat.module.url' => static function ( ContainerInterface $container ): string { /** diff --git a/modules/ppcp-order-tracking/services.php b/modules/ppcp-order-tracking/services.php index 4b8e91005..bbad6b9ba 100644 --- a/modules/ppcp-order-tracking/services.php +++ b/modules/ppcp-order-tracking/services.php @@ -11,6 +11,7 @@ namespace WooCommerce\PayPalCommerce\OrderTracking; use WooCommerce\PayPalCommerce\OrderTracking\Integration\GermanizedShipmentIntegration; use WooCommerce\PayPalCommerce\OrderTracking\Integration\ShipmentTrackingIntegration; +use WooCommerce\PayPalCommerce\OrderTracking\Integration\ShipStationIntegration; use WooCommerce\PayPalCommerce\OrderTracking\Integration\YithShipmentIntegration; use WooCommerce\PayPalCommerce\OrderTracking\Shipment\ShipmentFactoryInterface; use WooCommerce\PayPalCommerce\OrderTracking\Shipment\ShipmentFactory; @@ -96,9 +97,10 @@ return array( $logger = $container->get( 'woocommerce.logger.woocommerce' ); $endpoint = $container->get( 'order-tracking.endpoint.controller' ); - $is_gzd_active = $container->get( 'compat.gzd.is_supported_plugin_version_active' ); - $is_wc_shipment_active = $container->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' ); - $is_yith_ywot_active = $container->get( 'compat.ywot.is_supported_plugin_version_active' ); + $is_gzd_active = $container->get( 'compat.gzd.is_supported_plugin_version_active' ); + $is_wc_shipment_active = $container->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' ); + $is_yith_ywot_active = $container->get( 'compat.ywot.is_supported_plugin_version_active' ); + $is_ship_station_active = $container->get( 'compat.shipstation.is_supported_plugin_version_active' ); $integrations = array(); @@ -114,6 +116,10 @@ return array( $integrations[] = new YithShipmentIntegration( $shipment_factory, $logger, $endpoint ); } + if ( $is_ship_station_active ) { + $integrations[] = new ShipStationIntegration( $shipment_factory, $logger, $endpoint ); + } + return $integrations; }, ); diff --git a/modules/ppcp-order-tracking/src/Integration/ShipStationIntegration.php b/modules/ppcp-order-tracking/src/Integration/ShipStationIntegration.php new file mode 100644 index 000000000..edcb28cf5 --- /dev/null +++ b/modules/ppcp-order-tracking/src/Integration/ShipStationIntegration.php @@ -0,0 +1,112 @@ +shipment_factory = $shipment_factory; + $this->logger = $logger; + $this->endpoint = $endpoint; + } + + /** + * {@inheritDoc} + */ + public function integrate(): void { + + add_action( + 'woocommerce_shipstation_shipnotify', + function( $wc_order, array $data ) { + if ( ! apply_filters( 'woocommerce_paypal_payments_sync_ship_station_tracking', true ) ) { + return; + } + + if ( ! is_a( $wc_order, WC_Order::class ) ) { + return; + } + + $order_id = $wc_order->get_id(); + $transaction_id = $wc_order->get_transaction_id(); + $tracking_number = $data['tracking_number'] ?? ''; + $carrier = $data['carrier'] ?? ''; + + if ( ! $tracking_number || ! is_string( $tracking_number ) || ! $carrier || ! is_string( $carrier ) || ! $transaction_id ) { + return; + } + + try { + $ppcp_shipment = $this->shipment_factory->create_shipment( + $order_id, + $transaction_id, + $tracking_number, + 'SHIPPED', + 'OTHER', + $carrier, + array() + ); + + $tracking_information = $this->endpoint->get_tracking_information( $order_id, $tracking_number ); + + $tracking_information + ? $this->endpoint->update_tracking_information( $ppcp_shipment, $order_id ) + : $this->endpoint->add_tracking_information( $ppcp_shipment, $order_id ); + + } catch ( Exception $exception ) { + $this->logger->error( "Couldn't sync tracking information: " . $exception->getMessage() ); + } + }, + 500, + 1 + ); + } +} From 19e6ecba934d376a55c88f93b795de8d9b5f8ff6 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 17 Oct 2023 16:45:38 +0400 Subject: [PATCH 17/46] Put tracking metabox in sidebar by default. --- modules/ppcp-order-tracking/src/OrderTrackingModule.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-order-tracking/src/OrderTrackingModule.php b/modules/ppcp-order-tracking/src/OrderTrackingModule.php index 94dc1ffd0..ae6bfecc2 100644 --- a/modules/ppcp-order-tracking/src/OrderTrackingModule.php +++ b/modules/ppcp-order-tracking/src/OrderTrackingModule.php @@ -102,7 +102,7 @@ class OrderTrackingModule implements ModuleInterface { __( 'PayPal Package Tracking', 'woocommerce-paypal-payments' ), array( $meta_box_renderer, 'render' ), $screen, - 'normal' + 'side' ); }, 10, From 28515abed6dcb4896795e0395c62f2bb2ccb0b10 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 17 Oct 2023 16:54:13 +0400 Subject: [PATCH 18/46] Fix the psalm warning --- .../src/Integration/ShipStationIntegration.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/ppcp-order-tracking/src/Integration/ShipStationIntegration.php b/modules/ppcp-order-tracking/src/Integration/ShipStationIntegration.php index edcb28cf5..8d294f724 100644 --- a/modules/ppcp-order-tracking/src/Integration/ShipStationIntegration.php +++ b/modules/ppcp-order-tracking/src/Integration/ShipStationIntegration.php @@ -66,6 +66,11 @@ class ShipStationIntegration implements Integration { add_action( 'woocommerce_shipstation_shipnotify', + /** + * Param type for $wc_order can be different. + * + * @psalm-suppress MissingClosureParamType + */ function( $wc_order, array $data ) { if ( ! apply_filters( 'woocommerce_paypal_payments_sync_ship_station_tracking', true ) ) { return; From 9bf0f846ac03bb8ad4e22f50eb2c4f3f76daaa8b Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 18 Oct 2023 19:17:30 +0400 Subject: [PATCH 19/46] disable tracking if payment is not captured --- .../src/TrackingAvailabilityTrait.php | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php b/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php index d3bde378c..b149259a3 100644 --- a/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php +++ b/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php @@ -9,25 +9,40 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\OrderTracking; +use WC_Order; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\Compat\AdminContextTrait; +use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; +use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; trait TrackingAvailabilityTrait { - use AdminContextTrait; - /** - * Checks if tracking is enabled. + * Checks if tracking should be enabled for current post. * * @param Bearer $bearer The Bearer. * @return bool */ protected function is_tracking_enabled( Bearer $bearer ): bool { + $post_id = (int) wc_clean( wp_unslash( $_GET['id'] ?? $_GET['post'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended + if ( ! $post_id ) { + return false; + } + + $order = wc_get_order( $post_id ); + if ( ! is_a( $order, WC_Order::class ) ) { + return false; + } + + $captured = $order->get_meta( AuthorizedPaymentsProcessor::CAPTURED_META_KEY ); + $is_captured = empty( $captured ) || wc_string_to_bool( $captured ); + $is_paypal_order_edit_page = $order->get_meta( PayPalGateway::ORDER_ID_META_KEY ) && ! empty( $order->get_transaction_id() ); + try { $token = $bearer->bearer(); - return $token->is_tracking_available() - && $this->is_paypal_order_edit_page() + return $is_paypal_order_edit_page + && $is_captured + && $token->is_tracking_available() && apply_filters( 'woocommerce_paypal_payments_shipment_tracking_enabled', true ); } catch ( RuntimeException $exception ) { return false; From c5d9fc2f5a9f28727921b4fbc0c98f1d0147568b Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 18 Oct 2023 19:20:08 +0400 Subject: [PATCH 20/46] Revert "disable tracking if payment is not captured" This reverts commit 9bf0f846ac03bb8ad4e22f50eb2c4f3f76daaa8b. --- .../src/TrackingAvailabilityTrait.php | 27 +++++-------------- 1 file changed, 6 insertions(+), 21 deletions(-) diff --git a/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php b/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php index b149259a3..d3bde378c 100644 --- a/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php +++ b/modules/ppcp-order-tracking/src/TrackingAvailabilityTrait.php @@ -9,40 +9,25 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\OrderTracking; -use WC_Order; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; -use WooCommerce\PayPalCommerce\WcGateway\Processor\AuthorizedPaymentsProcessor; +use WooCommerce\PayPalCommerce\Compat\AdminContextTrait; trait TrackingAvailabilityTrait { + use AdminContextTrait; + /** - * Checks if tracking should be enabled for current post. + * Checks if tracking is enabled. * * @param Bearer $bearer The Bearer. * @return bool */ protected function is_tracking_enabled( Bearer $bearer ): bool { - $post_id = (int) wc_clean( wp_unslash( $_GET['id'] ?? $_GET['post'] ?? '' ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended - if ( ! $post_id ) { - return false; - } - - $order = wc_get_order( $post_id ); - if ( ! is_a( $order, WC_Order::class ) ) { - return false; - } - - $captured = $order->get_meta( AuthorizedPaymentsProcessor::CAPTURED_META_KEY ); - $is_captured = empty( $captured ) || wc_string_to_bool( $captured ); - $is_paypal_order_edit_page = $order->get_meta( PayPalGateway::ORDER_ID_META_KEY ) && ! empty( $order->get_transaction_id() ); - try { $token = $bearer->bearer(); - return $is_paypal_order_edit_page - && $is_captured - && $token->is_tracking_available() + return $token->is_tracking_available() + && $this->is_paypal_order_edit_page() && apply_filters( 'woocommerce_paypal_payments_shipment_tracking_enabled', true ); } catch ( RuntimeException $exception ) { return false; From e9d46d8ee9eb3b24800d048b0025a4b77e8d1456 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Thu, 26 Oct 2023 18:04:08 +0100 Subject: [PATCH 21/46] Fix warnings --- modules/ppcp-api-client/src/ApiModule.php | 4 ++-- modules/ppcp-api-client/src/Helper/OrderTransient.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-api-client/src/ApiModule.php b/modules/ppcp-api-client/src/ApiModule.php index ed09ecddc..42bc1f117 100644 --- a/modules/ppcp-api-client/src/ApiModule.php +++ b/modules/ppcp-api-client/src/ApiModule.php @@ -48,8 +48,8 @@ class ApiModule implements ModuleInterface { 'ppcp_create_order_request_body_data', function( array $data ) use ( $c ) { - foreach ( $data['purchase_units'] as $purchase_unit_index => $purchase_unit ) { - foreach ( $purchase_unit['items'] as $item_index => $item ) { + foreach ( ( $data['purchase_units'] ?? array() ) as $purchase_unit_index => $purchase_unit ) { + foreach ( ( $purchase_unit['items'] ?? array() ) as $item_index => $item ) { $data['purchase_units'][ $purchase_unit_index ]['items'][ $item_index ]['name'] = apply_filters( 'woocommerce_paypal_payments_cart_line_item_name', $item['name'], $item['cart_item_key'] ?? null ); } diff --git a/modules/ppcp-api-client/src/Helper/OrderTransient.php b/modules/ppcp-api-client/src/Helper/OrderTransient.php index b6b7a0d99..efe980928 100644 --- a/modules/ppcp-api-client/src/Helper/OrderTransient.php +++ b/modules/ppcp-api-client/src/Helper/OrderTransient.php @@ -102,7 +102,7 @@ class OrderTransient { $transient = array(); } - if ( ! is_array( $transient['notes'] ) ) { + if ( ! is_array( $transient['notes'] ?? null ) ) { $transient['notes'] = array(); } From 93abbefb5bbd56a591c5cf9b4df996ed6eb6b907 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Fri, 27 Oct 2023 11:26:28 +0400 Subject: [PATCH 22/46] Create tracking integration for Wc Shipping & Tax plugin --- .../Integration/WcShippingTaxIntegration.php | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php diff --git a/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php b/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php new file mode 100644 index 000000000..27fd83511 --- /dev/null +++ b/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php @@ -0,0 +1,169 @@ +shipment_factory = $shipment_factory; + $this->logger = $logger; + $this->endpoint = $endpoint; + $this->bearer = $bearer; + } + + /** + * {@inheritDoc} + */ + public function integrate(): void { + + add_filter( + 'rest_post_dispatch', + function( WP_HTTP_Response $response, WP_REST_Server $server, WP_REST_Request $request ): WP_HTTP_Response { + if ( ! $this->is_tracking_enabled( $this->bearer ) || ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipping_tax', true ) ) { + return $response; + } + + $params = $request->get_params() ?? array(); + $order_id = (int) $params['order_id'] ?? 0; + + if ( ! $order_id > 0 || "/wc/v1/connect/label/{$order_id}" !== $request->get_route() ) { + return $response; + } + + $data = $response->get_data() ?? array(); + $labels = $data['labels'] ?? array(); + + if ( empty( $labels ) ) { + return $response; + } + + foreach ( $labels as $label ) { + $wc_order = wc_get_order( $order_id ); + if ( ! is_a( $wc_order, WC_Order::class ) ) { + return $response; + } + + $transaction_id = $wc_order->get_transaction_id(); + $tracking_number = $label['tracking'] ?? ''; + $carrier = $label['carrier_id'] ?? $label['service_name'] ?? ''; + $items = array_map( 'intval', $label['product_ids'] ?? array() ); + + if ( ! $tracking_number || ! $carrier || ! $transaction_id ) { + return $response; + } + + $this->sync_tracking( $order_id, $transaction_id, $tracking_number, $carrier, $items ); + } + + return $response; + }, + 10, + 3 + ); + + } + + /** + * Syncs (add | update) the PayPal tracking with given info. + * + * @param int $wc_order_id The WC order ID. + * @param string $transaction_id The transaction ID. + * @param string $tracking_number The tracking number. + * @param string $carrier The shipment carrier. + * @param int[] $items The list of line items IDs. + * @return void + */ + protected function sync_tracking( + int $wc_order_id, + string $transaction_id, + string $tracking_number, + string $carrier, + array $items + ) { + try { + $ppcp_shipment = $this->shipment_factory->create_shipment( + $wc_order_id, + $transaction_id, + $tracking_number, + 'SHIPPED', + 'OTHER', + $carrier, + $items + ); + + $tracking_information = $this->endpoint->get_tracking_information( $wc_order_id, $tracking_number ); + + $tracking_information + ? $this->endpoint->update_tracking_information( $ppcp_shipment, $wc_order_id ) + : $this->endpoint->add_tracking_information( $ppcp_shipment, $wc_order_id ); + + } catch ( Exception $exception ) { + $this->logger->error( "Couldn't sync tracking information: " . $exception->getMessage() ); + } + } +} From 42ee3559198b3bddf296f0973b57fb9ea27b588d Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Fri, 27 Oct 2023 11:28:04 +0400 Subject: [PATCH 23/46] Service to check if Wc Shipping & Tax is active --- modules/ppcp-compat/services.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index 767c8b14d..378eb9b45 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -68,6 +68,9 @@ return array( 'compat.shipstation.is_supported_plugin_version_active' => function (): bool { return function_exists( 'woocommerce_shipstation_init' ); }, + 'compat.wc_shipping_tax.is_supported_plugin_version_active' => function (): bool { + return class_exists( 'WC_Connect_Loader' ); + }, 'compat.module.url' => static function ( ContainerInterface $container ): string { /** From 2b4294100026f164ac2dadc7c296f4103297f220 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Fri, 27 Oct 2023 11:28:50 +0400 Subject: [PATCH 24/46] Init the integration for Wc Shipping & Tax --- modules/ppcp-order-tracking/services.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/modules/ppcp-order-tracking/services.php b/modules/ppcp-order-tracking/services.php index bbad6b9ba..2846668ca 100644 --- a/modules/ppcp-order-tracking/services.php +++ b/modules/ppcp-order-tracking/services.php @@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\OrderTracking; use WooCommerce\PayPalCommerce\OrderTracking\Integration\GermanizedShipmentIntegration; use WooCommerce\PayPalCommerce\OrderTracking\Integration\ShipmentTrackingIntegration; use WooCommerce\PayPalCommerce\OrderTracking\Integration\ShipStationIntegration; +use WooCommerce\PayPalCommerce\OrderTracking\Integration\WcShippingTaxIntegration; use WooCommerce\PayPalCommerce\OrderTracking\Integration\YithShipmentIntegration; use WooCommerce\PayPalCommerce\OrderTracking\Shipment\ShipmentFactoryInterface; use WooCommerce\PayPalCommerce\OrderTracking\Shipment\ShipmentFactory; @@ -96,11 +97,13 @@ return array( $shipment_factory = $container->get( 'order-tracking.shipment.factory' ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); $endpoint = $container->get( 'order-tracking.endpoint.controller' ); + $bearer = $container->get( 'api.bearer' ); - $is_gzd_active = $container->get( 'compat.gzd.is_supported_plugin_version_active' ); - $is_wc_shipment_active = $container->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' ); - $is_yith_ywot_active = $container->get( 'compat.ywot.is_supported_plugin_version_active' ); - $is_ship_station_active = $container->get( 'compat.shipstation.is_supported_plugin_version_active' ); + $is_gzd_active = $container->get( 'compat.gzd.is_supported_plugin_version_active' ); + $is_wc_shipment_active = $container->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' ); + $is_yith_ywot_active = $container->get( 'compat.ywot.is_supported_plugin_version_active' ); + $is_ship_station_active = $container->get( 'compat.shipstation.is_supported_plugin_version_active' ); + $is_wc_shipping_tax_active = $container->get( 'compat.wc_shipping_tax.is_supported_plugin_version_active' ); $integrations = array(); @@ -120,6 +123,10 @@ return array( $integrations[] = new ShipStationIntegration( $shipment_factory, $logger, $endpoint ); } + if ( $is_wc_shipping_tax_active ) { + $integrations[] = new WcShippingTaxIntegration( $shipment_factory, $logger, $endpoint, $bearer ); + } + return $integrations; }, ); From 54d73fcbaea782798909cadefb8d309762232416 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Fri, 27 Oct 2023 14:58:36 +0400 Subject: [PATCH 25/46] The check will not work on REST --- modules/ppcp-order-tracking/services.php | 3 +-- .../Integration/WcShippingTaxIntegration.php | 21 +++++-------------- 2 files changed, 6 insertions(+), 18 deletions(-) diff --git a/modules/ppcp-order-tracking/services.php b/modules/ppcp-order-tracking/services.php index 2846668ca..37154cd65 100644 --- a/modules/ppcp-order-tracking/services.php +++ b/modules/ppcp-order-tracking/services.php @@ -97,7 +97,6 @@ return array( $shipment_factory = $container->get( 'order-tracking.shipment.factory' ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); $endpoint = $container->get( 'order-tracking.endpoint.controller' ); - $bearer = $container->get( 'api.bearer' ); $is_gzd_active = $container->get( 'compat.gzd.is_supported_plugin_version_active' ); $is_wc_shipment_active = $container->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' ); @@ -124,7 +123,7 @@ return array( } if ( $is_wc_shipping_tax_active ) { - $integrations[] = new WcShippingTaxIntegration( $shipment_factory, $logger, $endpoint, $bearer ); + $integrations[] = new WcShippingTaxIntegration( $shipment_factory, $logger, $endpoint ); } return $integrations; diff --git a/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php b/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php index 27fd83511..a78f483c6 100644 --- a/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php +++ b/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php @@ -12,7 +12,6 @@ namespace WooCommerce\PayPalCommerce\OrderTracking\Integration; use Exception; use Psr\Log\LoggerInterface; use WC_Order; -use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\Compat\Integration; use WooCommerce\PayPalCommerce\OrderTracking\Endpoint\OrderTrackingEndpoint; use WooCommerce\PayPalCommerce\OrderTracking\Shipment\ShipmentFactoryInterface; @@ -49,31 +48,21 @@ class WcShippingTaxIntegration implements Integration { */ protected $endpoint; - /** - * The bearer. - * - * @var Bearer - */ - private $bearer; - /** * The WcShippingTaxIntegration constructor. * * @param ShipmentFactoryInterface $shipment_factory The shipment factory. * @param LoggerInterface $logger The logger. * @param OrderTrackingEndpoint $endpoint The order tracking endpoint. - * @param Bearer $bearer The bearer. */ public function __construct( ShipmentFactoryInterface $shipment_factory, LoggerInterface $logger, - OrderTrackingEndpoint $endpoint, - Bearer $bearer + OrderTrackingEndpoint $endpoint ) { $this->shipment_factory = $shipment_factory; $this->logger = $logger; $this->endpoint = $endpoint; - $this->bearer = $bearer; } /** @@ -84,14 +73,14 @@ class WcShippingTaxIntegration implements Integration { add_filter( 'rest_post_dispatch', function( WP_HTTP_Response $response, WP_REST_Server $server, WP_REST_Request $request ): WP_HTTP_Response { - if ( ! $this->is_tracking_enabled( $this->bearer ) || ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipping_tax', true ) ) { + if ( ! apply_filters( 'woocommerce_paypal_payments_sync_wc_shipping_tax', true ) ) { return $response; } - $params = $request->get_params() ?? array(); - $order_id = (int) $params['order_id'] ?? 0; + $params = $request->get_params(); + $order_id = (int) ( $params['order_id'] ?? 0 ); - if ( ! $order_id > 0 || "/wc/v1/connect/label/{$order_id}" !== $request->get_route() ) { + if ( ! $order_id || "/wc/v1/connect/label/{$order_id}" !== $request->get_route() ) { return $response; } From 6f8fe3b7c0231fb4c8adcde7e1f6e6f34118381c Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Fri, 27 Oct 2023 14:59:50 +0400 Subject: [PATCH 26/46] Update the tracking metabox dynamically --- .../resources/js/tracking-compat.js | 17 +++++++++++++++ modules/ppcp-compat/services.php | 1 + .../ppcp-compat/src/Assets/CompatAssets.php | 21 ++++++++++++++----- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/modules/ppcp-compat/resources/js/tracking-compat.js b/modules/ppcp-compat/resources/js/tracking-compat.js index b62158ff1..d26bda2e9 100644 --- a/modules/ppcp-compat/resources/js/tracking-compat.js +++ b/modules/ppcp-compat/resources/js/tracking-compat.js @@ -9,7 +9,9 @@ document.addEventListener( const loadLocation = location.href + " " + orderTrackingContainerSelector + ">*"; const gzdSyncEnabled = config.gzd_sync_enabled; const wcShipmentSyncEnabled = config.wc_shipment_sync_enabled; + const wcShippingTaxSyncEnabled = config.wc_shipping_tax_sync_enabled; const wcShipmentSaveButton = document.querySelector('#woocommerce-shipment-tracking .button-save-form'); + const wcShipmentTaxBuyLabelButtonSelector = '.components-modal__screen-overlay .label-purchase-modal__sidebar .purchase-section button.components-button'; const toggleLoaderVisibility = function() { const loader = document.querySelector('.ppcp-tracking-loader'); @@ -45,5 +47,20 @@ document.addEventListener( waitForTrackingUpdate(jQuery('#shipment-tracking-form')); }) } + + if (wcShippingTaxSyncEnabled && typeof(wcShippingTaxSyncEnabled) != 'undefined' && wcShippingTaxSyncEnabled != null) { + document.addEventListener('click', function(event) { + const wcShipmentTaxBuyLabelButton = event.target.closest(wcShipmentTaxBuyLabelButtonSelector); + + if (wcShipmentTaxBuyLabelButton) { + toggleLoaderVisibility(); + setTimeout(function () { + jQuery(orderTrackingContainerSelector).load(loadLocation, "", function(){ + toggleLoaderVisibility(); + }); + }, 5000); + } + }); + } }, ); diff --git a/modules/ppcp-compat/services.php b/modules/ppcp-compat/services.php index 378eb9b45..9907a15c0 100644 --- a/modules/ppcp-compat/services.php +++ b/modules/ppcp-compat/services.php @@ -90,6 +90,7 @@ return array( $container->get( 'ppcp.asset-version' ), $container->get( 'compat.gzd.is_supported_plugin_version_active' ), $container->get( 'compat.wc_shipment_tracking.is_supported_plugin_version_active' ), + $container->get( 'compat.wc_shipping_tax.is_supported_plugin_version_active' ), $container->get( 'api.bearer' ) ); }, diff --git a/modules/ppcp-compat/src/Assets/CompatAssets.php b/modules/ppcp-compat/src/Assets/CompatAssets.php index c1febf93f..85e0bde7b 100644 --- a/modules/ppcp-compat/src/Assets/CompatAssets.php +++ b/modules/ppcp-compat/src/Assets/CompatAssets.php @@ -47,6 +47,13 @@ class CompatAssets { */ protected $is_wc_shipment_active; + /** + * Whether WC Shipping & Tax plugin is active + * + * @var bool + */ + private $is_wc_shipping_tax_active; + /** * The bearer. * @@ -61,6 +68,7 @@ class CompatAssets { * @param string $version The assets version. * @param bool $is_gzd_active Whether Germanized plugin is active. * @param bool $is_wc_shipment_active Whether WC Shipments plugin is active. + * @param bool $is_wc_shipping_tax_active Whether WC Shipping & Tax plugin is active. * @param Bearer $bearer The bearer. */ public function __construct( @@ -68,14 +76,16 @@ class CompatAssets { string $version, bool $is_gzd_active, bool $is_wc_shipment_active, + bool $is_wc_shipping_tax_active, Bearer $bearer ) { - $this->module_url = $module_url; - $this->version = $version; - $this->is_gzd_active = $is_gzd_active; - $this->is_wc_shipment_active = $is_wc_shipment_active; - $this->bearer = $bearer; + $this->module_url = $module_url; + $this->version = $version; + $this->is_gzd_active = $is_gzd_active; + $this->is_wc_shipment_active = $is_wc_shipment_active; + $this->is_wc_shipping_tax_active = $is_wc_shipping_tax_active; + $this->bearer = $bearer; } /** @@ -99,6 +109,7 @@ class CompatAssets { array( 'gzd_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_gzd_tracking', true ) && $this->is_gzd_active, 'wc_shipment_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_wc_shipment_tracking', true ) && $this->is_wc_shipment_active, + 'wc_shipping_tax_sync_enabled' => apply_filters( 'woocommerce_paypal_payments_sync_wc_shipping_tax', true ) && $this->is_wc_shipping_tax_active, ) ); } From 9f93faa15936e36705eaf10b3508ff98d0e64352 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Fri, 27 Oct 2023 15:13:56 +0400 Subject: [PATCH 27/46] Fix the shipment title styles --- modules/ppcp-order-tracking/resources/css/order-edit-page.scss | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/ppcp-order-tracking/resources/css/order-edit-page.scss b/modules/ppcp-order-tracking/resources/css/order-edit-page.scss index c9a112ead..fc0c511b2 100644 --- a/modules/ppcp-order-tracking/resources/css/order-edit-page.scss +++ b/modules/ppcp-order-tracking/resources/css/order-edit-page.scss @@ -49,6 +49,8 @@ h4 { display: inline-block; margin: 10px 0px; + max-width: 83%; + overflow: hidden; } button { From 2591e4cbdf3b150897031fb364559c414227aed5 Mon Sep 17 00:00:00 2001 From: Alex P Date: Mon, 30 Oct 2023 10:10:03 +0200 Subject: [PATCH 28/46] Fix is_cart() check in ajax cart totals refresh --- .../ppcp-button/src/Helper/ContextTrait.php | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-button/src/Helper/ContextTrait.php b/modules/ppcp-button/src/Helper/ContextTrait.php index 189796b75..651bf7f85 100644 --- a/modules/ppcp-button/src/Helper/ContextTrait.php +++ b/modules/ppcp-button/src/Helper/ContextTrait.php @@ -34,6 +34,28 @@ trait ContextTrait { return false; } + /** + * Checks WC is_cart() + WC cart ajax requests. + */ + private function is_cart(): bool { + if ( is_cart() ) { + return true; + } + + /** + * The filter returning whether to detect WC cart ajax requests. + */ + if ( apply_filters( 'ppcp_check_ajax_cart', true ) ) { + // phpcs:ignore WordPress.Security + $wc_ajax = $_GET['wc-ajax'] ?? ''; + if ( in_array( $wc_ajax, array( 'update_shipping_method' ), true ) ) { + return true; + } + } + + return false; + } + /** * The current context. * @@ -56,7 +78,7 @@ trait ContextTrait { return 'cart-block'; } - if ( is_cart() ) { + if ( $this->is_cart() ) { return 'cart'; } From c8fc78c0e201dc47dab491a29bac77e365b64e5f Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 30 Oct 2023 15:18:11 +0400 Subject: [PATCH 29/46] Change the REST rout name --- .../Integration/WcShippingTaxIntegration.php | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php b/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php index a78f483c6..a808c6ade 100644 --- a/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php +++ b/modules/ppcp-order-tracking/src/Integration/WcShippingTaxIntegration.php @@ -79,31 +79,32 @@ class WcShippingTaxIntegration implements Integration { $params = $request->get_params(); $order_id = (int) ( $params['order_id'] ?? 0 ); + $label_id = (int) ( $params['label_ids'] ?? 0 ); - if ( ! $order_id || "/wc/v1/connect/label/{$order_id}" !== $request->get_route() ) { + if ( ! $order_id || "/wc/v1/connect/label/{$order_id}/{$label_id}" !== $request->get_route() ) { return $response; } $data = $response->get_data() ?? array(); $labels = $data['labels'] ?? array(); - if ( empty( $labels ) ) { - return $response; - } - foreach ( $labels as $label ) { - $wc_order = wc_get_order( $order_id ); - if ( ! is_a( $wc_order, WC_Order::class ) ) { - return $response; + $tracking_number = $label['tracking'] ?? ''; + if ( ! $tracking_number ) { + continue; } - $transaction_id = $wc_order->get_transaction_id(); - $tracking_number = $label['tracking'] ?? ''; - $carrier = $label['carrier_id'] ?? $label['service_name'] ?? ''; - $items = array_map( 'intval', $label['product_ids'] ?? array() ); + $wc_order = wc_get_order( $order_id ); + if ( ! is_a( $wc_order, WC_Order::class ) ) { + continue; + } - if ( ! $tracking_number || ! $carrier || ! $transaction_id ) { - return $response; + $transaction_id = $wc_order->get_transaction_id(); + $carrier = $label['carrier_id'] ?? $label['service_name'] ?? ''; + $items = array_map( 'intval', $label['product_ids'] ?? array() ); + + if ( ! $carrier || ! $transaction_id ) { + continue; } $this->sync_tracking( $order_id, $transaction_id, $tracking_number, $carrier, $items ); From a3fb743c73e960e201600927098004a11d27e633 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Mon, 30 Oct 2023 15:19:31 +0400 Subject: [PATCH 30/46] Wait for 10 seconds and refresh the metabox --- modules/ppcp-compat/resources/js/tracking-compat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-compat/resources/js/tracking-compat.js b/modules/ppcp-compat/resources/js/tracking-compat.js index d26bda2e9..f6d2c80e4 100644 --- a/modules/ppcp-compat/resources/js/tracking-compat.js +++ b/modules/ppcp-compat/resources/js/tracking-compat.js @@ -58,7 +58,7 @@ document.addEventListener( jQuery(orderTrackingContainerSelector).load(loadLocation, "", function(){ toggleLoaderVisibility(); }); - }, 5000); + }, 10000); } }); } From 48133aab78d956a9aad469af57735472fcca29ea Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Mon, 30 Oct 2023 15:45:06 +0000 Subject: [PATCH 31/46] Add Italy country eligibility to ApplePay and GooglePay. --- modules/ppcp-applepay/services.php | 54 +++++++++++++++++++---------- modules/ppcp-googlepay/services.php | 54 +++++++++++++++++++---------- 2 files changed, 72 insertions(+), 36 deletions(-) diff --git a/modules/ppcp-applepay/services.php b/modules/ppcp-applepay/services.php index 919f6a25b..a5fcfe331 100644 --- a/modules/ppcp-applepay/services.php +++ b/modules/ppcp-applepay/services.php @@ -130,6 +130,24 @@ return array( return apply_filters( 'woocommerce_paypal_payments_applepay_supported_country_currency_matrix', array( + 'CA' => array( + 'AUD', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'JPY', + 'NOK', + 'NZD', + 'PLN', + 'SEK', + 'SGD', + 'USD', + ), 'GB' => array( 'AUD', 'CAD', @@ -148,6 +166,24 @@ return array( 'SGD', 'USD', ), + 'IT' => array( + 'AUD', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'JPY', + 'NOK', + 'NZD', + 'PLN', + 'SEK', + 'SGD', + 'USD', + ), 'US' => array( 'AUD', 'CAD', @@ -156,24 +192,6 @@ return array( 'JPY', 'USD', ), - 'CA' => array( - 'AUD', - 'CAD', - 'CHF', - 'CZK', - 'DKK', - 'EUR', - 'GBP', - 'HKD', - 'HUF', - 'JPY', - 'NOK', - 'NZD', - 'PLN', - 'SEK', - 'SGD', - 'USD', - ), ) ); }, diff --git a/modules/ppcp-googlepay/services.php b/modules/ppcp-googlepay/services.php index 02a9ccc9d..4d1ef8986 100644 --- a/modules/ppcp-googlepay/services.php +++ b/modules/ppcp-googlepay/services.php @@ -90,6 +90,24 @@ return array( return apply_filters( 'woocommerce_paypal_payments_googlepay_supported_country_currency_matrix', array( + 'CA' => array( + 'AUD', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'JPY', + 'NOK', + 'NZD', + 'PLN', + 'SEK', + 'SGD', + 'USD', + ), 'GB' => array( 'AUD', 'CAD', @@ -108,6 +126,24 @@ return array( 'SGD', 'USD', ), + 'IT' => array( + 'AUD', + 'CAD', + 'CHF', + 'CZK', + 'DKK', + 'EUR', + 'GBP', + 'HKD', + 'HUF', + 'JPY', + 'NOK', + 'NZD', + 'PLN', + 'SEK', + 'SGD', + 'USD', + ), 'US' => array( 'AUD', 'CAD', @@ -116,24 +152,6 @@ return array( 'JPY', 'USD', ), - 'CA' => array( - 'AUD', - 'CAD', - 'CHF', - 'CZK', - 'DKK', - 'EUR', - 'GBP', - 'HKD', - 'HUF', - 'JPY', - 'NOK', - 'NZD', - 'PLN', - 'SEK', - 'SGD', - 'USD', - ), ) ); }, From 35be33a0cb3bea8aac1e0b44973fae093002d471 Mon Sep 17 00:00:00 2001 From: Alex P Date: Tue, 31 Oct 2023 11:31:25 +0200 Subject: [PATCH 32/46] Refactor location to hook conversion --- .../ppcp-button/src/Assets/SmartButton.php | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 2c2762970..5a802ab2c 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -402,7 +402,7 @@ class SmartButton implements SmartButtonInterface { case 'cart': return $this->messages_renderer_hook( $location, $this->proceed_to_checkout_button_renderer_hook(), 19 ); case 'pay-now': - return $this->messages_renderer_hook( 'pay_order', 'woocommerce_pay_order_before_submit', 10 ); + return $this->messages_renderer_hook( $location, $default_pay_order_hook, 10 ); case 'product': return $this->messages_renderer_hook( $location, $this->single_product_renderer_hook(), 30 ); case 'shop': @@ -1399,18 +1399,20 @@ class SmartButton implements SmartButtonInterface { * @return array An array with 'name' and 'priority' keys. */ private function messages_renderer_hook( string $location, string $default_hook, int $default_priority ): array { + $location_hook = $this->location_to_hook( $location ); + /** * The filter returning the action name that will be used for rendering Pay Later messages. */ $hook = (string) apply_filters( - "woocommerce_paypal_payments_${location}_messages_renderer_hook", + "woocommerce_paypal_payments_${location_hook}_messages_renderer_hook", $default_hook ); /** * The filter returning the action priority that will be used for rendering Pay Later messages. */ $priority = (int) apply_filters( - "woocommerce_paypal_payments_${location}_messages_renderer_priority", + "woocommerce_paypal_payments_${location_hook}_messages_renderer_priority", $default_priority ); return array( @@ -1724,4 +1726,18 @@ class SmartButton implements SmartButtonInterface { } + /** + * Converts the location name into the name used in hooks. + * + * @param string $location The location. + * @return string + */ + private function location_to_hook( string $location ): string { + switch ( $location ) { + case 'pay-now': + return 'pay_order'; + default: + return $location; + } + } } From 9fdcef4b0d186842d2be0eae046abe1e3df1540a Mon Sep 17 00:00:00 2001 From: Alex P Date: Tue, 31 Oct 2023 11:32:19 +0200 Subject: [PATCH 33/46] Add before/after message wrapper hooks --- modules/ppcp-button/src/Assets/SmartButton.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 5a802ab2c..e47f76884 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -685,7 +685,8 @@ class SmartButton implements SmartButtonInterface { $product = wc_get_product(); - $location = $this->location(); + $location = $this->location(); + $location_hook = $this->location_to_hook( $location ); if ( $location === 'product' && is_a( $product, WC_Product::class ) @@ -697,7 +698,17 @@ class SmartButton implements SmartButtonInterface { return; } + /** + * A hook executed before rendering of the PCP Pay Later messages wrapper. + */ + do_action( "ppcp_before_{$location_hook}_message_wrapper" ); + echo '
'; + + /** + * A hook executed after rendering of the PCP Pay Later messages wrapper. + */ + do_action( "ppcp_after_{$location_hook}_message_wrapper" ); } /** From f535e70cb116332e237f563b7108df6363169a1f Mon Sep 17 00:00:00 2001 From: Alex P Date: Tue, 31 Oct 2023 11:42:35 +0200 Subject: [PATCH 34/46] Move messages via js on pay order page --- .../ppcp-button/src/Assets/SmartButton.php | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index e47f76884..9210e6d58 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -395,7 +395,9 @@ class SmartButton implements SmartButtonInterface { return false; } - $get_hook = function ( string $location ): ?array { + $default_pay_order_hook = 'woocommerce_pay_order_before_submit'; + + $get_hook = function ( string $location ) use ( $default_pay_order_hook ): ?array { switch ( $location ) { case 'checkout': return $this->messages_renderer_hook( $location, 'woocommerce_review_order_before_payment', 10 ); @@ -425,6 +427,28 @@ class SmartButton implements SmartButtonInterface { $hook['priority'] ); + // Looks like there are no hooks like woocommerce_review_order_before_payment on the pay for order page, so have to move using JS. + if ( $location === 'pay-now' && $hook['name'] === $default_pay_order_hook && + /** + * The filter returning true if Pay Later messages should be displayed before payment methods + * on the pay for order page, like in checkout. + */ + apply_filters( + 'woocommerce_paypal_payments_put_pay_order_messages_before_payment_methods', + true + ) + ) { + add_action( + 'ppcp_after_pay_order_message_wrapper', + function () { + echo ' +'; + } + ); + } + return true; } From 2cac44d473e7bce4104792556dbd6f454cbc3419 Mon Sep 17 00:00:00 2001 From: Alex P Date: Tue, 31 Oct 2023 11:42:49 +0200 Subject: [PATCH 35/46] Fix psalm --- modules/ppcp-button/src/Assets/SmartButton.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 9210e6d58..48d098161 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -705,7 +705,7 @@ document.querySelector("#payment").before(document.querySelector("#ppcp-messages /** * Renders the HTML for the credit messaging. */ - public function message_renderer() { + public function message_renderer(): void { $product = wc_get_product(); From ad32a4ff21937cc4f7a88cd37281a769e515e487 Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Tue, 31 Oct 2023 10:35:29 +0000 Subject: [PATCH 36/46] Add PayNow support to ApplePay --- .../resources/js/ApplepayButton.js | 60 +++++++++++++++---- .../resources/js/Context/BaseHandler.js | 39 ++++++------ .../js/Context/ContextHandlerFactory.js | 4 +- .../resources/js/Context/PayNowHandler.js | 35 +++++++++++ .../js/Context/SingleProductHandler.js | 13 +--- 5 files changed, 109 insertions(+), 42 deletions(-) create mode 100644 modules/ppcp-applepay/resources/js/Context/PayNowHandler.js diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index 15615d7ee..2c1b6fb4c 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -244,6 +244,11 @@ class ApplepayButton { requiredShippingContactFields: ["postalAddress", "email", "phone"], requiredBillingContactFields: ["postalAddress", "email", "phone"], } + + if (!this.contextHandler.shippingAllowed()) { + baseRequest.requiredShippingContactFields = []; + } + const paymentDataRequest = Object.assign({}, baseRequest); paymentDataRequest.currencyCode = buttonConfig.shop.currencyCode; paymentDataRequest.total = { @@ -508,18 +513,53 @@ class ApplepayButton { if (confirmOrderResponse && confirmOrderResponse.approveApplePayPayment) { if (confirmOrderResponse.approveApplePayPayment.status === "APPROVED") { try { - let data = { - billing_contact: event.payment.billingContact, - shipping_contact: event.payment.shippingContact, - paypal_order_id: id, - }; - let authorizationResult = await processInWooAndCapture(data); - if (authorizationResult.result === "success") { - session.completePayment(ApplePaySession.STATUS_SUCCESS) - window.location.href = authorizationResult.redirect + + if (!this.contextHandler.shippingAllowed()) { + // No shipping, expect immediate capture, ex: PayNow. + + let approveFailed = false; + await this.contextHandler.approveOrder({ + orderID: id + }, { // actions mock object. + restart: () => new Promise((resolve, reject) => { + approveFailed = true; + resolve(); + }), + order: { + get: () => new Promise((resolve, reject) => { + resolve(null); + }) + } + }); + + if (!approveFailed) { + this.log('onpaymentauthorized approveOrder OK'); + session.completePayment(ApplePaySession.STATUS_SUCCESS); + } else { + this.log('onpaymentauthorized approveOrder FAIL'); + session.completePayment(ApplePaySession.STATUS_FAILURE); + session.abort() + console.error(error); + } + } else { - session.completePayment(ApplePaySession.STATUS_FAILURE) + // Default payment. + + let data = { + billing_contact: event.payment.billingContact, + shipping_contact: event.payment.shippingContact, + paypal_order_id: id, + }; + let authorizationResult = await processInWooAndCapture(data); + if (authorizationResult.result === "success") { + session.completePayment(ApplePaySession.STATUS_SUCCESS) + window.location.href = authorizationResult.redirect + } else { + session.completePayment(ApplePaySession.STATUS_FAILURE) + } + } + } catch (error) { session.completePayment(ApplePaySession.STATUS_FAILURE); session.abort() diff --git a/modules/ppcp-applepay/resources/js/Context/BaseHandler.js b/modules/ppcp-applepay/resources/js/Context/BaseHandler.js index dea7de698..f08c2d6a1 100644 --- a/modules/ppcp-applepay/resources/js/Context/BaseHandler.js +++ b/modules/ppcp-applepay/resources/js/Context/BaseHandler.js @@ -1,8 +1,6 @@ import ErrorHandler from "../../../../ppcp-button/resources/js/modules/ErrorHandler"; import CartActionHandler from "../../../../ppcp-button/resources/js/modules/ActionHandler/CartActionHandler"; -import onApprove - from "../../../../ppcp-button/resources/js/modules/OnApproveHandler/onApproveForContinue"; class BaseHandler { @@ -11,6 +9,10 @@ class BaseHandler { this.ppcpConfig = ppcpConfig; } + shippingAllowed() { + return true; + } + transactionInfo() { return new Promise((resolve, reject) => { @@ -42,30 +44,25 @@ class BaseHandler { } createOrder() { - const errorHandler = new ErrorHandler( - this.ppcpConfig.labels.error.generic, - document.querySelector('.woocommerce-notices-wrapper') - ); - - const actionHandler = new CartActionHandler( - this.ppcpConfig, - errorHandler, - ); - - return actionHandler.configuration().createOrder(null, null); + return this.actionHandler().configuration().createOrder(null, null); } - approveOrderForContinue(data, actions) { - const errorHandler = new ErrorHandler( + approveOrder(data, actions) { + return this.actionHandler().configuration().onApprove(data, actions); + } + + actionHandler() { + return new CartActionHandler( + this.ppcpConfig, + this.errorHandler(), + ); + } + + errorHandler() { + return new ErrorHandler( this.ppcpConfig.labels.error.generic, document.querySelector('.woocommerce-notices-wrapper') ); - - let onApproveHandler = onApprove({ - config: this.ppcpConfig - }, errorHandler); - - return onApproveHandler(data, actions); } } diff --git a/modules/ppcp-applepay/resources/js/Context/ContextHandlerFactory.js b/modules/ppcp-applepay/resources/js/Context/ContextHandlerFactory.js index 72ee4f5fa..04338354b 100644 --- a/modules/ppcp-applepay/resources/js/Context/ContextHandlerFactory.js +++ b/modules/ppcp-applepay/resources/js/Context/ContextHandlerFactory.js @@ -4,6 +4,7 @@ import CheckoutHandler from "./CheckoutHandler"; import CartBlockHandler from "./CartBlockHandler"; import CheckoutBlockHandler from "./CheckoutBlockHandler"; import MiniCartHandler from "./MiniCartHandler"; +import PayNowHandler from "./PayNowHandler"; class ContextHandlerFactory { @@ -14,8 +15,9 @@ class ContextHandlerFactory { case 'cart': return new CartHandler(buttonConfig, ppcpConfig); case 'checkout': - case 'pay-now': // same as checkout return new CheckoutHandler(buttonConfig, ppcpConfig); + case 'pay-now': + return new PayNowHandler(buttonConfig, ppcpConfig); case 'mini-cart': return new MiniCartHandler(buttonConfig, ppcpConfig); case 'cart-block': diff --git a/modules/ppcp-applepay/resources/js/Context/PayNowHandler.js b/modules/ppcp-applepay/resources/js/Context/PayNowHandler.js new file mode 100644 index 000000000..add275608 --- /dev/null +++ b/modules/ppcp-applepay/resources/js/Context/PayNowHandler.js @@ -0,0 +1,35 @@ +import Spinner from "../../../../ppcp-button/resources/js/modules/Helper/Spinner"; +import BaseHandler from "./BaseHandler"; +import CheckoutActionHandler + from "../../../../ppcp-button/resources/js/modules/ActionHandler/CheckoutActionHandler"; + +class PayNowHandler extends BaseHandler { + + shippingAllowed() { + return false; + } + + transactionInfo() { + return new Promise(async (resolve, reject) => { + const data = this.ppcpConfig['pay_now']; + + resolve({ + countryCode: data.country_code, + currencyCode: data.currency_code, + totalPriceStatus: 'FINAL', + totalPrice: data.total_str + }); + }); + } + + actionHandler() { + return new CheckoutActionHandler( + this.ppcpConfig, + this.errorHandler(), + new Spinner() + ); + } + +} + +export default PayNowHandler; diff --git a/modules/ppcp-applepay/resources/js/Context/SingleProductHandler.js b/modules/ppcp-applepay/resources/js/Context/SingleProductHandler.js index ddb7ad531..a014f2ae6 100644 --- a/modules/ppcp-applepay/resources/js/Context/SingleProductHandler.js +++ b/modules/ppcp-applepay/resources/js/Context/SingleProductHandler.js @@ -48,23 +48,16 @@ class SingleProductHandler extends BaseHandler { }); } - createOrder() { - const errorHandler = new ErrorHandler( - this.ppcpConfig.labels.error.generic, - document.querySelector('.woocommerce-notices-wrapper') - ); - - const actionHandler = new SingleProductActionHandler( + actionHandler() { + return new SingleProductActionHandler( this.ppcpConfig, new UpdateCart( this.ppcpConfig.ajax.change_cart.endpoint, this.ppcpConfig.ajax.change_cart.nonce, ), document.querySelector('form.cart'), - errorHandler, + this.errorHandler(), ); - - return actionHandler.configuration().createOrder(); } } From da8f18d8c57b895ee30dd32067c45a1fd85ed3a1 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 31 Oct 2023 15:28:24 +0400 Subject: [PATCH 37/46] Remove the "smart_button_locale_override" setting --- .../Settings/Fields/paypal-smart-button-fields.php | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php index 0eb00c82e..82fa1d5f3 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php @@ -71,17 +71,6 @@ return function ( ContainerInterface $container, array $fields ): array { 'requirements' => array(), 'gateway' => 'paypal', ), - 'smart_button_locale_override' => array( - 'title' => __( 'PayPal Buttons Locale', 'woocommerce-paypal-payments' ), - 'type' => 'checkbox', - 'label' => __( 'Display localized PayPal smart buttons by passing the WordPress locale.', 'woocommerce-paypal-payments' ), - 'desc_tip' => true, - 'description' => __( 'Determine the display language for the PayPal smart buttons and interface.', 'woocommerce-paypal-payments' ), - 'default' => false, - 'screens' => array( State::STATE_START, State::STATE_ONBOARDED ), - 'requirements' => array(), - 'gateway' => 'paypal', - ), 'smart_button_enable_styling_per_location' => array( 'title' => __( 'Customize Smart Buttons Per Location', 'woocommerce-paypal-payments' ), 'type' => 'checkbox', From 55f89451ea5d7c86236c0160c2c06b34dfaeda18 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 31 Oct 2023 16:33:44 +0400 Subject: [PATCH 38/46] Create language map for smart buttons --- modules/ppcp-wc-gateway/services.php | 73 +++++++++++-------- .../Fields/paypal-smart-button-fields.php | 16 ++++ 2 files changed, 57 insertions(+), 32 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 57a58db18..9f9f96305 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1424,38 +1424,47 @@ return array( ), 'wcgateway.wp-paypal-locales-map' => static function( ContainerInterface $container ): array { return array( - 'ar' => 'ar_EG', - 'arq' => 'ar_EG', - 'ary' => 'ar_EG', - 'de_AT' => 'de_DE', - 'de_CH' => 'de_DE', - 'de_CH_informal' => 'de_DE', - 'de_DE_formal' => 'de_DE', - 'el' => 'el_GR', - 'es_AR' => 'es_ES', - 'es_CL' => 'es_ES', - 'es_CO' => 'es_ES', - 'es_CR' => 'es_ES', - 'es_DO' => 'es_ES', - 'es_GT' => 'es_ES', - 'es_HN' => 'es_ES', - 'es_MX' => 'es_ES', - 'es_PE' => 'es_ES', - 'es_PR' => 'es_ES', - 'es_ES' => 'es_ES', - 'es_UY' => 'es_ES', - 'es_VE' => 'es_ES', - 'fi' => 'fi_FI', - 'fr_BE' => 'fr_FR', - 'ja' => 'ja_JP', - 'nb_NO' => 'no_NO', - 'nn_NO' => 'no_NO', - 'nl_BE' => 'nl_NL', - 'nl_NL_formal' => 'nl_NL', - 'pt_AO' => 'pt_PT', - 'pt_PT_ao90' => 'pt_PT', - 'th' => 'th_TH', - 'zh_SG' => 'zh_CN', + '' => __( 'Browser language', 'woocommerce-paypal-payments' ), + 'ar-DZ' => __( 'Arabic (Algeria)', 'woocommerce-paypal-payments' ), + 'ar-BH' => __( 'Arabic (Bahrain)', 'woocommerce-paypal-payments' ), + 'ar-EG' => __( 'Arabic (Egypt)', 'woocommerce-paypal-payments' ), + 'ar-JO' => __( 'Arabic (Jordan)', 'woocommerce-paypal-payments' ), + 'ar-KW' => __( 'Arabic (Kuwait)', 'woocommerce-paypal-payments' ), + 'ar-MA' => __( 'Arabic (Morocco)', 'woocommerce-paypal-payments' ), + 'ar-SA' => __( 'Arabic (Saudi Arabia)', 'woocommerce-paypal-payments' ), + 'cs-CZ' => __( 'Czech', 'woocommerce-paypal-payments' ), + 'zh-CN' => __( 'Chinese (Simplified)', 'woocommerce-paypal-payments' ), + 'zh-HK' => __( 'Chinese (Hong Kong)', 'woocommerce-paypal-payments' ), + 'zh-TW' => __( 'Chinese (Traditional)', 'woocommerce-paypal-payments' ), + 'da-DK' => __( 'Danish', 'woocommerce-paypal-payments' ), + 'nl-NL' => __( 'Dutch', 'woocommerce-paypal-payments' ), + 'en-AU' => __( 'English (Australia)', 'woocommerce-paypal-payments' ), + 'en-GB' => __( 'English (United Kingdom)', 'woocommerce-paypal-payments' ), + 'en-US' => __( 'English (United States)', 'woocommerce-paypal-payments' ), + 'fi-FI' => __( 'Finnish', 'woocommerce-paypal-payments' ), + 'fr-CA' => __( 'French (Canada)', 'woocommerce-paypal-payments' ), + 'fr-FR' => __( 'French (France)', 'woocommerce-paypal-payments' ), + 'de-DE' => __( 'German (Germany)', 'woocommerce-paypal-payments' ), + 'de-CH' => __( 'German (Switzerland)', 'woocommerce-paypal-payments' ), + 'de-AT' => __( 'German (Austria)', 'woocommerce-paypal-payments' ), + 'de-LU' => __( 'German (Luxembourg)', 'woocommerce-paypal-payments' ), + 'el-GR' => __( 'Greek', 'woocommerce-paypal-payments' ), + 'he-IL' => __( 'Hebrew', 'woocommerce-paypal-payments' ), + 'hu-HU' => __( 'Hungarian', 'woocommerce-paypal-payments' ), + 'id-ID' => __( 'Indonesian', 'woocommerce-paypal-payments' ), + 'it-IT' => __( 'Italian', 'woocommerce-paypal-payments' ), + 'ja-JP' => __( 'Japanese', 'woocommerce-paypal-payments' ), + 'ko-KR' => __( 'Korean', 'woocommerce-paypal-payments' ), + 'no-NO' => __( 'Norwegian', 'woocommerce-paypal-payments' ), + 'es-ES' => __( 'Spanish (Spain)', 'woocommerce-paypal-payments' ), + 'es-MX' => __( 'Spanish (Mexico)', 'woocommerce-paypal-payments' ), + 'pl-PL' => __( 'Polish', 'woocommerce-paypal-payments' ), + 'pt-BR' => __( 'Portuguese (Brazil)', 'woocommerce-paypal-payments' ), + 'pt-PT' => __( 'Portuguese (Portugal)', 'woocommerce-paypal-payments' ), + 'ru-RU' => __( 'Russian', 'woocommerce-paypal-payments' ), + 'sk-SK' => __( 'Slovak', 'woocommerce-paypal-payments' ), + 'sv-SE' => __( 'Swedish', 'woocommerce-paypal-payments' ), + 'th-TH' => __( 'Thai', 'woocommerce-paypal-payments' ), ); }, 'wcgateway.paypal-locale' => static function( ContainerInterface $container ): string { diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php index 82fa1d5f3..cc1b8d1f0 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php @@ -80,6 +80,22 @@ return function ( ContainerInterface $container, array $fields ): array { 'requirements' => array(), 'gateway' => 'paypal', ), + 'smart_button_language' => array( + 'title' => __( 'Smart Button Language', 'woocommerce-paypal-payments' ), + 'type' => 'select', + 'desc_tip' => true, + 'description' => __( + 'The language and region used for the displayed PayPal Smart Buttons. The default value is the current language and region setting in a browser.', + 'woocommerce-paypal-payments' + ), + 'class' => array(), + 'input_class' => array( 'wc-enhanced-select' ), + 'default' => 'en', + 'options' => $container->get('wcgateway.wp-paypal-locales-map'), + 'screens' => array( State::STATE_ONBOARDED ), + 'gateway' => 'paypal', + 'requirements' => array(), + ), // General button styles. 'button_general_layout' => array( 'title' => __( 'Button Layout', 'woocommerce-paypal-payments' ), From 2938a5c6d4dc36ff294c60ef25dc4a4302db4410 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 31 Oct 2023 16:56:21 +0400 Subject: [PATCH 39/46] Change the smart button language setting placement --- .../Fields/paypal-smart-button-fields.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php index cc1b8d1f0..2cfec8fd6 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php @@ -71,15 +71,6 @@ return function ( ContainerInterface $container, array $fields ): array { 'requirements' => array(), 'gateway' => 'paypal', ), - 'smart_button_enable_styling_per_location' => array( - 'title' => __( 'Customize Smart Buttons Per Location', 'woocommerce-paypal-payments' ), - 'type' => 'checkbox', - 'label' => __( 'Customize smart button style per location', 'woocommerce-paypal-payments' ), - 'default' => true, - 'screens' => array( State::STATE_START, State::STATE_ONBOARDED ), - 'requirements' => array(), - 'gateway' => 'paypal', - ), 'smart_button_language' => array( 'title' => __( 'Smart Button Language', 'woocommerce-paypal-payments' ), 'type' => 'select', @@ -96,6 +87,15 @@ return function ( ContainerInterface $container, array $fields ): array { 'gateway' => 'paypal', 'requirements' => array(), ), + 'smart_button_enable_styling_per_location' => array( + 'title' => __( 'Customize Smart Buttons Per Location', 'woocommerce-paypal-payments' ), + 'type' => 'checkbox', + 'label' => __( 'Customize smart button style per location', 'woocommerce-paypal-payments' ), + 'default' => true, + 'screens' => array( State::STATE_START, State::STATE_ONBOARDED ), + 'requirements' => array(), + 'gateway' => 'paypal', + ), // General button styles. 'button_general_layout' => array( 'title' => __( 'Button Layout', 'woocommerce-paypal-payments' ), From 3aa81bd144f4befce907572d673020bf33effaaf Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 31 Oct 2023 18:03:55 +0400 Subject: [PATCH 40/46] Locale is now saved in DB --- modules/ppcp-button/services.php | 3 +- .../ppcp-button/src/Assets/SmartButton.php | 17 ++-- modules/ppcp-wc-gateway/services.php | 88 +++++++++---------- 3 files changed, 46 insertions(+), 62 deletions(-) diff --git a/modules/ppcp-button/services.php b/modules/ppcp-button/services.php index 92c3637e4..9267307d8 100644 --- a/modules/ppcp-button/services.php +++ b/modules/ppcp-button/services.php @@ -110,8 +110,7 @@ return array( $container->get( 'button.early-wc-checkout-validation-enabled' ), $container->get( 'button.pay-now-contexts' ), $container->get( 'wcgateway.funding-sources-without-redirect' ), - $container->get( 'woocommerce.logger.woocommerce' ), - $container->get( 'wcgateway.paypal-locale' ) + $container->get( 'woocommerce.logger.woocommerce' ) ); }, 'button.url' => static function ( ContainerInterface $container ): string { diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index c83a1cd10..25c35cc16 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -197,13 +197,6 @@ class SmartButton implements SmartButtonInterface { */ private $session_handler; - /** - * The locale. - * - * @var string - */ - protected $locale; - /** * SmartButton constructor. * @@ -227,7 +220,6 @@ class SmartButton implements SmartButtonInterface { * @param array $pay_now_contexts The contexts that should have the Pay Now button. * @param string[] $funding_sources_without_redirect The sources that do not cause issues about redirecting (on mobile, ...) and sometimes not returning back. * @param LoggerInterface $logger The logger. - * @param string $locale The locale. */ public function __construct( string $module_url, @@ -249,8 +241,7 @@ class SmartButton implements SmartButtonInterface { bool $early_validation_enabled, array $pay_now_contexts, array $funding_sources_without_redirect, - LoggerInterface $logger, - string $locale + LoggerInterface $logger ) { $this->module_url = $module_url; @@ -1213,8 +1204,10 @@ class SmartButton implements SmartButtonInterface { $params['enable-funding'] = implode( ',', array_unique( $enable_funding ) ); } - if ( $this->settings->has( 'smart_button_locale_override' ) && $this->settings->get( 'smart_button_locale_override' ) ) { - $params['locale'] = $this->locale; + $locale = $this->settings->has( 'smart_button_language' ) ? $this->settings->get( 'smart_button_language' ) : ''; + + if ( $locale ) { + $params['locale'] = $locale; } return $params; diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 9f9f96305..62cced8e8 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1425,54 +1425,46 @@ return array( 'wcgateway.wp-paypal-locales-map' => static function( ContainerInterface $container ): array { return array( '' => __( 'Browser language', 'woocommerce-paypal-payments' ), - 'ar-DZ' => __( 'Arabic (Algeria)', 'woocommerce-paypal-payments' ), - 'ar-BH' => __( 'Arabic (Bahrain)', 'woocommerce-paypal-payments' ), - 'ar-EG' => __( 'Arabic (Egypt)', 'woocommerce-paypal-payments' ), - 'ar-JO' => __( 'Arabic (Jordan)', 'woocommerce-paypal-payments' ), - 'ar-KW' => __( 'Arabic (Kuwait)', 'woocommerce-paypal-payments' ), - 'ar-MA' => __( 'Arabic (Morocco)', 'woocommerce-paypal-payments' ), - 'ar-SA' => __( 'Arabic (Saudi Arabia)', 'woocommerce-paypal-payments' ), - 'cs-CZ' => __( 'Czech', 'woocommerce-paypal-payments' ), - 'zh-CN' => __( 'Chinese (Simplified)', 'woocommerce-paypal-payments' ), - 'zh-HK' => __( 'Chinese (Hong Kong)', 'woocommerce-paypal-payments' ), - 'zh-TW' => __( 'Chinese (Traditional)', 'woocommerce-paypal-payments' ), - 'da-DK' => __( 'Danish', 'woocommerce-paypal-payments' ), - 'nl-NL' => __( 'Dutch', 'woocommerce-paypal-payments' ), - 'en-AU' => __( 'English (Australia)', 'woocommerce-paypal-payments' ), - 'en-GB' => __( 'English (United Kingdom)', 'woocommerce-paypal-payments' ), - 'en-US' => __( 'English (United States)', 'woocommerce-paypal-payments' ), - 'fi-FI' => __( 'Finnish', 'woocommerce-paypal-payments' ), - 'fr-CA' => __( 'French (Canada)', 'woocommerce-paypal-payments' ), - 'fr-FR' => __( 'French (France)', 'woocommerce-paypal-payments' ), - 'de-DE' => __( 'German (Germany)', 'woocommerce-paypal-payments' ), - 'de-CH' => __( 'German (Switzerland)', 'woocommerce-paypal-payments' ), - 'de-AT' => __( 'German (Austria)', 'woocommerce-paypal-payments' ), - 'de-LU' => __( 'German (Luxembourg)', 'woocommerce-paypal-payments' ), - 'el-GR' => __( 'Greek', 'woocommerce-paypal-payments' ), - 'he-IL' => __( 'Hebrew', 'woocommerce-paypal-payments' ), - 'hu-HU' => __( 'Hungarian', 'woocommerce-paypal-payments' ), - 'id-ID' => __( 'Indonesian', 'woocommerce-paypal-payments' ), - 'it-IT' => __( 'Italian', 'woocommerce-paypal-payments' ), - 'ja-JP' => __( 'Japanese', 'woocommerce-paypal-payments' ), - 'ko-KR' => __( 'Korean', 'woocommerce-paypal-payments' ), - 'no-NO' => __( 'Norwegian', 'woocommerce-paypal-payments' ), - 'es-ES' => __( 'Spanish (Spain)', 'woocommerce-paypal-payments' ), - 'es-MX' => __( 'Spanish (Mexico)', 'woocommerce-paypal-payments' ), - 'pl-PL' => __( 'Polish', 'woocommerce-paypal-payments' ), - 'pt-BR' => __( 'Portuguese (Brazil)', 'woocommerce-paypal-payments' ), - 'pt-PT' => __( 'Portuguese (Portugal)', 'woocommerce-paypal-payments' ), - 'ru-RU' => __( 'Russian', 'woocommerce-paypal-payments' ), - 'sk-SK' => __( 'Slovak', 'woocommerce-paypal-payments' ), - 'sv-SE' => __( 'Swedish', 'woocommerce-paypal-payments' ), - 'th-TH' => __( 'Thai', 'woocommerce-paypal-payments' ), + 'ar_DZ' => __( 'Arabic (Algeria)', 'woocommerce-paypal-payments' ), + 'ar_BH' => __( 'Arabic (Bahrain)', 'woocommerce-paypal-payments' ), + 'ar_EG' => __( 'Arabic (Egypt)', 'woocommerce-paypal-payments' ), + 'ar_JO' => __( 'Arabic (Jordan)', 'woocommerce-paypal-payments' ), + 'ar_KW' => __( 'Arabic (Kuwait)', 'woocommerce-paypal-payments' ), + 'ar_MA' => __( 'Arabic (Morocco)', 'woocommerce-paypal-payments' ), + 'ar_SA' => __( 'Arabic (Saudi Arabia)', 'woocommerce-paypal-payments' ), + 'cs_CZ' => __( 'Czech', 'woocommerce-paypal-payments' ), + 'zh_CN' => __( 'Chinese (Simplified)', 'woocommerce-paypal-payments' ), + 'zh_HK' => __( 'Chinese (Hong Kong)', 'woocommerce-paypal-payments' ), + 'zh_TW' => __( 'Chinese (Traditional)', 'woocommerce-paypal-payments' ), + 'da_DK' => __( 'Danish', 'woocommerce-paypal-payments' ), + 'nl_NL' => __( 'Dutch', 'woocommerce-paypal-payments' ), + 'en_AU' => __( 'English (Australia)', 'woocommerce-paypal-payments' ), + 'en_GB' => __( 'English (United Kingdom)', 'woocommerce-paypal-payments' ), + 'en_US' => __( 'English (United States)', 'woocommerce-paypal-payments' ), + 'fi_FI' => __( 'Finnish', 'woocommerce-paypal-payments' ), + 'fr_CA' => __( 'French (Canada)', 'woocommerce-paypal-payments' ), + 'fr_FR' => __( 'French (France)', 'woocommerce-paypal-payments' ), + 'de_DE' => __( 'German (Germany)', 'woocommerce-paypal-payments' ), + 'de_CH' => __( 'German (Switzerland)', 'woocommerce-paypal-payments' ), + 'de_AT' => __( 'German (Austria)', 'woocommerce-paypal-payments' ), + 'de_LU' => __( 'German (Luxembourg)', 'woocommerce-paypal-payments' ), + 'el_GR' => __( 'Greek', 'woocommerce-paypal-payments' ), + 'he_IL' => __( 'Hebrew', 'woocommerce-paypal-payments' ), + 'hu_HU' => __( 'Hungarian', 'woocommerce-paypal-payments' ), + 'id_ID' => __( 'Indonesian', 'woocommerce-paypal-payments' ), + 'it_IT' => __( 'Italian', 'woocommerce-paypal-payments' ), + 'ja_JP' => __( 'Japanese', 'woocommerce-paypal-payments' ), + 'ko_KR' => __( 'Korean', 'woocommerce-paypal-payments' ), + 'no_NO' => __( 'Norwegian', 'woocommerce-paypal-payments' ), + 'es_ES' => __( 'Spanish (Spain)', 'woocommerce-paypal-payments' ), + 'es_MX' => __( 'Spanish (Mexico)', 'woocommerce-paypal-payments' ), + 'pl_PL' => __( 'Polish', 'woocommerce-paypal-payments' ), + 'pt_BR' => __( 'Portuguese (Brazil)', 'woocommerce-paypal-payments' ), + 'pt_PT' => __( 'Portuguese (Portugal)', 'woocommerce-paypal-payments' ), + 'ru_RU' => __( 'Russian', 'woocommerce-paypal-payments' ), + 'sk_SK' => __( 'Slovak', 'woocommerce-paypal-payments' ), + 'sv_SE' => __( 'Swedish', 'woocommerce-paypal-payments' ), + 'th_TH' => __( 'Thai', 'woocommerce-paypal-payments' ), ); }, - 'wcgateway.paypal-locale' => static function( ContainerInterface $container ): string { - $locale = get_user_locale(); - $wp_paypal_locale_map = $container->get( 'wcgateway.wp-paypal-locales-map' ); - - $locale = $wp_paypal_locale_map[ $locale ] ?? $locale; - - return apply_filters( 'woocommerce_paypal_payments_button_locale_override', $locale ); - }, ); From 21c8ba99afbdb554b2bc71bbcd643dede4e5d640 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 31 Oct 2023 18:16:21 +0400 Subject: [PATCH 41/46] Remove locale param --- modules/ppcp-button/src/Assets/SmartButton.php | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index 25c35cc16..a25618e2b 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -264,7 +264,6 @@ class SmartButton implements SmartButtonInterface { $this->pay_now_contexts = $pay_now_contexts; $this->funding_sources_without_redirect = $funding_sources_without_redirect; $this->logger = $logger; - $this->locale = $locale; } /** From 976e8b90cacc0022cd2e1caa999d2221bd8f7bca Mon Sep 17 00:00:00 2001 From: Pedro Silva Date: Tue, 31 Oct 2023 15:00:05 +0000 Subject: [PATCH 42/46] Fix ApplePay and GooglePay on block pages --- modules/ppcp-applepay/resources/js/ApplepayButton.js | 2 +- modules/ppcp-applepay/src/ApplepayModule.php | 3 ++- modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php | 2 ++ modules/ppcp-googlepay/src/GooglepayModule.php | 3 ++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-applepay/resources/js/ApplepayButton.js b/modules/ppcp-applepay/resources/js/ApplepayButton.js index 81d2603ee..f9c188741 100644 --- a/modules/ppcp-applepay/resources/js/ApplepayButton.js +++ b/modules/ppcp-applepay/resources/js/ApplepayButton.js @@ -25,7 +25,7 @@ class ApplepayButton { this.updated_contact_info = [] this.selectedShippingMethod = [] - this.nonce = document.getElementById('woocommerce-process-checkout-nonce')?.value + this.nonce = document.getElementById('woocommerce-process-checkout-nonce')?.value || buttonConfig.nonce this.log = function() { if ( this.buttonConfig.is_debug ) { diff --git a/modules/ppcp-applepay/src/ApplepayModule.php b/modules/ppcp-applepay/src/ApplepayModule.php index b81329811..b47409f0c 100644 --- a/modules/ppcp-applepay/src/ApplepayModule.php +++ b/modules/ppcp-applepay/src/ApplepayModule.php @@ -89,7 +89,8 @@ class ApplepayModule implements ModuleInterface { $module->render_buttons( $c, $apple_payment_method ); $apple_payment_method->bootstrap_ajax_request(); - } + }, + 1 ); add_filter( diff --git a/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php b/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php index 0b15fbe78..882776cf1 100644 --- a/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php +++ b/modules/ppcp-applepay/src/Assets/DataToAppleButtonScripts.php @@ -148,6 +148,7 @@ class DataToAppleButtonScripts { 'totalLabel' => $total_label, ), 'ajax_url' => admin_url( 'admin-ajax.php' ), + 'nonce' => wp_create_nonce( 'woocommerce-process_checkout' ), ); } @@ -195,6 +196,7 @@ class DataToAppleButtonScripts { 'totalLabel' => $total_label, ), 'ajax_url' => admin_url( 'admin-ajax.php' ), + 'nonce' => wp_create_nonce( 'woocommerce-process_checkout' ), ); } } diff --git a/modules/ppcp-googlepay/src/GooglepayModule.php b/modules/ppcp-googlepay/src/GooglepayModule.php index 94f70ea09..083f8eba7 100644 --- a/modules/ppcp-googlepay/src/GooglepayModule.php +++ b/modules/ppcp-googlepay/src/GooglepayModule.php @@ -155,7 +155,8 @@ class GooglepayModule implements ModuleInterface { } ); - } + }, + 1 ); } From 7b02136f517dbc0f49c44c2884f5e125ec3ee1f3 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 31 Oct 2023 19:36:06 +0400 Subject: [PATCH 43/46] handle live preview for smart button language --- modules/ppcp-wc-gateway/resources/js/gateway-settings.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js index 7886131d9..a84350cb7 100644 --- a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js +++ b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js @@ -115,7 +115,7 @@ document.addEventListener( 'currency': PayPalCommerceGatewaySettings.currency, 'integration-date': PayPalCommerceGatewaySettings.integration_date, 'components': PayPalCommerceGatewaySettings.components, - 'enable-funding': ['venmo', 'paylater'], + 'enable-funding': ['venmo', 'paylater'] }; if (PayPalCommerceGatewaySettings.environment === 'sandbox') { @@ -134,6 +134,11 @@ document.addEventListener( settings['disable-funding'] = disabledSources; } + const smartButtonLocale = document.getElementById('ppcp-smart_button_language') + if (smartButtonLocale?.length > 0 && smartButtonLocale?.value !== '') { + settings['locale'] = smartButtonLocale.value; + } + return settings; } From ad7de79b38607dc67e5d0eeb3b14fdb5061896c0 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 31 Oct 2023 19:48:48 +0400 Subject: [PATCH 44/46] Check if language selector exists --- modules/ppcp-wc-gateway/resources/js/gateway-settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js index a84350cb7..afec3a426 100644 --- a/modules/ppcp-wc-gateway/resources/js/gateway-settings.js +++ b/modules/ppcp-wc-gateway/resources/js/gateway-settings.js @@ -134,7 +134,7 @@ document.addEventListener( settings['disable-funding'] = disabledSources; } - const smartButtonLocale = document.getElementById('ppcp-smart_button_language') + const smartButtonLocale = document.getElementById('ppcp-smart_button_language'); if (smartButtonLocale?.length > 0 && smartButtonLocale?.value !== '') { settings['locale'] = smartButtonLocale.value; } From de8e78fde5e8f6bbe05b4cc9ffdf3a725936f9d9 Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Tue, 31 Oct 2023 20:06:50 +0400 Subject: [PATCH 45/46] Add filter to override the locales --- modules/ppcp-wc-gateway/services.php | 87 ++++++++++--------- .../Fields/paypal-smart-button-fields.php | 4 +- 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index 62cced8e8..063afa9a3 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -1423,48 +1423,51 @@ return array( } ), 'wcgateway.wp-paypal-locales-map' => static function( ContainerInterface $container ): array { - return array( - '' => __( 'Browser language', 'woocommerce-paypal-payments' ), - 'ar_DZ' => __( 'Arabic (Algeria)', 'woocommerce-paypal-payments' ), - 'ar_BH' => __( 'Arabic (Bahrain)', 'woocommerce-paypal-payments' ), - 'ar_EG' => __( 'Arabic (Egypt)', 'woocommerce-paypal-payments' ), - 'ar_JO' => __( 'Arabic (Jordan)', 'woocommerce-paypal-payments' ), - 'ar_KW' => __( 'Arabic (Kuwait)', 'woocommerce-paypal-payments' ), - 'ar_MA' => __( 'Arabic (Morocco)', 'woocommerce-paypal-payments' ), - 'ar_SA' => __( 'Arabic (Saudi Arabia)', 'woocommerce-paypal-payments' ), - 'cs_CZ' => __( 'Czech', 'woocommerce-paypal-payments' ), - 'zh_CN' => __( 'Chinese (Simplified)', 'woocommerce-paypal-payments' ), - 'zh_HK' => __( 'Chinese (Hong Kong)', 'woocommerce-paypal-payments' ), - 'zh_TW' => __( 'Chinese (Traditional)', 'woocommerce-paypal-payments' ), - 'da_DK' => __( 'Danish', 'woocommerce-paypal-payments' ), - 'nl_NL' => __( 'Dutch', 'woocommerce-paypal-payments' ), - 'en_AU' => __( 'English (Australia)', 'woocommerce-paypal-payments' ), - 'en_GB' => __( 'English (United Kingdom)', 'woocommerce-paypal-payments' ), - 'en_US' => __( 'English (United States)', 'woocommerce-paypal-payments' ), - 'fi_FI' => __( 'Finnish', 'woocommerce-paypal-payments' ), - 'fr_CA' => __( 'French (Canada)', 'woocommerce-paypal-payments' ), - 'fr_FR' => __( 'French (France)', 'woocommerce-paypal-payments' ), - 'de_DE' => __( 'German (Germany)', 'woocommerce-paypal-payments' ), - 'de_CH' => __( 'German (Switzerland)', 'woocommerce-paypal-payments' ), - 'de_AT' => __( 'German (Austria)', 'woocommerce-paypal-payments' ), - 'de_LU' => __( 'German (Luxembourg)', 'woocommerce-paypal-payments' ), - 'el_GR' => __( 'Greek', 'woocommerce-paypal-payments' ), - 'he_IL' => __( 'Hebrew', 'woocommerce-paypal-payments' ), - 'hu_HU' => __( 'Hungarian', 'woocommerce-paypal-payments' ), - 'id_ID' => __( 'Indonesian', 'woocommerce-paypal-payments' ), - 'it_IT' => __( 'Italian', 'woocommerce-paypal-payments' ), - 'ja_JP' => __( 'Japanese', 'woocommerce-paypal-payments' ), - 'ko_KR' => __( 'Korean', 'woocommerce-paypal-payments' ), - 'no_NO' => __( 'Norwegian', 'woocommerce-paypal-payments' ), - 'es_ES' => __( 'Spanish (Spain)', 'woocommerce-paypal-payments' ), - 'es_MX' => __( 'Spanish (Mexico)', 'woocommerce-paypal-payments' ), - 'pl_PL' => __( 'Polish', 'woocommerce-paypal-payments' ), - 'pt_BR' => __( 'Portuguese (Brazil)', 'woocommerce-paypal-payments' ), - 'pt_PT' => __( 'Portuguese (Portugal)', 'woocommerce-paypal-payments' ), - 'ru_RU' => __( 'Russian', 'woocommerce-paypal-payments' ), - 'sk_SK' => __( 'Slovak', 'woocommerce-paypal-payments' ), - 'sv_SE' => __( 'Swedish', 'woocommerce-paypal-payments' ), - 'th_TH' => __( 'Thai', 'woocommerce-paypal-payments' ), + return apply_filters( + 'woocommerce_paypal_payments_button_locales', + array( + '' => __( 'Browser language', 'woocommerce-paypal-payments' ), + 'ar_DZ' => __( 'Arabic (Algeria)', 'woocommerce-paypal-payments' ), + 'ar_BH' => __( 'Arabic (Bahrain)', 'woocommerce-paypal-payments' ), + 'ar_EG' => __( 'Arabic (Egypt)', 'woocommerce-paypal-payments' ), + 'ar_JO' => __( 'Arabic (Jordan)', 'woocommerce-paypal-payments' ), + 'ar_KW' => __( 'Arabic (Kuwait)', 'woocommerce-paypal-payments' ), + 'ar_MA' => __( 'Arabic (Morocco)', 'woocommerce-paypal-payments' ), + 'ar_SA' => __( 'Arabic (Saudi Arabia)', 'woocommerce-paypal-payments' ), + 'cs_CZ' => __( 'Czech', 'woocommerce-paypal-payments' ), + 'zh_CN' => __( 'Chinese (Simplified)', 'woocommerce-paypal-payments' ), + 'zh_HK' => __( 'Chinese (Hong Kong)', 'woocommerce-paypal-payments' ), + 'zh_TW' => __( 'Chinese (Traditional)', 'woocommerce-paypal-payments' ), + 'da_DK' => __( 'Danish', 'woocommerce-paypal-payments' ), + 'nl_NL' => __( 'Dutch', 'woocommerce-paypal-payments' ), + 'en_AU' => __( 'English (Australia)', 'woocommerce-paypal-payments' ), + 'en_GB' => __( 'English (United Kingdom)', 'woocommerce-paypal-payments' ), + 'en_US' => __( 'English (United States)', 'woocommerce-paypal-payments' ), + 'fi_FI' => __( 'Finnish', 'woocommerce-paypal-payments' ), + 'fr_CA' => __( 'French (Canada)', 'woocommerce-paypal-payments' ), + 'fr_FR' => __( 'French (France)', 'woocommerce-paypal-payments' ), + 'de_DE' => __( 'German (Germany)', 'woocommerce-paypal-payments' ), + 'de_CH' => __( 'German (Switzerland)', 'woocommerce-paypal-payments' ), + 'de_AT' => __( 'German (Austria)', 'woocommerce-paypal-payments' ), + 'de_LU' => __( 'German (Luxembourg)', 'woocommerce-paypal-payments' ), + 'el_GR' => __( 'Greek', 'woocommerce-paypal-payments' ), + 'he_IL' => __( 'Hebrew', 'woocommerce-paypal-payments' ), + 'hu_HU' => __( 'Hungarian', 'woocommerce-paypal-payments' ), + 'id_ID' => __( 'Indonesian', 'woocommerce-paypal-payments' ), + 'it_IT' => __( 'Italian', 'woocommerce-paypal-payments' ), + 'ja_JP' => __( 'Japanese', 'woocommerce-paypal-payments' ), + 'ko_KR' => __( 'Korean', 'woocommerce-paypal-payments' ), + 'no_NO' => __( 'Norwegian', 'woocommerce-paypal-payments' ), + 'es_ES' => __( 'Spanish (Spain)', 'woocommerce-paypal-payments' ), + 'es_MX' => __( 'Spanish (Mexico)', 'woocommerce-paypal-payments' ), + 'pl_PL' => __( 'Polish', 'woocommerce-paypal-payments' ), + 'pt_BR' => __( 'Portuguese (Brazil)', 'woocommerce-paypal-payments' ), + 'pt_PT' => __( 'Portuguese (Portugal)', 'woocommerce-paypal-payments' ), + 'ru_RU' => __( 'Russian', 'woocommerce-paypal-payments' ), + 'sk_SK' => __( 'Slovak', 'woocommerce-paypal-payments' ), + 'sv_SE' => __( 'Swedish', 'woocommerce-paypal-payments' ), + 'th_TH' => __( 'Thai', 'woocommerce-paypal-payments' ), + ) ); }, ); diff --git a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php index 2cfec8fd6..b5a7e527c 100644 --- a/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php +++ b/modules/ppcp-wc-gateway/src/Settings/Fields/paypal-smart-button-fields.php @@ -71,7 +71,7 @@ return function ( ContainerInterface $container, array $fields ): array { 'requirements' => array(), 'gateway' => 'paypal', ), - 'smart_button_language' => array( + 'smart_button_language' => array( 'title' => __( 'Smart Button Language', 'woocommerce-paypal-payments' ), 'type' => 'select', 'desc_tip' => true, @@ -82,7 +82,7 @@ return function ( ContainerInterface $container, array $fields ): array { 'class' => array(), 'input_class' => array( 'wc-enhanced-select' ), 'default' => 'en', - 'options' => $container->get('wcgateway.wp-paypal-locales-map'), + 'options' => $container->get( 'wcgateway.wp-paypal-locales-map' ), 'screens' => array( State::STATE_ONBOARDED ), 'gateway' => 'paypal', 'requirements' => array(), From 7e05be307694419231cb759a4bf9023da470186e Mon Sep 17 00:00:00 2001 From: Narek Zakarian Date: Wed, 1 Nov 2023 19:47:58 +0400 Subject: [PATCH 46/46] Add filter to change the smart button locale --- modules/ppcp-button/src/Assets/SmartButton.php | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/ppcp-button/src/Assets/SmartButton.php b/modules/ppcp-button/src/Assets/SmartButton.php index a25618e2b..73b0b240a 100644 --- a/modules/ppcp-button/src/Assets/SmartButton.php +++ b/modules/ppcp-button/src/Assets/SmartButton.php @@ -1204,6 +1204,7 @@ class SmartButton implements SmartButtonInterface { } $locale = $this->settings->has( 'smart_button_language' ) ? $this->settings->get( 'smart_button_language' ) : ''; + $locale = (string) apply_filters( 'woocommerce_paypal_payments_smart_buttons_locale', $locale ); if ( $locale ) { $params['locale'] = $locale;