diff --git a/modules/ppcp-wc-gateway/connection-tab-settings.php b/modules/ppcp-wc-gateway/connection-tab-settings.php index 600bc70f4..c65814dad 100644 --- a/modules/ppcp-wc-gateway/connection-tab-settings.php +++ b/modules/ppcp-wc-gateway/connection-tab-settings.php @@ -20,6 +20,12 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return function ( ContainerInterface $container, array $fields ): array { + $current_page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' ); + + if ( $current_page_id !== Settings::CONNECTION_TAB_ID ) { + return $fields; + } + $state = $container->get( 'onboarding.state' ); assert( $state instanceof State ); diff --git a/modules/ppcp-wc-gateway/services.php b/modules/ppcp-wc-gateway/services.php index c438574cf..c9ac66910 100644 --- a/modules/ppcp-wc-gateway/services.php +++ b/modules/ppcp-wc-gateway/services.php @@ -59,7 +59,6 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\SectionsRenderer; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsListener; use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer; -use WooCommerce\PayPalCommerce\Webhooks\Status\WebhooksStatusPage; return array( 'wcgateway.paypal-gateway' => static function ( ContainerInterface $container ): PayPalGateway { @@ -159,7 +158,7 @@ return array( } $section = isset( $_GET['section'] ) ? sanitize_text_field( wp_unslash( $_GET['section'] ) ) : ''; - return in_array( $section, array( Settings::CONNECTION_TAB_ID, PayPalGateway::ID, CreditCardGateway::ID, WebhooksStatusPage::ID, PayUponInvoiceGateway::ID, CardButtonGateway::ID, OXXOGateway::ID ), true ); + return in_array( $section, array( Settings::CONNECTION_TAB_ID, PayPalGateway::ID, CreditCardGateway::ID, PayUponInvoiceGateway::ID, CardButtonGateway::ID, OXXOGateway::ID ), true ); }, 'wcgateway.current-ppcp-settings-page-id' => static function ( ContainerInterface $container ): string { @@ -224,14 +223,13 @@ return array( CardButtonGateway::ID => __( 'PayPal Card Button', 'woocommerce-paypal-payments' ), OXXOGateway::ID => __( 'OXXO', 'woocommerce-paypal-payments' ), PayUponInvoiceGateway::ID => __( 'Pay upon Invoice', 'woocommerce-paypal-payments' ), - WebhooksStatusPage::ID => __( 'Webhooks Status', 'woocommerce-paypal-payments' ), ); // Remove for all not registered in WC gateways that cannot render anything in this case. $gateways = WC()->payment_gateways->payment_gateways(); foreach ( array_diff( array_keys( $sections ), - array( Settings::CONNECTION_TAB_ID, PayPalGateway::ID, CreditCardGateway::ID, WebhooksStatusPage::ID ) + array( Settings::CONNECTION_TAB_ID, PayPalGateway::ID, CreditCardGateway::ID ) ) as $id ) { if ( ! isset( $gateways[ $id ] ) ) { unset( $sections[ $id ] ); @@ -276,6 +274,8 @@ return array( $page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' ); $signup_link_cache = $container->get( 'onboarding.signup-link-cache' ); $signup_link_ids = $container->get( 'onboarding.signup-link-ids' ); + $pui_status_cache = $container->get( 'pui.status-cache' ); + $dcc_status_cache = $container->get( 'dcc.status-cache' ); return new SettingsListener( $settings, $fields, @@ -285,7 +285,9 @@ return array( $bearer, $page_id, $signup_link_cache, - $signup_link_ids + $signup_link_ids, + $pui_status_cache, + $dcc_status_cache ); }, 'wcgateway.order-processor' => static function ( ContainerInterface $container ): OrderProcessor { @@ -351,8 +353,28 @@ return array( return new FeesRenderer(); }, + 'wcgateway.settings.should-render-settings' => static function ( ContainerInterface $container ): bool { + + $sections = array( + Settings::CONNECTION_TAB_ID => __( 'Connection', 'woocommerce-paypal-payments' ), + PayPalGateway::ID => __( 'PayPal Checkout', 'woocommerce-paypal-payments' ), + CreditCardGateway::ID => __( 'PayPal Card Processing', 'woocommerce-paypal-payments' ), + CardButtonGateway::ID => __( 'PayPal Card Button', 'woocommerce-paypal-payments' ), + ); + + $current_page_id = $container->get( 'wcgateway.current-ppcp-settings-page-id' ); + + return array_key_exists( $current_page_id, $sections ); + }, + 'wcgateway.settings.fields' => static function ( ContainerInterface $container ): array { + $should_render_settings = $container->get( 'wcgateway.settings.should-render-settings' ); + + if ( ! $should_render_settings ) { + return array(); + } + $state = $container->get( 'onboarding.state' ); assert( $state instanceof State ); @@ -1894,7 +1916,7 @@ return array( $settings = $container->get( 'wcgateway.settings' ); $partner_endpoint = $container->get( 'api.endpoint.partners' ); - return new DCCProductStatus( $settings, $partner_endpoint ); + return new DCCProductStatus( $settings, $partner_endpoint, $container->get( 'dcc.status-cache' ) ); }, 'button.helper.messages-disclaimers' => static function ( ContainerInterface $container ): MessagesDisclaimers { @@ -1958,7 +1980,8 @@ return array( 'wcgateway.pay-upon-invoice-product-status' => static function( ContainerInterface $container ): PayUponInvoiceProductStatus { return new PayUponInvoiceProductStatus( $container->get( 'wcgateway.settings' ), - $container->get( 'api.endpoint.partners' ) + $container->get( 'api.endpoint.partners' ), + $container->get( 'pui.status-cache' ) ); }, 'wcgateway.pay-upon-invoice' => static function ( ContainerInterface $container ): PayUponInvoice { @@ -2211,4 +2234,10 @@ return array( esc_html( $pui_button_text ) ); }, + 'pui.status-cache' => static function( ContainerInterface $container ): Cache { + return new Cache( 'ppcp-paypal-pui-status-cache' ); + }, + 'dcc.status-cache' => static function( ContainerInterface $container ): Cache { + return new Cache( 'ppcp-paypal-dcc-status-cache' ); + }, ); diff --git a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php index 0c6ca1f50..b4364e498 100644 --- a/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php +++ b/modules/ppcp-wc-gateway/src/Gateway/PayPalGateway.php @@ -29,7 +29,6 @@ use WooCommerce\PayPalCommerce\WcGateway\Processor\RefundProcessor; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; use WooCommerce\PayPalCommerce\WcGateway\Settings\SettingsRenderer; use Psr\Container\ContainerInterface; -use WooCommerce\PayPalCommerce\Webhooks\Status\WebhooksStatusPage; /** * Class PayPalGateway @@ -297,9 +296,6 @@ class PayPalGateway extends \WC_Payment_Gateway { if ( $this->is_credit_card_tab() ) { return __( 'PayPal Card Processing', 'woocommerce-paypal-payments' ); } - if ( $this->is_webhooks_tab() ) { - return __( 'Webhooks Status', 'woocommerce-paypal-payments' ); - } if ( $this->is_paypal_tab() ) { return __( 'PayPal Checkout', 'woocommerce-paypal-payments' ); } @@ -326,12 +322,6 @@ class PayPalGateway extends \WC_Payment_Gateway { 'woocommerce-paypal-payments' ); } - if ( $this->is_webhooks_tab() ) { - return __( - 'Status of the webhooks subscription.', - 'woocommerce-paypal-payments' - ); - } if ( is_admin() ) { return __( @@ -372,16 +362,6 @@ class PayPalGateway extends \WC_Payment_Gateway { return is_admin() && PayUponInvoiceGateway::ID === $this->page_id; } - /** - * Whether we are on the Webhooks Status tab. - * - * @return bool - */ - private function is_webhooks_tab() : bool { - return is_admin() - && WebhooksStatusPage::ID === $this->page_id; - } - /** * Whether we are on the connection tab. * diff --git a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php index e13fd38af..bd55cfbff 100644 --- a/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php +++ b/modules/ppcp-wc-gateway/src/Helper/DCCProductStatus.php @@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Helper; use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct; +use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** @@ -19,6 +20,15 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; */ class DCCProductStatus { + const DCC_STATUS_CACHE_KEY = 'dcc_status_cache'; + + /** + * The Cache. + * + * @var Cache + */ + protected $cache; + /** * Caches the status for the current load. * @@ -44,13 +54,16 @@ class DCCProductStatus { * * @param Settings $settings The Settings. * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. + * @param Cache $cache The cache. */ public function __construct( Settings $settings, - PartnersEndpoint $partners_endpoint + PartnersEndpoint $partners_endpoint, + Cache $cache ) { $this->settings = $settings; $this->partners_endpoint = $partners_endpoint; + $this->cache = $cache; } /** @@ -59,6 +72,10 @@ class DCCProductStatus { * @return bool */ public function dcc_is_active() : bool { + if ( $this->cache->has( self::DCC_STATUS_CACHE_KEY ) ) { + return (bool) $this->cache->get( self::DCC_STATUS_CACHE_KEY ); + } + if ( is_bool( $this->current_status_cache ) ) { return $this->current_status_cache; } @@ -92,9 +109,11 @@ class DCCProductStatus { $this->settings->set( 'products_dcc_enabled', true ); $this->settings->persist(); $this->current_status_cache = true; + $this->cache->set( self::DCC_STATUS_CACHE_KEY, true, 3 * MONTH_IN_SECONDS ); return true; } } + $this->cache->set( self::DCC_STATUS_CACHE_KEY, false, 3 * MONTH_IN_SECONDS ); $this->current_status_cache = false; return false; diff --git a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php index 6512e4ded..b8953a4dc 100644 --- a/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php +++ b/modules/ppcp-wc-gateway/src/Helper/PayUponInvoiceProductStatus.php @@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Helper; use Throwable; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\PartnersEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Entity\SellerStatusProduct; +use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; /** @@ -19,6 +20,15 @@ use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; */ class PayUponInvoiceProductStatus { + const PUI_STATUS_CACHE_KEY = 'pui_status_cache'; + + /** + * The Cache. + * + * @var Cache + */ + protected $cache; + /** * Caches the status for the current load. * @@ -44,13 +54,16 @@ class PayUponInvoiceProductStatus { * * @param Settings $settings The Settings. * @param PartnersEndpoint $partners_endpoint The Partner Endpoint. + * @param Cache $cache The cache. */ public function __construct( Settings $settings, - PartnersEndpoint $partners_endpoint + PartnersEndpoint $partners_endpoint, + Cache $cache ) { $this->settings = $settings; $this->partners_endpoint = $partners_endpoint; + $this->cache = $cache; } /** @@ -59,6 +72,10 @@ class PayUponInvoiceProductStatus { * @return bool */ public function pui_is_active() : bool { + if ( $this->cache->has( self::PUI_STATUS_CACHE_KEY ) ) { + return (bool) $this->cache->get( self::PUI_STATUS_CACHE_KEY ); + } + if ( is_bool( $this->current_status_cache ) ) { return $this->current_status_cache; } @@ -95,9 +112,11 @@ class PayUponInvoiceProductStatus { $this->settings->set( 'products_pui_enabled', true ); $this->settings->persist(); $this->current_status_cache = true; + $this->cache->set( self::PUI_STATUS_CACHE_KEY, true, 3 * MONTH_IN_SECONDS ); return true; } } + $this->cache->set( self::PUI_STATUS_CACHE_KEY, false, 3 * MONTH_IN_SECONDS ); $this->current_status_cache = false; return false; diff --git a/modules/ppcp-wc-gateway/src/Settings/PageMatcherTrait.php b/modules/ppcp-wc-gateway/src/Settings/PageMatcherTrait.php index 08f379afb..85dcc51f0 100644 --- a/modules/ppcp-wc-gateway/src/Settings/PageMatcherTrait.php +++ b/modules/ppcp-wc-gateway/src/Settings/PageMatcherTrait.php @@ -12,7 +12,6 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Settings; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CardButtonGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; -use WooCommerce\PayPalCommerce\Webhooks\Status\WebhooksStatusPage; /** * Class PageMatcherTrait. @@ -37,7 +36,6 @@ trait PageMatcherTrait { PayPalGateway::ID => 'paypal', CreditCardGateway::ID => 'dcc', // TODO: consider using just the gateway ID for PayPal and DCC too. CardButtonGateway::ID => CardButtonGateway::ID, - WebhooksStatusPage::ID => WebhooksStatusPage::ID, ); return array_key_exists( $current_page_id, $gateway_page_id_map ) && in_array( $gateway_page_id_map[ $current_page_id ], $allowed_gateways, true ); diff --git a/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php b/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php index 0735f671d..8775b6d32 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php +++ b/modules/ppcp-wc-gateway/src/Settings/SectionsRenderer.php @@ -11,7 +11,6 @@ namespace WooCommerce\PayPalCommerce\WcGateway\Settings; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Gateway\CreditCardGateway; -use WooCommerce\PayPalCommerce\Webhooks\Status\WebhooksStatusPage; /** * Class SectionsRenderer @@ -77,7 +76,7 @@ class SectionsRenderer { foreach ( $this->sections as $id => $label ) { $url = admin_url( 'admin.php?page=wc-settings&tab=checkout§ion=' . $id ); - if ( in_array( $id, array( Settings::CONNECTION_TAB_ID, CreditCardGateway::ID, WebhooksStatusPage::ID ), true ) ) { + if ( in_array( $id, array( Settings::CONNECTION_TAB_ID, CreditCardGateway::ID ), true ) ) { // We need section=ppcp-gateway for the webhooks page because it is not a gateway, // and for DCC because otherwise it will not render the page if gateway is not available (country/currency). // Other gateways render fields differently, and their pages are not expected to work when gateway is not available. diff --git a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php index d9c184e7f..cf43fa518 100644 --- a/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php +++ b/modules/ppcp-wc-gateway/src/Settings/SettingsListener.php @@ -15,6 +15,8 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; use WooCommerce\PayPalCommerce\Onboarding\State; use WooCommerce\PayPalCommerce\WcGateway\Gateway\PayPalGateway; +use WooCommerce\PayPalCommerce\WcGateway\Helper\DCCProductStatus; +use WooCommerce\PayPalCommerce\WcGateway\Helper\PayUponInvoiceProductStatus; use WooCommerce\PayPalCommerce\Webhooks\WebhookRegistrar; use WooCommerce\PayPalCommerce\WcGateway\Exception\NotFoundException; @@ -95,6 +97,20 @@ class SettingsListener { */ protected $signup_link_ids; + /** + * The PUI status cache. + * + * @var Cache + */ + protected $pui_status_cache; + + /** + * The DCC status cache. + * + * @var Cache + */ + protected $dcc_status_cache; + /** * SettingsListener constructor. * @@ -107,6 +123,8 @@ class SettingsListener { * @param string $page_id ID of the current PPCP gateway settings page, or empty if it is not such page. * @param Cache $signup_link_cache The signup link cache. * @param array $signup_link_ids Signup link ids. + * @param Cache $pui_status_cache The PUI status cache. + * @param Cache $dcc_status_cache The DCC status cache. */ public function __construct( Settings $settings, @@ -117,7 +135,9 @@ class SettingsListener { Bearer $bearer, string $page_id, Cache $signup_link_cache, - array $signup_link_ids + array $signup_link_ids, + Cache $pui_status_cache, + Cache $dcc_status_cache ) { $this->settings = $settings; @@ -129,6 +149,8 @@ class SettingsListener { $this->page_id = $page_id; $this->signup_link_cache = $signup_link_cache; $this->signup_link_ids = $signup_link_ids; + $this->pui_status_cache = $pui_status_cache; + $this->dcc_status_cache = $dcc_status_cache; } /** @@ -307,6 +329,14 @@ class SettingsListener { $this->cache->delete( PayPalBearer::CACHE_KEY ); } + if ( $this->pui_status_cache->has( PayUponInvoiceProductStatus::PUI_STATUS_CACHE_KEY ) ) { + $this->pui_status_cache->delete( PayUponInvoiceProductStatus::PUI_STATUS_CACHE_KEY ); + } + + if ( $this->dcc_status_cache->has( DCCProductStatus::DCC_STATUS_CACHE_KEY ) ) { + $this->dcc_status_cache->delete( DCCProductStatus::DCC_STATUS_CACHE_KEY ); + } + if ( isset( $_GET['ppcp-onboarding-error'] ) ) { $url = remove_query_arg( 'ppcp-onboarding-error' ); wp_safe_redirect( $url, 302 ); diff --git a/modules/ppcp-webhooks/extensions.php b/modules/ppcp-webhooks/extensions.php index 425c960f8..480c6474d 100644 --- a/modules/ppcp-webhooks/extensions.php +++ b/modules/ppcp-webhooks/extensions.php @@ -10,25 +10,35 @@ declare(strict_types=1); namespace WooCommerce\PayPalCommerce\Webhooks; use WooCommerce\PayPalCommerce\Onboarding\State; -use WooCommerce\PayPalCommerce\Webhooks\Status\WebhooksStatusPage; +use WooCommerce\PayPalCommerce\WcGateway\Settings\Settings; return array( 'wcgateway.settings.fields' => static function ( $container, array $fields ): array { $status_page_fields = array( - 'webhooks_list' => array( + 'webhook_status_heading' => array( + 'heading' => __( 'Webhook Status', 'woocommerce-paypal-payments' ), + 'type' => 'ppcp-heading', + 'screens' => array( + State::STATE_ONBOARDED, + ), + 'requirements' => array(), + 'gateway' => Settings::CONNECTION_TAB_ID, + 'description' => __( 'Status of the webhooks subscription.', 'woocommerce-paypal-payments' ), + ), + 'webhooks_list' => array( 'title' => __( 'Subscribed webhooks', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-table', 'screens' => array( State::STATE_ONBOARDED, ), 'requirements' => array(), - 'gateway' => WebhooksStatusPage::ID, + 'gateway' => Settings::CONNECTION_TAB_ID, 'classes' => array( 'ppcp-webhooks-table' ), 'value' => function () use ( $container ) : array { return $container->get( 'webhook.status.registered-webhooks-data' ); }, ), - 'webhooks_resubscribe' => array( + 'webhooks_resubscribe' => array( 'title' => __( 'Resubscribe webhooks', 'woocommerce-paypal-payments' ), 'type' => 'ppcp-text', 'text' => '', @@ -36,7 +46,7 @@ return array( State::STATE_ONBOARDED, ), 'requirements' => array(), - 'gateway' => WebhooksStatusPage::ID, + 'gateway' => Settings::CONNECTION_TAB_ID, 'description' => __( 'Click to remove the current webhook subscription and subscribe again, for example, if the website domain or URL structure changed.', 'woocommerce-paypal-payments' ), ), ); @@ -54,7 +64,7 @@ return array( State::STATE_ONBOARDED, ), 'requirements' => array(), - 'gateway' => WebhooksStatusPage::ID, + 'gateway' => Settings::CONNECTION_TAB_ID, 'description' => __( 'Click to request a sample webhook payload from PayPal, allowing to check that your server can successfully receive webhooks.', 'woocommerce-paypal-payments' ), ), ) diff --git a/modules/ppcp-webhooks/src/Status/WebhooksStatusPage.php b/modules/ppcp-webhooks/src/Status/WebhooksStatusPage.php deleted file mode 100644 index 54dd56c1c..000000000 --- a/modules/ppcp-webhooks/src/Status/WebhooksStatusPage.php +++ /dev/null @@ -1,18 +0,0 @@ -get( 'wcgateway.current-ppcp-settings-page-id' ); - if ( WebhooksStatusPage::ID === $page_id ) { - $GLOBALS['hide_save_button'] = true; - $asset_loader = $container->get( 'webhook.status.assets' ); + if ( Settings::CONNECTION_TAB_ID === $page_id ) { + $asset_loader = $container->get( 'webhook.status.assets' ); assert( $asset_loader instanceof WebhooksStatusPageAssets ); add_action( 'init', diff --git a/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php b/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php index b866317db..bad2dda33 100644 --- a/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php +++ b/tests/PHPUnit/WcGateway/Settings/SettingsListenerTest.php @@ -36,6 +36,8 @@ class SettingsListenerTest extends ModularTestCase $bearer = Mockery::mock(Bearer::class); $signup_link_cache = Mockery::mock(Cache::class); $signup_link_ids = array(); + $pui_status_cache = Mockery::mock(Cache::class); + $dcc_status_cache = Mockery::mock(Cache::class); $testee = new SettingsListener( $settings, @@ -46,7 +48,9 @@ class SettingsListenerTest extends ModularTestCase $bearer, PayPalGateway::ID, $signup_link_cache, - $signup_link_ids + $signup_link_ids, + $pui_status_cache, + $dcc_status_cache ); $_GET['section'] = PayPalGateway::ID; @@ -76,6 +80,10 @@ class SettingsListenerTest extends ModularTestCase ->andReturn(false); $signup_link_cache->shouldReceive('has') ->andReturn(false); + $pui_status_cache->shouldReceive('has') + ->andReturn(false); + $dcc_status_cache->shouldReceive('has') + ->andReturn(false); $testee->listen(); }