Merge pull request #3194 from woocommerce/PCP-4290-direct-traffic-from-the-wc-gateway-screen-to-the-payment-methods-tab

Add gateway redirects to new settings UI with highlight support (4290)
This commit is contained in:
Emili Castells 2025-03-07 15:11:58 +01:00 committed by GitHub
commit 3cb69f0ae0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 188 additions and 10 deletions

View file

@ -1,3 +1,4 @@
import { useEffect } from '@wordpress/element';
import SettingsCard from '../../../../ReusableComponents/SettingsCard';
import { PaymentMethodsBlock } from '../../../../ReusableComponents/SettingsBlocks';
import usePaymentDependencyState from '../../../../../hooks/usePaymentDependencyState';
@ -6,20 +7,20 @@ import PaymentDependencyMessage from './PaymentDependencyMessage';
import SettingDependencyMessage from './SettingDependencyMessage';
import SpinnerOverlay from '../../../../ReusableComponents/SpinnerOverlay';
import { PaymentHooks, SettingsHooks } from '../../../../../data';
import { useNavigation } from '../../../../../hooks/useNavigation';
/**
* Renders a payment method card with dependency handling
*
* @param {Object} props - Component props
* @param {string} props.id - Unique identifier for the card
* @param {string} props.title - Title of the payment method card
* @param {string} props.description - Description of the payment method
* @param {string} props.icon - Icon path for the payment method
* @param {Array} props.methods - List of payment methods to display
* @param {Object} props.methodsMap - Map of all payment methods by ID
* @param {Function} props.onTriggerModal - Callback when a method is clicked
* @param {boolean} props.isDisabled - Whether the entire card is disabled
* @param {(string|JSX.Element)} props.disabledMessage - Message to show when disabled
* @param {Object} props - Component props
* @param {string} props.id - Unique identifier for the card
* @param {string} props.title - Title of the payment method card
* @param {string} props.description - Description of the payment method
* @param {string} props.icon - Icon path for the payment method
* @param {Array} props.methods - List of payment methods to display
* @param {Object} props.methodsMap - Map of all payment methods by ID
* @param {Function} props.onTriggerModal - Callback when a method is clicked
* @param {boolean} props.isDisabled - Whether the entire card is disabled
* @return {JSX.Element} The rendered component
*/
const PaymentMethodCard = ( {
@ -34,6 +35,7 @@ const PaymentMethodCard = ( {
} ) => {
const { isReady: isPaymentStoreReady } = PaymentHooks.useStore();
const { isReady: isSettingsStoreReady } = SettingsHooks.useStore();
const { handleHighlightFromUrl } = useNavigation();
const paymentDependencies = usePaymentDependencyState(
methods,
@ -42,6 +44,12 @@ const PaymentMethodCard = ( {
const settingDependencies = useSettingDependencyState( methods );
useEffect( () => {
if ( isPaymentStoreReady && isSettingsStoreReady ) {
handleHighlightFromUrl();
}
}, [ handleHighlightFromUrl, isPaymentStoreReady, isSettingsStoreReady ] );
if ( ! isPaymentStoreReady || ! isSettingsStoreReady ) {
return <SpinnerOverlay asModal={ true } />;
}

View file

@ -1,3 +1,5 @@
import { scrollAndHighlight } from '../utils/scrollAndHighlight';
/**
* Navigate to the WooCommerce "Payments" settings tab, i.e. exit the settings app.
*/
@ -22,9 +24,38 @@ const goToPluginSettings = ( panel = null ) => {
window.location.href = url;
};
/**
* Check URL for highlight parameter and scroll to the element if present.
*
* @return {boolean} Whether a highlight parameter was found and processed
*/
const handleHighlightFromUrl = () => {
const urlParams = new URLSearchParams( window.location.search );
const elementId = urlParams.get( 'highlight' );
if ( elementId ) {
setTimeout( () => {
scrollAndHighlight( elementId );
// Clean up the URL by removing the highlight parameter.
urlParams.delete( 'highlight' );
const newUrl =
window.location.pathname +
( urlParams.toString() ? '?' + urlParams.toString() : '' ) +
window.location.hash;
window.history.replaceState( {}, document.title, newUrl );
}, 100 );
return true;
}
return false;
};
export const useNavigation = () => {
return {
goToWooCommercePaymentsTab,
goToPluginSettings,
handleHighlightFromUrl,
};
};

View file

@ -37,6 +37,7 @@ use WooCommerce\PayPalCommerce\Settings\Handler\ConnectionListener;
use WooCommerce\PayPalCommerce\Settings\Service\AuthenticationManager;
use WooCommerce\PayPalCommerce\Settings\Service\ConnectionUrlGenerator;
use WooCommerce\PayPalCommerce\Settings\Service\FeaturesEligibilityService;
use WooCommerce\PayPalCommerce\Settings\Service\GatewayRedirectService;
use WooCommerce\PayPalCommerce\Settings\Service\OnboardingUrlManager;
use WooCommerce\PayPalCommerce\Settings\Service\TodosEligibilityService;
use WooCommerce\PayPalCommerce\Settings\Service\TodosSortingAndFilteringService;
@ -566,4 +567,7 @@ return array(
$container->get( 'settings.data.todos' )
);
},
'settings.service.gateway-redirect' => static function (): GatewayRedirectService {
return new GatewayRedirectService();
},
);

View file

@ -0,0 +1,129 @@
<?php
/**
* Provides gateway redirect handling logic.
*
* @package WooCommerce\PayPalCommerce\Settings\Service
*/
declare( strict_types = 1 );
namespace WooCommerce\PayPalCommerce\Settings\Service;
use WooCommerce\PayPalCommerce\Axo\Gateway\AxoGateway;
use WooCommerce\PayPalCommerce\Applepay\ApplePayGateway;
use WooCommerce\PayPalCommerce\Googlepay\GooglePayGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\BancontactGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\BlikGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\EPSGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\IDealGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\MultibancoGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\MyBankGateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\P24Gateway;
use WooCommerce\PayPalCommerce\LocalAlternativePaymentMethods\TrustlyGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO\OXXO;
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayUponInvoice\PayUponInvoiceGateway;
/**
* GatewayRedirectService class. Handles redirects from individual gateway
* settings URLs to the new Settings UI page.
*/
class GatewayRedirectService {
/**
* List of gateways to redirect.
*
* @var string[]
*/
private array $gateways;
/**
* Constructor.
*/
public function __construct() {
$this->gateways = array(
AxoGateway::ID,
GooglePayGateway::ID,
ApplePayGateway::ID,
CreditCardGateway::ID,
CardButtonGateway::ID,
BancontactGateway::ID,
BlikGateway::ID,
EPSGateway::ID,
IDealGateway::ID,
MyBankGateway::ID,
P24Gateway::ID,
TrustlyGateway::ID,
MultibancoGateway::ID,
OXXO::ID,
PayUponInvoiceGateway::ID,
);
}
/**
* Register hooks.
*
* @return void
*/
public function register(): void {
add_action(
'admin_init',
array( $this, 'handle_redirects' )
);
}
/**
* Handle redirects for gateway settings pages.
*
* @return void
*/
public function handle_redirects(): void {
if ( ! is_admin() ) {
return;
}
// Get current URL parameters.
// phpcs:disable WordPress.Security.NonceVerification.Recommended
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
// phpcs:disable WordPress.Security.ValidatedSanitizedInput.MissingUnslash
// The sanitize_get_param method handles unslashing and sanitization internally.
$page = isset( $_GET['page'] ) ? $this->sanitize_get_param( $_GET['page'] ) : '';
$tab = isset( $_GET['tab'] ) ? $this->sanitize_get_param( $_GET['tab'] ) : '';
$section = isset( $_GET['section'] ) ? $this->sanitize_get_param( $_GET['section'] ) : '';
// phpcs:enable WordPress.Security.ValidatedSanitizedInput.MissingUnslash
// phpcs:enable WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
// phpcs:enable WordPress.Security.NonceVerification.Recommended
// Check if we're on a WooCommerce settings page and checkout tab.
if ( $page !== 'wc-settings' || $tab !== 'checkout' ) {
return;
}
// Check if we're on one of the gateway settings pages we want to redirect.
if ( in_array( $section, $this->gateways, true ) ) {
$redirect_url = admin_url(
sprintf(
'admin.php?page=wc-settings&tab=checkout&section=ppcp-gateway&panel=payment-methods&highlight=%s',
$section
)
);
wp_safe_redirect( $redirect_url );
exit;
}
}
/**
* Sanitizes a GET parameter that could be string or array.
*
* @param mixed $param The parameter to sanitize.
* @return string The sanitized parameter.
*/
private function sanitize_get_param( $param ): string {
if ( is_array( $param ) ) {
return '';
}
return sanitize_text_field( wp_unslash( $param ) );
}
}

View file

@ -28,6 +28,7 @@ use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile;
use WooCommerce\PayPalCommerce\Settings\Data\TodosModel;
use WooCommerce\PayPalCommerce\Settings\Endpoint\RestEndpoint;
use WooCommerce\PayPalCommerce\Settings\Handler\ConnectionListener;
use WooCommerce\PayPalCommerce\Settings\Service\GatewayRedirectService;
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule;
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
@ -577,6 +578,11 @@ class SettingsModule implements ServiceModule, ExecutableModule {
}
);
// Redirect payment method links in the WC Payment Gateway to the new UI Payment Methods tab.
$gateway_redirect_service = $container->get( 'settings.service.gateway-redirect' );
assert( $gateway_redirect_service instanceof GatewayRedirectService );
$gateway_redirect_service->register();
return true;
}