From 77d3a5c19cf11ebe1e08c66a43d0e5247665bead Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 19 Nov 2021 17:25:08 +0200 Subject: [PATCH 01/12] Refactor Yes/No output --- .../src/StatusReportModule.php | 54 +++++++++++-------- 1 file changed, 32 insertions(+), 22 deletions(-) diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index 99440538c..567fa1e2c 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -64,7 +64,9 @@ class StatusReportModule implements ModuleInterface { array( 'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ), 'description' => esc_html__( 'Whether PayPal account is correctly configured or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->onboarded( $bearer, $state ), + 'value' => $this->bool_to_text( + $this->onboarded( $bearer, $state ) + ), ), array( 'label' => esc_html__( 'Shop country code', 'woocommerce-paypal-payments' ), @@ -74,21 +76,23 @@ class StatusReportModule implements ModuleInterface { array( 'label' => esc_html__( 'PayPal card processing available in country', 'woocommerce-paypal-payments' ), 'description' => esc_html__( 'Whether PayPal card processing is available in country or not.', 'woocommerce-paypal-payments' ), - 'value' => $dcc_applies->for_country_currency() - ? esc_html__( 'Yes', 'woocommerce-paypal-payments' ) - : esc_html__( 'No', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( + $dcc_applies->for_country_currency() + ), ), array( 'label' => esc_html__( 'Pay Later messaging available in country', 'woocommerce-paypal-payments' ), 'description' => esc_html__( 'Whether Pay Later is available in country or not.', 'woocommerce-paypal-payments' ), - 'value' => $messages_apply->for_country() - ? esc_html__( 'Yes', 'woocommerce-paypal-payments' ) - : esc_html__( 'No', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( + $messages_apply->for_country() + ), ), array( 'label' => esc_html__( 'Vault enabled', 'woocommerce-paypal-payments' ), 'description' => esc_html__( 'Whether vaulting is enabled on PayPal account or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->vault_enabled( $bearer ), + 'value' => $this->bool_to_text( + $this->vault_enabled( $bearer ) + ), ), ); @@ -112,37 +116,43 @@ class StatusReportModule implements ModuleInterface { * * @param Bearer $bearer The bearer. * @param State $state The state. - * @return string + * @return bool */ - private function onboarded( $bearer, $state ): string { + private function onboarded( Bearer $bearer, State $state ): bool { try { $token = $bearer->bearer(); } catch ( RuntimeException $exception ) { - return esc_html__( 'No', 'woocommerce-paypal-payments' ); + return false; } $current_state = $state->current_state(); - if ( $token->is_valid() && $current_state === $state::STATE_ONBOARDED ) { - return esc_html__( 'Yes', 'woocommerce-paypal-payments' ); - } - - return esc_html__( 'No', 'woocommerce-paypal-payments' ); + return $token->is_valid() && $current_state === $state::STATE_ONBOARDED; } /** * It returns whether vaulting is enabled or not. * * @param Bearer $bearer The bearer. - * @return string + * @return bool */ - private function vault_enabled( $bearer ) { + private function vault_enabled( Bearer $bearer ): bool { try { $token = $bearer->bearer(); - return $token->vaulting_available() - ? esc_html__( 'Yes', 'woocommerce-paypal-payments' ) - : esc_html__( 'No', 'woocommerce-paypal-payments' ); + return $token->vaulting_available(); } catch ( RuntimeException $exception ) { - return esc_html__( 'No', 'woocommerce-paypal-payments' ); + return false; } } + + /** + * Converts the bool value to "Yes" or "No". + * + * @param bool $value The value. + * @return string + */ + private function bool_to_text( bool $value ): string { + return $value + ? esc_html__( 'Yes', 'woocommerce-paypal-payments' ) + : esc_html__( 'No', 'woocommerce-paypal-payments' ); + } } From 9ba675d1f51d3a96a09cae39ab9a47787f9cbf67 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 19 Nov 2021 17:25:47 +0200 Subject: [PATCH 02/12] Add logging status to status report --- modules/ppcp-status-report/src/StatusReportModule.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index 567fa1e2c..96cb51f5d 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -44,6 +44,8 @@ class StatusReportModule implements ModuleInterface { add_action( 'woocommerce_system_status_report', function () use ( $c ) { + $settings = $c->get( 'wcgateway.settings' ); + assert( $settings instanceof ContainerInterface ); /* @var State $state The state. */ $state = $c->get( 'onboarding.state' ); @@ -94,6 +96,13 @@ class StatusReportModule implements ModuleInterface { $this->vault_enabled( $bearer ) ), ), + array( + 'label' => esc_html__( 'Logging enabled', 'woocommerce-paypal-payments' ), + 'description' => esc_html__( 'Whether logging of plugin events and errors is enabled.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( + $settings->has( 'logging_enabled' ) && $settings->get( 'logging_enabled' ) + ), + ), ); echo wp_kses_post( From 195474ad6eb21bd0c93b5cc25b47b8c7ef774f35 Mon Sep 17 00:00:00 2001 From: Alex P Date: Mon, 22 Nov 2021 18:20:00 +0200 Subject: [PATCH 03/12] Check currency support for status report --- modules/ppcp-api-client/services.php | 4 ++ .../src/Helper/CurrencySupport.php | 70 +++++++++++++++++++ .../src/StatusReportModule.php | 11 +++ 3 files changed, 85 insertions(+) create mode 100644 modules/ppcp-api-client/src/Helper/CurrencySupport.php diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index 50434c467..707d2e24d 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -39,6 +39,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\ShippingFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookEventFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookFactory; use WooCommerce\PayPalCommerce\ApiClient\Helper\Cache; +use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencySupport; use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies; use WooCommerce\PayPalCommerce\ApiClient\Repository\ApplicationContextRepository; use WooCommerce\PayPalCommerce\ApiClient\Repository\CartRepository; @@ -301,4 +302,7 @@ return array( 'api.helpers.dccapplies' => static function ( ContainerInterface $container ) : DccApplies { return new DccApplies(); }, + 'api.helpers.currency-support' => static function ( ContainerInterface $container ) : CurrencySupport { + return new CurrencySupport(); + }, ); diff --git a/modules/ppcp-api-client/src/Helper/CurrencySupport.php b/modules/ppcp-api-client/src/Helper/CurrencySupport.php new file mode 100644 index 000000000..925ee4386 --- /dev/null +++ b/modules/ppcp-api-client/src/Helper/CurrencySupport.php @@ -0,0 +1,70 @@ +supported_currencies, true ); + } + + /** + * Returns whether the current WC currency is supported. + * + * @return bool + */ + public function supports_wc_currency(): bool { + return $this->supports_currency( get_woocommerce_currency() ); + } +} diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index 96cb51f5d..e00c842b2 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -16,6 +16,7 @@ use Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; +use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencySupport; use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies; use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; use WooCommerce\PayPalCommerce\Onboarding\State; @@ -53,6 +54,9 @@ class StatusReportModule implements ModuleInterface { /* @var Bearer $bearer The bearer. */ $bearer = $c->get( 'api.bearer' ); + $currency_support = $c->get( 'api.helpers.currency-support' ); + assert( $currency_support instanceof CurrencySupport ); + /* @var DccApplies $dcc_applies The ddc applies. */ $dcc_applies = $c->get( 'api.helpers.dccapplies' ); @@ -75,6 +79,13 @@ class StatusReportModule implements ModuleInterface { 'description' => esc_html__( 'Country / State value on Settings / General / Store Address.', 'woocommerce-paypal-payments' ), 'value' => wc_get_base_location()['country'], ), + array( + 'label' => esc_html__( 'WooCommerce currency supported', 'woocommerce-paypal-payments' ), + 'description' => esc_html__( 'Whether PayPal supports the default store currency or not.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( + $currency_support->supports_wc_currency() + ), + ), array( 'label' => esc_html__( 'PayPal card processing available in country', 'woocommerce-paypal-payments' ), 'description' => esc_html__( 'Whether PayPal card processing is available in country or not.', 'woocommerce-paypal-payments' ), From b8b4766fbad92c7c173ce128f73c603e9ab5c5d1 Mon Sep 17 00:00:00 2001 From: Alex P Date: Mon, 22 Nov 2021 18:21:01 +0200 Subject: [PATCH 04/12] Show if PPEC was used in status report --- modules/ppcp-compat/src/PPEC/PPECHelper.php | 9 +++++++++ modules/ppcp-status-report/src/StatusReportModule.php | 10 ++++++++++ 2 files changed, 19 insertions(+) diff --git a/modules/ppcp-compat/src/PPEC/PPECHelper.php b/modules/ppcp-compat/src/PPEC/PPECHelper.php index ec1543b70..09fca3c19 100644 --- a/modules/ppcp-compat/src/PPEC/PPECHelper.php +++ b/modules/ppcp-compat/src/PPEC/PPECHelper.php @@ -29,6 +29,15 @@ class PPECHelper { const PPEC_SETTINGS_OPTION_NAME = 'woocommerce_ppec_paypal_settings'; + /** + * Checks if the PayPal Express Checkout plugin was configured previously. + * + * @return bool + */ + public static function is_plugin_configured() { + return is_array( get_option( self::PPEC_SETTINGS_OPTION_NAME ) ); + } + /** * Checks if the PayPal Express Checkout plugin is active. * diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index e00c842b2..20f54f7eb 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -19,6 +19,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencySupport; use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies; use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; +use WooCommerce\PayPalCommerce\Compat\PPEC\PPECHelper; use WooCommerce\PayPalCommerce\Onboarding\State; /** @@ -66,6 +67,8 @@ class StatusReportModule implements ModuleInterface { /* @var Renderer $renderer The renderer. */ $renderer = $c->get( 'status-report.renderer' ); + $had_ppec_plugin = PPECHelper::is_plugin_configured(); + $items = array( array( 'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ), @@ -114,6 +117,13 @@ class StatusReportModule implements ModuleInterface { $settings->has( 'logging_enabled' ) && $settings->get( 'logging_enabled' ) ), ), + array( + 'label' => esc_html__( 'Used PayPal Checkout plugin', 'woocommerce-paypal-payments' ), + 'description' => esc_html__( 'Whether the PayPal Checkout Gateway plugin was configured previously or not', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( + $had_ppec_plugin + ), + ), ); echo wp_kses_post( From f845acefbe8717eb5427a8364efcc95ede338b35 Mon Sep 17 00:00:00 2001 From: Alex P Date: Wed, 24 Nov 2021 11:52:14 +0200 Subject: [PATCH 05/12] Add webhook status to status report --- .../src/StatusReportModule.php | 9 +++ modules/ppcp-webhooks/services.php | 11 +++ .../src/IncomingWebhookEndpoint.php | 12 +++ .../ppcp-webhooks/src/WebhookInfoStorage.php | 76 +++++++++++++++++++ .../ppcp-webhooks/src/WebhookRegistrar.php | 20 ++++- 5 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 modules/ppcp-webhooks/src/WebhookInfoStorage.php diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index 20f54f7eb..c26302bd2 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -21,6 +21,7 @@ use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies; use WooCommerce\PayPalCommerce\Button\Helper\MessagesApply; use WooCommerce\PayPalCommerce\Compat\PPEC\PPECHelper; use WooCommerce\PayPalCommerce\Onboarding\State; +use WooCommerce\PayPalCommerce\Webhooks\WebhookInfoStorage; /** * Class StatusReportModule @@ -64,6 +65,9 @@ class StatusReportModule implements ModuleInterface { /* @var MessagesApply $messages_apply The messages apply. */ $messages_apply = $c->get( 'button.helper.messages-apply' ); + $last_webhook_storage = $c->get( 'webhook.last-webhook-storage' ); + assert( $last_webhook_storage instanceof WebhookInfoStorage ); + /* @var Renderer $renderer The renderer. */ $renderer = $c->get( 'status-report.renderer' ); @@ -103,6 +107,11 @@ class StatusReportModule implements ModuleInterface { $messages_apply->for_country() ), ), + array( + 'label' => esc_html__( 'Webhook status', 'woocommerce-paypal-payments' ), + 'description' => esc_html__( 'Whether we received webhooks successfully.', 'woocommerce-paypal-payments' ), + 'value' => $last_webhook_storage->is_empty() ? 'Unknown' : 'OK', + ), array( 'label' => esc_html__( 'Vault enabled', 'woocommerce-paypal-payments' ), 'description' => esc_html__( 'Whether vaulting is enabled on PayPal account or not.', 'woocommerce-paypal-payments' ), diff --git a/modules/ppcp-webhooks/services.php b/modules/ppcp-webhooks/services.php index 8282ef3f6..13b0b5e54 100644 --- a/modules/ppcp-webhooks/services.php +++ b/modules/ppcp-webhooks/services.php @@ -32,11 +32,13 @@ return array( $factory = $container->get( 'api.factory.webhook' ); $endpoint = $container->get( 'api.endpoint.webhook' ); $rest_endpoint = $container->get( 'webhook.endpoint.controller' ); + $last_webhook_storage = $container->get( 'webhook.last-webhook-storage' ); $logger = $container->get( 'woocommerce.logger.woocommerce' ); return new WebhookRegistrar( $factory, $endpoint, $rest_endpoint, + $last_webhook_storage, $logger ); }, @@ -48,6 +50,7 @@ return array( $verify_request = ! defined( 'PAYPAL_WEBHOOK_REQUEST_VERIFICATION' ) || PAYPAL_WEBHOOK_REQUEST_VERIFICATION; $webhook_event_factory = $container->get( 'api.factory.webhook-event' ); $simulation = $container->get( 'webhook.status.simulation' ); + $last_webhook_storage = $container->get( 'webhook.last-webhook-storage' ); return new IncomingWebhookEndpoint( $webhook_endpoint, @@ -56,6 +59,7 @@ return array( $verify_request, $webhook_event_factory, $simulation, + $last_webhook_storage, ... $handler ); }, @@ -183,6 +187,13 @@ return array( ); }, + 'webhook.last-webhook-storage' => static function ( ContainerInterface $container ): WebhookInfoStorage { + return new WebhookInfoStorage( $container->get( 'webhook.last-webhook-storage.key' ) ); + }, + 'webhook.last-webhook-storage.key' => static function ( ContainerInterface $container ): string { + return 'ppcp-last-webhook'; + }, + 'webhook.module-url' => static function ( ContainerInterface $container ): string { return plugins_url( '/modules/ppcp-webhooks/', diff --git a/modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php b/modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php index ed96e6974..9f8bbcf7a 100644 --- a/modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php +++ b/modules/ppcp-webhooks/src/IncomingWebhookEndpoint.php @@ -76,6 +76,13 @@ class IncomingWebhookEndpoint { */ private $simulation; + /** + * The last webhook info storage. + * + * @var WebhookInfoStorage + */ + private $last_webhook_storage; + /** * IncomingWebhookEndpoint constructor. * @@ -85,6 +92,7 @@ class IncomingWebhookEndpoint { * @param bool $verify_request Whether requests need to be verified or not. * @param WebhookEventFactory $webhook_event_factory The webhook event factory. * @param WebhookSimulation $simulation The simulation handler. + * @param WebhookInfoStorage $last_webhook_storage The last webhook info storage. * @param RequestHandler ...$handlers The handlers, which process a request in the end. */ public function __construct( @@ -94,6 +102,7 @@ class IncomingWebhookEndpoint { bool $verify_request, WebhookEventFactory $webhook_event_factory, WebhookSimulation $simulation, + WebhookInfoStorage $last_webhook_storage, RequestHandler ...$handlers ) { @@ -103,6 +112,7 @@ class IncomingWebhookEndpoint { $this->logger = $logger; $this->verify_request = $verify_request; $this->webhook_event_factory = $webhook_event_factory; + $this->last_webhook_storage = $last_webhook_storage; $this->simulation = $simulation; } @@ -176,6 +186,8 @@ class IncomingWebhookEndpoint { public function handle_request( \WP_REST_Request $request ): \WP_REST_Response { $event = $this->event_from_request( $request ); + $this->last_webhook_storage->save( $event ); + if ( $this->simulation->is_simulation_event( $event ) ) { $this->logger->info( 'Received simulated webhook.' ); $this->simulation->receive( $event ); diff --git a/modules/ppcp-webhooks/src/WebhookInfoStorage.php b/modules/ppcp-webhooks/src/WebhookInfoStorage.php new file mode 100644 index 000000000..9fb9865f6 --- /dev/null +++ b/modules/ppcp-webhooks/src/WebhookInfoStorage.php @@ -0,0 +1,76 @@ +key = $key; + } + + /** + * Saves the info about webhook event. + * + * @param WebhookEvent $webhook_event The webhook event to save. + */ + public function save( WebhookEvent $webhook_event ): void { + $data = array( + 'id' => $webhook_event->id(), + 'received_time' => time(), + ); + + update_option( $this->key, $data ); + } + + /** + * Returns the stored data or null. + */ + public function get_data(): ?array { + $data = get_option( $this->key ); + if ( ! $data || ! is_array( $data ) ) { + return null; + } + return $data; + } + + /** + * Checks if there is any stored data. + */ + public function is_empty(): bool { + $data = get_option( $this->key ); + return ! $data || ! is_array( $data ); + } + + /** + * Removes the stored data. + */ + public function clear(): void { + delete_option( $this->key ); + } +} diff --git a/modules/ppcp-webhooks/src/WebhookRegistrar.php b/modules/ppcp-webhooks/src/WebhookRegistrar.php index e737e293e..c16aa9acd 100644 --- a/modules/ppcp-webhooks/src/WebhookRegistrar.php +++ b/modules/ppcp-webhooks/src/WebhookRegistrar.php @@ -44,6 +44,13 @@ class WebhookRegistrar { */ private $rest_endpoint; + /** + * The last webhook info storage. + * + * @var WebhookInfoStorage + */ + private $last_webhook_storage; + /** * The logger. * @@ -57,19 +64,22 @@ class WebhookRegistrar { * @param WebhookFactory $webhook_factory The Webhook factory. * @param WebhookEndpoint $endpoint The Webhook endpoint. * @param IncomingWebhookEndpoint $rest_endpoint The WordPress Rest API endpoint. + * @param WebhookInfoStorage $last_webhook_storage The last webhook info storage. * @param LoggerInterface $logger The logger. */ public function __construct( WebhookFactory $webhook_factory, WebhookEndpoint $endpoint, IncomingWebhookEndpoint $rest_endpoint, + WebhookInfoStorage $last_webhook_storage, LoggerInterface $logger ) { - $this->webhook_factory = $webhook_factory; - $this->endpoint = $endpoint; - $this->rest_endpoint = $rest_endpoint; - $this->logger = $logger; + $this->webhook_factory = $webhook_factory; + $this->endpoint = $endpoint; + $this->rest_endpoint = $rest_endpoint; + $this->last_webhook_storage = $last_webhook_storage; + $this->logger = $logger; } /** @@ -92,6 +102,7 @@ class WebhookRegistrar { self::KEY, $created->to_array() ); + $this->last_webhook_storage->clear(); $this->logger->info( 'Webhooks subscribed.' ); return true; } catch ( RuntimeException $error ) { @@ -120,6 +131,7 @@ class WebhookRegistrar { if ( $success ) { delete_option( self::KEY ); + $this->last_webhook_storage->clear(); $this->logger->info( 'Webhooks deleted.' ); } return $success; From 0ac3dae104ee778d8c5fb5fb872365680343d2e5 Mon Sep 17 00:00:00 2001 From: dinamiko Date: Wed, 24 Nov 2021 17:13:31 +0100 Subject: [PATCH 06/12] Fix error handler clear messages --- modules/ppcp-button/resources/js/modules/ErrorHandler.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/ErrorHandler.js b/modules/ppcp-button/resources/js/modules/ErrorHandler.js index 8c4d7149f..b3f865ddb 100644 --- a/modules/ppcp-button/resources/js/modules/ErrorHandler.js +++ b/modules/ppcp-button/resources/js/modules/ErrorHandler.js @@ -73,11 +73,13 @@ class ErrorHandler { clear() { - if (! this.wrapper.classList.contains('woocommerce-error')) { + if (this.messagesList === null) { return; } - this.wrapper.classList.remove('woocommerce-error'); - this.wrapper.innerText = ''; + + while( this.messagesList.firstChild ){ + this.messagesList.removeChild( this.messagesList.firstChild ); + } } } From 602e1e59c7e08f4c5f879ab5c91af969689d3e85 Mon Sep 17 00:00:00 2001 From: Alex P Date: Thu, 25 Nov 2021 10:33:54 +0200 Subject: [PATCH 07/12] Add non-translated export label to status report --- modules/ppcp-status-report/src/Renderer.php | 4 +- .../src/StatusReportModule.php | 63 +++++++++++-------- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/modules/ppcp-status-report/src/Renderer.php b/modules/ppcp-status-report/src/Renderer.php index 680006bcd..1435febd6 100644 --- a/modules/ppcp-status-report/src/Renderer.php +++ b/modules/ppcp-status-report/src/Renderer.php @@ -37,7 +37,9 @@ class Renderer { foreach ( $items as $item ) { ?> - + + + diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index c26302bd2..5b6186ea9 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -75,61 +75,70 @@ class StatusReportModule implements ModuleInterface { $items = array( array( - 'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ), - 'description' => esc_html__( 'Whether PayPal account is correctly configured or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'label' => esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Onboarded', + 'description' => esc_html__( 'Whether PayPal account is correctly configured or not.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( $this->onboarded( $bearer, $state ) ), ), array( - 'label' => esc_html__( 'Shop country code', 'woocommerce-paypal-payments' ), - 'description' => esc_html__( 'Country / State value on Settings / General / Store Address.', 'woocommerce-paypal-payments' ), - 'value' => wc_get_base_location()['country'], + 'label' => esc_html__( 'Shop country code', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Shop country code', + 'description' => esc_html__( 'Country / State value on Settings / General / Store Address.', 'woocommerce-paypal-payments' ), + 'value' => wc_get_base_location()['country'], ), array( - 'label' => esc_html__( 'WooCommerce currency supported', 'woocommerce-paypal-payments' ), - 'description' => esc_html__( 'Whether PayPal supports the default store currency or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'label' => esc_html__( 'WooCommerce currency supported', 'woocommerce-paypal-payments' ), + 'exported_label' => 'WooCommerce currency supported', + 'description' => esc_html__( 'Whether PayPal supports the default store currency or not.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( $currency_support->supports_wc_currency() ), ), array( - 'label' => esc_html__( 'PayPal card processing available in country', 'woocommerce-paypal-payments' ), - 'description' => esc_html__( 'Whether PayPal card processing is available in country or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'label' => esc_html__( 'PayPal card processing available in country', 'woocommerce-paypal-payments' ), + 'exported_label' => 'PayPal card processing available in country', + 'description' => esc_html__( 'Whether PayPal card processing is available in country or not.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( $dcc_applies->for_country_currency() ), ), array( - 'label' => esc_html__( 'Pay Later messaging available in country', 'woocommerce-paypal-payments' ), - 'description' => esc_html__( 'Whether Pay Later is available in country or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'label' => esc_html__( 'Pay Later messaging available in country', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Pay Later messaging available in country', + 'description' => esc_html__( 'Whether Pay Later is available in country or not.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( $messages_apply->for_country() ), ), array( - 'label' => esc_html__( 'Webhook status', 'woocommerce-paypal-payments' ), - 'description' => esc_html__( 'Whether we received webhooks successfully.', 'woocommerce-paypal-payments' ), - 'value' => $last_webhook_storage->is_empty() ? 'Unknown' : 'OK', + 'label' => esc_html__( 'Webhook status', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Webhook status', + 'description' => esc_html__( 'Whether we received webhooks successfully.', 'woocommerce-paypal-payments' ), + 'value' => $last_webhook_storage->is_empty() ? 'Unknown' : 'OK', ), array( - 'label' => esc_html__( 'Vault enabled', 'woocommerce-paypal-payments' ), - 'description' => esc_html__( 'Whether vaulting is enabled on PayPal account or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'label' => esc_html__( 'Vault enabled', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Vault enabled', + 'description' => esc_html__( 'Whether vaulting is enabled on PayPal account or not.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( $this->vault_enabled( $bearer ) ), ), array( - 'label' => esc_html__( 'Logging enabled', 'woocommerce-paypal-payments' ), - 'description' => esc_html__( 'Whether logging of plugin events and errors is enabled.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'label' => esc_html__( 'Logging enabled', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Logging enabled', + 'description' => esc_html__( 'Whether logging of plugin events and errors is enabled.', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( $settings->has( 'logging_enabled' ) && $settings->get( 'logging_enabled' ) ), ), array( - 'label' => esc_html__( 'Used PayPal Checkout plugin', 'woocommerce-paypal-payments' ), - 'description' => esc_html__( 'Whether the PayPal Checkout Gateway plugin was configured previously or not', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'label' => esc_html__( 'Used PayPal Checkout plugin', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Used PayPal Checkout plugin', + 'description' => esc_html__( 'Whether the PayPal Checkout Gateway plugin was configured previously or not', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( $had_ppec_plugin ), ), From 5322f101b4d2c73384583bd12383c16556cf4c64 Mon Sep 17 00:00:00 2001 From: Alex P Date: Thu, 25 Nov 2021 11:19:58 +0200 Subject: [PATCH 08/12] Add whether Reference Transactions are enabled to status report --- modules/ppcp-api-client/services.php | 8 + .../Endpoint/BillingAgreementsEndpoint.php | 138 ++++++++++++++++++ .../src/StatusReportModule.php | 25 ++++ 3 files changed, 171 insertions(+) create mode 100644 modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php diff --git a/modules/ppcp-api-client/services.php b/modules/ppcp-api-client/services.php index acb879e2b..be80943bf 100644 --- a/modules/ppcp-api-client/services.php +++ b/modules/ppcp-api-client/services.php @@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\ApiClient; use Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\IdentityToken; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\LoginSeller; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\OrderEndpoint; @@ -191,6 +192,13 @@ return array( $subscription_helper ); }, + 'api.endpoint.billing-agreements' => static function ( ContainerInterface $container ): BillingAgreementsEndpoint { + return new BillingAgreementsEndpoint( + $container->get( 'api.host' ), + $container->get( 'api.bearer' ), + $container->get( 'woocommerce.logger.woocommerce' ) + ); + }, 'api.repository.paypal-request-id' => static function( ContainerInterface $container ) : PayPalRequestIdRepository { return new PayPalRequestIdRepository(); }, diff --git a/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php new file mode 100644 index 000000000..9618574b5 --- /dev/null +++ b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php @@ -0,0 +1,138 @@ +host = $host; + $this->bearer = $bearer; + $this->logger = $logger; + } + + /** + * Creates a billing agreement token. + * + * @param string $description The description. + * @param string $return_url The return URL. + * @param string $cancel_url The cancel URL. + * + * @throws RuntimeException If the request fails. + * @throws PayPalApiException If the request fails. + */ + public function create_token( string $description, string $return_url, string $cancel_url ): stdClass { + $data = array( + 'description' => $description, + 'payer' => array( + 'payment_method' => 'PAYPAL', + ), + 'plan' => array( + 'type' => 'MERCHANT_INITIATED_BILLING', + 'merchant_preferences' => array( + 'return_url' => $return_url, + 'cancel_url' => $cancel_url, + 'skip_shipping_address' => true, + ), + ), + ); + + $bearer = $this->bearer->bearer(); + $url = trailingslashit( $this->host ) . 'v1/billing-agreements/agreement-tokens'; + $args = array( + 'method' => 'POST', + 'headers' => array( + 'Authorization' => 'Bearer ' . $bearer->token(), + 'Content-Type' => 'application/json', + ), + 'body' => wp_json_encode( $data ), + ); + $response = $this->request( $url, $args ); + + if ( is_wp_error( $response ) || ! is_array( $response ) ) { + throw new RuntimeException( 'Not able to create a billing agreement token.' ); + } + + $json = json_decode( $response['body'] ); + $status_code = (int) wp_remote_retrieve_response_code( $response ); + if ( 201 !== $status_code ) { + throw new PayPalApiException( + $json, + $status_code + ); + } + + return $json; + } + + /** + * Checks if reference transactions are enabled in account. + * + * @throws RuntimeException If the request fails (no auth, no connection, etc.). + */ + public function reference_transaction_enabled(): bool { + try { + $this->create_token( + 'Checking if reference transactions are enabled', + 'https://example.com/return', + 'https://example.com/cancel' + ); + + return true; + } catch ( PayPalApiException $exception ) { + return false; + } + } +} diff --git a/modules/ppcp-status-report/src/StatusReportModule.php b/modules/ppcp-status-report/src/StatusReportModule.php index 5b6186ea9..5f5a30935 100644 --- a/modules/ppcp-status-report/src/StatusReportModule.php +++ b/modules/ppcp-status-report/src/StatusReportModule.php @@ -15,6 +15,7 @@ use Interop\Container\ServiceProviderInterface; use Psr\Container\ContainerInterface; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; use WooCommerce\PayPalCommerce\ApiClient\Authentication\PayPalBearer; +use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingAgreementsEndpoint; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Helper\CurrencySupport; use WooCommerce\PayPalCommerce\ApiClient\Helper\DccApplies; @@ -68,6 +69,9 @@ class StatusReportModule implements ModuleInterface { $last_webhook_storage = $c->get( 'webhook.last-webhook-storage' ); assert( $last_webhook_storage instanceof WebhookInfoStorage ); + $billing_agreements_endpoint = $c->get( 'api.endpoint.billing-agreements' ); + assert( $billing_agreements_endpoint instanceof BillingAgreementsEndpoint ); + /* @var Renderer $renderer The renderer. */ $renderer = $c->get( 'status-report.renderer' ); @@ -134,6 +138,14 @@ class StatusReportModule implements ModuleInterface { $settings->has( 'logging_enabled' ) && $settings->get( 'logging_enabled' ) ), ), + array( + 'label' => esc_html__( 'Reference Transactions', 'woocommerce-paypal-payments' ), + 'exported_label' => 'Reference Transactions', + 'description' => esc_html__( 'Whether Reference Transactions are enabled for the connected account', 'woocommerce-paypal-payments' ), + 'value' => $this->bool_to_text( + $this->reference_transaction_enabled( $billing_agreements_endpoint ) + ), + ), array( 'label' => esc_html__( 'Used PayPal Checkout plugin', 'woocommerce-paypal-payments' ), 'exported_label' => 'Used PayPal Checkout plugin', @@ -192,6 +204,19 @@ class StatusReportModule implements ModuleInterface { } } + /** + * Checks if reference transactions are enabled in account. + * + * @param BillingAgreementsEndpoint $billing_agreements_endpoint The endpoint. + */ + private function reference_transaction_enabled( BillingAgreementsEndpoint $billing_agreements_endpoint ): bool { + try { + return $billing_agreements_endpoint->reference_transaction_enabled(); + } catch ( RuntimeException $exception ) { + return false; + } + } + /** * Converts the bool value to "Yes" or "No". * From 162a0886b7df8bfc65ef211b81a37d85262cb6fb Mon Sep 17 00:00:00 2001 From: dinamiko Date: Thu, 25 Nov 2021 10:36:56 +0100 Subject: [PATCH 09/12] Use `innerHTML` to clear element inner content --- modules/ppcp-button/resources/js/modules/ErrorHandler.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/ppcp-button/resources/js/modules/ErrorHandler.js b/modules/ppcp-button/resources/js/modules/ErrorHandler.js index b3f865ddb..9cd4ac174 100644 --- a/modules/ppcp-button/resources/js/modules/ErrorHandler.js +++ b/modules/ppcp-button/resources/js/modules/ErrorHandler.js @@ -77,9 +77,7 @@ class ErrorHandler { return; } - while( this.messagesList.firstChild ){ - this.messagesList.removeChild( this.messagesList.firstChild ); - } + this.messagesList.innerHTML = ''; } } From fc20b05de83612e7d65d93f1052b2634263bda4d Mon Sep 17 00:00:00 2001 From: Alex P Date: Thu, 25 Nov 2021 11:55:09 +0200 Subject: [PATCH 10/12] Use icons instead of yes/no For consistency with WC and to avoid translation --- modules/ppcp-status-report/src/Renderer.php | 2 +- .../src/StatusReportModule.php | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/ppcp-status-report/src/Renderer.php b/modules/ppcp-status-report/src/Renderer.php index 1435febd6..eefa70eea 100644 --- a/modules/ppcp-status-report/src/Renderer.php +++ b/modules/ppcp-status-report/src/Renderer.php @@ -41,7 +41,7 @@ class Renderer { - + esc_html__( 'Onboarded', 'woocommerce-paypal-payments' ), 'exported_label' => 'Onboarded', 'description' => esc_html__( 'Whether PayPal account is correctly configured or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'value' => $this->bool_to_html( $this->onboarded( $bearer, $state ) ), ), @@ -96,7 +96,7 @@ class StatusReportModule implements ModuleInterface { 'label' => esc_html__( 'WooCommerce currency supported', 'woocommerce-paypal-payments' ), 'exported_label' => 'WooCommerce currency supported', 'description' => esc_html__( 'Whether PayPal supports the default store currency or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'value' => $this->bool_to_html( $currency_support->supports_wc_currency() ), ), @@ -104,7 +104,7 @@ class StatusReportModule implements ModuleInterface { 'label' => esc_html__( 'PayPal card processing available in country', 'woocommerce-paypal-payments' ), 'exported_label' => 'PayPal card processing available in country', 'description' => esc_html__( 'Whether PayPal card processing is available in country or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'value' => $this->bool_to_html( $dcc_applies->for_country_currency() ), ), @@ -112,7 +112,7 @@ class StatusReportModule implements ModuleInterface { 'label' => esc_html__( 'Pay Later messaging available in country', 'woocommerce-paypal-payments' ), 'exported_label' => 'Pay Later messaging available in country', 'description' => esc_html__( 'Whether Pay Later is available in country or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'value' => $this->bool_to_html( $messages_apply->for_country() ), ), @@ -120,13 +120,13 @@ class StatusReportModule implements ModuleInterface { 'label' => esc_html__( 'Webhook status', 'woocommerce-paypal-payments' ), 'exported_label' => 'Webhook status', 'description' => esc_html__( 'Whether we received webhooks successfully.', 'woocommerce-paypal-payments' ), - 'value' => $last_webhook_storage->is_empty() ? 'Unknown' : 'OK', + 'value' => $this->bool_to_html( ! $last_webhook_storage->is_empty() ), ), array( 'label' => esc_html__( 'Vault enabled', 'woocommerce-paypal-payments' ), 'exported_label' => 'Vault enabled', 'description' => esc_html__( 'Whether vaulting is enabled on PayPal account or not.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'value' => $this->bool_to_html( $this->vault_enabled( $bearer ) ), ), @@ -134,7 +134,7 @@ class StatusReportModule implements ModuleInterface { 'label' => esc_html__( 'Logging enabled', 'woocommerce-paypal-payments' ), 'exported_label' => 'Logging enabled', 'description' => esc_html__( 'Whether logging of plugin events and errors is enabled.', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'value' => $this->bool_to_html( $settings->has( 'logging_enabled' ) && $settings->get( 'logging_enabled' ) ), ), @@ -142,7 +142,7 @@ class StatusReportModule implements ModuleInterface { 'label' => esc_html__( 'Reference Transactions', 'woocommerce-paypal-payments' ), 'exported_label' => 'Reference Transactions', 'description' => esc_html__( 'Whether Reference Transactions are enabled for the connected account', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'value' => $this->bool_to_html( $this->reference_transaction_enabled( $billing_agreements_endpoint ) ), ), @@ -150,7 +150,7 @@ class StatusReportModule implements ModuleInterface { 'label' => esc_html__( 'Used PayPal Checkout plugin', 'woocommerce-paypal-payments' ), 'exported_label' => 'Used PayPal Checkout plugin', 'description' => esc_html__( 'Whether the PayPal Checkout Gateway plugin was configured previously or not', 'woocommerce-paypal-payments' ), - 'value' => $this->bool_to_text( + 'value' => $this->bool_to_html( $had_ppec_plugin ), ), @@ -218,14 +218,14 @@ class StatusReportModule implements ModuleInterface { } /** - * Converts the bool value to "Yes" or "No". + * Converts the bool value to "yes" icon or dash. * * @param bool $value The value. * @return string */ - private function bool_to_text( bool $value ): string { + private function bool_to_html( bool $value ): string { return $value - ? esc_html__( 'Yes', 'woocommerce-paypal-payments' ) - : esc_html__( 'No', 'woocommerce-paypal-payments' ); + ? '' + : ''; } } From 74a1fb5a569aea63ed39de66672a9d18564007c3 Mon Sep 17 00:00:00 2001 From: Alex P Date: Thu, 25 Nov 2021 12:42:18 +0200 Subject: [PATCH 11/12] Update tests --- tests/PHPUnit/StatusReport/RendererTest.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/PHPUnit/StatusReport/RendererTest.php b/tests/PHPUnit/StatusReport/RendererTest.php index 0b83d86ff..4be0c713f 100644 --- a/tests/PHPUnit/StatusReport/RendererTest.php +++ b/tests/PHPUnit/StatusReport/RendererTest.php @@ -12,20 +12,23 @@ class RendererTest extends TestCase { $items = [ [ - 'label' => 'Foo', + 'label' => 'Translated Foo', + 'exported_label' => 'Foo', 'description' => 'Bar', 'value' => 'Baz' ], ]; when('esc_attr')->returnArg(); + when('wp_kses_post')->returnArg(); when('wc_help_tip')->returnArg(); $testee = new Renderer(); $result = $testee->render('Some title here', $items); self::assertStringContainsString('

Some title here

', $result); - self::assertStringContainsString('Foo', $result); + self::assertStringContainsString('data-export-label="Foo"', $result); + self::assertStringContainsString('Translated Foo', $result); self::assertStringContainsString('Bar', $result); self::assertStringContainsString('Baz', $result); } From aceeee95e93ac3bd2cc9eb5be8b2408afcc81539 Mon Sep 17 00:00:00 2001 From: Alex P Date: Thu, 25 Nov 2021 18:25:22 +0200 Subject: [PATCH 12/12] Remove unused imports --- .../src/Endpoint/BillingAgreementsEndpoint.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php index 9618574b5..3fd590367 100644 --- a/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php +++ b/modules/ppcp-api-client/src/Endpoint/BillingAgreementsEndpoint.php @@ -11,12 +11,8 @@ namespace WooCommerce\PayPalCommerce\ApiClient\Endpoint; use stdClass; use WooCommerce\PayPalCommerce\ApiClient\Authentication\Bearer; -use WooCommerce\PayPalCommerce\ApiClient\Entity\Webhook; -use WooCommerce\PayPalCommerce\ApiClient\Entity\WebhookEvent; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; -use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookEventFactory; -use WooCommerce\PayPalCommerce\ApiClient\Factory\WebhookFactory; use Psr\Log\LoggerInterface; /**