mirror of
https://github.com/woocommerce/woocommerce-paypal-payments.git
synced 2025-09-04 08:47:23 +08:00
Merge remote-tracking branch 'origin/trunk' into PCP-3814-Create-dashboard-placeholder-page-in-new-settings-module
This commit is contained in:
commit
637a9c6dca
55 changed files with 2102 additions and 244 deletions
|
@ -67,7 +67,7 @@ class BillingSubscriptions {
|
|||
*/
|
||||
public function suspend( string $id ):void {
|
||||
$data = array(
|
||||
'reason' => 'Suspended by customer',
|
||||
'reason' => sprintf( 'Suspended by %s.', is_admin() ? 'merchant' : 'customer' ),
|
||||
);
|
||||
|
||||
$bearer = $this->bearer->bearer();
|
||||
|
@ -107,7 +107,7 @@ class BillingSubscriptions {
|
|||
*/
|
||||
public function activate( string $id ): void {
|
||||
$data = array(
|
||||
'reason' => 'Reactivated by customer',
|
||||
'reason' => sprintf( 'Reactivated by %s.', is_admin() ? 'merchant' : 'customer' ),
|
||||
);
|
||||
|
||||
$bearer = $this->bearer->bearer();
|
||||
|
@ -148,7 +148,7 @@ class BillingSubscriptions {
|
|||
*/
|
||||
public function cancel( string $id ): void {
|
||||
$data = array(
|
||||
'reason' => 'Cancelled by customer',
|
||||
'reason' => sprintf( 'Cancelled by %s.', is_admin() ? 'merchant' : 'customer' ),
|
||||
);
|
||||
|
||||
$bearer = $this->bearer->bearer();
|
||||
|
|
|
@ -113,7 +113,7 @@ class BlocksPaymentMethod extends AbstractPaymentMethodType {
|
|||
'id' => $this->name,
|
||||
'title' => $paypal_data['title'], // TODO : see if we should use another.
|
||||
'description' => $paypal_data['description'], // TODO : see if we should use another.
|
||||
'enabled' => $paypal_data['enabled'], // This button is enabled when PayPal buttons are.
|
||||
'enabled' => $paypal_data['smartButtonsEnabled'], // This button is enabled when PayPal buttons are.
|
||||
'scriptData' => $script_data,
|
||||
);
|
||||
}
|
||||
|
|
|
@ -19,11 +19,9 @@ export function CardFields( {
|
|||
config,
|
||||
eventRegistration,
|
||||
emitResponse,
|
||||
components,
|
||||
} ) {
|
||||
const { onPaymentSetup } = eventRegistration;
|
||||
const { responseTypes } = emitResponse;
|
||||
const { PaymentMethodIcons } = components;
|
||||
|
||||
const [ cardFieldsForm, setCardFieldsForm ] = useState();
|
||||
const getCardFieldsForm = ( cardFieldsForm ) => {
|
||||
|
@ -95,10 +93,6 @@ export function CardFields( {
|
|||
} }
|
||||
>
|
||||
<PayPalCardFieldsForm />
|
||||
<PaymentMethodIcons
|
||||
icons={ config.card_icons }
|
||||
align="left"
|
||||
/>
|
||||
<CheckoutHandler
|
||||
getCardFieldsForm={ getCardFieldsForm }
|
||||
getSavePayment={ getSavePayment }
|
||||
|
|
|
@ -1,19 +1,30 @@
|
|||
import { registerPaymentMethod } from '@woocommerce/blocks-registry';
|
||||
import { CardFields } from './Components/card-fields';
|
||||
import {registerPaymentMethod} from '@woocommerce/blocks-registry';
|
||||
import {CardFields} from './Components/card-fields';
|
||||
|
||||
const config = wc.wcSettings.getSetting( 'ppcp-credit-card-gateway_data' );
|
||||
const config = wc.wcSettings.getSetting('ppcp-credit-card-gateway_data');
|
||||
|
||||
registerPaymentMethod( {
|
||||
name: config.id,
|
||||
label: <div dangerouslySetInnerHTML={ { __html: config.title } } />,
|
||||
content: <CardFields config={ config } />,
|
||||
edit: <CardFields config={ config } />,
|
||||
ariaLabel: config.title,
|
||||
canMakePayment: () => {
|
||||
return true;
|
||||
},
|
||||
supports: {
|
||||
showSavedCards: true,
|
||||
features: config.supports,
|
||||
},
|
||||
} );
|
||||
const Label = ({components, config}) => {
|
||||
const {PaymentMethodIcons} = components;
|
||||
return <>
|
||||
<span dangerouslySetInnerHTML={{__html: config.title}}/>
|
||||
<PaymentMethodIcons
|
||||
icons={ config.card_icons }
|
||||
align="right"
|
||||
/>
|
||||
</>
|
||||
}
|
||||
|
||||
registerPaymentMethod({
|
||||
name: config.id,
|
||||
label: <Label config={config}/>,
|
||||
content: <CardFields config={config}/>,
|
||||
edit: <CardFields config={config}/>,
|
||||
ariaLabel: config.title,
|
||||
canMakePayment: () => {
|
||||
return true;
|
||||
},
|
||||
supports: {
|
||||
showSavedCards: true,
|
||||
features: config.supports,
|
||||
},
|
||||
});
|
||||
|
|
|
@ -739,11 +739,8 @@ if ( cartHasSubscriptionProducts( config.scriptData ) ) {
|
|||
features.push( 'subscriptions' );
|
||||
}
|
||||
|
||||
if ( block_enabled && config.enabled ) {
|
||||
if (
|
||||
( config.addPlaceOrderMethod || config.usePlaceOrder ) &&
|
||||
! config.scriptData.continuation
|
||||
) {
|
||||
if ( block_enabled ) {
|
||||
if ( config.placeOrderEnabled && ! config.scriptData.continuation ) {
|
||||
let descriptionElement = (
|
||||
<div
|
||||
dangerouslySetInnerHTML={ { __html: config.description } }
|
||||
|
@ -776,7 +773,7 @@ if ( block_enabled && config.enabled ) {
|
|||
placeOrderButtonLabel: config.placeOrderButtonText,
|
||||
ariaLabel: config.title,
|
||||
canMakePayment: () => {
|
||||
return config.enabled;
|
||||
return true;
|
||||
},
|
||||
supports: {
|
||||
features,
|
||||
|
@ -798,7 +795,7 @@ if ( block_enabled && config.enabled ) {
|
|||
features: [ ...features, 'ppcp_continuation' ],
|
||||
},
|
||||
} );
|
||||
} else if ( ! config.usePlaceOrder ) {
|
||||
} else if ( config.smartButtonsEnabled ) {
|
||||
for ( const fundingSource of [
|
||||
'paypal',
|
||||
...config.enabledFundingSources,
|
||||
|
|
|
@ -47,6 +47,7 @@ return array(
|
|||
$container->get( 'blocks.settings.final_review_enabled' ),
|
||||
$container->get( 'session.cancellation.view' ),
|
||||
$container->get( 'session.handler' ),
|
||||
$container->get( 'wc-subscriptions.helper' ),
|
||||
$container->get( 'blocks.add-place-order-method' ),
|
||||
$container->get( 'wcgateway.use-place-order-button' ),
|
||||
$container->get( 'wcgateway.place-order-button-text' ),
|
||||
|
|
|
@ -19,6 +19,7 @@ use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
/**
|
||||
* Class PayPalPaymentMethod
|
||||
|
@ -87,6 +88,13 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
|||
*/
|
||||
private $session_handler;
|
||||
|
||||
/**
|
||||
* The Subscription Helper.
|
||||
*
|
||||
* @var SubscriptionHelper
|
||||
*/
|
||||
private $subscription_helper;
|
||||
|
||||
/**
|
||||
* Whether to create a non-express method with the standard "Place order" button.
|
||||
*
|
||||
|
@ -141,6 +149,7 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
|||
* @param bool $final_review_enabled Whether the final review is enabled.
|
||||
* @param CancelView $cancellation_view The cancellation view.
|
||||
* @param SessionHandler $session_handler The Session handler.
|
||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||
* @param bool $add_place_order_method Whether to create a non-express method with the standard "Place order" button.
|
||||
* @param bool $use_place_order Whether to use the standard "Place order" button instead of PayPal buttons.
|
||||
* @param string $place_order_button_text The text for the standard "Place order" button.
|
||||
|
@ -158,6 +167,7 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
|||
bool $final_review_enabled,
|
||||
CancelView $cancellation_view,
|
||||
SessionHandler $session_handler,
|
||||
SubscriptionHelper $subscription_helper,
|
||||
bool $add_place_order_method,
|
||||
bool $use_place_order,
|
||||
string $place_order_button_text,
|
||||
|
@ -175,6 +185,7 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
|||
$this->final_review_enabled = $final_review_enabled;
|
||||
$this->cancellation_view = $cancellation_view;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->subscription_helper = $subscription_helper;
|
||||
$this->add_place_order_method = $add_place_order_method;
|
||||
$this->use_place_order = $use_place_order;
|
||||
$this->place_order_button_text = $place_order_button_text;
|
||||
|
@ -195,9 +206,7 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
|||
// Do not load when definitely not needed,
|
||||
// but we still need to check the locations later and handle in JS
|
||||
// because has_block cannot be called here (too early).
|
||||
return $this->plugin_settings->has( 'enabled' ) && $this->plugin_settings->get( 'enabled' )
|
||||
&& ( $this->settings_status->is_smart_button_enabled_for_location( 'checkout-block-express' ) ||
|
||||
$this->settings_status->is_smart_button_enabled_for_location( 'cart-block' ) );
|
||||
return $this->plugin_settings->has( 'enabled' ) && $this->plugin_settings->get( 'enabled' );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -245,15 +254,19 @@ class PayPalPaymentMethod extends AbstractPaymentMethodType {
|
|||
);
|
||||
}
|
||||
|
||||
$smart_buttons_enabled = ! $this->use_place_order
|
||||
&& $this->settings_status->is_smart_button_enabled_for_location( $script_data['context'] ?? 'block-checkout' );
|
||||
$place_order_enabled = ( $this->use_place_order || $this->add_place_order_method )
|
||||
&& ! $this->subscription_helper->cart_contains_subscription();
|
||||
|
||||
return array(
|
||||
'id' => $this->gateway->id,
|
||||
'title' => $this->gateway->title,
|
||||
'description' => $this->gateway->description,
|
||||
'enabled' => $this->settings_status->is_smart_button_enabled_for_location( $script_data['context'] ?? 'checkout' ),
|
||||
'smartButtonsEnabled' => $smart_buttons_enabled,
|
||||
'placeOrderEnabled' => $place_order_enabled,
|
||||
'fundingSource' => $this->session_handler->funding_source(),
|
||||
'finalReviewEnabled' => $this->final_review_enabled,
|
||||
'addPlaceOrderMethod' => $this->add_place_order_method,
|
||||
'usePlaceOrder' => $this->use_place_order,
|
||||
'placeOrderButtonText' => $this->place_order_button_text,
|
||||
'placeOrderButtonDescription' => $this->place_order_button_description,
|
||||
'enabledFundingSources' => $funding_sources,
|
||||
|
|
|
@ -233,6 +233,15 @@ class SingleProductBootstap {
|
|||
this.form(),
|
||||
this.errorHandler
|
||||
);
|
||||
if (
|
||||
! this.gateway.vaultingEnabled &&
|
||||
[ 'subscription', 'variable-subscription' ].includes(
|
||||
this.gateway.productType
|
||||
) &&
|
||||
this.gateway.manualRenewalEnabled !== '1'
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
PayPalCommerceGateway.data_client_id.has_subscriptions &&
|
||||
|
|
|
@ -37,6 +37,7 @@ use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply;
|
|||
use WooCommerce\PayPalCommerce\Button\Helper\ThreeDSecure;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||
|
||||
return array(
|
||||
'button.client_id' => static function ( ContainerInterface $container ): string {
|
||||
|
@ -101,12 +102,20 @@ return array(
|
|||
return $obj->get_context();
|
||||
},
|
||||
'button.smart-button' => static function ( ContainerInterface $container ): SmartButtonInterface {
|
||||
$state = $container->get( 'onboarding.state' );
|
||||
if ( $container->get( 'wcgateway.use-place-order-button' )
|
||||
&& in_array( $container->get( 'button.context' ), array( 'checkout', 'pay-now' ), true )
|
||||
) {
|
||||
return new DisabledSmartButton();
|
||||
$context = $container->get( 'button.context' );
|
||||
|
||||
$settings_status = $container->get( 'wcgateway.settings.status' );
|
||||
assert( $settings_status instanceof SettingsStatus );
|
||||
|
||||
if ( in_array( $context, array( 'checkout', 'pay-now' ), true ) ) {
|
||||
if ( $container->get( 'wcgateway.use-place-order-button' )
|
||||
|| ! $settings_status->is_smart_button_enabled_for_location( $context )
|
||||
) {
|
||||
return new DisabledSmartButton();
|
||||
}
|
||||
}
|
||||
|
||||
$state = $container->get( 'onboarding.state' );
|
||||
if ( $state->current_state() !== State::STATE_ONBOARDED ) {
|
||||
return new DisabledSmartButton();
|
||||
}
|
||||
|
@ -125,7 +134,6 @@ return array(
|
|||
$messages_apply = $container->get( 'button.helper.messages-apply' );
|
||||
$environment = $container->get( 'onboarding.environment' );
|
||||
$payment_token_repository = $container->get( 'vaulting.repository.payment-token' );
|
||||
$settings_status = $container->get( 'wcgateway.settings.status' );
|
||||
return new SmartButton(
|
||||
$container->get( 'button.url' ),
|
||||
$container->get( 'ppcp.asset-version' ),
|
||||
|
|
|
@ -1031,8 +1031,11 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
|||
* @return bool
|
||||
*/
|
||||
private function has_subscriptions(): bool {
|
||||
if ( ! $this->subscription_helper->plugin_is_active() ) {
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
! $this->subscription_helper->accept_only_automatic_payment_gateways()
|
||||
$this->subscription_helper->accept_manual_renewals()
|
||||
&& $this->paypal_subscriptions_enabled() !== true
|
||||
) {
|
||||
return false;
|
||||
|
@ -1318,8 +1321,17 @@ document.querySelector("#payment").before(document.querySelector(".ppcp-messages
|
|||
'should_handle_shipping_in_paypal' => $this->should_handle_shipping_in_paypal && ! $this->is_checkout(),
|
||||
'needShipping' => $this->need_shipping(),
|
||||
'vaultingEnabled' => $this->settings->has( 'vault_enabled' ) && $this->settings->get( 'vault_enabled' ),
|
||||
'productType' => null,
|
||||
'manualRenewalEnabled' => $this->subscription_helper->accept_manual_renewals(),
|
||||
);
|
||||
|
||||
if ( is_product() ) {
|
||||
$product = wc_get_product( get_the_ID() );
|
||||
if ( is_a( $product, \WC_Product::class ) ) {
|
||||
$localize['productType'] = $product->get_type();
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'pay-now' === $this->context() ) {
|
||||
$localize['pay_now'] = $this->pay_now_script_data();
|
||||
}
|
||||
|
|
|
@ -101,7 +101,7 @@ class CompatModule implements ServiceModule, ExtendingModule, ExecutableModule {
|
|||
add_action(
|
||||
'woocommerce_init',
|
||||
function() {
|
||||
if ( is_callable( array( WC(), 'is_wc_admin_active' ) ) && WC()->is_wc_admin_active() && class_exists( 'Automattic\WooCommerce\Admin\Notes\Notes' ) ) {
|
||||
if ( is_admin() && is_callable( array( WC(), 'is_wc_admin_active' ) ) && WC()->is_wc_admin_active() && class_exists( 'Automattic\WooCommerce\Admin\Notes\Notes' ) ) {
|
||||
PPEC\DeactivateNote::init();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -174,6 +174,7 @@ return array(
|
|||
$container->get( 'googlepay.sdk_url' ),
|
||||
$container->get( 'ppcp.asset-version' ),
|
||||
$container->get( 'session.handler' ),
|
||||
$container->get( 'wc-subscriptions.helper' ),
|
||||
$container->get( 'wcgateway.settings' ),
|
||||
$container->get( 'onboarding.environment' ),
|
||||
$container->get( 'wcgateway.settings.status' ),
|
||||
|
|
|
@ -107,7 +107,7 @@ class BlocksPaymentMethod extends AbstractPaymentMethodType {
|
|||
'id' => $this->name,
|
||||
'title' => $paypal_data['title'], // See if we should use another.
|
||||
'description' => $paypal_data['description'], // See if we should use another.
|
||||
'enabled' => $paypal_data['enabled'], // This button is enabled when PayPal buttons are.
|
||||
'enabled' => $paypal_data['smartButtonsEnabled'], // This button is enabled when PayPal buttons are.
|
||||
'scriptData' => $this->button->script_data(),
|
||||
);
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ use WooCommerce\PayPalCommerce\Session\SessionHandler;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\SettingsStatus;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings;
|
||||
use WooCommerce\PayPalCommerce\WcSubscriptions\Helper\SubscriptionHelper;
|
||||
|
||||
/**
|
||||
* Class Button
|
||||
|
@ -85,37 +86,47 @@ class Button implements ButtonInterface {
|
|||
*/
|
||||
private $session_handler;
|
||||
|
||||
/**
|
||||
* The Subscription Helper.
|
||||
*
|
||||
* @var SubscriptionHelper
|
||||
*/
|
||||
private $subscription_helper;
|
||||
|
||||
/**
|
||||
* SmartButton constructor.
|
||||
*
|
||||
* @param string $module_url The URL to the module.
|
||||
* @param string $sdk_url The URL to the SDK.
|
||||
* @param string $version The assets version.
|
||||
* @param SessionHandler $session_handler The Session handler.
|
||||
* @param Settings $settings The Settings.
|
||||
* @param Environment $environment The environment object.
|
||||
* @param SettingsStatus $settings_status The Settings status helper.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param string $module_url The URL to the module.
|
||||
* @param string $sdk_url The URL to the SDK.
|
||||
* @param string $version The assets version.
|
||||
* @param SessionHandler $session_handler The Session handler.
|
||||
* @param SubscriptionHelper $subscription_helper The subscription helper.
|
||||
* @param Settings $settings The Settings.
|
||||
* @param Environment $environment The environment object.
|
||||
* @param SettingsStatus $settings_status The Settings status helper.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
string $module_url,
|
||||
string $sdk_url,
|
||||
string $version,
|
||||
SessionHandler $session_handler,
|
||||
SubscriptionHelper $subscription_helper,
|
||||
Settings $settings,
|
||||
Environment $environment,
|
||||
SettingsStatus $settings_status,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
$this->module_url = $module_url;
|
||||
$this->sdk_url = $sdk_url;
|
||||
$this->version = $version;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->settings = $settings;
|
||||
$this->environment = $environment;
|
||||
$this->settings_status = $settings_status;
|
||||
$this->logger = $logger;
|
||||
$this->module_url = $module_url;
|
||||
$this->sdk_url = $sdk_url;
|
||||
$this->version = $version;
|
||||
$this->session_handler = $session_handler;
|
||||
$this->subscription_helper = $subscription_helper;
|
||||
$this->settings = $settings;
|
||||
$this->environment = $environment;
|
||||
$this->settings_status = $settings_status;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -233,6 +244,21 @@ class Button implements ButtonInterface {
|
|||
$button_enabled_payorder = true;
|
||||
$button_enabled_minicart = $this->settings_status->is_smart_button_enabled_for_location( 'mini-cart' );
|
||||
|
||||
if (
|
||||
$this->subscription_helper->plugin_is_active()
|
||||
&& ! $this->subscription_helper->accept_manual_renewals()
|
||||
) {
|
||||
if ( is_product() && $this->subscription_helper->current_product_is_subscription() ) {
|
||||
return false;
|
||||
}
|
||||
if ( $this->subscription_helper->order_pay_contains_subscription() ) {
|
||||
return false;
|
||||
}
|
||||
if ( $this->subscription_helper->cart_contains_subscription() ) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Param types removed to avoid third-party issues.
|
||||
*
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
import {
|
||||
setVisible,
|
||||
setVisibleByClass,
|
||||
} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
||||
|
||||
document.addEventListener( 'DOMContentLoaded', () => {
|
||||
const payLaterMessagingSelectableLocations = [
|
||||
'product',
|
||||
|
@ -216,6 +221,18 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
|||
replace();
|
||||
};
|
||||
|
||||
const hideElements = ( selectorGroup ) => {
|
||||
selectorGroup.forEach( ( selector ) =>
|
||||
setVisibleByClass( selector, false, 'hide' )
|
||||
);
|
||||
};
|
||||
|
||||
const showElements = ( selectorGroup ) => {
|
||||
selectorGroup.forEach( ( selector ) =>
|
||||
setVisibleByClass( selector, true, 'hide' )
|
||||
);
|
||||
};
|
||||
|
||||
const toggleInputsBySelectedLocations = (
|
||||
stylingPerSelector,
|
||||
locationsSelector,
|
||||
|
@ -226,30 +243,30 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
|||
const payLaterMessagingEnabled = document.querySelector(
|
||||
payLaterMessagingEnabledSelector
|
||||
);
|
||||
const stylingPerElement = document.querySelector( stylingPerSelector );
|
||||
const locationsElement = document.querySelector( locationsSelector );
|
||||
const stylingPerElementWrapper = stylingPerElement?.closest( 'tr' );
|
||||
const stylingPerElementWrapperSelector =
|
||||
'#' + stylingPerElementWrapper?.getAttribute( 'id' );
|
||||
|
||||
const stylingPerElement = document.querySelector( stylingPerSelector );
|
||||
if ( ! stylingPerElement ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const stylingPerElementWrapper = stylingPerElement.closest( 'tr' );
|
||||
|
||||
const toggleElementsBySelectedLocations = () => {
|
||||
stylingPerElementWrapper.style.display = '';
|
||||
const selectedLocations = getSelectedLocations( locationsSelector );
|
||||
const emptySmartButtonLocationMessage = jQuery(
|
||||
'.ppcp-empty-smart-button-location'
|
||||
|
||||
setVisibleByClass(
|
||||
stylingPerElementWrapper,
|
||||
selectedLocations.length > 0,
|
||||
'hide'
|
||||
);
|
||||
|
||||
if ( selectedLocations.length === 0 ) {
|
||||
hideElements(
|
||||
groupToHideOnChecked.concat(
|
||||
stylingPerElementWrapperSelector
|
||||
)
|
||||
hideElements( groupToHideOnChecked );
|
||||
|
||||
const emptySmartButtonLocationMessage = document.querySelector(
|
||||
'.ppcp-empty-smart-button-location'
|
||||
);
|
||||
if ( emptySmartButtonLocationMessage.length === 0 ) {
|
||||
if ( ! emptySmartButtonLocationMessage ) {
|
||||
jQuery(
|
||||
PayPalCommerceSettings.empty_smart_button_location_message
|
||||
).insertAfter(
|
||||
|
@ -277,11 +294,11 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
|||
);
|
||||
|
||||
groupToShowOnChecked.forEach( ( element ) => {
|
||||
if ( inputSelectors.includes( element ) ) {
|
||||
document.querySelector( element ).style.display = '';
|
||||
return;
|
||||
}
|
||||
document.querySelector( element ).style.display = 'none';
|
||||
setVisibleByClass(
|
||||
element,
|
||||
inputSelectors.includes( element ),
|
||||
'hide'
|
||||
);
|
||||
} );
|
||||
|
||||
if ( inputType === 'messages' ) {
|
||||
|
@ -289,18 +306,6 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
|||
}
|
||||
};
|
||||
|
||||
const hideElements = ( selectroGroup ) => {
|
||||
selectroGroup.forEach( ( elementToHide ) => {
|
||||
document.querySelector( elementToHide ).style.display = 'none';
|
||||
} );
|
||||
};
|
||||
|
||||
const showElements = ( selectroGroup ) => {
|
||||
selectroGroup.forEach( ( elementToShow ) => {
|
||||
document.querySelector( elementToShow ).style.display = '';
|
||||
} );
|
||||
};
|
||||
|
||||
groupToggle( stylingPerSelector, groupToShowOnChecked );
|
||||
toggleElementsBySelectedLocations();
|
||||
|
||||
|
@ -327,7 +332,7 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
|||
} );
|
||||
|
||||
// We need to use jQuery here as the select might be a select2 element, which doesn't use native events.
|
||||
jQuery( locationsElement ).on( 'change', function () {
|
||||
jQuery( locationsSelector ).on( 'change', function () {
|
||||
const emptySmartButtonLocationMessage = jQuery(
|
||||
'.ppcp-empty-smart-button-location'
|
||||
);
|
||||
|
@ -457,6 +462,38 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
|||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hide the subscription settings when smart buttons are disabled for checkout,
|
||||
* since the basic redirect gateway is disabled for subscriptions.
|
||||
*/
|
||||
const initSettingsHidingForPlaceOrderGateway = () => {
|
||||
const selectors = [
|
||||
'#field-paypal_saved_payments',
|
||||
'#field-subscriptions_mode',
|
||||
'#field-vault_enabled',
|
||||
];
|
||||
|
||||
const updateSettingsVisibility = () => {
|
||||
const selectedLocations = getSelectedLocations(
|
||||
smartButtonLocationsSelect
|
||||
);
|
||||
const hasCheckoutSmartButtons =
|
||||
selectedLocations.includes( 'checkout' ) ||
|
||||
selectedLocations.includes( 'checkout-block-express' );
|
||||
|
||||
selectors.forEach( ( selector ) => {
|
||||
setVisibleByClass( selector, hasCheckoutSmartButtons, 'hide' );
|
||||
} );
|
||||
};
|
||||
|
||||
updateSettingsVisibility();
|
||||
|
||||
jQuery( smartButtonLocationsSelect ).on(
|
||||
'change',
|
||||
updateSettingsVisibility
|
||||
);
|
||||
};
|
||||
|
||||
( () => {
|
||||
removeDisabledCardIcons(
|
||||
'select[name="ppcp[disable_cards][]"]',
|
||||
|
@ -488,6 +525,8 @@ document.addEventListener( 'DOMContentLoaded', () => {
|
|||
|
||||
toggleMessagingEnabled();
|
||||
|
||||
initSettingsHidingForPlaceOrderGateway();
|
||||
|
||||
groupToggle( '#ppcp-vault_enabled', [
|
||||
'#field-subscription_behavior_when_vault_fails',
|
||||
] );
|
||||
|
|
|
@ -117,7 +117,7 @@ class OnboardingAssets {
|
|||
array(
|
||||
'empty_smart_button_location_message' => sprintf(
|
||||
'<p class="description ppcp-empty-smart-button-location">%1$s</p>',
|
||||
__( 'Note: If no button location is selected, the PayPal gateway will not be available.', 'woocommerce-paypal-payments' )
|
||||
__( 'Note: PayPal buttons and advanced payment features (Alternative Payment Methods, Subscriptions, etc.) are unavailable if no Smart Button Location is configured.', 'woocommerce-paypal-payments' )
|
||||
),
|
||||
)
|
||||
);
|
||||
|
|
|
@ -124,7 +124,7 @@ class MetaBoxRenderer {
|
|||
<label for="ppcp-tracking-items"><?php echo esc_html__( 'Select items for this shipment', 'woocommerce-paypal-payments' ); ?></label>
|
||||
<select multiple class="wc-enhanced-select ppcp-tracking-items" id="ppcp-tracking-items" name="ppcp-tracking[items]">
|
||||
<?php foreach ( $order_items as $item ) : ?>
|
||||
<option value="<?php echo intval( $item->get_id() ); ?>"><?php echo esc_html( $item->get_name() ); ?></option>
|
||||
<option value="<?php echo intval( $item->get_id() ); ?>"><?php echo esc_attr( wp_strip_all_tags( $item->get_name() ) ); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
|
|
|
@ -40,4 +40,13 @@ return array(
|
|||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
'paypal-subscriptions.renewal-handler' => static function ( ContainerInterface $container ): RenewalHandler {
|
||||
return new RenewalHandler( $container->get( 'woocommerce.logger.woocommerce' ) );
|
||||
},
|
||||
'paypal-subscriptions.status' => static function ( ContainerInterface $container ): SubscriptionStatus {
|
||||
return new SubscriptionStatus(
|
||||
$container->get( 'api.endpoint.billing-subscriptions' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
);
|
||||
|
|
|
@ -187,6 +187,9 @@ class PayPalSubscriptionsModule implements ServiceModule, ExtendingModule, Execu
|
|||
30
|
||||
);
|
||||
|
||||
/**
|
||||
* Executed when updating WC Subscription.
|
||||
*/
|
||||
add_action(
|
||||
'woocommerce_process_shop_subscription_meta',
|
||||
/**
|
||||
|
@ -194,65 +197,41 @@ class PayPalSubscriptionsModule implements ServiceModule, ExtendingModule, Execu
|
|||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
function( $id, $post ) use ( $c ) {
|
||||
function( $id ) use ( $c ) {
|
||||
$subscription = wcs_get_subscription( $id );
|
||||
if ( ! is_a( $subscription, WC_Subscription::class ) ) {
|
||||
if ( $subscription === false ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
|
||||
if ( ! $subscription_id ) {
|
||||
return;
|
||||
}
|
||||
$subscriptions_endpoint = $c->get( 'api.endpoint.billing-subscriptions' );
|
||||
assert( $subscriptions_endpoint instanceof BillingSubscriptions );
|
||||
|
||||
if ( $subscription->get_status() === 'cancelled' ) {
|
||||
try {
|
||||
$subscriptions_endpoint->cancel( $subscription_id );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
$subscription_status = $c->get( 'paypal-subscriptions.status' );
|
||||
assert( $subscription_status instanceof SubscriptionStatus );
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
$logger->error( 'Could not cancel subscription product on PayPal. ' . $error );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $subscription->get_status() === 'pending-cancel' ) {
|
||||
try {
|
||||
$subscriptions_endpoint->suspend( $subscription_id );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
$logger->error( 'Could not suspend subscription product on PayPal. ' . $error );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $subscription->get_status() === 'active' ) {
|
||||
try {
|
||||
$current_subscription = $subscriptions_endpoint->subscription( $subscription_id );
|
||||
if ( $current_subscription->status === 'SUSPENDED' ) {
|
||||
$subscriptions_endpoint->activate( $subscription_id );
|
||||
}
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
$logger = $c->get( 'woocommerce.logger.woocommerce' );
|
||||
$logger->error( 'Could not reactivate subscription product on PayPal. ' . $error );
|
||||
}
|
||||
}
|
||||
$subscription_status->update_status( $subscription->get_status(), $subscription_id );
|
||||
},
|
||||
20,
|
||||
2
|
||||
20
|
||||
);
|
||||
|
||||
/**
|
||||
* Update subscription status from WC Subscriptions list page action link.
|
||||
*/
|
||||
add_action(
|
||||
'woocommerce_subscription_status_updated',
|
||||
function( WC_Subscription $subscription ) use ( $c ) {
|
||||
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
|
||||
if ( ! $subscription_id ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subscription_status = $c->get( 'paypal-subscriptions.status' );
|
||||
assert( $subscription_status instanceof SubscriptionStatus );
|
||||
|
||||
$subscription_status->update_status( $subscription->get_status(), $subscription_id );
|
||||
}
|
||||
);
|
||||
|
||||
add_filter(
|
||||
|
@ -717,11 +696,18 @@ class PayPalSubscriptionsModule implements ServiceModule, ExtendingModule, Execu
|
|||
* @param WC_Product $product The product.
|
||||
* @param SubscriptionsApiHandler $subscriptions_api_handler The subscription api handler.
|
||||
* @return void
|
||||
*
|
||||
* @psalm-suppress PossiblyInvalidCast
|
||||
*/
|
||||
private function update_subscription_product_meta( WC_Product $product, SubscriptionsApiHandler $subscriptions_api_handler ): void {
|
||||
// phpcs:ignore WordPress.Security.NonceVerification
|
||||
$enable_subscription_product = wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) );
|
||||
$product->update_meta_data( '_ppcp_enable_subscription_product', $enable_subscription_product );
|
||||
$enable_subscription_product = wc_string_to_bool( (string) wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) ) );
|
||||
$product->update_meta_data( '_ppcp_enable_subscription_product', wc_bool_to_string( $enable_subscription_product ) );
|
||||
|
||||
if ( ! $enable_subscription_product ) {
|
||||
$product->save();
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! $product->get_sold_individually() ) {
|
||||
$product->set_sold_individually( true );
|
||||
|
@ -729,7 +715,7 @@ class PayPalSubscriptionsModule implements ServiceModule, ExtendingModule, Execu
|
|||
|
||||
$product->save();
|
||||
|
||||
if ( ( $product->get_type() === 'subscription' || $product->get_type() === 'subscription_variation' ) && $enable_subscription_product === 'yes' ) {
|
||||
if ( $product->get_type() === 'subscription' || $product->get_type() === 'subscription_variation' ) {
|
||||
if ( $product->meta_exists( 'ppcp_subscription_product' ) && $product->meta_exists( 'ppcp_subscription_plan' ) ) {
|
||||
$subscriptions_api_handler->update_product( $product );
|
||||
$subscriptions_api_handler->update_plan( $product );
|
||||
|
|
107
modules/ppcp-paypal-subscriptions/src/RenewalHandler.php
Normal file
107
modules/ppcp-paypal-subscriptions/src/RenewalHandler.php
Normal file
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
/**
|
||||
* Subscriptions renewal handler.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayPalSubscriptions;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Data_Exception;
|
||||
use WC_Order;
|
||||
use WC_Subscription;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||
|
||||
/**
|
||||
* Class RenewalHandler
|
||||
*/
|
||||
class RenewalHandler {
|
||||
|
||||
use TransactionIdHandlingTrait;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* RenewalHandler constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct( LoggerInterface $logger ) {
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process subscription renewal.
|
||||
*
|
||||
* @param WC_Subscription[] $subscriptions WC Subscriptions.
|
||||
* @param string $transaction_id PayPal transaction ID.
|
||||
* @return void
|
||||
* @throws WC_Data_Exception If something goes wrong while setting payment method.
|
||||
*/
|
||||
public function process( array $subscriptions, string $transaction_id ): void {
|
||||
foreach ( $subscriptions as $subscription ) {
|
||||
if ( $this->is_for_renewal_order( $subscription ) ) {
|
||||
$renewal_order = wcs_create_renewal_order( $subscription );
|
||||
if ( is_a( $renewal_order, WC_Order::class ) ) {
|
||||
$this->logger->info(
|
||||
sprintf(
|
||||
'Processing renewal order #%s for subscription #%s',
|
||||
$renewal_order->get_id(),
|
||||
$subscription->get_id()
|
||||
)
|
||||
);
|
||||
|
||||
$renewal_order->set_payment_method( $subscription->get_payment_method() );
|
||||
$renewal_order->payment_complete();
|
||||
$this->update_transaction_id( $transaction_id, $renewal_order, $this->logger );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$parent_order = wc_get_order( $subscription->get_parent() );
|
||||
if ( is_a( $parent_order, WC_Order::class ) ) {
|
||||
$this->logger->info(
|
||||
sprintf(
|
||||
'Processing parent order #%s for subscription #%s',
|
||||
$parent_order->get_id(),
|
||||
$subscription->get_id()
|
||||
)
|
||||
);
|
||||
|
||||
$subscription->update_meta_data( '_ppcp_is_subscription_renewal', 'true' );
|
||||
$subscription->save_meta_data();
|
||||
$this->update_transaction_id( $transaction_id, $parent_order, $this->logger );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether subscription order is for renewal or not.
|
||||
*
|
||||
* @param WC_Subscription $subscription WC Subscription.
|
||||
* @return bool
|
||||
*/
|
||||
private function is_for_renewal_order( WC_Subscription $subscription ): bool {
|
||||
$subscription_renewal_meta = $subscription->get_meta( '_ppcp_is_subscription_renewal' ) ?? '';
|
||||
if ( $subscription_renewal_meta === 'true' ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (
|
||||
time() >= $subscription->get_time( 'start' )
|
||||
&& ( time() - $subscription->get_time( 'start' ) ) <= ( 8 * HOUR_IN_SECONDS )
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
144
modules/ppcp-paypal-subscriptions/src/SubscriptionStatus.php
Normal file
144
modules/ppcp-paypal-subscriptions/src/SubscriptionStatus.php
Normal file
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
/**
|
||||
* Handles PayPal subscription status.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcSubscriptions
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\PayPalSubscriptions;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
|
||||
|
||||
/**
|
||||
* Class SubscriptionStatus
|
||||
*/
|
||||
class SubscriptionStatus {
|
||||
|
||||
/**
|
||||
* Billing subscriptions endpoint.
|
||||
*
|
||||
* @var BillingSubscriptions
|
||||
*/
|
||||
private $subscriptions_endpoint;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* SubscriptionStatus constructor.
|
||||
*
|
||||
* @param BillingSubscriptions $subscriptions_endpoint Billing subscriptions endpoint.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
BillingSubscriptions $subscriptions_endpoint,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->subscriptions_endpoint = $subscriptions_endpoint;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates PayPal subscription status from the given WC Subscription status.
|
||||
*
|
||||
* @param string $subscription_status The WC Subscription status.
|
||||
* @param string $subscription_id The PayPal Subscription ID.
|
||||
* @return void
|
||||
*/
|
||||
public function update_status( string $subscription_status, string $subscription_id ): void {
|
||||
if ( $subscription_status === 'pending-cancel' || $subscription_status === 'cancelled' ) {
|
||||
try {
|
||||
$current_subscription = $this->subscriptions_endpoint->subscription( $subscription_id );
|
||||
if ( $current_subscription->status === 'CANCELLED' ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->logger->info(
|
||||
sprintf(
|
||||
'Canceling PayPal subscription #%s.',
|
||||
$subscription_id
|
||||
)
|
||||
);
|
||||
|
||||
$this->subscriptions_endpoint->cancel( $subscription_id );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$this->logger->error(
|
||||
sprintf(
|
||||
'Could not cancel PayPal subscription #%s. %s',
|
||||
$subscription_id,
|
||||
$this->get_error( $exception )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( $subscription_status === 'on-hold' ) {
|
||||
try {
|
||||
$this->logger->info(
|
||||
sprintf(
|
||||
'Suspending PayPal subscription #%s.',
|
||||
$subscription_id
|
||||
)
|
||||
);
|
||||
|
||||
$this->subscriptions_endpoint->suspend( $subscription_id );
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$this->logger->error(
|
||||
sprintf(
|
||||
'Could not suspend PayPal subscription #%s. %s',
|
||||
$subscription_id,
|
||||
$this->get_error( $exception )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( $subscription_status === 'active' ) {
|
||||
try {
|
||||
$current_subscription = $this->subscriptions_endpoint->subscription( $subscription_id );
|
||||
if ( $current_subscription->status === 'SUSPENDED' ) {
|
||||
$this->logger->info(
|
||||
sprintf(
|
||||
'Activating suspended PayPal subscription #%s.',
|
||||
$subscription_id
|
||||
)
|
||||
);
|
||||
|
||||
$this->subscriptions_endpoint->activate( $subscription_id );
|
||||
}
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$this->logger->error(
|
||||
sprintf(
|
||||
'Could not reactivate PayPal subscription #%s. %s',
|
||||
$subscription_id,
|
||||
$this->get_error( $exception )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get error from exception.
|
||||
*
|
||||
* @param RuntimeException $exception The exception.
|
||||
* @return string
|
||||
*/
|
||||
private function get_error( RuntimeException $exception ): string {
|
||||
$error = $exception->getMessage();
|
||||
if ( is_a( $exception, PayPalApiException::class ) ) {
|
||||
$error = $exception->get_details( $error );
|
||||
}
|
||||
|
||||
return $error;
|
||||
}
|
||||
}
|
|
@ -8,5 +8,9 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@wordpress/scripts": "^30.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@wordpress/data": "^10.10.0",
|
||||
"@wordpress/data-controls": "^4.10.0"
|
||||
}
|
||||
}
|
||||
|
|
2
modules/ppcp-settings/resources/js/data/constants.js
Normal file
2
modules/ppcp-settings/resources/js/data/constants.js
Normal file
|
@ -0,0 +1,2 @@
|
|||
export const NAMESPACE = '/wc/v3/wc_paypal';
|
||||
export const STORE_NAME = 'wc/paypal';
|
7
modules/ppcp-settings/resources/js/data/index.js
Normal file
7
modules/ppcp-settings/resources/js/data/index.js
Normal file
|
@ -0,0 +1,7 @@
|
|||
import { STORE_NAME } from './constants';
|
||||
import { initStore } from './store';
|
||||
|
||||
initStore();
|
||||
|
||||
export const WC_PAYPAL_STORE_NAME = STORE_NAME;
|
||||
export * from './onboarding/hooks';
|
|
@ -0,0 +1,5 @@
|
|||
export default {
|
||||
SET_ONBOARDING_DETAILS: 'SET_ONBOARDING_DETAILS',
|
||||
SET_IS_SAVING_ONBOARDING_DETAILS: 'SET_IS_SAVING_ONBOARDING_DETAILS',
|
||||
SET_ONBOARDING_STEP: 'SET_ONBOARDING_STEP',
|
||||
};
|
|
@ -0,0 +1,79 @@
|
|||
import { dispatch, select } from '@wordpress/data';
|
||||
import { apiFetch } from '@wordpress/data-controls';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import ACTION_TYPES from './action-types';
|
||||
import { NAMESPACE, STORE_NAME } from '../constants';
|
||||
|
||||
/**
|
||||
* Persistent. Set the full onboarding details, usually during app initialization.
|
||||
*
|
||||
* @param {Object} payload
|
||||
* @return {{payload, type: string}} The action.
|
||||
*/
|
||||
export const updateOnboardingDetails = ( payload ) => {
|
||||
return {
|
||||
type: ACTION_TYPES.SET_ONBOARDING_DETAILS,
|
||||
payload,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Persistent. Sets the onboarding wizard to a new step.
|
||||
*
|
||||
* @param {number} step
|
||||
* @return {{type: string, step}} An action.
|
||||
*/
|
||||
export const setOnboardingStep = ( step ) => {
|
||||
return {
|
||||
type: ACTION_TYPES.SET_ONBOARDING_STEP,
|
||||
step,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Non-persistent. Changes the "saving" flag.
|
||||
*
|
||||
* @param {boolean} isSaving
|
||||
* @return {{type: string, isSaving}} The action.
|
||||
*/
|
||||
export const updateIsSaving = ( isSaving ) => {
|
||||
return {
|
||||
type: ACTION_TYPES.SET_IS_SAVING_ONBOARDING_DETAILS,
|
||||
isSaving,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Saves the persistent details to the WP database.
|
||||
*
|
||||
* @return {Generator<any>} A generator function that handles the saving process.
|
||||
*/
|
||||
export function* persist() {
|
||||
let error = null;
|
||||
|
||||
try {
|
||||
const path = `${ NAMESPACE }/onboarding`;
|
||||
const data = select( STORE_NAME ).getOnboardingData();
|
||||
|
||||
yield updateIsSaving( true );
|
||||
|
||||
yield apiFetch( {
|
||||
path,
|
||||
method: 'post',
|
||||
data,
|
||||
} );
|
||||
|
||||
yield dispatch( 'core/notices' ).createSuccessNotice(
|
||||
__( 'Progress saved.', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
} catch ( e ) {
|
||||
error = e;
|
||||
yield dispatch( 'core/notices' ).createErrorNotice(
|
||||
__( 'Error saving progress.', 'woocommerce-paypal-payments' )
|
||||
);
|
||||
} finally {
|
||||
yield updateIsSaving( false );
|
||||
}
|
||||
|
||||
return error === null;
|
||||
}
|
23
modules/ppcp-settings/resources/js/data/onboarding/hooks.js
Normal file
23
modules/ppcp-settings/resources/js/data/onboarding/hooks.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { useSelect, useDispatch } from '@wordpress/data';
|
||||
import { STORE_NAME } from '../constants';
|
||||
|
||||
export const useOnboardingDetails = () => {
|
||||
const { setOnboardingStep, persist } = useDispatch( STORE_NAME );
|
||||
|
||||
const onboardingStep = useSelect( ( select ) => {
|
||||
return select( STORE_NAME ).getOnboardingStep();
|
||||
}, [] );
|
||||
|
||||
const isSaving = useSelect( ( select ) => {
|
||||
return select( STORE_NAME ).isSaving();
|
||||
}, [] );
|
||||
|
||||
return {
|
||||
onboardingStep,
|
||||
isSaving,
|
||||
setOnboardingStep: async ( step ) => {
|
||||
setOnboardingStep( step );
|
||||
await persist();
|
||||
},
|
||||
};
|
||||
};
|
|
@ -0,0 +1,6 @@
|
|||
import reducer from './reducer';
|
||||
import * as selectors from './selectors';
|
||||
import * as actions from './actions';
|
||||
import * as resolvers from './resolvers';
|
||||
|
||||
export { reducer, selectors, actions, resolvers };
|
|
@ -0,0 +1,42 @@
|
|||
import ACTION_TYPES from './action-types';
|
||||
|
||||
const defaultState = {
|
||||
isSaving: false,
|
||||
data: {
|
||||
step: 0,
|
||||
},
|
||||
};
|
||||
|
||||
export const onboardingReducer = (
|
||||
state = defaultState,
|
||||
{ type, ...action }
|
||||
) => {
|
||||
switch ( type ) {
|
||||
case ACTION_TYPES.SET_ONBOARDING_DETAILS:
|
||||
return {
|
||||
...state,
|
||||
data: action.payload,
|
||||
};
|
||||
|
||||
case ACTION_TYPES.SET_IS_SAVING_ONBOARDING_DETAILS:
|
||||
return {
|
||||
...state,
|
||||
isSaving: action.isSaving,
|
||||
};
|
||||
|
||||
case ACTION_TYPES.SET_ONBOARDING_STEP:
|
||||
return {
|
||||
...state,
|
||||
data: {
|
||||
...( state.data || {} ),
|
||||
step: action.step,
|
||||
},
|
||||
};
|
||||
|
||||
default:
|
||||
}
|
||||
|
||||
return state;
|
||||
};
|
||||
|
||||
export default onboardingReducer;
|
|
@ -0,0 +1,24 @@
|
|||
import { dispatch } from '@wordpress/data';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { apiFetch } from '@wordpress/data-controls';
|
||||
import { NAMESPACE } from '../constants';
|
||||
import { updateOnboardingDetails } from './actions';
|
||||
|
||||
/**
|
||||
* Retrieve settings from the site's REST API.
|
||||
*/
|
||||
export function* getOnboardingData() {
|
||||
const path = `${ NAMESPACE }/onboarding`;
|
||||
|
||||
try {
|
||||
const result = yield apiFetch( { path } );
|
||||
yield updateOnboardingDetails( result );
|
||||
} catch ( e ) {
|
||||
yield dispatch( 'core/notices' ).createErrorNotice(
|
||||
__(
|
||||
'Error retrieving onboarding details.',
|
||||
'woocommerce-paypal-payments'
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
const EMPTY_OBJ = {};
|
||||
|
||||
const getOnboardingState = ( state ) => {
|
||||
if ( ! state ) {
|
||||
return EMPTY_OBJ;
|
||||
}
|
||||
|
||||
return state.onboarding || EMPTY_OBJ;
|
||||
};
|
||||
|
||||
export const getOnboardingData = ( state ) => {
|
||||
return getOnboardingState( state ).data || EMPTY_OBJ;
|
||||
};
|
||||
|
||||
export const isSaving = ( state ) => {
|
||||
return getOnboardingState( state ).isSaving || false;
|
||||
};
|
||||
|
||||
export const getOnboardingStep = ( state ) => {
|
||||
return getOnboardingData( state ).step || 0;
|
||||
};
|
30
modules/ppcp-settings/resources/js/data/store.js
Normal file
30
modules/ppcp-settings/resources/js/data/store.js
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { createReduxStore, register, combineReducers } from '@wordpress/data';
|
||||
import { controls } from '@wordpress/data-controls';
|
||||
import { STORE_NAME } from './constants';
|
||||
import * as onboarding from './onboarding';
|
||||
|
||||
const actions = {};
|
||||
const selectors = {};
|
||||
const resolvers = {};
|
||||
|
||||
[ onboarding ].forEach( ( item ) => {
|
||||
Object.assign( actions, { ...item.actions } );
|
||||
Object.assign( selectors, { ...item.selectors } );
|
||||
Object.assign( resolvers, { ...item.resolvers } );
|
||||
} );
|
||||
|
||||
const reducer = combineReducers( {
|
||||
onboarding: onboarding.reducer,
|
||||
} );
|
||||
|
||||
export const initStore = () => {
|
||||
const store = createReduxStore( STORE_NAME, {
|
||||
reducer,
|
||||
controls,
|
||||
actions,
|
||||
selectors,
|
||||
resolvers,
|
||||
} );
|
||||
|
||||
register( store );
|
||||
};
|
|
@ -10,9 +10,11 @@ declare( strict_types = 1 );
|
|||
namespace WooCommerce\PayPalCommerce\Settings;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Psr\Container\ContainerInterface;
|
||||
use WooCommerce\PayPalCommerce\Settings\Endpoint\OnboardingRestEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile;
|
||||
|
||||
return array(
|
||||
'settings.url' => static function ( ContainerInterface $container ) : string {
|
||||
'settings.url' => static function ( ContainerInterface $container ) : string {
|
||||
/**
|
||||
* The path cannot be false.
|
||||
*
|
||||
|
@ -23,4 +25,10 @@ return array(
|
|||
dirname( realpath( __FILE__ ), 3 ) . '/woocommerce-paypal-payments.php'
|
||||
);
|
||||
},
|
||||
'settings.data.onboarding' => static function ( ContainerInterface $container ) : OnboardingProfile {
|
||||
return new OnboardingProfile();
|
||||
},
|
||||
'settings.rest.onboarding' => static function ( ContainerInterface $container ) : OnboardingRestEndpoint {
|
||||
return new OnboardingRestEndpoint( $container->get( 'settings.data.onboarding' ) );
|
||||
},
|
||||
);
|
||||
|
|
42
modules/ppcp-settings/src/Data/OnboardingProfile.php
Normal file
42
modules/ppcp-settings/src/Data/OnboardingProfile.php
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
/**
|
||||
* Settings container class
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Settings\Data
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Settings\Data;
|
||||
|
||||
/**
|
||||
* This class serves as a container for managing the onboarding profile details
|
||||
* within the WooCommerce PayPal Commerce plugin. It provides methods to retrieve
|
||||
* and save the onboarding profile data using WordPress options.
|
||||
*/
|
||||
class OnboardingProfile {
|
||||
/**
|
||||
* Options key where profile details are stored.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private const KEY = 'woocommerce-ppcp-data-onboarding';
|
||||
|
||||
/**
|
||||
* Returns the current onboarding profile details.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_data() : array {
|
||||
return get_option( self::KEY, array() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the onboarding profile details.
|
||||
*
|
||||
* @param array $data The profile details to save.
|
||||
*/
|
||||
public function save_data( array $data ) : void {
|
||||
update_option( self::KEY, $data );
|
||||
}
|
||||
}
|
114
modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php
Normal file
114
modules/ppcp-settings/src/Endpoint/OnboardingRestEndpoint.php
Normal file
|
@ -0,0 +1,114 @@
|
|||
<?php
|
||||
/**
|
||||
* REST endpoint to manage the onboarding module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Settings\Endpoint
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Settings\Endpoint;
|
||||
|
||||
use WP_REST_Server;
|
||||
use WP_REST_Response;
|
||||
use WP_REST_Request;
|
||||
use WooCommerce\PayPalCommerce\Settings\Data\OnboardingProfile;
|
||||
|
||||
/**
|
||||
* REST controller for the onboarding module.
|
||||
*
|
||||
* Responsible for persisting and loading the state of the onboarding wizard.
|
||||
*/
|
||||
class OnboardingRestEndpoint extends RestEndpoint {
|
||||
/**
|
||||
* The base path for this REST controller.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $rest_base = 'onboarding';
|
||||
|
||||
/**
|
||||
* The settings instance.
|
||||
*
|
||||
* @var OnboardingProfile
|
||||
*/
|
||||
protected $profile;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param OnboardingProfile $profile The settings instance.
|
||||
*/
|
||||
public function __construct( OnboardingProfile $profile ) {
|
||||
$this->profile = $profile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure REST API routes.
|
||||
*/
|
||||
public function register_routes() {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => array( $this, 'get_details' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
array(
|
||||
array(
|
||||
'methods' => WP_REST_Server::EDITABLE,
|
||||
'callback' => array( $this, 'update_details' ),
|
||||
'permission_callback' => array( $this, 'check_permission' ),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an object with all details of the current onboarding wizard
|
||||
* progress.
|
||||
*
|
||||
* @return WP_REST_Response The current state of the onboarding wizard.
|
||||
*/
|
||||
public function get_details() : WP_REST_Response {
|
||||
$details = $this->profile->get_data();
|
||||
|
||||
return rest_ensure_response( $details );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Receives an object with onboarding details and persists it in the DB.
|
||||
*
|
||||
* @param WP_REST_Request $request Full data about the request.
|
||||
*
|
||||
* @return WP_REST_Response The current state of the onboarding wizard.
|
||||
*/
|
||||
public function update_details( WP_REST_Request $request ) : WP_REST_Response {
|
||||
$details = $this->profile->get_data();
|
||||
|
||||
$get_param = fn( $key ) => wc_clean( wp_unslash( $request->get_param( $key ) ) );
|
||||
|
||||
$raw_step = $get_param( 'step' );
|
||||
$raw_completed = $get_param( 'completed' );
|
||||
|
||||
if ( is_numeric( $raw_step ) ) {
|
||||
$details['step'] = intval( $raw_step );
|
||||
}
|
||||
if ( null !== $raw_completed ) {
|
||||
$details['completed'] = (bool) $raw_completed;
|
||||
}
|
||||
|
||||
$this->profile->save_data( $details );
|
||||
|
||||
return rest_ensure_response( $details );
|
||||
}
|
||||
}
|
36
modules/ppcp-settings/src/Endpoint/RestEndpoint.php
Normal file
36
modules/ppcp-settings/src/Endpoint/RestEndpoint.php
Normal file
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
/**
|
||||
* REST endpoint to manage the onboarding module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\Settings\Endpoint
|
||||
*/
|
||||
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Settings\Endpoint;
|
||||
|
||||
use WC_REST_Controller;
|
||||
|
||||
/**
|
||||
* Base class for REST controllers in the settings module.
|
||||
*
|
||||
* This is a base class for specific REST endpoints; do not instantiate this
|
||||
* class directly.
|
||||
*/
|
||||
class RestEndpoint extends WC_REST_Controller {
|
||||
/**
|
||||
* Endpoint namespace.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $namespace = 'wc/v3/wc_paypal';
|
||||
|
||||
/**
|
||||
* Verify access.
|
||||
*
|
||||
* Override this method if custom permissions required.
|
||||
*/
|
||||
public function check_permission() : bool {
|
||||
return current_user_can( 'manage_woocommerce' );
|
||||
}
|
||||
}
|
|
@ -2,10 +2,11 @@
|
|||
/**
|
||||
* The Settings module.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\AxoBlock
|
||||
* @package WooCommerce\PayPalCommerce\Settings
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
declare( strict_types = 1 );
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\Settings;
|
||||
|
||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule;
|
||||
|
@ -22,14 +23,14 @@ class SettingsModule implements ServiceModule, ExecutableModule {
|
|||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function services(): array {
|
||||
public function services() : array {
|
||||
return require __DIR__ . '/../services.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function run( ContainerInterface $container ): bool {
|
||||
public function run( ContainerInterface $container ) : bool {
|
||||
add_action(
|
||||
'admin_enqueue_scripts',
|
||||
/**
|
||||
|
@ -37,7 +38,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
|
|||
*
|
||||
* @psalm-suppress MissingClosureParamType
|
||||
*/
|
||||
static function( $hook_suffix ) use ( $container ) {
|
||||
static function ( $hook_suffix ) use ( $container ) {
|
||||
if ( 'woocommerce_page_wc-settings' !== $hook_suffix ) {
|
||||
return;
|
||||
}
|
||||
|
@ -92,7 +93,7 @@ class SettingsModule implements ServiceModule, ExecutableModule {
|
|||
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_gateway_admin_options_wrapper',
|
||||
static function(): void {
|
||||
static function () : void {
|
||||
global $hide_save_button;
|
||||
$hide_save_button = true;
|
||||
|
||||
|
@ -100,6 +101,14 @@ class SettingsModule implements ServiceModule, ExecutableModule {
|
|||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'rest_api_init',
|
||||
static function () use ( $container ) : void {
|
||||
$onboarding_endpoint = $container->get( 'settings.rest.onboarding' );
|
||||
$onboarding_endpoint->register_routes();
|
||||
}
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1095,7 +1095,7 @@
|
|||
"@babel/plugin-transform-modules-commonjs" "^7.25.7"
|
||||
"@babel/plugin-transform-typescript" "^7.25.7"
|
||||
|
||||
"@babel/runtime@7.25.7", "@babel/runtime@^7.8.4":
|
||||
"@babel/runtime@7.25.7", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
|
||||
version "7.25.7"
|
||||
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.7.tgz#7ffb53c37a8f247c8c4d335e89cdf16a2e0d0fb6"
|
||||
integrity sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==
|
||||
|
@ -1871,6 +1871,31 @@
|
|||
"@svgr/plugin-jsx" "8.1.0"
|
||||
"@svgr/plugin-svgo" "8.1.0"
|
||||
|
||||
"@tannin/compile@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@tannin/compile/-/compile-1.1.0.tgz#1e4d1c5364cbfeffa1c20352c053e19ef20ffe93"
|
||||
integrity sha512-n8m9eNDfoNZoxdvWiTfW/hSPhehzLJ3zW7f8E7oT6mCROoMNWCB4TYtv041+2FMAxweiE0j7i1jubQU4MEC/Gg==
|
||||
dependencies:
|
||||
"@tannin/evaluate" "^1.2.0"
|
||||
"@tannin/postfix" "^1.1.0"
|
||||
|
||||
"@tannin/evaluate@^1.2.0":
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@tannin/evaluate/-/evaluate-1.2.0.tgz#468a13c45eff45340108836fc46c708457199c3f"
|
||||
integrity sha512-3ioXvNowbO/wSrxsDG5DKIMxC81P0QrQTYai8zFNY+umuoHWRPbQ/TuuDEOju9E+jQDXmj6yI5GyejNuh8I+eg==
|
||||
|
||||
"@tannin/plural-forms@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@tannin/plural-forms/-/plural-forms-1.1.0.tgz#cffbb060d2640a56a314e3c77cbf6ea6072b51d5"
|
||||
integrity sha512-xl9R2mDZO/qiHam1AgMnAES6IKIg7OBhcXqy6eDsRCdXuxAFPcjrej9HMjyCLE0DJ/8cHf0i5OQTstuBRhpbHw==
|
||||
dependencies:
|
||||
"@tannin/compile" "^1.1.0"
|
||||
|
||||
"@tannin/postfix@^1.1.0":
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@tannin/postfix/-/postfix-1.1.0.tgz#6071f4204ae26c2e885cf3a3f1203a9f71e3f291"
|
||||
integrity sha512-oocsqY7g0cR+Gur5jRQLSrX2OtpMLMse1I10JQBm8CdGMrDkh1Mg2gjsiquMHRtBs4Qwu5wgEp5GgIYHk4SNPw==
|
||||
|
||||
"@tootallnate/once@2":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
|
||||
|
@ -2074,6 +2099,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/minimist/-/minimist-1.2.5.tgz#ec10755e871497bcd83efe927e43ec46e8c0747e"
|
||||
integrity sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==
|
||||
|
||||
"@types/mousetrap@^1.6.8":
|
||||
version "1.6.15"
|
||||
resolved "https://registry.yarnpkg.com/@types/mousetrap/-/mousetrap-1.6.15.tgz#f144a0c539a4cef553a631824651d48267e53c86"
|
||||
integrity sha512-qL0hyIMNPow317QWW/63RvL1x5MVMV+Ru3NaY9f/CuEpCqrmb7WeuK2071ZY5hczOnm38qExWM2i2WtkXLSqFw==
|
||||
|
||||
"@types/node-forge@^1.3.0":
|
||||
version "1.3.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/node-forge/-/node-forge-1.3.11.tgz#0972ea538ddb0f4d9c2fa0ec5db5724773a604da"
|
||||
|
@ -2098,6 +2128,11 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.2.tgz#5950e50960793055845e956c427fc2b0d70c5239"
|
||||
integrity sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==
|
||||
|
||||
"@types/prop-types@*":
|
||||
version "15.7.13"
|
||||
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.13.tgz#2af91918ee12d9d32914feb13f5326658461b451"
|
||||
integrity sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==
|
||||
|
||||
"@types/qs@*":
|
||||
version "6.9.16"
|
||||
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.16.tgz#52bba125a07c0482d26747d5d4947a64daf8f794"
|
||||
|
@ -2108,6 +2143,21 @@
|
|||
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
|
||||
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
|
||||
|
||||
"@types/react-dom@^18.2.25":
|
||||
version "18.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.3.1.tgz#1e4654c08a9cdcfb6594c780ac59b55aad42fe07"
|
||||
integrity sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==
|
||||
dependencies:
|
||||
"@types/react" "*"
|
||||
|
||||
"@types/react@*", "@types/react@^18.2.79":
|
||||
version "18.3.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.3.11.tgz#9d530601ff843ee0d7030d4227ea4360236bd537"
|
||||
integrity sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==
|
||||
dependencies:
|
||||
"@types/prop-types" "*"
|
||||
csstype "^3.0.2"
|
||||
|
||||
"@types/retry@0.12.0":
|
||||
version "0.12.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/retry/-/retry-0.12.0.tgz#2b35eccfcee7d38cd72ad99232fbd58bffb3c84d"
|
||||
|
@ -2498,6 +2548,15 @@
|
|||
resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-2.0.5.tgz#325db42395cd49fe6c14057f9a900e427df8810e"
|
||||
integrity sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==
|
||||
|
||||
"@wordpress/api-fetch@^7.10.0":
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/api-fetch/-/api-fetch-7.10.0.tgz#25fc63c531c905e6a917074dd0fd6b945bab809e"
|
||||
integrity sha512-sL71KkvtdGdaZmy7T0+nsTaBVhN0LSwkm3nh/qnebIYzpjZeiPWF/QeoGtJk/lKB15HjbTbfwvFEjiMI4dFvhA==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@wordpress/i18n" "^5.10.0"
|
||||
"@wordpress/url" "^4.10.0"
|
||||
|
||||
"@wordpress/babel-preset-default@^8.10.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/babel-preset-default/-/babel-preset-default-8.10.0.tgz#4a95c09ec206c3a219698488cfc3731dbe0b67f4"
|
||||
|
@ -2525,6 +2584,56 @@
|
|||
resolved "https://registry.yarnpkg.com/@wordpress/browserslist-config/-/browserslist-config-6.10.0.tgz#09e569dd518649c011f5acbc743eae8645f75cd8"
|
||||
integrity sha512-X5BG4xWvr1Qq9S2x5ERCF7V4bpa24zbj8cWYbIJaGiCfi6vp6dFI1SbvuZPXfKyThyytTVYBvEIr6CSm6G8fuQ==
|
||||
|
||||
"@wordpress/compose@^7.10.0":
|
||||
version "7.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/compose/-/compose-7.10.0.tgz#b2e094dfb82f8b19c4619516ab78fc3f520029da"
|
||||
integrity sha512-/j4+wXthaV/KMt0VANvhhRJEJfPc21c7Tq1ZeLxgsbkq4xmi9qXeDT91cvP/U+Ta3phf15K8vdxMr8MqHHiFoQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@types/mousetrap" "^1.6.8"
|
||||
"@wordpress/deprecated" "^4.10.0"
|
||||
"@wordpress/dom" "^4.10.0"
|
||||
"@wordpress/element" "^6.10.0"
|
||||
"@wordpress/is-shallow-equal" "^5.10.0"
|
||||
"@wordpress/keycodes" "^4.10.0"
|
||||
"@wordpress/priority-queue" "^3.10.0"
|
||||
"@wordpress/undo-manager" "^1.10.0"
|
||||
change-case "^4.1.2"
|
||||
clipboard "^2.0.11"
|
||||
mousetrap "^1.6.5"
|
||||
use-memo-one "^1.1.1"
|
||||
|
||||
"@wordpress/data-controls@^4.10.0":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/data-controls/-/data-controls-4.10.0.tgz#100dcf4700f7efcd289823d76e019d85b31343ea"
|
||||
integrity sha512-a7IBnxmzZYIYQzj5iPgBfHZPR65gj+AONNFHM7EUIe9FuyqWtPHy/1jUB7z95ataadh+G4d62ZwZiR1O+prSxg==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@wordpress/api-fetch" "^7.10.0"
|
||||
"@wordpress/data" "^10.10.0"
|
||||
"@wordpress/deprecated" "^4.10.0"
|
||||
|
||||
"@wordpress/data@^10.10.0":
|
||||
version "10.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/data/-/data-10.10.0.tgz#da8fc4004bd9f7376f7ac17148a68158ae651174"
|
||||
integrity sha512-oyYl89p86+U9W6vKDqScKhUGKKzsnETj9rg8zOnT4K9ceOScjGCgdCE+XxcY9exeRg33aSYDjmvnsXXYStBYmA==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@wordpress/compose" "^7.10.0"
|
||||
"@wordpress/deprecated" "^4.10.0"
|
||||
"@wordpress/element" "^6.10.0"
|
||||
"@wordpress/is-shallow-equal" "^5.10.0"
|
||||
"@wordpress/priority-queue" "^3.10.0"
|
||||
"@wordpress/private-apis" "^1.10.0"
|
||||
"@wordpress/redux-routine" "^5.10.0"
|
||||
deepmerge "^4.3.0"
|
||||
equivalent-key-map "^0.2.2"
|
||||
is-plain-object "^5.0.0"
|
||||
is-promise "^4.0.0"
|
||||
redux "^4.1.2"
|
||||
rememo "^4.0.2"
|
||||
use-memo-one "^1.1.1"
|
||||
|
||||
"@wordpress/dependency-extraction-webpack-plugin@^6.10.0":
|
||||
version "6.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/dependency-extraction-webpack-plugin/-/dependency-extraction-webpack-plugin-6.10.0.tgz#45ed2e9e4dfbb60bd131de755d30f07e74f68d1c"
|
||||
|
@ -2532,6 +2641,22 @@
|
|||
dependencies:
|
||||
json2php "^0.0.7"
|
||||
|
||||
"@wordpress/deprecated@^4.10.0":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/deprecated/-/deprecated-4.10.0.tgz#26f4d44e929779ebaf730545799aa07a3544a213"
|
||||
integrity sha512-lktJKX3AxrskTuLbJuKY/Mzg9De6MYcOzEEL+RUHxfIx8wMtiDnVTAf7epur9XuHVOmdgCCRT6D44I23MoS0sw==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@wordpress/hooks" "^4.10.0"
|
||||
|
||||
"@wordpress/dom@^4.10.0":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/dom/-/dom-4.10.0.tgz#f6fcfbbb813b657315c1416f51e9c3f9ad557ce1"
|
||||
integrity sha512-1ZRCrDB2TV44GLwaUH9HRGQGQqXcawSEmzVPABQwfwzkUKijfbRdsWqpHrTLqlSZRImHEdp6oSON+1JmCNhXSw==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@wordpress/deprecated" "^4.10.0"
|
||||
|
||||
"@wordpress/e2e-test-utils-playwright@^1.10.0":
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/e2e-test-utils-playwright/-/e2e-test-utils-playwright-1.10.0.tgz#41c1a9293c70afae6a2c214bf539c8bdb288f945"
|
||||
|
@ -2544,6 +2669,27 @@
|
|||
mime "^3.0.0"
|
||||
web-vitals "^4.2.1"
|
||||
|
||||
"@wordpress/element@^6.10.0":
|
||||
version "6.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/element/-/element-6.10.0.tgz#17ff5970576c96c3b2ba4f5e81c81dc99f2ce221"
|
||||
integrity sha512-7zW+14vHqEn45nszSLMUqE5IbzOtvgUUgF56qlMhwabpG4l/zhaj3gO3wLDI19C13ih1vOdSjzPc3At4fB3tRQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@types/react" "^18.2.79"
|
||||
"@types/react-dom" "^18.2.25"
|
||||
"@wordpress/escape-html" "^3.10.0"
|
||||
change-case "^4.1.2"
|
||||
is-plain-object "^5.0.0"
|
||||
react "^18.3.0"
|
||||
react-dom "^18.3.0"
|
||||
|
||||
"@wordpress/escape-html@^3.10.0":
|
||||
version "3.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/escape-html/-/escape-html-3.10.0.tgz#bdc51085a77e12de55c2bd90bd223883a58e0702"
|
||||
integrity sha512-3glY3MhXEHlPP0/hrS3vkRmAOHtutvoHGhkr8vnva6TLg4CsAeo42nYbuFJ+ukVMWdCtmV+28UjOeiYtG/fZOA==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
|
||||
"@wordpress/eslint-plugin@^21.3.0":
|
||||
version "21.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/eslint-plugin/-/eslint-plugin-21.3.0.tgz#3857262f10446afa207357232f05086db47ed387"
|
||||
|
@ -2567,6 +2713,32 @@
|
|||
globals "^13.12.0"
|
||||
requireindex "^1.2.0"
|
||||
|
||||
"@wordpress/hooks@^4.10.0":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/hooks/-/hooks-4.10.0.tgz#de020f6dacb250387fbbfa8f797ec0ede7fddbad"
|
||||
integrity sha512-LcorV5Z9XoJCKyj5Ulgw1HPHyM2mxsSInC7wl5cuIgDFmuwPTfRndUDGWz/v86GX1GnUIB0h/ggd53vx1HiW4A==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
|
||||
"@wordpress/i18n@^5.10.0":
|
||||
version "5.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/i18n/-/i18n-5.10.0.tgz#55db9299240d92496a3d3ecb046eb6c682ef7734"
|
||||
integrity sha512-HZ6UcMHsjOocDI0zVAuP4JIl97LRmpGo/lVxzVIreaLoYitmYVDUzji02u1o7sEdRWc1Hpkm2/oO/9275rJg1w==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@wordpress/hooks" "^4.10.0"
|
||||
gettext-parser "^1.3.1"
|
||||
memize "^2.1.0"
|
||||
sprintf-js "^1.1.1"
|
||||
tannin "^1.2.0"
|
||||
|
||||
"@wordpress/is-shallow-equal@^5.10.0":
|
||||
version "5.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/is-shallow-equal/-/is-shallow-equal-5.10.0.tgz#71f2cc3ad3fc7cfc509dc1837dd0bc7c2b953917"
|
||||
integrity sha512-KOkZzOnmjpH7hzPiaXUjhUlfKIGTzL7qUdNHBC1SFDOYpnRUSw8f1AtWxRpPBHl5dieYVx0x1qjOWjm/DtTOXg==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
|
||||
"@wordpress/jest-console@^8.10.0":
|
||||
version "8.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/jest-console/-/jest-console-8.10.0.tgz#80c1942bb0effbbed1a831c2a71d046c36a83369"
|
||||
|
@ -2583,6 +2755,14 @@
|
|||
"@wordpress/jest-console" "^8.10.0"
|
||||
babel-jest "29.7.0"
|
||||
|
||||
"@wordpress/keycodes@^4.10.0":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/keycodes/-/keycodes-4.10.0.tgz#306b56a9188d6545f669acbe5a1225e547d49d10"
|
||||
integrity sha512-2i+N90HBMqQegtGqeVB8pJz8ZgKAY1eZmQegE9MXczYVac85DDOoxhY/41c44s6Kwl3waJ2Zght6UXE0OUFMxw==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@wordpress/i18n" "^5.10.0"
|
||||
|
||||
"@wordpress/npm-package-json-lint-config@^5.10.0":
|
||||
version "5.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/npm-package-json-lint-config/-/npm-package-json-lint-config-5.10.0.tgz#5b8951370c82b74d71e38023df29059e4c4fa552"
|
||||
|
@ -2601,6 +2781,31 @@
|
|||
resolved "https://registry.yarnpkg.com/@wordpress/prettier-config/-/prettier-config-4.10.0.tgz#33376a39005b1645287c511853aa9666ce0e7b78"
|
||||
integrity sha512-zT06uXepAWoXiBY8t1M5dz+DcyZ00Sm005YTJvjrLeMRLCEX9lZuZtqA/rYZsABzT90KJvdDTNP+2FsoZSOQcQ==
|
||||
|
||||
"@wordpress/priority-queue@^3.10.0":
|
||||
version "3.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/priority-queue/-/priority-queue-3.10.0.tgz#63ce26931279b5a863520feb29e7199da366463e"
|
||||
integrity sha512-Gjbw5NmRLrZ9KkiROJlL4I/s96bMlpd7gGkQbcCyyeLIZduGxQDzI4Jih5s0Xrm7Gj8WFd57wRDe/voZJR0ZsQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
requestidlecallback "^0.3.0"
|
||||
|
||||
"@wordpress/private-apis@^1.10.0":
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/private-apis/-/private-apis-1.10.0.tgz#90d69128566a0a1d0b41e510098b4ed99892380a"
|
||||
integrity sha512-gH6ZHmkc01MC431nMyjxFmU/77jVliOwjuv6SffQUgHMJyM75LiKC8CU8LEeLWbn3obG87m/n7Quj5p2MjtaeA==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
|
||||
"@wordpress/redux-routine@^5.10.0":
|
||||
version "5.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/redux-routine/-/redux-routine-5.10.0.tgz#08ba44240040eec18e2c2b64948a488d9cbad581"
|
||||
integrity sha512-oDqZDjz8H/bt02IEoIZCwsUsL17UOEnMg/heV0PoJxo3k5MTrvqJqzgBLoSC0PFzx/pwOo4TwvwCL+kjjm5gCQ==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
is-plain-object "^5.0.0"
|
||||
is-promise "^4.0.0"
|
||||
rungen "^0.3.2"
|
||||
|
||||
"@wordpress/scripts@^30.3.0":
|
||||
version "30.3.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/scripts/-/scripts-30.3.0.tgz#d3ab491de79b31a2a12490ff08ef6b1f7db18619"
|
||||
|
@ -2677,6 +2882,22 @@
|
|||
stylelint-config-recommended "^14.0.1"
|
||||
stylelint-config-recommended-scss "^14.1.0"
|
||||
|
||||
"@wordpress/undo-manager@^1.10.0":
|
||||
version "1.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/undo-manager/-/undo-manager-1.10.0.tgz#beec1d89d44e01e3fa3fa01b28eafe897101c47d"
|
||||
integrity sha512-WaLwZ+AlfXQm9PhLf6kwCBaD5DoKaIqelRsgAaqa4APjgMBlxktQ1dadime0CO9+e8R2kLwAE3rxQXhGjicRMw==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
"@wordpress/is-shallow-equal" "^5.10.0"
|
||||
|
||||
"@wordpress/url@^4.10.0":
|
||||
version "4.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/url/-/url-4.10.0.tgz#6ac02f3de91bfcce06378ba4a8038e3ccd08551b"
|
||||
integrity sha512-SKlXocsTlaSee2trXcB0N3jdIfEGMnPiqNxxvTjeeBmsP/47MMXu5lXYslYyYlQbluhAR5/RMf0o3WqZAF2uOg==
|
||||
dependencies:
|
||||
"@babel/runtime" "7.25.7"
|
||||
remove-accents "^0.5.0"
|
||||
|
||||
"@wordpress/warning@^3.10.0":
|
||||
version "3.10.0"
|
||||
resolved "https://registry.yarnpkg.com/@wordpress/warning/-/warning-3.10.0.tgz#29276d268cb89f554df3bc1ae48eab27787c8337"
|
||||
|
@ -3544,6 +3765,15 @@ clean-webpack-plugin@^3.0.0:
|
|||
"@types/webpack" "^4.4.31"
|
||||
del "^4.1.1"
|
||||
|
||||
clipboard@^2.0.11:
|
||||
version "2.0.11"
|
||||
resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.11.tgz#62180360b97dd668b6b3a84ec226975762a70be5"
|
||||
integrity sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==
|
||||
dependencies:
|
||||
good-listener "^1.2.2"
|
||||
select "^1.1.2"
|
||||
tiny-emitter "^2.0.0"
|
||||
|
||||
cliui@^8.0.1:
|
||||
version "8.0.1"
|
||||
resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa"
|
||||
|
@ -4002,6 +4232,11 @@ cssstyle@^2.3.0:
|
|||
dependencies:
|
||||
cssom "~0.3.6"
|
||||
|
||||
csstype@^3.0.2:
|
||||
version "3.1.3"
|
||||
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
|
||||
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
|
||||
|
||||
cwd@^0.10.0:
|
||||
version "0.10.0"
|
||||
resolved "https://registry.yarnpkg.com/cwd/-/cwd-0.10.0.tgz#172400694057c22a13b0cf16162c7e4b7a7fe567"
|
||||
|
@ -4146,7 +4381,7 @@ deep-is@^0.1.3:
|
|||
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831"
|
||||
integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==
|
||||
|
||||
deepmerge@^4.2.2, deepmerge@^4.3.1:
|
||||
deepmerge@^4.2.2, deepmerge@^4.3.0, deepmerge@^4.3.1:
|
||||
version "4.3.1"
|
||||
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
|
||||
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
|
||||
|
@ -4208,6 +4443,11 @@ delayed-stream@~1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
|
||||
|
||||
delegate@^3.1.2:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166"
|
||||
integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==
|
||||
|
||||
depd@2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/depd/-/depd-2.0.0.tgz#b696163cc757560d09cf22cc8fad1571b79e76df"
|
||||
|
@ -4383,6 +4623,13 @@ encodeurl@~2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
|
||||
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
|
||||
|
||||
encoding@^0.1.12:
|
||||
version "0.1.13"
|
||||
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9"
|
||||
integrity sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==
|
||||
dependencies:
|
||||
iconv-lite "^0.6.2"
|
||||
|
||||
end-of-stream@^1.1.0:
|
||||
version "1.4.4"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||
|
@ -4426,6 +4673,11 @@ envinfo@^7.7.3:
|
|||
resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.14.0.tgz#26dac5db54418f2a4c1159153a0b2ae980838aae"
|
||||
integrity sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==
|
||||
|
||||
equivalent-key-map@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.yarnpkg.com/equivalent-key-map/-/equivalent-key-map-0.2.2.tgz#be4d57049bb8d46a81d6e256c1628465620c2a13"
|
||||
integrity sha512-xvHeyCDbZzkpN4VHQj/n+j2lOwL0VWszG30X4cOrc9Y7Tuo2qCdZK/0AMod23Z5dCtNUbaju6p0rwOhHUk05ew==
|
||||
|
||||
error-ex@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
|
||||
|
@ -5342,6 +5594,14 @@ get-uri@^6.0.1:
|
|||
debug "^4.3.4"
|
||||
fs-extra "^11.2.0"
|
||||
|
||||
gettext-parser@^1.3.1:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/gettext-parser/-/gettext-parser-1.4.0.tgz#f8baf34a292f03d5e42f02df099d301f167a7ace"
|
||||
integrity sha512-sedZYLHlHeBop/gZ1jdg59hlUEcpcZJofLq2JFwJT1zTqAU3l2wFv6IsuwFHGqbiT9DWzMUW4/em2+hspnmMMA==
|
||||
dependencies:
|
||||
encoding "^0.1.12"
|
||||
safe-buffer "^5.1.1"
|
||||
|
||||
glob-parent@^5.1.2, glob-parent@~5.1.2:
|
||||
version "5.1.2"
|
||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4"
|
||||
|
@ -5467,6 +5727,13 @@ globjoin@^0.1.4:
|
|||
resolved "https://registry.yarnpkg.com/globjoin/-/globjoin-0.1.4.tgz#2f4494ac8919e3767c5cbb691e9f463324285d43"
|
||||
integrity sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==
|
||||
|
||||
good-listener@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50"
|
||||
integrity sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==
|
||||
dependencies:
|
||||
delegate "^3.1.2"
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
|
||||
|
@ -5707,7 +5974,7 @@ iconv-lite@0.4.24:
|
|||
dependencies:
|
||||
safer-buffer ">= 2.1.2 < 3"
|
||||
|
||||
iconv-lite@0.6.3, iconv-lite@^0.6.3:
|
||||
iconv-lite@0.6.3, iconv-lite@^0.6.2, iconv-lite@^0.6.3:
|
||||
version "0.6.3"
|
||||
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
|
||||
integrity sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==
|
||||
|
@ -6071,6 +6338,11 @@ is-potential-custom-element-name@^1.0.1:
|
|||
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5"
|
||||
integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==
|
||||
|
||||
is-promise@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-4.0.0.tgz#42ff9f84206c1991d26debf520dd5c01042dd2f3"
|
||||
integrity sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==
|
||||
|
||||
is-regex@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958"
|
||||
|
@ -7194,6 +7466,11 @@ memfs@^3.4.3:
|
|||
dependencies:
|
||||
fs-monkey "^1.0.4"
|
||||
|
||||
memize@^2.1.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/memize/-/memize-2.1.0.tgz#6ddd4717887d94825748149ece00d04cf868ce0d"
|
||||
integrity sha512-yywVJy8ctVlN5lNPxsep5urnZ6TTclwPEyigM9M3Bi8vseJBOfqNrGWN/r8NzuIt3PovM323W04blJfGQfQSVg==
|
||||
|
||||
meow@^13.2.0:
|
||||
version "13.2.0"
|
||||
resolved "https://registry.yarnpkg.com/meow/-/meow-13.2.0.tgz#6b7d63f913f984063b3cc261b6e8800c4cd3474f"
|
||||
|
@ -7367,6 +7644,11 @@ mkdirp-classic@^0.5.2:
|
|||
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||
|
||||
mousetrap@^1.6.5:
|
||||
version "1.6.5"
|
||||
resolved "https://registry.yarnpkg.com/mousetrap/-/mousetrap-1.6.5.tgz#8a766d8c272b08393d5f56074e0b5ec183485bf9"
|
||||
integrity sha512-QNo4kEepaIBwiT8CDhP98umTetp+JNfQYBWvC1pc6/OAibuXtRcxZ58Qz8skvEHYvURne/7R8T5VoOI7rDsEUA==
|
||||
|
||||
mrmime@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.0.tgz#151082a6e06e59a9a39b46b3e14d5cfe92b3abb4"
|
||||
|
@ -8423,6 +8705,14 @@ raw-body@2.5.2:
|
|||
iconv-lite "0.4.24"
|
||||
unpipe "1.0.0"
|
||||
|
||||
react-dom@^18.3.0:
|
||||
version "18.3.1"
|
||||
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
|
||||
integrity sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
scheduler "^0.23.2"
|
||||
|
||||
react-is@^16.13.1:
|
||||
version "16.13.1"
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"
|
||||
|
@ -8520,6 +8810,13 @@ redent@^3.0.0:
|
|||
indent-string "^4.0.0"
|
||||
strip-indent "^3.0.0"
|
||||
|
||||
redux@^4.1.2:
|
||||
version "4.2.1"
|
||||
resolved "https://registry.yarnpkg.com/redux/-/redux-4.2.1.tgz#c08f4306826c49b5e9dc901dee0452ea8fce6197"
|
||||
integrity sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==
|
||||
dependencies:
|
||||
"@babel/runtime" "^7.9.2"
|
||||
|
||||
reflect.getprototypeof@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859"
|
||||
|
@ -8596,6 +8893,21 @@ regjsparser@^0.11.0:
|
|||
dependencies:
|
||||
jsesc "~3.0.2"
|
||||
|
||||
rememo@^4.0.2:
|
||||
version "4.0.2"
|
||||
resolved "https://registry.yarnpkg.com/rememo/-/rememo-4.0.2.tgz#8af1f09fd3bf5809ca0bfd0b803926c67ead8c1e"
|
||||
integrity sha512-NVfSP9NstE3QPNs/TnegQY0vnJnstKQSpcrsI2kBTB3dB2PkdfKdTa+abbjMIDqpc63fE5LfjLgfMst0ULMFxQ==
|
||||
|
||||
remove-accents@^0.5.0:
|
||||
version "0.5.0"
|
||||
resolved "https://registry.yarnpkg.com/remove-accents/-/remove-accents-0.5.0.tgz#77991f37ba212afba162e375b627631315bed687"
|
||||
integrity sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==
|
||||
|
||||
requestidlecallback@^0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.yarnpkg.com/requestidlecallback/-/requestidlecallback-0.3.0.tgz#6fb74e0733f90df3faa4838f9f6a2a5f9b742ac5"
|
||||
integrity sha512-TWHFkT7S9p7IxLC5A1hYmAYQx2Eb9w1skrXmQ+dS1URyvR8tenMLl4lHbqEOUnpEYxNKpkVMXUgknVpBZWXXfQ==
|
||||
|
||||
require-directory@^2.1.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
|
||||
|
@ -8735,6 +9047,11 @@ run-parallel@^1.1.4, run-parallel@^1.1.9:
|
|||
dependencies:
|
||||
queue-microtask "^1.2.2"
|
||||
|
||||
rungen@^0.3.2:
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/rungen/-/rungen-0.3.2.tgz#400c09ebe914e7b17e0b6ef3263400fc2abc7cb3"
|
||||
integrity sha512-zWl10xu2D7zoR8zSC2U6bg5bYF6T/Wk7rxwp8IPaJH7f0Ge21G03kNHVgHR7tyVkSSfAOG0Rqf/Cl38JftSmtw==
|
||||
|
||||
rxjs@^7.8.1:
|
||||
version "7.8.1"
|
||||
resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.8.1.tgz#6f6f3d99ea8044291efd92e7c7fcf562c4057543"
|
||||
|
@ -8757,7 +9074,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1:
|
|||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
|
||||
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
|
||||
|
||||
safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@~5.2.0:
|
||||
safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@~5.2.0:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6"
|
||||
integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==
|
||||
|
@ -8801,6 +9118,13 @@ saxes@^6.0.0:
|
|||
dependencies:
|
||||
xmlchars "^2.2.0"
|
||||
|
||||
scheduler@^0.23.2:
|
||||
version "0.23.2"
|
||||
resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.23.2.tgz#414ba64a3b282892e944cf2108ecc078d115cdc3"
|
||||
integrity sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==
|
||||
dependencies:
|
||||
loose-envify "^1.1.0"
|
||||
|
||||
schema-utils@^3.0.0, schema-utils@^3.1.1, schema-utils@^3.2.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
|
||||
|
@ -8825,6 +9149,11 @@ select-hose@^2.0.0:
|
|||
resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca"
|
||||
integrity sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==
|
||||
|
||||
select@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d"
|
||||
integrity sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==
|
||||
|
||||
selfsigned@^2.1.1:
|
||||
version "2.4.1"
|
||||
resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-2.4.1.tgz#560d90565442a3ed35b674034cec4e95dceb4ae0"
|
||||
|
@ -9190,7 +9519,7 @@ speedline-core@^1.4.3:
|
|||
image-ssim "^0.2.0"
|
||||
jpeg-js "^0.4.1"
|
||||
|
||||
sprintf-js@^1.1.3:
|
||||
sprintf-js@^1.1.1, sprintf-js@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.1.3.tgz#4914b903a2f8b685d17fdf78a70e917e872e444a"
|
||||
integrity sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==
|
||||
|
@ -9541,6 +9870,13 @@ table@^6.8.2:
|
|||
string-width "^4.2.3"
|
||||
strip-ansi "^6.0.1"
|
||||
|
||||
tannin@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/tannin/-/tannin-1.2.0.tgz#1da6fe65280dca4c3d84efb075b077b1b94362a6"
|
||||
integrity sha512-U7GgX/RcSeUETbV7gYgoz8PD7Ni4y95pgIP/Z6ayI3CfhSujwKEBlGFTCRN+Aqnuyf4AN2yHL+L8x+TCGjb9uA==
|
||||
dependencies:
|
||||
"@tannin/plural-forms" "^1.1.0"
|
||||
|
||||
tapable@^2.1.1, tapable@^2.2.0, tapable@^2.2.1:
|
||||
version "2.2.1"
|
||||
resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0"
|
||||
|
@ -9630,6 +9966,11 @@ thunky@^1.0.2:
|
|||
resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d"
|
||||
integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
|
||||
|
||||
tiny-emitter@^2.0.0:
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
|
||||
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
|
||||
|
||||
tmpl@1.0.5:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
|
||||
|
@ -9958,6 +10299,11 @@ urlpattern-polyfill@10.0.0:
|
|||
resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz#f0a03a97bfb03cdf33553e5e79a2aadd22cac8ec"
|
||||
integrity sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==
|
||||
|
||||
use-memo-one@^1.1.1:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/use-memo-one/-/use-memo-one-1.1.3.tgz#2fd2e43a2169eabc7496960ace8c79efef975e99"
|
||||
integrity sha512-g66/K7ZQGYrI6dy8GLpVcMsBp4s17xNkYJVSMvTEevGy3nDxHOfE6z8BVE22+5G5x7t3+bhzrlTDB7ObrEE0cQ==
|
||||
|
||||
util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
|
||||
|
|
53
modules/ppcp-wc-gateway/resources/js/void-button.js
Normal file
53
modules/ppcp-wc-gateway/resources/js/void-button.js
Normal file
|
@ -0,0 +1,53 @@
|
|||
import {
|
||||
hide,
|
||||
show,
|
||||
} from '../../../ppcp-button/resources/js/modules/Helper/Hiding';
|
||||
|
||||
document.addEventListener( 'DOMContentLoaded', function () {
|
||||
const refundButton = document.querySelector( 'button.refund-items' );
|
||||
if ( ! refundButton ) {
|
||||
return;
|
||||
}
|
||||
|
||||
refundButton.insertAdjacentHTML(
|
||||
'afterend',
|
||||
`<button class="button" type="button" id="pcpVoid">${ PcpVoidButton.button_text }</button>`
|
||||
);
|
||||
|
||||
hide( refundButton );
|
||||
|
||||
const voidButton = document.querySelector( '#pcpVoid' );
|
||||
|
||||
voidButton.addEventListener( 'click', async () => {
|
||||
if ( ! window.confirm( PcpVoidButton.popup_text ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
voidButton.setAttribute( 'disabled', 'disabled' );
|
||||
|
||||
const res = await fetch( PcpVoidButton.ajax.void.endpoint, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
credentials: 'same-origin',
|
||||
body: JSON.stringify( {
|
||||
nonce: PcpVoidButton.ajax.void.nonce,
|
||||
wc_order_id: PcpVoidButton.wc_order_id,
|
||||
} ),
|
||||
} );
|
||||
|
||||
const data = await res.json();
|
||||
|
||||
if ( ! data.success ) {
|
||||
hide( voidButton );
|
||||
show( refundButton );
|
||||
|
||||
alert( PcpVoidButton.error_text );
|
||||
|
||||
throw Error( data.data.message );
|
||||
}
|
||||
|
||||
location.reload();
|
||||
} );
|
||||
} );
|
|
@ -25,8 +25,10 @@ use WooCommerce\PayPalCommerce\Onboarding\Environment;
|
|||
use WooCommerce\PayPalCommerce\Onboarding\Render\OnboardingOptionsRenderer;
|
||||
use WooCommerce\PayPalCommerce\Onboarding\State;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Admin\RenderReauthorizeAction;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Assets\VoidButtonAssets;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\CaptureCardPayment;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\VoidOrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\CartCheckoutDetector;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\FeesUpdater;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Settings\WcTasks\Factory\SimpleRedirectTaskFactory;
|
||||
|
@ -46,7 +48,6 @@ use WooCommerce\PayPalCommerce\WcGateway\Checkout\DisableGateways;
|
|||
use WooCommerce\PayPalCommerce\WcGateway\Cli\SettingsCommand;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\ReturnUrlEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNet;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNetSessionId;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FraudNet\FraudNetSourceWebsiteId;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\FundingSource\FundingSourceRenderer;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway;
|
||||
|
@ -515,12 +516,20 @@ return array(
|
|||
);
|
||||
},
|
||||
'wcgateway.processor.refunds' => static function ( ContainerInterface $container ): RefundProcessor {
|
||||
$order_endpoint = $container->get( 'api.endpoint.order' );
|
||||
$payments_endpoint = $container->get( 'api.endpoint.payments' );
|
||||
$refund_fees_updater = $container->get( 'wcgateway.helper.refund-fees-updater' );
|
||||
$prefix = $container->get( 'api.prefix' );
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
return new RefundProcessor( $order_endpoint, $payments_endpoint, $refund_fees_updater, $prefix, $logger );
|
||||
return new RefundProcessor(
|
||||
$container->get( 'api.endpoint.order' ),
|
||||
$container->get( 'api.endpoint.payments' ),
|
||||
$container->get( 'wcgateway.helper.refund-fees-updater' ),
|
||||
$container->get( 'wcgateway.allowed_refund_payment_methods' ),
|
||||
$container->get( 'api.prefix' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
'wcgateway.allowed_refund_payment_methods' => static function ( ContainerInterface $container ): array {
|
||||
return apply_filters(
|
||||
'woocommerce_paypal_payments_allowed_refund_payment_methods',
|
||||
array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID, PayUponInvoiceGateway::ID )
|
||||
);
|
||||
},
|
||||
'wcgateway.processor.authorized-payments' => static function ( ContainerInterface $container ): AuthorizedPaymentsProcessor {
|
||||
$order_endpoint = $container->get( 'api.endpoint.order' );
|
||||
|
@ -1421,7 +1430,10 @@ return array(
|
|||
return new OXXO(
|
||||
$container->get( 'wcgateway.checkout-helper' ),
|
||||
$container->get( 'wcgateway.url' ),
|
||||
$container->get( 'ppcp.asset-version' )
|
||||
$container->get( 'ppcp.asset-version' ),
|
||||
$container->get( 'api.endpoint.order' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' ),
|
||||
$container->get( 'api.factory.capture' )
|
||||
);
|
||||
},
|
||||
'wcgateway.oxxo-gateway' => static function( ContainerInterface $container ): OXXOGateway {
|
||||
|
@ -1916,6 +1928,24 @@ return array(
|
|||
return $simple_redirect_tasks;
|
||||
},
|
||||
|
||||
'wcgateway.void-button.assets' => function( ContainerInterface $container ) : VoidButtonAssets {
|
||||
return new VoidButtonAssets(
|
||||
$container->get( 'wcgateway.url' ),
|
||||
$container->get( 'ppcp.asset-version' ),
|
||||
$container->get( 'api.endpoint.order' ),
|
||||
$container->get( 'wcgateway.processor.refunds' ),
|
||||
$container->get( 'wcgateway.allowed_refund_payment_methods' )
|
||||
);
|
||||
},
|
||||
'wcgateway.void-button.endpoint' => function( ContainerInterface $container ) : VoidOrderEndpoint {
|
||||
return new VoidOrderEndpoint(
|
||||
$container->get( 'button.request-data' ),
|
||||
$container->get( 'api.endpoint.order' ),
|
||||
$container->get( 'wcgateway.processor.refunds' ),
|
||||
$container->get( 'woocommerce.logger.woocommerce' )
|
||||
);
|
||||
},
|
||||
|
||||
'wcgateway.settings.admin-settings-enabled' => static function( ContainerInterface $container ): bool {
|
||||
return $container->has( 'settings.url' );
|
||||
},
|
||||
|
|
171
modules/ppcp-wc-gateway/src/Assets/VoidButtonAssets.php
Normal file
171
modules/ppcp-wc-gateway/src/Assets/VoidButtonAssets.php
Normal file
|
@ -0,0 +1,171 @@
|
|||
<?php
|
||||
/**
|
||||
* Register and configure assets for the void button.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\WcGateway\Assets
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Assets;
|
||||
|
||||
use Exception;
|
||||
use WC_AJAX;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\VoidOrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||
use WP_Screen;
|
||||
|
||||
/**
|
||||
* Class VoidButtonAssets
|
||||
*/
|
||||
class VoidButtonAssets {
|
||||
|
||||
/**
|
||||
* The URL of this module.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $module_url;
|
||||
|
||||
/**
|
||||
* The assets version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* The order endpoint.
|
||||
*
|
||||
* @var OrderEndpoint
|
||||
*/
|
||||
private $order_endpoint;
|
||||
|
||||
/**
|
||||
* The Refund Processor.
|
||||
*
|
||||
* @var RefundProcessor
|
||||
*/
|
||||
private $refund_processor;
|
||||
|
||||
/**
|
||||
* The methods that can be refunded.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $allowed_refund_payment_methods;
|
||||
|
||||
/**
|
||||
* VoidButtonAssets constructor.
|
||||
*
|
||||
* @param string $module_url The url of this module.
|
||||
* @param string $version The assets version.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||
* @param array $allowed_refund_payment_methods The methods that can be refunded.
|
||||
*/
|
||||
public function __construct(
|
||||
string $module_url,
|
||||
string $version,
|
||||
OrderEndpoint $order_endpoint,
|
||||
RefundProcessor $refund_processor,
|
||||
array $allowed_refund_payment_methods
|
||||
) {
|
||||
$this->module_url = $module_url;
|
||||
$this->version = $version;
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->refund_processor = $refund_processor;
|
||||
$this->allowed_refund_payment_methods = $allowed_refund_payment_methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if should register assets on the current page.
|
||||
*/
|
||||
public function should_register(): bool {
|
||||
if ( ! is_admin() || wp_doing_ajax() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
global $theorder;
|
||||
|
||||
if ( ! $theorder instanceof WC_Order ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$current_screen = get_current_screen();
|
||||
if ( ! $current_screen instanceof WP_Screen ) {
|
||||
return false;
|
||||
}
|
||||
if ( $current_screen->post_type !== 'shop_order' ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( ! in_array( $theorder->get_payment_method(), $this->allowed_refund_payment_methods, true ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Skip if there are refunds already, it is probably not voidable anymore + void cannot be partial.
|
||||
if ( $theorder->get_remaining_refund_amount() !== $theorder->get_total() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$order_id = $theorder->get_meta( PayPalGateway::ORDER_ID_META_KEY );
|
||||
if ( ! $order_id ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
$order = $this->order_endpoint->order( $order_id );
|
||||
|
||||
if ( $this->refund_processor->determine_refund_mode( $order ) !== RefundProcessor::REFUND_MODE_VOID ) {
|
||||
return false;
|
||||
}
|
||||
} catch ( Exception $exception ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueues the assets.
|
||||
*/
|
||||
public function register(): void {
|
||||
global $theorder;
|
||||
assert( $theorder instanceof WC_Order );
|
||||
|
||||
wp_enqueue_script(
|
||||
'ppcp-void-button',
|
||||
trailingslashit( $this->module_url ) . 'assets/js/void-button.js',
|
||||
array(),
|
||||
$this->version,
|
||||
true
|
||||
);
|
||||
|
||||
wp_localize_script(
|
||||
'ppcp-void-button',
|
||||
'PcpVoidButton',
|
||||
array(
|
||||
'button_text' => __( 'Void authorization', 'woocommerce-paypal-payments' ),
|
||||
'popup_text' => __(
|
||||
'After voiding an authorized transaction, you cannot capture any funds associated with that transaction, and the funds are returned to the customer. Voiding an authorization cancels the entire open amount.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'error_text' => __(
|
||||
'The operation failed. Use the Refund button if the funds were already captured.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'wc_order_id' => $theorder->get_id(),
|
||||
'ajax' => array(
|
||||
'void' => array(
|
||||
'endpoint' => WC_AJAX::get_endpoint( VoidOrderEndpoint::ENDPOINT ),
|
||||
'nonce' => wp_create_nonce( VoidOrderEndpoint::nonce() ),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -97,7 +97,7 @@ class DisableGateways {
|
|||
|
||||
if ( ! $this->settings_status->is_smart_button_enabled_for_location( 'checkout' ) ) {
|
||||
unset( $methods[ CardButtonGateway::ID ] );
|
||||
if ( ! $this->session_handler->order() && is_checkout() ) {
|
||||
if ( $this->subscription_helper->cart_contains_subscription() ) {
|
||||
unset( $methods[ PayPalGateway::ID ] );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,6 +112,7 @@ class ReturnUrlEndpoint {
|
|||
}
|
||||
|
||||
if ( $wc_order->get_payment_method() === OXXOGateway::ID ) {
|
||||
$this->session_handler->destroy_session_data();
|
||||
wp_safe_redirect( wc_get_checkout_url() );
|
||||
exit();
|
||||
}
|
||||
|
|
198
modules/ppcp-wc-gateway/src/Endpoint/VoidOrderEndpoint.php
Normal file
198
modules/ppcp-wc-gateway/src/Endpoint/VoidOrderEndpoint.php
Normal file
|
@ -0,0 +1,198 @@
|
|||
<?php
|
||||
/**
|
||||
* The Void Order endpoint.
|
||||
*
|
||||
* @package WooCommerce\PayPalCommerce\ApiClient\Endpoint
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace WooCommerce\PayPalCommerce\WcGateway\Endpoint;
|
||||
|
||||
use Exception;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WC_Order_Item_Fee;
|
||||
use WC_Order_Item_Product;
|
||||
use WC_Order_Item_Shipping;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\Button\Endpoint\RequestData;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor;
|
||||
|
||||
/**
|
||||
* Class VoidOrderEndpoint
|
||||
*/
|
||||
class VoidOrderEndpoint {
|
||||
|
||||
const ENDPOINT = 'ppc-void-order';
|
||||
|
||||
/**
|
||||
* The order endpoint.
|
||||
*
|
||||
* @var OrderEndpoint
|
||||
*/
|
||||
private $order_endpoint;
|
||||
|
||||
/**
|
||||
* The Refund Processor.
|
||||
*
|
||||
* @var RefundProcessor
|
||||
*/
|
||||
private $refund_processor;
|
||||
|
||||
/**
|
||||
* The Request Data Helper.
|
||||
*
|
||||
* @var RequestData
|
||||
*/
|
||||
private $request_data;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* VoidOrderEndpoint constructor.
|
||||
*
|
||||
* @param RequestData $request_data The Request Data Helper.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param RefundProcessor $refund_processor The Refund Processor.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
public function __construct(
|
||||
RequestData $request_data,
|
||||
OrderEndpoint $order_endpoint,
|
||||
RefundProcessor $refund_processor,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
$this->request_data = $request_data;
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->refund_processor = $refund_processor;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the nonce.
|
||||
*/
|
||||
public static function nonce(): string {
|
||||
return self::ENDPOINT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the incoming request.
|
||||
*/
|
||||
public function handle_request(): void {
|
||||
$request = $this->request_data->read_request( self::nonce() );
|
||||
|
||||
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => 'Invalid request.',
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$wc_order_id = (int) $request['wc_order_id'];
|
||||
|
||||
$wc_order = wc_get_order( $wc_order_id );
|
||||
if ( ! $wc_order instanceof WC_Order ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => 'WC order not found.',
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
$order_id = $wc_order->get_meta( PayPalGateway::ORDER_ID_META_KEY );
|
||||
if ( ! $order_id ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => 'PayPal order ID not found in meta.',
|
||||
)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
$order = $this->order_endpoint->order( $order_id );
|
||||
|
||||
$this->refund_processor->void( $order );
|
||||
|
||||
$this->make_refunded( $wc_order );
|
||||
} catch ( Exception $exception ) {
|
||||
wp_send_json_error(
|
||||
array(
|
||||
'message' => 'Void failed. ' . $exception->getMessage(),
|
||||
)
|
||||
);
|
||||
$this->logger->error( 'Void failed. ' . $exception->getMessage() );
|
||||
return;
|
||||
}
|
||||
|
||||
wp_send_json_success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of items for the wc_create_refund data,
|
||||
* making all items refunded (max qty, total, taxes).
|
||||
*
|
||||
* @param WC_Order $wc_order The WC order.
|
||||
*/
|
||||
protected function refund_items( WC_Order $wc_order ): array {
|
||||
$refunded_items = array();
|
||||
foreach ( $wc_order->get_items( array( 'line_item', 'fee', 'shipping' ) ) as $item ) {
|
||||
// Some methods like get_taxes() are not defined in WC_Order_Item.
|
||||
if (
|
||||
! $item instanceof WC_Order_Item_Product
|
||||
&& ! $item instanceof WC_Order_Item_Fee
|
||||
&& ! $item instanceof WC_Order_Item_Shipping
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$taxes = array();
|
||||
$item_taxes = $item->get_taxes();
|
||||
/**
|
||||
* The type is not really guaranteed in the code.
|
||||
*
|
||||
* @psalm-suppress RedundantConditionGivenDocblockType
|
||||
*/
|
||||
if ( is_array( $item_taxes ) && isset( $item_taxes['total'] ) ) {
|
||||
$taxes = $item_taxes['total'];
|
||||
}
|
||||
|
||||
$refunded_items[ $item->get_id() ] = array(
|
||||
'qty' => $item->get_type() === 'line_item' ? $item->get_quantity() : 0,
|
||||
'refund_total' => $item->get_total(),
|
||||
'refund_tax' => $taxes,
|
||||
);
|
||||
}
|
||||
return $refunded_items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a full refund.
|
||||
*
|
||||
* @param WC_Order $wc_order The WC order.
|
||||
*/
|
||||
private function make_refunded( WC_Order $wc_order ): void {
|
||||
wc_create_refund(
|
||||
array(
|
||||
'amount' => $wc_order->get_total(),
|
||||
'reason' => __( 'Voided authorization', 'woocommerce-paypal-payments' ),
|
||||
'order_id' => $wc_order->get_id(),
|
||||
'line_items' => $this->refund_items( $wc_order ),
|
||||
'refund_payment' => false,
|
||||
'restock_items' => (bool) apply_filters( 'woocommerce_paypal_payments_void_restock_items', true ),
|
||||
)
|
||||
);
|
||||
|
||||
$wc_order->set_status( 'refunded' );
|
||||
}
|
||||
}
|
||||
|
|
@ -10,13 +10,19 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\WcGateway\Gateway\OXXO;
|
||||
|
||||
use Automattic\WooCommerce\Internal\DataStores\Orders\CustomOrdersTableController;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\ApiClient\Factory\CaptureFactory;
|
||||
use WooCommerce\PayPalCommerce\Button\Exception\RuntimeException;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Helper\CheckoutHelper;
|
||||
|
||||
/**
|
||||
* Class OXXO.
|
||||
*/
|
||||
class OXXO {
|
||||
public const ID = 'ppcp-oxxo-gateway';
|
||||
|
||||
/**
|
||||
* The checkout helper.
|
||||
|
@ -40,21 +46,51 @@ class OXXO {
|
|||
protected $asset_version;
|
||||
|
||||
/**
|
||||
* OXXO constructor.
|
||||
* The order endpoint.
|
||||
*
|
||||
* @param CheckoutHelper $checkout_helper The checkout helper.
|
||||
* @param string $module_url The module URL.
|
||||
* @param string $asset_version The asset version.
|
||||
* @var OrderEndpoint
|
||||
*/
|
||||
protected $order_endpoint;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
*
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
protected $logger;
|
||||
|
||||
/**
|
||||
* The capture factory.
|
||||
*
|
||||
* @var CaptureFactory
|
||||
*/
|
||||
protected $capture_factory;
|
||||
|
||||
/**
|
||||
* OXXO constructor
|
||||
*
|
||||
* @param CheckoutHelper $checkout_helper The checkout helper.
|
||||
* @param string $module_url The module URL.
|
||||
* @param string $asset_version The asset version.
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param CaptureFactory $capture_factory The capture factory.
|
||||
*/
|
||||
public function __construct(
|
||||
CheckoutHelper $checkout_helper,
|
||||
string $module_url,
|
||||
string $asset_version
|
||||
string $asset_version,
|
||||
OrderEndpoint $order_endpoint,
|
||||
LoggerInterface $logger,
|
||||
CaptureFactory $capture_factory
|
||||
) {
|
||||
|
||||
$this->checkout_helper = $checkout_helper;
|
||||
$this->module_url = $module_url;
|
||||
$this->asset_version = $asset_version;
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->logger = $logger;
|
||||
$this->capture_factory = $capture_factory;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -199,6 +235,46 @@ class OXXO {
|
|||
}
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Process PayPal fees
|
||||
*/
|
||||
add_action(
|
||||
'woocommerce_paypal_payments_payment_capture_completed_webhook_handler',
|
||||
function ( WC_Order $wc_order, string $order_id ) {
|
||||
try {
|
||||
if ( $wc_order->get_payment_method() !== OXXO::ID ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$order = $this->order_endpoint->order( $order_id );
|
||||
$payments = $order->purchase_units()[0]->payments();
|
||||
|
||||
if ( ! $payments ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$capture = $payments->captures()[0] ?? null;
|
||||
|
||||
if ( $capture ) {
|
||||
$breakdown = $capture->seller_receivable_breakdown();
|
||||
if ( $breakdown ) {
|
||||
$wc_order->update_meta_data( PayPalGateway::FEES_META_KEY, $breakdown->to_array() );
|
||||
$paypal_fee = $breakdown->paypal_fee();
|
||||
if ( $paypal_fee ) {
|
||||
$wc_order->update_meta_data( 'PayPal Transaction Fee', (string) $paypal_fee->value() );
|
||||
}
|
||||
|
||||
$wc_order->save_meta_data();
|
||||
}
|
||||
}
|
||||
} catch ( RuntimeException $exception ) {
|
||||
$this->logger->error( $exception->getMessage() );
|
||||
}
|
||||
},
|
||||
10,
|
||||
2
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -366,7 +366,7 @@ class PayPalGateway extends \WC_Payment_Gateway {
|
|||
'type' => 'checkbox',
|
||||
'desc_tip' => true,
|
||||
'description' => __( 'In order to use PayPal or Advanced Card Processing, you need to enable the Gateway.', 'woocommerce-paypal-payments' ),
|
||||
'label' => __( 'Enable PayPal features for your store', 'woocommerce-paypal-payments' ),
|
||||
'label' => __( 'Enable the PayPal gateway and more features for your store.', 'woocommerce-paypal-payments' ),
|
||||
'default' => 'no',
|
||||
),
|
||||
'ppcp' => array(
|
||||
|
|
|
@ -33,9 +33,9 @@ use WooCommerce\PayPalCommerce\WcGateway\Helper\RefundFeesUpdater;
|
|||
class RefundProcessor {
|
||||
use RefundMetaTrait;
|
||||
|
||||
private const REFUND_MODE_REFUND = 'refund';
|
||||
private const REFUND_MODE_VOID = 'void';
|
||||
private const REFUND_MODE_UNKNOWN = 'unknown';
|
||||
public const REFUND_MODE_REFUND = 'refund';
|
||||
public const REFUND_MODE_VOID = 'void';
|
||||
public const REFUND_MODE_UNKNOWN = 'unknown';
|
||||
|
||||
/**
|
||||
* The order endpoint.
|
||||
|
@ -72,12 +72,20 @@ class RefundProcessor {
|
|||
*/
|
||||
private $refund_fees_updater;
|
||||
|
||||
/**
|
||||
* The methods that can be refunded.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $allowed_refund_payment_methods;
|
||||
|
||||
/**
|
||||
* RefundProcessor constructor.
|
||||
*
|
||||
* @param OrderEndpoint $order_endpoint The order endpoint.
|
||||
* @param PaymentsEndpoint $payments_endpoint The payments endpoint.
|
||||
* @param RefundFeesUpdater $refund_fees_updater The refund fees updater.
|
||||
* @param array $allowed_refund_payment_methods The methods that can be refunded.
|
||||
* @param string $prefix The prefix.
|
||||
* @param LoggerInterface $logger The logger.
|
||||
*/
|
||||
|
@ -85,15 +93,17 @@ class RefundProcessor {
|
|||
OrderEndpoint $order_endpoint,
|
||||
PaymentsEndpoint $payments_endpoint,
|
||||
RefundFeesUpdater $refund_fees_updater,
|
||||
array $allowed_refund_payment_methods,
|
||||
string $prefix,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->payments_endpoint = $payments_endpoint;
|
||||
$this->refund_fees_updater = $refund_fees_updater;
|
||||
$this->prefix = $prefix;
|
||||
$this->logger = $logger;
|
||||
$this->order_endpoint = $order_endpoint;
|
||||
$this->payments_endpoint = $payments_endpoint;
|
||||
$this->refund_fees_updater = $refund_fees_updater;
|
||||
$this->allowed_refund_payment_methods = $allowed_refund_payment_methods;
|
||||
$this->prefix = $prefix;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -109,11 +119,7 @@ class RefundProcessor {
|
|||
*/
|
||||
public function process( WC_Order $wc_order, float $amount = null, string $reason = '' ) : bool {
|
||||
try {
|
||||
$allowed_refund_payment_methods = apply_filters(
|
||||
'woocommerce_paypal_payments_allowed_refund_payment_methods',
|
||||
array( PayPalGateway::ID, CreditCardGateway::ID, CardButtonGateway::ID, PayUponInvoiceGateway::ID )
|
||||
);
|
||||
if ( ! in_array( $wc_order->get_payment_method(), $allowed_refund_payment_methods, true ) ) {
|
||||
if ( ! in_array( $wc_order->get_payment_method(), $this->allowed_refund_payment_methods, true ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -134,7 +140,7 @@ class RefundProcessor {
|
|||
)
|
||||
);
|
||||
|
||||
$mode = $this->determine_refund_mode( $payments );
|
||||
$mode = $this->determine_refund_mode( $order );
|
||||
|
||||
switch ( $mode ) {
|
||||
case self::REFUND_MODE_REFUND:
|
||||
|
@ -226,11 +232,13 @@ class RefundProcessor {
|
|||
/**
|
||||
* Determines the refunding mode.
|
||||
*
|
||||
* @param Payments $payments The order payments state.
|
||||
* @param Order $order The order.
|
||||
*
|
||||
* @return string One of the REFUND_MODE_ constants.
|
||||
*/
|
||||
private function determine_refund_mode( Payments $payments ): string {
|
||||
public function determine_refund_mode( Order $order ): string {
|
||||
$payments = $this->get_payments( $order );
|
||||
|
||||
$authorizations = $payments->authorizations();
|
||||
if ( $authorizations ) {
|
||||
foreach ( $authorizations as $authorization ) {
|
||||
|
|
|
@ -226,14 +226,11 @@ return function ( ContainerInterface $container, array $fields ): array {
|
|||
'description' => sprintf(
|
||||
// translators: %1$s and %2$s are the opening and closing of HTML <a> tag.
|
||||
__(
|
||||
'Customize the appearance of the PayPal smart buttons on the %1$sClassic Checkout page%2$s.
|
||||
%3$sCheckout Buttons must be enabled to display the PayPal gateway on the Checkout page.
|
||||
',
|
||||
'Customize the appearance of the PayPal smart buttons on the %1$sClassic Checkout page%2$s.',
|
||||
'woocommerce-paypal-payments'
|
||||
),
|
||||
'<a href="https://woocommerce.com/document/woocommerce-paypal-payments/#button-on-checkout" target="_blank">',
|
||||
'</a>',
|
||||
'<br />'
|
||||
'</a>'
|
||||
),
|
||||
'type' => 'ppcp-heading',
|
||||
'screens' => array(
|
||||
|
|
|
@ -21,7 +21,9 @@ use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExecutableModule
|
|||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ExtendingModule;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ModuleClassNameIdTrait;
|
||||
use WooCommerce\PayPalCommerce\Vendor\Inpsyde\Modularity\Module\ServiceModule;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Assets\VoidButtonAssets;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\RefreshFeatureStatusEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Endpoint\VoidOrderEndpoint;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\CreditCardOrderInfoHandlingTrait;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\AdminNotices\Repository\Repository;
|
||||
|
@ -90,6 +92,7 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul
|
|||
$this->register_columns( $c );
|
||||
$this->register_checkout_paypal_address_preset( $c );
|
||||
$this->register_wc_tasks( $c );
|
||||
$this->register_void_button( $c );
|
||||
|
||||
add_action(
|
||||
'woocommerce_sections_checkout',
|
||||
|
@ -848,21 +851,19 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul
|
|||
* @return void
|
||||
*/
|
||||
protected function register_wc_tasks( ContainerInterface $container ): void {
|
||||
$simple_redirect_tasks = $container->get( 'wcgateway.settings.wc-tasks.simple-redirect-tasks' );
|
||||
if ( empty( $simple_redirect_tasks ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$task_registrar = $container->get( 'wcgateway.settings.wc-tasks.task-registrar' );
|
||||
assert( $task_registrar instanceof TaskRegistrarInterface );
|
||||
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
assert( $logger instanceof LoggerInterface );
|
||||
|
||||
add_action(
|
||||
'init',
|
||||
static function () use ( $simple_redirect_tasks, $task_registrar, $logger ): void {
|
||||
static function () use ( $container ): void {
|
||||
$logger = $container->get( 'woocommerce.logger.woocommerce' );
|
||||
assert( $logger instanceof LoggerInterface );
|
||||
try {
|
||||
$simple_redirect_tasks = $container->get( 'wcgateway.settings.wc-tasks.simple-redirect-tasks' );
|
||||
if ( empty( $simple_redirect_tasks ) ) {
|
||||
return;
|
||||
}
|
||||
$task_registrar = $container->get( 'wcgateway.settings.wc-tasks.task-registrar' );
|
||||
assert( $task_registrar instanceof TaskRegistrarInterface );
|
||||
|
||||
$task_registrar->register( $simple_redirect_tasks );
|
||||
} catch ( Exception $exception ) {
|
||||
$logger->error( "Failed to create a task in the 'Things to do next' section of WC. " . $exception->getMessage() );
|
||||
|
@ -870,4 +871,33 @@ class WCGatewayModule implements ServiceModule, ExtendingModule, ExecutableModul
|
|||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the assets and ajax endpoint for the void button.
|
||||
*
|
||||
* @param ContainerInterface $container The container.
|
||||
*/
|
||||
protected function register_void_button( ContainerInterface $container ): void {
|
||||
add_action(
|
||||
'admin_enqueue_scripts',
|
||||
static function () use ( $container ) {
|
||||
$assets = $container->get( 'wcgateway.void-button.assets' );
|
||||
assert( $assets instanceof VoidButtonAssets );
|
||||
|
||||
if ( $assets->should_register() ) {
|
||||
$assets->register();
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
add_action(
|
||||
'wc_ajax_' . VoidOrderEndpoint::ENDPOINT,
|
||||
static function () use ( $container ) {
|
||||
$endpoint = $container->get( 'wcgateway.void-button.endpoint' );
|
||||
assert( $endpoint instanceof VoidOrderEndpoint );
|
||||
|
||||
$endpoint->handle_request();
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ module.exports = {
|
|||
'gateway-settings': path.resolve('./resources/js/gateway-settings.js'),
|
||||
'fraudnet': path.resolve('./resources/js/fraudnet.js'),
|
||||
'oxxo': path.resolve('./resources/js/oxxo.js'),
|
||||
'void-button': path.resolve('./resources/js/void-button.js'),
|
||||
'gateway-settings-style': path.resolve('./resources/css/gateway-settings.scss'),
|
||||
'common-style': path.resolve('./resources/css/common.scss'),
|
||||
},
|
||||
|
|
|
@ -17,6 +17,7 @@ use WC_Product_Subscription_Variation;
|
|||
use WC_Subscription;
|
||||
use WC_Subscriptions;
|
||||
use WC_Subscriptions_Product;
|
||||
use WCS_Manual_Renewal_Manager;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException;
|
||||
|
||||
/**
|
||||
|
@ -83,20 +84,15 @@ class SubscriptionHelper {
|
|||
}
|
||||
|
||||
/**
|
||||
* Whether only automatic payment gateways are accepted.
|
||||
* Whether manual renewals are accepted.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function accept_only_automatic_payment_gateways(): bool {
|
||||
|
||||
if ( ! $this->plugin_is_active() ) {
|
||||
public function accept_manual_renewals(): bool {
|
||||
if ( ! class_exists( WCS_Manual_Renewal_Manager::class ) ) {
|
||||
return false;
|
||||
}
|
||||
$accept_manual_renewals = 'no' !== get_option(
|
||||
\WC_Subscriptions_Admin::$option_prefix . '_accept_manual_renewals',
|
||||
'no'
|
||||
);
|
||||
return ! $accept_manual_renewals;
|
||||
return WCS_Manual_Renewal_Manager::is_manual_renewal_enabled();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -99,7 +99,7 @@ return array(
|
|||
new VaultPaymentTokenCreated( $logger, $prefix, $authorized_payments_processor, $payment_token_factory, $payment_token_helper ),
|
||||
new VaultPaymentTokenDeleted( $logger ),
|
||||
new PaymentCapturePending( $logger ),
|
||||
new PaymentSaleCompleted( $logger ),
|
||||
new PaymentSaleCompleted( $logger, $container->get( 'paypal-subscriptions.renewal-handler' ) ),
|
||||
new PaymentSaleRefunded( $logger, $refund_fees_updater ),
|
||||
new BillingSubscriptionCancelled( $logger ),
|
||||
new BillingPlanPricingChangeActivated( $logger ),
|
||||
|
|
|
@ -10,8 +10,8 @@ declare(strict_types=1);
|
|||
namespace WooCommerce\PayPalCommerce\Webhooks\Handler;
|
||||
|
||||
use Psr\Log\LoggerInterface;
|
||||
use WC_Order;
|
||||
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
|
||||
use WC_Data_Exception;
|
||||
use WooCommerce\PayPalCommerce\PayPalSubscriptions\RenewalHandler;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
|
||||
|
@ -20,7 +20,14 @@ use WP_REST_Response;
|
|||
*/
|
||||
class PaymentSaleCompleted implements RequestHandler {
|
||||
|
||||
use TransactionIdHandlingTrait, RequestHandlerTrait;
|
||||
use RequestHandlerTrait;
|
||||
|
||||
/**
|
||||
* Renewal handler.
|
||||
*
|
||||
* @var RenewalHandler
|
||||
*/
|
||||
private $renewal_handler;
|
||||
|
||||
/**
|
||||
* The logger.
|
||||
|
@ -33,9 +40,11 @@ class PaymentSaleCompleted implements RequestHandler {
|
|||
* PaymentSaleCompleted constructor.
|
||||
*
|
||||
* @param LoggerInterface $logger The logger.
|
||||
* @param RenewalHandler $renewal_handler Renewal handler.
|
||||
*/
|
||||
public function __construct( LoggerInterface $logger ) {
|
||||
$this->logger = $logger;
|
||||
public function __construct( LoggerInterface $logger, RenewalHandler $renewal_handler ) {
|
||||
$this->logger = $logger;
|
||||
$this->renewal_handler = $renewal_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -68,7 +77,7 @@ class PaymentSaleCompleted implements RequestHandler {
|
|||
*/
|
||||
public function handle_request( WP_REST_Request $request ): WP_REST_Response {
|
||||
if ( is_null( $request['resource'] ) ) {
|
||||
return $this->failure_response();
|
||||
return $this->failure_response( 'Could not retrieve resource.' );
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'wcs_get_subscriptions' ) ) {
|
||||
|
@ -85,7 +94,7 @@ class PaymentSaleCompleted implements RequestHandler {
|
|||
return $this->failure_response( 'Could not retrieve transaction id for subscription.' );
|
||||
}
|
||||
|
||||
$args = array(
|
||||
$args = array(
|
||||
// phpcs:ignore WordPress.DB.SlowDBQuery
|
||||
'meta_query' => array(
|
||||
array(
|
||||
|
@ -95,24 +104,13 @@ class PaymentSaleCompleted implements RequestHandler {
|
|||
),
|
||||
),
|
||||
);
|
||||
$subscriptions = wcs_get_subscriptions( $args );
|
||||
foreach ( $subscriptions as $subscription ) {
|
||||
$is_renewal = $subscription->get_meta( '_ppcp_is_subscription_renewal' ) ?? '';
|
||||
if ( $is_renewal ) {
|
||||
$renewal_order = wcs_create_renewal_order( $subscription );
|
||||
if ( is_a( $renewal_order, WC_Order::class ) ) {
|
||||
$renewal_order->set_payment_method( $subscription->get_payment_method() );
|
||||
$renewal_order->payment_complete();
|
||||
$this->update_transaction_id( $transaction_id, $renewal_order, $this->logger );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$parent_order = wc_get_order( $subscription->get_parent() );
|
||||
if ( is_a( $parent_order, WC_Order::class ) ) {
|
||||
$subscription->update_meta_data( '_ppcp_is_subscription_renewal', 'true' );
|
||||
$subscription->save_meta_data();
|
||||
$this->update_transaction_id( $transaction_id, $parent_order, $this->logger );
|
||||
$subscriptions = wcs_get_subscriptions( $args );
|
||||
if ( $subscriptions ) {
|
||||
try {
|
||||
$this->renewal_handler->process( $subscriptions, $transaction_id );
|
||||
} catch ( WC_Data_Exception $exception ) {
|
||||
return $this->failure_response( 'Could not update payment method.' );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue