From 7fcda592f75f3e9b3052838a7140aece018024f9 Mon Sep 17 00:00:00 2001 From: David Remer Date: Thu, 27 Aug 2020 13:10:16 +0300 Subject: [PATCH] coding standards for webhook module --- .../src/Helper/EarlyOrderHandler.php | 2 +- .../src/Endpoint/ReturnUrlEndpoint.php | 2 +- modules.local/ppcp-webhooks/extensions.php | 9 +- modules.local/ppcp-webhooks/module.php | 7 +- modules.local/ppcp-webhooks/services.php | 81 +++---- .../ppcp-webhooks/src/Handler/PrefixTrait.php | 17 -- .../src/Handler/RequestHandler.php | 15 -- ...ed.php => class-checkoutorderapproved.php} | 121 ++++++---- ...d.php => class-checkoutordercompleted.php} | 94 +++++--- ....php => class-paymentcapturecompleted.php} | 73 ++++-- ...d.php => class-paymentcapturerefunded.php} | 71 ++++-- ...d.php => class-paymentcapturereversed.php} | 74 ++++-- .../src/Handler/class-prefixtrait.php | 37 +++ .../src/Handler/class-requesthandler.php | 41 ++++ .../src/IncomingWebhookEndpoint.php | 141 ------------ .../ppcp-webhooks/src/WebhookRegistrar.php | 73 ------ .../src/class-incomingwebhookendpoint.php | 214 ++++++++++++++++++ ...hookModule.php => class-webhookmodule.php} | 34 ++- .../src/class-webhookregistrar.php | 116 ++++++++++ 19 files changed, 813 insertions(+), 409 deletions(-) delete mode 100644 modules.local/ppcp-webhooks/src/Handler/PrefixTrait.php delete mode 100644 modules.local/ppcp-webhooks/src/Handler/RequestHandler.php rename modules.local/ppcp-webhooks/src/Handler/{CheckoutOrderApproved.php => class-checkoutorderapproved.php} (56%) rename modules.local/ppcp-webhooks/src/Handler/{CheckoutOrderCompleted.php => class-checkoutordercompleted.php} (50%) rename modules.local/ppcp-webhooks/src/Handler/{PaymentCaptureCompleted.php => class-paymentcapturecompleted.php} (54%) rename modules.local/ppcp-webhooks/src/Handler/{PaymentCaptureRefunded.php => class-paymentcapturerefunded.php} (60%) rename modules.local/ppcp-webhooks/src/Handler/{PaymentCaptureReversed.php => class-paymentcapturereversed.php} (55%) create mode 100644 modules.local/ppcp-webhooks/src/Handler/class-prefixtrait.php create mode 100644 modules.local/ppcp-webhooks/src/Handler/class-requesthandler.php delete mode 100644 modules.local/ppcp-webhooks/src/IncomingWebhookEndpoint.php delete mode 100644 modules.local/ppcp-webhooks/src/WebhookRegistrar.php create mode 100644 modules.local/ppcp-webhooks/src/class-incomingwebhookendpoint.php rename modules.local/ppcp-webhooks/src/{WebhookModule.php => class-webhookmodule.php} (69%) create mode 100644 modules.local/ppcp-webhooks/src/class-webhookregistrar.php diff --git a/modules.local/ppcp-button/src/Helper/EarlyOrderHandler.php b/modules.local/ppcp-button/src/Helper/EarlyOrderHandler.php index 7b467163f..b56015dd8 100644 --- a/modules.local/ppcp-button/src/Helper/EarlyOrderHandler.php +++ b/modules.local/ppcp-button/src/Helper/EarlyOrderHandler.php @@ -55,7 +55,7 @@ class EarlyOrderHandler { $orderId = false; foreach ( $order->purchaseUnits() as $purchaseUnit ) { if ( $purchaseUnit->customId() === sanitize_text_field( wp_unslash( $_REQUEST['ppcp-resume-order'] ) ) ) { - $orderId = (int) $this->sanitizeCustomId( $purchaseUnit->customId() ); + $orderId = (int) $this->sanitize_custom_id( $purchaseUnit->customId() ); } } if ( $orderId === $resumeOrderId ) { diff --git a/modules.local/ppcp-wc-gateway/src/Endpoint/ReturnUrlEndpoint.php b/modules.local/ppcp-wc-gateway/src/Endpoint/ReturnUrlEndpoint.php index a83ea1ed4..8f105d4a8 100644 --- a/modules.local/ppcp-wc-gateway/src/Endpoint/ReturnUrlEndpoint.php +++ b/modules.local/ppcp-wc-gateway/src/Endpoint/ReturnUrlEndpoint.php @@ -31,7 +31,7 @@ class ReturnUrlEndpoint { exit; } - $wcOrderId = $this->sanitizeCustomId( $order->purchaseUnits()[0]->customId() ); + $wcOrderId = $this->sanitize_custom_id( $order->purchaseUnits()[0]->customId() ); if ( ! $wcOrderId ) { exit; } diff --git a/modules.local/ppcp-webhooks/extensions.php b/modules.local/ppcp-webhooks/extensions.php index ca4be65b8..562446555 100644 --- a/modules.local/ppcp-webhooks/extensions.php +++ b/modules.local/ppcp-webhooks/extensions.php @@ -1,9 +1,12 @@ function(ContainerInterface $container) : WebhookRegistrar { - $factory = $container->get('api.factory.webhook'); - $endpoint = $container->get('api.endpoint.webhook'); - $restEndpoint = $container->get('webhook.endpoint.controller'); - return new WebhookRegistrar( - $factory, - $endpoint, - $restEndpoint - ); - }, - 'webhook.endpoint.controller' => function(ContainerInterface $container) : IncomingWebhookEndpoint { - $webhookEndpoint = $container->get('api.endpoint.webhook'); - $webhookFactory = $container->get('api.factory.webhook'); - $handler = $container->get('webhook.endpoint.handler'); - $logger = $container->get('woocommerce.logger.woocommerce'); - $verifyRequest = ! defined('PAYPAL_WEBHOOK_REQUEST_VERIFICATION') || PAYPAL_WEBHOOK_REQUEST_VERIFICATION; + 'webhook.registrar' => function( ContainerInterface $container ) : WebhookRegistrar { + $factory = $container->get( 'api.factory.webhook' ); + $endpoint = $container->get( 'api.endpoint.webhook' ); + $rest_endpoint = $container->get( 'webhook.endpoint.controller' ); + return new WebhookRegistrar( + $factory, + $endpoint, + $rest_endpoint + ); + }, + 'webhook.endpoint.controller' => function( ContainerInterface $container ) : IncomingWebhookEndpoint { + $webhook_endpoint = $container->get( 'api.endpoint.webhook' ); + $webhook_factory = $container->get( 'api.factory.webhook' ); + $handler = $container->get( 'webhook.endpoint.handler' ); + $logger = $container->get( 'woocommerce.logger.woocommerce' ); + $verify_request = ! defined( 'PAYPAL_WEBHOOK_REQUEST_VERIFICATION' ) || PAYPAL_WEBHOOK_REQUEST_VERIFICATION; - return new IncomingWebhookEndpoint( - $webhookEndpoint, - $webhookFactory, - $logger, - $verifyRequest, - ... $handler - ); - }, - 'webhook.endpoint.handler' => function(ContainerInterface $container) : array { - $logger = $container->get('woocommerce.logger.woocommerce'); - $prefix = $container->get('api.prefix'); - $orderEndpoint = $container->get('api.endpoint.order'); - return [ - new CheckoutOrderApproved($logger, $prefix, $orderEndpoint), - new CheckoutOrderCompleted($logger, $prefix), - new PaymentCaptureRefunded($logger, $prefix), - new PaymentCaptureReversed($logger, $prefix), - new PaymentCaptureCompleted($logger, $prefix), - ]; - } -]; + return new IncomingWebhookEndpoint( + $webhook_endpoint, + $webhook_factory, + $logger, + $verify_request, + ... $handler + ); + }, + 'webhook.endpoint.handler' => function( ContainerInterface $container ) : array { + $logger = $container->get( 'woocommerce.logger.woocommerce' ); + $prefix = $container->get( 'api.prefix' ); + $order_endpoint = $container->get( 'api.endpoint.order' ); + return array( + new CheckoutOrderApproved( $logger, $prefix, $order_endpoint ), + new CheckoutOrderCompleted( $logger, $prefix ), + new PaymentCaptureRefunded( $logger, $prefix ), + new PaymentCaptureReversed( $logger, $prefix ), + new PaymentCaptureCompleted( $logger, $prefix ), + ); + }, +); diff --git a/modules.local/ppcp-webhooks/src/Handler/PrefixTrait.php b/modules.local/ppcp-webhooks/src/Handler/PrefixTrait.php deleted file mode 100644 index ca2669413..000000000 --- a/modules.local/ppcp-webhooks/src/Handler/PrefixTrait.php +++ /dev/null @@ -1,17 +0,0 @@ -prefix, '', $customId ); - return (int) $orderId; - } -} diff --git a/modules.local/ppcp-webhooks/src/Handler/RequestHandler.php b/modules.local/ppcp-webhooks/src/Handler/RequestHandler.php deleted file mode 100644 index 2694e4905..000000000 --- a/modules.local/ppcp-webhooks/src/Handler/RequestHandler.php +++ /dev/null @@ -1,15 +0,0 @@ -logger = $logger; - $this->prefix = $prefix; - $this->orderEndpoint = $orderEndpoint; + /** + * The order endpoint. + * + * @var OrderEndpoint + */ + private $order_endpoint; + + /** + * CheckoutOrderApproved constructor. + * + * @param LoggerInterface $logger The logger. + * @param string $prefix The prefix. + * @param OrderEndpoint $order_endpoint The order endpoint. + */ + public function __construct( LoggerInterface $logger, string $prefix, OrderEndpoint $order_endpoint ) { + $this->logger = $logger; + $this->prefix = $prefix; + $this->order_endpoint = $order_endpoint; } - public function eventTypes(): array { + /** + * The event types a handler handles. + * + * @return array + */ + public function event_types(): array { return array( 'CHECKOUT.ORDER.APPROVED', ); } - public function responsibleForRequest( \WP_REST_Request $request ): bool { - return in_array( $request['event_type'], $this->eventTypes(), true ); + /** + * Whether a handler is responsible for a given request or not. + * + * @param \WP_REST_Request $request The request. + * + * @return bool + */ + public function responsible_for_request( \WP_REST_Request $request ): bool { + return in_array( $request['event_type'], $this->event_types(), true ); } - //phpcs:disable Inpsyde.CodeQuality.FunctionLength.TooLong - public function handleRequest( \WP_REST_Request $request ): \WP_REST_Response { - $response = array( 'success' => false ); - $customIds = array_filter( + /** + * Responsible for handling the request. + * + * @param \WP_REST_Request $request The request. + * + * @return \WP_REST_Response + */ + public function handle_request( \WP_REST_Request $request ): \WP_REST_Response { + $response = array( 'success' => false ); + $custom_ids = array_filter( array_map( - static function ( array $purchaseUnit ): string { - return isset( $purchaseUnit['custom_id'] ) ? - (string) $purchaseUnit['custom_id'] : ''; + static function ( array $purchase_unit ): string { + return isset( $purchase_unit['custom_id'] ) ? + (string) $purchase_unit['custom_id'] : ''; }, isset( $request['resource']['purchase_units'] ) ? (array) $request['resource']['purchase_units'] : array() ), - static function ( string $orderId ): bool { - return ! empty( $orderId ); + static function ( string $order_id ): bool { + return ! empty( $order_id ); } ); - if ( empty( $customIds ) ) { + if ( empty( $custom_ids ) ) { $message = sprintf( // translators: %s is the PayPal webhook Id. __( @@ -70,7 +114,7 @@ class CheckoutOrderApproved implements RequestHandler { try { $order = isset( $request['resource']['id'] ) ? - $this->orderEndpoint->order( $request['resource']['id'] ) : null; + $this->order_endpoint->order( $request['resource']['id'] ) : null; if ( ! $order ) { $message = sprintf( // translators: %s is the PayPal webhook Id. @@ -92,7 +136,7 @@ class CheckoutOrderApproved implements RequestHandler { } if ( $order->intent() === 'CAPTURE' ) { - $this->orderEndpoint->capture( $order ); + $this->order_endpoint->capture( $order ); } } catch ( RuntimeException $error ) { $message = sprintf( @@ -114,19 +158,19 @@ class CheckoutOrderApproved implements RequestHandler { return rest_ensure_response( $response ); } - $wcOrderIds = array_map( + $wc_order_ids = array_map( array( $this, - 'sanitizeCustomId', + 'sanitize_custom_id', ), - $customIds + $custom_ids ); - $args = array( - 'post__in' => $wcOrderIds, + $args = array( + 'post__in' => $wc_order_ids, 'limit' => -1, ); - $wcOrders = wc_get_orders( $args ); - if ( ! $wcOrders ) { + $wc_orders = wc_get_orders( $args ); + if ( ! $wc_orders ) { $message = sprintf( // translators: %s is the PayPal order Id. __( 'Order for PayPal order %s not found.', 'woocommerce-paypal-commerce-gateway' ), @@ -143,20 +187,22 @@ class CheckoutOrderApproved implements RequestHandler { return rest_ensure_response( $response ); } - $newStatus = $order->intent() === 'CAPTURE' ? 'processing' : 'on-hold'; - $statusMessage = $order->intent() === 'CAPTURE' ? + $new_status = $order->intent() === 'CAPTURE' ? 'processing' : 'on-hold'; + $status_message = $order->intent() === 'CAPTURE' ? __( 'Payment received.', 'woocommerce-paypal-commerce-gateway' ) : __( 'Payment can be captured.', 'woocommerce-paypal-commerce-gateway' ); - foreach ( $wcOrders as $wcOrder ) { - if ( ! in_array( $wcOrder->get_status(), array( 'pending', 'on-hold' ), true ) ) { + foreach ( $wc_orders as $wc_order ) { + if ( ! in_array( $wc_order->get_status(), array( 'pending', 'on-hold' ), true ) ) { continue; } /** - * @var \WC_Order $wcOrder + * The Woocommerce order. + * + * @var \WC_Order $wc_order */ - $wcOrder->update_status( - $newStatus, - $statusMessage + $wc_order->update_status( + $new_status, + $status_message ); $this->logger->log( 'info', @@ -166,16 +212,15 @@ class CheckoutOrderApproved implements RequestHandler { 'Order %s has been updated through PayPal', 'woocommerce-paypal-commerce-gateway' ), - (string) $wcOrder->get_id() + (string) $wc_order->get_id() ), array( 'request' => $request, - 'order' => $wcOrder, + 'order' => $wc_order, ) ); } $response['success'] = true; return rest_ensure_response( $response ); } - //phpcs:enable Inpsyde.CodeQuality.FunctionLength.TooLong } diff --git a/modules.local/ppcp-webhooks/src/Handler/CheckoutOrderCompleted.php b/modules.local/ppcp-webhooks/src/Handler/class-checkoutordercompleted.php similarity index 50% rename from modules.local/ppcp-webhooks/src/Handler/CheckoutOrderCompleted.php rename to modules.local/ppcp-webhooks/src/Handler/class-checkoutordercompleted.php index d1c739cd4..01b6fe651 100644 --- a/modules.local/ppcp-webhooks/src/Handler/CheckoutOrderCompleted.php +++ b/modules.local/ppcp-webhooks/src/Handler/class-checkoutordercompleted.php @@ -1,4 +1,9 @@ logger = $logger; $this->prefix = $prefix; } - public function eventTypes(): array { + /** + * The event types a handler handles. + * + * @return array + */ + public function event_types(): array { return array( 'CHECKOUT.ORDER.COMPLETED', ); } - public function responsibleForRequest( \WP_REST_Request $request ): bool { - return in_array( $request['event_type'], $this->eventTypes(), true ); + /** + * Whether a handler is responsible for a given request or not. + * + * @param \WP_REST_Request $request The request. + * + * @return bool + */ + public function responsible_for_request( \WP_REST_Request $request ): bool { + return in_array( $request['event_type'], $this->event_types(), true ); } - // phpcs:disable Inpsyde.CodeQuality.FunctionLength.TooLong - public function handleRequest( \WP_REST_Request $request ): \WP_REST_Response { - $response = array( 'success' => false ); - $customIds = array_filter( + /** + * Responsible for handling the request. + * + * @param \WP_REST_Request $request The request. + * + * @return \WP_REST_Response + */ + public function handle_request( \WP_REST_Request $request ): \WP_REST_Response { + $response = array( 'success' => false ); + $custom_ids = array_filter( array_map( - static function ( array $purchaseUnit ): string { - return isset( $purchaseUnit['custom_id'] ) ? - (string) $purchaseUnit['custom_id'] : ''; + static function ( array $purchase_unit ): string { + return isset( $purchase_unit['custom_id'] ) ? + (string) $purchase_unit['custom_id'] : ''; }, isset( $request['resource']['purchase_units'] ) ? (array) $request['resource']['purchase_units'] : array() ), - static function ( string $orderId ): bool { - return ! empty( $orderId ); + static function ( string $order_id ): bool { + return ! empty( $order_id ); } ); - if ( empty( $customIds ) ) { + if ( empty( $custom_ids ) ) { $message = sprintf( // translators: %s is the PayPal webhook Id. __( @@ -63,19 +101,19 @@ class CheckoutOrderCompleted implements RequestHandler { return rest_ensure_response( $response ); } - $orderIds = array_map( + $order_ids = array_map( array( $this, - 'sanitizeCustomId', + 'sanitize_custom_id', ), - $customIds + $custom_ids ); - $args = array( - 'post__in' => $orderIds, + $args = array( + 'post__in' => $order_ids, 'limit' => -1, ); - $wcOrders = wc_get_orders( $args ); - if ( ! $wcOrders ) { + $wc_orders = wc_get_orders( $args ); + if ( ! $wc_orders ) { $message = sprintf( // translators: %s is the PayPal order Id. __( 'Order for PayPal order %s not found.', 'woocommerce-paypal-commerce-gateway' ), @@ -92,14 +130,16 @@ class CheckoutOrderCompleted implements RequestHandler { return rest_ensure_response( $response ); } - foreach ( $wcOrders as $wcOrder ) { - if ( ! in_array( $wcOrder->get_status(), array( 'pending', 'on-hold' ), true ) ) { + foreach ( $wc_orders as $wc_order ) { + if ( ! in_array( $wc_order->get_status(), array( 'pending', 'on-hold' ), true ) ) { continue; } /** - * @var \WC_Order $wcOrder + * The Woocommerce order. + * + * @var \WC_Order $wc_order */ - $wcOrder->update_status( + $wc_order->update_status( 'processing', __( 'Payment received.', 'woocommerce-paypal-commerce-gateway' ) ); @@ -111,16 +151,16 @@ class CheckoutOrderCompleted implements RequestHandler { 'Order %s has been updated through PayPal', 'woocommerce-paypal-commerce-gateway' ), - (string) $wcOrder->get_id() + (string) $wc_order->get_id() ), array( 'request' => $request, - 'order' => $wcOrder, + 'order' => $wc_order, ) ); } $response['success'] = true; return rest_ensure_response( $response ); } - // phpcs:enable Inpsyde.CodeQuality.FunctionLength.TooLong + // phpcs:enable Inpsyde.CodeQuality.FunctionLength.TooLong } diff --git a/modules.local/ppcp-webhooks/src/Handler/PaymentCaptureCompleted.php b/modules.local/ppcp-webhooks/src/Handler/class-paymentcapturecompleted.php similarity index 54% rename from modules.local/ppcp-webhooks/src/Handler/PaymentCaptureCompleted.php rename to modules.local/ppcp-webhooks/src/Handler/class-paymentcapturecompleted.php index fee7380b2..242619a47 100644 --- a/modules.local/ppcp-webhooks/src/Handler/PaymentCaptureCompleted.php +++ b/modules.local/ppcp-webhooks/src/Handler/class-paymentcapturecompleted.php @@ -1,4 +1,9 @@ logger = $logger; $this->prefix = $prefix; } - public function eventTypes(): array { + /** + * The event types a handler handles. + * + * @return array + */ + public function event_types(): array { return array( 'PAYMENT.CAPTURE.COMPLETED' ); } - public function responsibleForRequest( \WP_REST_Request $request ): bool { - return in_array( $request['event_type'], $this->eventTypes(), true ); + /** + * Whether a handler is responsible for a given request or not. + * + * @param \WP_REST_Request $request The request. + * + * @return bool + */ + public function responsible_for_request( \WP_REST_Request $request ): bool { + return in_array( $request['event_type'], $this->event_types(), true ); } - // phpcs:disable Inpsyde.CodeQuality.FunctionLength.TooLong - public function handleRequest( \WP_REST_Request $request ): \WP_REST_Response { + /** + * Responsible for handling the request. + * + * @param \WP_REST_Request $request The request. + * + * @return \WP_REST_Response + */ + public function handle_request( \WP_REST_Request $request ): \WP_REST_Response { $response = array( 'success' => false ); - $orderId = isset( $request['resource']['custom_id'] ) ? - $this->sanitizeCustomId( $request['resource']['custom_id'] ) : 0; - if ( ! $orderId ) { + $order_id = isset( $request['resource']['custom_id'] ) ? + $this->sanitize_custom_id( $request['resource']['custom_id'] ) : 0; + if ( ! $order_id ) { $message = sprintf( // translators: %s is the PayPal webhook Id. __( @@ -49,9 +87,9 @@ class PaymentCaptureCompleted implements RequestHandler { $response['message'] = $message; return rest_ensure_response( $response ); } - $wcOrder = wc_get_order( $orderId ); + $wc_order = wc_get_order( $order_id ); - if ( ! is_a( $wcOrder, \WC_Order::class ) ) { + if ( ! is_a( $wc_order, \WC_Order::class ) ) { $message = sprintf( // translators: %s is the PayPal webhook Id. __( @@ -71,17 +109,17 @@ class PaymentCaptureCompleted implements RequestHandler { return rest_ensure_response( $response ); } - if ( $wcOrder->get_status() !== 'on-hold' ) { + if ( $wc_order->get_status() !== 'on-hold' ) { $response['success'] = true; return rest_ensure_response( $response ); } - $wcOrder->add_order_note( + $wc_order->add_order_note( __( 'Payment successfully captured.', 'woocommerce-paypal-commerce-gateway' ) ); - $wcOrder->set_status( 'processing' ); - $wcOrder->update_meta_data( PayPalGateway::CAPTURED_META_KEY, 'true' ); - $wcOrder->save(); + $wc_order->set_status( 'processing' ); + $wc_order->update_meta_data( PayPalGateway::CAPTURED_META_KEY, 'true' ); + $wc_order->save(); $this->logger->log( 'info', sprintf( @@ -90,15 +128,14 @@ class PaymentCaptureCompleted implements RequestHandler { 'Order %s has been updated through PayPal', 'woocommerce-paypal-commerce-gateway' ), - (string) $wcOrder->get_id() + (string) $wc_order->get_id() ), array( 'request' => $request, - 'order' => $wcOrder, + 'order' => $wc_order, ) ); $response['success'] = true; return rest_ensure_response( $response ); } - // phpcs:enable Inpsyde.CodeQuality.FunctionLength.TooLong } diff --git a/modules.local/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php b/modules.local/ppcp-webhooks/src/Handler/class-paymentcapturerefunded.php similarity index 60% rename from modules.local/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php rename to modules.local/ppcp-webhooks/src/Handler/class-paymentcapturerefunded.php index 1edef6b59..012c45535 100644 --- a/modules.local/ppcp-webhooks/src/Handler/PaymentCaptureRefunded.php +++ b/modules.local/ppcp-webhooks/src/Handler/class-paymentcapturerefunded.php @@ -1,4 +1,9 @@ logger = $logger; $this->prefix = $prefix; } - public function eventTypes(): array { + /** + * The event types a handler handles. + * + * @return array + */ + public function event_types(): array { return array( 'PAYMENT.CAPTURE.REFUNDED' ); } - public function responsibleForRequest( \WP_REST_Request $request ): bool { - return in_array( $request['event_type'], $this->eventTypes(), true ); + /** + * Whether a handler is responsible for a given request or not. + * + * @param \WP_REST_Request $request The request. + * + * @return bool + */ + public function responsible_for_request( \WP_REST_Request $request ): bool { + return in_array( $request['event_type'], $this->event_types(), true ); } - // phpcs:disable Inpsyde.CodeQuality.FunctionLength.TooLong - public function handleRequest( \WP_REST_Request $request ): \WP_REST_Response { + /** + * Responsible for handling the request. + * + * @param \WP_REST_Request $request The request. + * + * @return \WP_REST_Response + */ + public function handle_request( \WP_REST_Request $request ): \WP_REST_Response { $response = array( 'success' => false ); - $orderId = isset( $request['resource']['custom_id'] ) ? - $this->sanitizeCustomId( $request['resource']['custom_id'] ) : 0; - if ( ! $orderId ) { + $order_id = isset( $request['resource']['custom_id'] ) ? + $this->sanitize_custom_id( $request['resource']['custom_id'] ) : 0; + if ( ! $order_id ) { $message = sprintf( // translators: %s is the PayPal webhook Id. __( @@ -49,8 +87,8 @@ class PaymentCaptureRefunded implements RequestHandler { return rest_ensure_response( $response ); } - $wcOrder = wc_get_order( $orderId ); - if ( ! is_a( $wcOrder, \WC_Order::class ) ) { + $wc_order = wc_get_order( $order_id ); + if ( ! is_a( $wc_order, \WC_Order::class ) ) { $message = sprintf( // translators: %s is the PayPal refund Id. __( 'Order for PayPal refund %s not found.', 'woocommerce-paypal-commerce-gateway' ), @@ -68,11 +106,13 @@ class PaymentCaptureRefunded implements RequestHandler { } /** - * @var \WC_Order $wcOrder + * The Woocommerce order. + * + * @var \WC_Order $wc_order */ $refund = wc_create_refund( array( - 'order_id' => $wcOrder->get_id(), + 'order_id' => $wc_order->get_id(), 'amount' => $request['resource']['amount']['value'], ) ); @@ -82,7 +122,7 @@ class PaymentCaptureRefunded implements RequestHandler { sprintf( // translators: %s is the order id. __( 'Order %s could not be refunded', 'woocommerce-paypal-commerce-gateway' ), - (string) $wcOrder->get_id() + (string) $wc_order->get_id() ), array( 'request' => $request, @@ -102,16 +142,15 @@ class PaymentCaptureRefunded implements RequestHandler { 'Order %1$s has been refunded with %2$s through PayPal', 'woocommerce-paypal-commerce-gateway' ), - (string) $wcOrder->get_id(), + (string) $wc_order->get_id(), (string) $refund->get_amount() ), array( 'request' => $request, - 'order' => $wcOrder, + 'order' => $wc_order, ) ); $response['success'] = true; return rest_ensure_response( $response ); } - // phpcs:enable Inpsyde.CodeQuality.FunctionLength.TooLong } diff --git a/modules.local/ppcp-webhooks/src/Handler/PaymentCaptureReversed.php b/modules.local/ppcp-webhooks/src/Handler/class-paymentcapturereversed.php similarity index 55% rename from modules.local/ppcp-webhooks/src/Handler/PaymentCaptureReversed.php rename to modules.local/ppcp-webhooks/src/Handler/class-paymentcapturereversed.php index 7685b6ef3..b46ec0031 100644 --- a/modules.local/ppcp-webhooks/src/Handler/PaymentCaptureReversed.php +++ b/modules.local/ppcp-webhooks/src/Handler/class-paymentcapturereversed.php @@ -1,4 +1,12 @@ logger = $logger; $this->prefix = $prefix; } - public function eventTypes(): array { + /** + * The event types a handler handles. + * + * @return array + */ + public function event_types(): array { return array( 'PAYMENT.CAPTURE.REVERSED', 'PAYMENT.ORDER.CANCELLED', @@ -24,16 +52,29 @@ class PaymentCaptureReversed implements RequestHandler { ); } - public function responsibleForRequest( \WP_REST_Request $request ): bool { - return in_array( $request['event_type'], $this->eventTypes(), true ); + /** + * Whether a handler is responsible for a given request or not. + * + * @param \WP_REST_Request $request The request. + * + * @return bool + */ + public function responsible_for_request( \WP_REST_Request $request ): bool { + return in_array( $request['event_type'], $this->event_types(), true ); } - // phpcs:disable Inpsyde.CodeQuality.FunctionLength.TooLong - public function handleRequest( \WP_REST_Request $request ): \WP_REST_Response { + /** + * Responsible for handling the request. + * + * @param \WP_REST_Request $request The request. + * + * @return \WP_REST_Response + */ + public function handle_request( \WP_REST_Request $request ): \WP_REST_Response { $response = array( 'success' => false ); - $orderId = isset( $request['resource']['custom_id'] ) ? - $this->sanitizeCustomId( $request['resource']['custom_id'] ) : 0; - if ( ! $orderId ) { + $order_id = isset( $request['resource']['custom_id'] ) ? + $this->sanitize_custom_id( $request['resource']['custom_id'] ) : 0; + if ( ! $order_id ) { $message = sprintf( // translators: %s is the PayPal webhook Id. __( @@ -53,8 +94,8 @@ class PaymentCaptureReversed implements RequestHandler { return rest_ensure_response( $response ); } - $wcOrder = wc_get_order( $orderId ); - if ( ! is_a( $wcOrder, \WC_Order::class ) ) { + $wc_order = wc_get_order( $order_id ); + if ( ! is_a( $wc_order, \WC_Order::class ) ) { $message = sprintf( // translators: %s is the PayPal refund Id. __( 'Order for PayPal refund %s not found.', 'woocommerce-paypal-commerce-gateway' ), @@ -72,9 +113,11 @@ class PaymentCaptureReversed implements RequestHandler { } /** - * @var \WC_Order $wcOrder + * The Woocommerce order. + * + * @var \WC_Order $wc_order */ - $response['success'] = (bool) $wcOrder->update_status( 'cancelled' ); + $response['success'] = (bool) $wc_order->update_status( 'cancelled' ); $message = $response['success'] ? sprintf( // translators: %1$s is the order id. @@ -82,21 +125,20 @@ class PaymentCaptureReversed implements RequestHandler { 'Order %1$s has been cancelled through PayPal', 'woocommerce-paypal-commerce-gateway' ), - (string) $wcOrder->get_id() + (string) $wc_order->get_id() ) : sprintf( // translators: %1$s is the order id. __( 'Failed to cancel order %1$s through PayPal', 'woocommerce-paypal-commerce-gateway' ), - (string) $wcOrder->get_id() + (string) $wc_order->get_id() ); $this->logger->log( $response['success'] ? 'info' : 'warning', $message, array( 'request' => $request, - 'order' => $wcOrder, + 'order' => $wc_order, ) ); return rest_ensure_response( $response ); } - // phpcs:enable Inpsyde.CodeQuality.FunctionLength.TooLong } diff --git a/modules.local/ppcp-webhooks/src/Handler/class-prefixtrait.php b/modules.local/ppcp-webhooks/src/Handler/class-prefixtrait.php new file mode 100644 index 000000000..ae1dfd7dc --- /dev/null +++ b/modules.local/ppcp-webhooks/src/Handler/class-prefixtrait.php @@ -0,0 +1,37 @@ +prefix, '', $custom_id ); + return (int) $id; + } +} diff --git a/modules.local/ppcp-webhooks/src/Handler/class-requesthandler.php b/modules.local/ppcp-webhooks/src/Handler/class-requesthandler.php new file mode 100644 index 000000000..99bd776da --- /dev/null +++ b/modules.local/ppcp-webhooks/src/Handler/class-requesthandler.php @@ -0,0 +1,41 @@ +webhookEndpoint = $webhookEndpoint; - $this->webhookFactory = $webhookFactory; - $this->handlers = $handlers; - $this->logger = $logger; - $this->verifyRequest = $verifyRequest; - } - - public function register(): bool { - return (bool) register_rest_route( - self::NAMESPACE, - self::ROUTE, - array( - 'methods' => array( - 'POST', - ), - 'callback' => array( - $this, - 'handleRequest', - ), - 'permission_callback' => array( - $this, - 'verifyRequest', - ), - - ) - ); - } - - public function verifyRequest(): bool { - if ( ! $this->verifyRequest ) { - return true; - } - try { - $data = (array) get_option( WebhookRegistrar::KEY, array() ); - $webhook = $this->webhookFactory->fromArray( $data ); - $result = $this->webhookEndpoint->verifyCurrentRequestForWebhook( $webhook ); - if ( ! $result ) { - $this->logger->log( - 'error', - __( 'Illegit Webhook request detected.', 'woocommerce-paypal-commerce-gateway' ), - ); - } - return $result; - } catch ( RuntimeException $exception ) { - $this->logger->log( - 'error', - sprintf( - // translators: %s is the error message. - __( - 'Illegit Webhook request detected: %s', - 'woocommerce-paypal-commerce-gateway' - ), - $exception->getMessage() - ) - ); - return false; - } - } - - public function handleRequest( \WP_REST_Request $request ): \WP_REST_Response { - - foreach ( $this->handlers as $handler ) { - if ( $handler->responsibleForRequest( $request ) ) { - $response = $handler->handleRequest( $request ); - $this->logger->log( - 'info', - sprintf( - // translators: %s is the event type - __( 'Webhook has been handled by %s', 'woocommerce-paypal-commerce-gateway' ), - ( $handler->eventTypes() ) ? current( $handler->eventTypes() ) : '' - ), - array( - 'request' => $request, - 'response' => $response, - ) - ); - return $response; - } - } - - $message = sprintf( - // translators: %s is the request type. - __( 'Could not find handler for request type %s', 'woocommerce-paypal-commerce-gateway' ), - $request['event_type'] - ); - $this->logger->log( - 'warning', - $message, - array( - 'request' => $request, - ) - ); - $response = array( - 'success' => false, - 'message' => $message, - ); - return rest_ensure_response( $response ); - } - - public function url(): string { - return rest_url( self::NAMESPACE . '/' . self::ROUTE ); - } - - public function handledEventTypes(): array { - $eventTypes = array(); - foreach ( $this->handlers as $handler ) { - $eventTypes = array_merge( $eventTypes, $handler->eventTypes() ); - } - return array_unique( $eventTypes ); - } -} diff --git a/modules.local/ppcp-webhooks/src/WebhookRegistrar.php b/modules.local/ppcp-webhooks/src/WebhookRegistrar.php deleted file mode 100644 index 71ad785c0..000000000 --- a/modules.local/ppcp-webhooks/src/WebhookRegistrar.php +++ /dev/null @@ -1,73 +0,0 @@ -webhookFactory = $webhookFactory; - $this->endpoint = $endpoint; - $this->restEndpoint = $restEndpoint; - } - - public function register(): bool { - $webhook = $this->webhookFactory->forUrlAndEvents( - $this->restEndpoint->url(), - $this->restEndpoint->handledEventTypes() - ); - - try { - $created = $this->endpoint->create( $webhook ); - if ( empty( $created->id() ) ) { - return false; - } - update_option( - self::KEY, - $created->toArray() - ); - return true; - } catch ( RuntimeException $error ) { - wp_schedule_single_event( - time() - 1, - self::EVENT_HOOK - ); - return false; - } - } - - public function unregister(): bool { - $data = (array) get_option( self::KEY, array() ); - if ( ! $data ) { - return false; - } - try { - $webhook = $this->webhookFactory->fromArray( $data ); - $success = $this->endpoint->delete( $webhook ); - } catch ( RuntimeException $error ) { - return false; - } - - if ( $success ) { - delete_option( self::KEY ); - } - return $success; - } -} diff --git a/modules.local/ppcp-webhooks/src/class-incomingwebhookendpoint.php b/modules.local/ppcp-webhooks/src/class-incomingwebhookendpoint.php new file mode 100644 index 000000000..9d08f3fa1 --- /dev/null +++ b/modules.local/ppcp-webhooks/src/class-incomingwebhookendpoint.php @@ -0,0 +1,214 @@ +webhook_endpoint = $webhook_endpoint; + $this->webhook_factory = $webhook_factory; + $this->handlers = $handlers; + $this->logger = $logger; + $this->verify_request = $verify_request; + } + + /** + * Registers the endpoint. + * + * @return bool + */ + public function register(): bool { + return (bool) register_rest_route( + self::NAMESPACE, + self::ROUTE, + array( + 'methods' => array( + 'POST', + ), + 'callback' => array( + $this, + 'handle_request', + ), + 'permission_callback' => array( + $this, + 'verify_request', + ), + ) + ); + } + + /** + * Verifies the current request. + * + * @return bool + */ + public function verify_request(): bool { + if ( ! $this->verify_request ) { + return true; + } + try { + $data = (array) get_option( WebhookRegistrar::KEY, array() ); + $webhook = $this->webhook_factory->fromArray( $data ); + $result = $this->webhook_endpoint->verifyCurrentRequestForWebhook( $webhook ); + if ( ! $result ) { + $this->logger->log( + 'error', + __( 'Illegit Webhook request detected.', 'woocommerce-paypal-commerce-gateway' ) + ); + } + return $result; + } catch ( RuntimeException $exception ) { + $this->logger->log( + 'error', + sprintf( + // translators: %s is the error message. + __( + 'Illegit Webhook request detected: %s', + 'woocommerce-paypal-commerce-gateway' + ), + $exception->getMessage() + ) + ); + return false; + } + } + + /** + * Handles the request. + * + * @param \WP_REST_Request $request The request. + * + * @return \WP_REST_Response + */ + public function handle_request( \WP_REST_Request $request ): \WP_REST_Response { + + foreach ( $this->handlers as $handler ) { + if ( $handler->responsible_for_request( $request ) ) { + $response = $handler->handle_request( $request ); + $this->logger->log( + 'info', + sprintf( + // translators: %s is the event type. + __( 'Webhook has been handled by %s', 'woocommerce-paypal-commerce-gateway' ), + ( $handler->event_types() ) ? current( $handler->event_types() ) : '' + ), + array( + 'request' => $request, + 'response' => $response, + ) + ); + return $response; + } + } + + $message = sprintf( + // translators: %s is the request type. + __( 'Could not find handler for request type %s', 'woocommerce-paypal-commerce-gateway' ), + $request['event_type'] + ); + $this->logger->log( + 'warning', + $message, + array( + 'request' => $request, + ) + ); + $response = array( + 'success' => false, + 'message' => $message, + ); + return rest_ensure_response( $response ); + } + + /** + * Returns the URL to the endpoint. + * + * @return string + */ + public function url(): string { + return rest_url( self::NAMESPACE . '/' . self::ROUTE ); + } + + /** + * Returns the event types, which are handled by the endpoint. + * + * @return array + */ + public function handled_event_types(): array { + $event_types = array(); + foreach ( $this->handlers as $handler ) { + $event_types = array_merge( $event_types, $handler->event_types() ); + } + return array_unique( $event_types ); + } +} diff --git a/modules.local/ppcp-webhooks/src/WebhookModule.php b/modules.local/ppcp-webhooks/src/class-webhookmodule.php similarity index 69% rename from modules.local/ppcp-webhooks/src/WebhookModule.php rename to modules.local/ppcp-webhooks/src/class-webhookmodule.php index 931653f08..203167db6 100644 --- a/modules.local/ppcp-webhooks/src/WebhookModule.php +++ b/modules.local/ppcp-webhooks/src/class-webhookmodule.php @@ -1,4 +1,9 @@ get( 'webhook.endpoint.controller' ); /** + * The Incoming Webhook Endpoint. + * * @var IncomingWebhookEndpoint $endpoint */ $endpoint->register(); @@ -38,6 +54,11 @@ class WebhookModule implements ModuleInterface { WebhookRegistrar::EVENT_HOOK, static function () use ( $container ) { $registrar = $container->get( 'webhook.registrar' ); + /** + * The Webhook Registrar. + * + * @var WebhookRegistrar $endpoint + */ $registrar->register(); } ); @@ -46,6 +67,11 @@ class WebhookModule implements ModuleInterface { 'woocommerce-paypal-commerce-gateway.deactivate', static function () use ( $container ) { $registrar = $container->get( 'webhook.registrar' ); + /** + * The Webhook Registrar. + * + * @var WebhookRegistrar $endpoint + */ $registrar->unregister(); } ); diff --git a/modules.local/ppcp-webhooks/src/class-webhookregistrar.php b/modules.local/ppcp-webhooks/src/class-webhookregistrar.php new file mode 100644 index 000000000..e817be5b7 --- /dev/null +++ b/modules.local/ppcp-webhooks/src/class-webhookregistrar.php @@ -0,0 +1,116 @@ +webhook_factory = $webhook_factory; + $this->endpoint = $endpoint; + $this->rest_endpoint = $rest_endpoint; + } + + /** + * Register Webhooks with PayPal. + * + * @return bool + */ + public function register(): bool { + $webhook = $this->webhook_factory->forUrlAndEvents( + $this->rest_endpoint->url(), + $this->rest_endpoint->handled_event_types() + ); + + try { + $created = $this->endpoint->create( $webhook ); + if ( empty( $created->id() ) ) { + return false; + } + update_option( + self::KEY, + $created->toArray() + ); + return true; + } catch ( RuntimeException $error ) { + wp_schedule_single_event( + time() - 1, + self::EVENT_HOOK + ); + return false; + } + } + + /** + * Unregister webhooks with PayPal. + * + * @return bool + */ + public function unregister(): bool { + $data = (array) get_option( self::KEY, array() ); + if ( ! $data ) { + return false; + } + try { + $webhook = $this->webhook_factory->fromArray( $data ); + $success = $this->endpoint->delete( $webhook ); + } catch ( RuntimeException $error ) { + return false; + } + + if ( $success ) { + delete_option( self::KEY ); + } + return $success; + } +}