Commit 0d1f44b3a0 for woocommerce
commit 0d1f44b3a0c5539342f7502f34ac59a7e8505dae
Author: Hannah Tinkler <hannah.tinkler@gmail.com>
Date: Thu Feb 5 12:32:44 2026 +0000
Updates how exceptions are handled to use `WC_Data_Exception` (#63045)
* Refactor PushNotifications library to use WC_Data_Exception.
- Add PushTokenInvalidDataException extending WC_Data_Exception
- Update PushTokenNotFoundException to extend WC_Data_Exception
- Replace InvalidArgumentException with PushTokenInvalidDataException
- Simplify convert_exception_to_wp_error to use getErrorCode/getCode
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/Controllers/PushTokenRestController.php b/plugins/woocommerce/src/Internal/PushNotifications/Controllers/PushTokenRestController.php
index 6f509d1ec7..0cfafa88cd 100644
--- a/plugins/woocommerce/src/Internal/PushNotifications/Controllers/PushTokenRestController.php
+++ b/plugins/woocommerce/src/Internal/PushNotifications/Controllers/PushTokenRestController.php
@@ -9,10 +9,13 @@ defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Internal\PushNotifications\DataStores\PushTokensDataStore;
use Automattic\WooCommerce\Internal\PushNotifications\Entities\PushToken;
use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenNotFoundException;
+use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenInvalidDataException;
use Automattic\WooCommerce\Internal\PushNotifications\PushNotifications;
use Automattic\WooCommerce\Internal\RestApiControllerBase;
-use InvalidArgumentException;
+use Automattic\WooCommerce\Proxies\LegacyProxy;
use Exception;
+use WC_Data_Exception;
+use WC_Logger;
use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
@@ -160,16 +163,19 @@ class PushTokenRestController extends RestApiControllerBase {
}
/**
- * Validates the token.
+ * Validates the token. This is done here as some of the validation rules
+ * depend on other parameters. Calls `validate_argument` after to check the
+ * PushToken validation rules which don't depend on other parameters.
*
* @since 10.6.0
*
* @param string $token The token string.
* @param WP_REST_Request $request The request object.
* @phpstan-param WP_REST_Request<array<string, mixed>> $request
+ * @param string $param The name of the parameter being validated.
* @return bool|WP_Error
*/
- public function validate_token( string $token, WP_REST_Request $request ) {
+ public function validate_token( string $token, WP_REST_Request $request, string $param ) {
if (
$request->get_param( 'platform' ) === PushToken::PLATFORM_APPLE
&& ! preg_match( '/^[A-Fa-f0-9]{64}$/', $token )
@@ -225,21 +231,24 @@ class PushTokenRestController extends RestApiControllerBase {
}
}
- return true;
+ return $this->validate_argument( $token, $request, $param );
}
/**
* Validates the device UUID, which is required unless the token is for
- * a browser.
+ * a browser. This is done here as some of the validation rules depend on
+ * other parameters. Calls `validate_argument` after to check the PushToken
+ * validation rules which don't depend on other parameters.
*
* @since 10.6.0
*
- * @param string $device_uuid The device UUID string.
+ * @param null|string $device_uuid The device UUID string.
* @param WP_REST_Request $request The request object.
* @phpstan-param WP_REST_Request<array<string, mixed>> $request
+ * @param string $param The name of the parameter being validated.
* @return bool|WP_Error
*/
- public function validate_device_uuid( ?string $device_uuid, WP_REST_Request $request ) {
+ public function validate_device_uuid( ?string $device_uuid, WP_REST_Request $request, string $param ) {
if (
! $device_uuid
&& $request->get_param( 'platform' ) !== PushToken::PLATFORM_BROWSER
@@ -271,6 +280,41 @@ class PushTokenRestController extends RestApiControllerBase {
);
}
+ return $this->validate_argument( $device_uuid, $request, $param );
+ }
+
+ /**
+ * Validates the other arguments from the request, if validation exists in
+ * the PushToken entity.
+ *
+ * @since 10.6.0
+ *
+ * @param mixed $value The value being validated.
+ * @param WP_REST_Request $request The request object.
+ * @phpstan-param WP_REST_Request<array<string, mixed>> $request
+ * @param string $param The name of the parameter being validated.
+ * @return bool|WP_Error
+ */
+ public function validate_argument( $value, WP_REST_Request $request, string $param ) {
+ $method = "set_$param";
+
+ if ( method_exists( PushToken::class, $method ) ) {
+ try {
+ $value = rest_sanitize_request_arg( $value, $request, $param );
+ $validator = new PushToken();
+ $validator->{ "set_$param" }( $value );
+ } catch ( PushTokenInvalidDataException $e ) {
+ return new WP_Error(
+ $e->getErrorCode(),
+ $e->getMessage(),
+ array(
+ 'status' => $e->getCode(),
+ 'param' => $param,
+ )
+ );
+ }
+ }
+
return true;
}
@@ -348,23 +392,32 @@ class PushTokenRestController extends RestApiControllerBase {
* @return WP_Error
*/
private function convert_exception_to_wp_error( Exception $e ): WP_Error {
- $exception_class = get_class( $e );
+ /**
+ * If the exception is `WC_Data_Exception`, and doesn't represent an
+ * internal server error (which may contain internal details that should
+ * be obscured) then format it as a `WP_Error`.
+ */
+ if (
+ $e instanceof WC_Data_Exception
+ && $e->getCode() !== WP_Http::INTERNAL_SERVER_ERROR
+ ) {
+ return new WP_Error(
+ $e->getErrorCode(),
+ $e->getMessage(),
+ $e->getErrorData()
+ );
+ }
- $slugs = array(
- PushTokenNotFoundException::class => 'woocommerce_rest_invalid_push_token',
- InvalidArgumentException::class => 'woocommerce_rest_invalid_argument',
- );
+ wc_get_container()
+ ->get( LegacyProxy::class )
+ ->call_function( 'wc_get_logger' )
+ ->error( (string) $e->getMessage(), array( 'source' => PushNotifications::FEATURE_NAME ) );
- $statuses = array(
- PushTokenNotFoundException::class => WP_Http::NOT_FOUND,
- InvalidArgumentException::class => WP_Http::BAD_REQUEST,
+ return new WP_Error(
+ 'woocommerce_internal_error',
+ 'Internal server error',
+ array( 'status' => WP_Http::INTERNAL_SERVER_ERROR )
);
-
- $slug = $slugs[ $exception_class ] ?? 'woocommerce_rest_internal_error';
- $status = $statuses[ $exception_class ] ?? WP_Http::INTERNAL_SERVER_ERROR;
- $message = ! isset( $slugs[ $exception_class ] ) ? 'Internal server error' : $e->getMessage();
-
- return new WP_Error( $slug, $message, array( 'status' => $status ) );
}
/**
@@ -384,13 +437,15 @@ class PushTokenRestController extends RestApiControllerBase {
'context' => array( 'delete' ),
'minimum' => 1,
'sanitize_callback' => 'absint',
+ 'validate_callback' => array( $this, 'validate_argument' ),
),
'origin' => array(
- 'description' => __( 'Origin', 'woocommerce' ),
- 'type' => 'string',
- 'required' => true,
- 'context' => array( 'create' ),
- 'enum' => PushToken::ORIGINS,
+ 'description' => __( 'Origin', 'woocommerce' ),
+ 'type' => 'string',
+ 'required' => true,
+ 'context' => array( 'create' ),
+ 'enum' => PushToken::ORIGINS,
+ 'validate_callback' => array( $this, 'validate_argument' ),
),
'device_uuid' => array(
'description' => __( 'Device UUID', 'woocommerce' ),
@@ -401,11 +456,12 @@ class PushTokenRestController extends RestApiControllerBase {
'sanitize_callback' => 'sanitize_text_field',
),
'platform' => array(
- 'description' => __( 'Platform', 'woocommerce' ),
- 'type' => 'string',
- 'required' => true,
- 'context' => array( 'create' ),
- 'enum' => PushToken::PLATFORMS,
+ 'description' => __( 'Platform', 'woocommerce' ),
+ 'type' => 'string',
+ 'required' => true,
+ 'context' => array( 'create' ),
+ 'enum' => PushToken::PLATFORMS,
+ 'validate_callback' => array( $this, 'validate_argument' ),
),
'token' => array(
'description' => __( 'Push Token', 'woocommerce' ),
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/DataStores/PushTokensDataStore.php b/plugins/woocommerce/src/Internal/PushNotifications/DataStores/PushTokensDataStore.php
index 0cff271282..2207c9bac2 100644
--- a/plugins/woocommerce/src/Internal/PushNotifications/DataStores/PushTokensDataStore.php
+++ b/plugins/woocommerce/src/Internal/PushNotifications/DataStores/PushTokensDataStore.php
@@ -10,9 +10,11 @@ namespace Automattic\WooCommerce\Internal\PushNotifications\DataStores;
defined( 'ABSPATH' ) || exit;
use Automattic\WooCommerce\Internal\PushNotifications\Entities\PushToken;
+use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenInvalidDataException;
use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenNotFoundException;
use Exception;
-use InvalidArgumentException;
+use WC_Data_Exception;
+use WP_Http;
use WP_Query;
/**
@@ -33,13 +35,13 @@ class PushTokensDataStore {
*
* @since 10.5.0
* @param PushToken $push_token An instance of PushToken.
- * @throws InvalidArgumentException If the token can't be created.
- * @throws Exception If the token creation fails.
+ * @throws PushTokenInvalidDataException If the token can't be created.
+ * @throws WC_Data_Exception If the token creation fails.
* @return void
*/
public function create( PushToken &$push_token ): void {
if ( ! $push_token->can_be_created() ) {
- throw new InvalidArgumentException(
+ throw new PushTokenInvalidDataException(
'Can\'t create push token because the push token data provided is invalid.'
);
}
@@ -55,8 +57,13 @@ class PushTokensDataStore {
);
if ( is_wp_error( $id ) ) {
- // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
- throw new Exception( $id->get_error_message() );
+ // phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped
+ throw new WC_Data_Exception(
+ (string) $id->get_error_code(),
+ $id->get_error_message(),
+ WP_Http::INTERNAL_SERVER_ERROR
+ );
+ // phpcs:enable WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
$push_token->set_id( $id );
@@ -67,13 +74,13 @@ class PushTokensDataStore {
*
* @since 10.5.0
* @param PushToken $push_token An instance of PushToken.
- * @throws InvalidArgumentException If the token can't be read.
+ * @throws PushTokenInvalidDataException If the token can't be read.
* @throws PushTokenNotFoundException If the token can't be found.
* @return void
*/
public function read( PushToken &$push_token ): void {
if ( ! $push_token->can_be_read() ) {
- throw new InvalidArgumentException(
+ throw new PushTokenInvalidDataException(
'Can\'t read push token because the push token data provided is invalid.'
);
}
@@ -95,7 +102,7 @@ class PushTokensDataStore {
&& PushToken::PLATFORM_BROWSER !== $meta['platform']
)
) {
- throw new InvalidArgumentException(
+ throw new PushTokenInvalidDataException(
'Can\'t read push token because the push token record is malformed.'
);
}
@@ -112,14 +119,14 @@ class PushTokensDataStore {
*
* @since 10.5.0
* @param PushToken $push_token An instance of PushToken.
- * @throws InvalidArgumentException If the token can't be updated.
+ * @throws PushTokenInvalidDataException If the token can't be updated.
* @throws PushTokenNotFoundException If the token can't be found.
- * @throws Exception If the token update fails.
+ * @throws WC_Data_Exception If the token update fails.
* @return void
*/
public function update( PushToken &$push_token ): void {
if ( ! $push_token->can_be_updated() ) {
- throw new InvalidArgumentException(
+ throw new PushTokenInvalidDataException(
'Can\'t update push token because the push token data provided is invalid.'
);
}
@@ -142,8 +149,13 @@ class PushTokensDataStore {
);
if ( is_wp_error( $result ) ) {
- // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
- throw new Exception( $result->get_error_message() );
+ // phpcs:disable WordPress.Security.EscapeOutput.ExceptionNotEscaped
+ throw new WC_Data_Exception(
+ (string) $result->get_error_code(),
+ $result->get_error_message(),
+ WP_Http::INTERNAL_SERVER_ERROR
+ );
+ // phpcs:enable WordPress.Security.EscapeOutput.ExceptionNotEscaped
}
if ( null === $push_token->get_device_uuid() ) {
@@ -156,13 +168,13 @@ class PushTokensDataStore {
*
* @since 10.5.0
* @param PushToken $push_token An instance of PushToken.
- * @throws InvalidArgumentException If the token can't be deleted.
+ * @throws PushTokenInvalidDataException If the token can't be deleted.
* @throws PushTokenNotFoundException If the token can't be found.
* @return void
*/
public function delete( PushToken &$push_token ): void {
if ( ! $push_token->can_be_deleted() ) {
- throw new InvalidArgumentException(
+ throw new PushTokenInvalidDataException(
'Can\'t delete push token because the push token data provided is invalid.'
);
}
@@ -186,7 +198,7 @@ class PushTokensDataStore {
* @since 10.5.0
* @param PushToken $push_token An instance of PushToken.
* @return null|PushToken
- * @throws InvalidArgumentException If push token is missing data.
+ * @throws PushTokenInvalidDataException If push token is missing data.
*/
public function get_by_token_or_device_id( PushToken &$push_token ): ?PushToken {
if (
@@ -209,7 +221,7 @@ class PushTokensDataStore {
&& ! $push_token->get_token()
)
) {
- throw new InvalidArgumentException(
+ throw new PushTokenInvalidDataException(
'Can\'t retrieve push token because the push token data provided is invalid.'
);
}
@@ -277,11 +289,11 @@ class PushTokensDataStore {
* @since 10.5.0
* @param PushToken $push_token An instance of PushToken.
* @return array
- * @throws InvalidArgumentException If the token can't be read.
+ * @throws PushTokenInvalidDataException If the token can't be read.
*/
private function build_meta_array_from_database( PushToken &$push_token ) {
if ( ! $push_token->can_be_read() ) {
- throw new InvalidArgumentException(
+ throw new PushTokenInvalidDataException(
'Can\'t read meta for push token because the push token data provided is invalid.'
);
}
@@ -309,7 +321,6 @@ class PushTokensDataStore {
* @since 10.5.0
* @param PushToken $push_token An instance of PushToken.
* @return array
- * @throws InvalidArgumentException If the token can't be read.
*/
private function build_meta_array_from_token( PushToken &$push_token ) {
return array_filter(
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/Entities/PushToken.php b/plugins/woocommerce/src/Internal/PushNotifications/Entities/PushToken.php
index a1676b4e8c..409bfb0932 100644
--- a/plugins/woocommerce/src/Internal/PushNotifications/Entities/PushToken.php
+++ b/plugins/woocommerce/src/Internal/PushNotifications/Entities/PushToken.php
@@ -6,7 +6,7 @@ namespace Automattic\WooCommerce\Internal\PushNotifications\Entities;
defined( 'ABSPATH' ) || exit;
-use InvalidArgumentException;
+use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenInvalidDataException;
/**
* Object representation of a push token.
@@ -141,7 +141,7 @@ class PushToken {
* @param string|null $device_uuid The UUID of the device that generated the token.
* @param string|null $platform The platform the token was generated by.
* @param string|null $origin The origin the token belongs to.
- * @throws InvalidArgumentException If any of the provided values fail validation.
+ * @throws PushTokenInvalidDataException If any of the provided values fail validation.
* @return PushToken
*
* @since 10.4.0
@@ -187,14 +187,14 @@ class PushToken {
* Sets the ID.
*
* @param int $id The id of the token post.
- * @throws InvalidArgumentException If ID is <= 0.
+ * @throws PushTokenInvalidDataException If ID is <= 0.
* @return void
*
* @since 10.4.0
*/
public function set_id( int $id ): void {
if ( $id <= 0 ) {
- throw new InvalidArgumentException( 'ID must be a positive integer.' );
+ throw new PushTokenInvalidDataException( 'ID must be a positive integer.' );
}
$this->id = $id;
@@ -204,14 +204,14 @@ class PushToken {
* Sets the user ID.
*
* @param int $user_id The id of the user who owns the token.
- * @throws InvalidArgumentException If ID is <= 0.
+ * @throws PushTokenInvalidDataException If ID is <= 0.
* @return void
*
* @since 10.4.0
*/
public function set_user_id( int $user_id ): void {
if ( $user_id <= 0 ) {
- throw new InvalidArgumentException( 'User ID must be a positive integer.' );
+ throw new PushTokenInvalidDataException( 'User ID must be a positive integer.' );
}
$this->user_id = $user_id;
@@ -221,7 +221,7 @@ class PushToken {
* Sets the token.
*
* @param string $token The token representing a device we can send a push notification to.
- * @throws InvalidArgumentException If token is empty or exceeds maximum length.
+ * @throws PushTokenInvalidDataException If token is empty or exceeds maximum length.
* @return void
*
* @since 10.4.0
@@ -230,11 +230,11 @@ class PushToken {
$token = trim( $token );
if ( '' === $token ) {
- throw new InvalidArgumentException( 'Token cannot be empty.' );
+ throw new PushTokenInvalidDataException( 'Token cannot be empty.' );
}
if ( strlen( $token ) > self::MAX_TOKEN_LENGTH ) {
- throw new InvalidArgumentException(
+ throw new PushTokenInvalidDataException(
// phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
sprintf( 'Token exceeds maximum length of %s.', self::MAX_TOKEN_LENGTH )
);
@@ -263,14 +263,14 @@ class PushToken {
* Sets the platform.
*
* @param string $platform The platform the token was generated by.
- * @throws InvalidArgumentException If the platform is invalid.
+ * @throws PushTokenInvalidDataException If the platform is invalid.
* @return void
*
* @since 10.4.0
*/
public function set_platform( string $platform ): void {
if ( ! in_array( $platform, self::PLATFORMS, true ) ) {
- throw new InvalidArgumentException( 'Platform for PushToken is invalid.' );
+ throw new PushTokenInvalidDataException( 'Platform for PushToken is invalid.' );
}
$this->platform = $platform;
@@ -280,14 +280,14 @@ class PushToken {
* Sets the origin.
*
* @param string $origin The origin of the token, e.g. the app it came from.
- * @throws InvalidArgumentException If the origin is invalid.
+ * @throws PushTokenInvalidDataException If the origin is invalid.
* @return void
*
* @since 10.4.0
*/
public function set_origin( string $origin ): void {
if ( ! in_array( $origin, self::ORIGINS, true ) ) {
- throw new InvalidArgumentException( 'Origin for PushToken is invalid.' );
+ throw new PushTokenInvalidDataException( 'Origin for PushToken is invalid.' );
}
$this->origin = $origin;
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/Exceptions/PushTokenInvalidDataException.php b/plugins/woocommerce/src/Internal/PushNotifications/Exceptions/PushTokenInvalidDataException.php
new file mode 100644
index 0000000000..dfa9769f1e
--- /dev/null
+++ b/plugins/woocommerce/src/Internal/PushNotifications/Exceptions/PushTokenInvalidDataException.php
@@ -0,0 +1,34 @@
+<?php
+/**
+ * PushTokenInvalidDataException class file.
+ */
+
+declare( strict_types = 1 );
+
+namespace Automattic\WooCommerce\Internal\PushNotifications\Exceptions;
+
+defined( 'ABSPATH' ) || exit;
+
+use WC_Data_Exception;
+use WP_Http;
+
+/**
+ * Exception thrown when push token data is invalid.
+ *
+ * @since 10.6.0
+ */
+class PushTokenInvalidDataException extends WC_Data_Exception {
+ /**
+ * Constructor.
+ *
+ * @since 10.6.0
+ * @param string $message The validation error message.
+ */
+ public function __construct( string $message ) {
+ parent::__construct(
+ 'woocommerce_invalid_data',
+ $message,
+ WP_Http::BAD_REQUEST
+ );
+ }
+}
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/Exceptions/PushTokenNotFoundException.php b/plugins/woocommerce/src/Internal/PushNotifications/Exceptions/PushTokenNotFoundException.php
index 509fdc47f3..afc4cd7198 100644
--- a/plugins/woocommerce/src/Internal/PushNotifications/Exceptions/PushTokenNotFoundException.php
+++ b/plugins/woocommerce/src/Internal/PushNotifications/Exceptions/PushTokenNotFoundException.php
@@ -9,7 +9,7 @@ namespace Automattic\WooCommerce\Internal\PushNotifications\Exceptions;
defined( 'ABSPATH' ) || exit;
-use Exception;
+use WC_Data_Exception;
use WP_Http;
/**
@@ -17,11 +17,17 @@ use WP_Http;
*
* @since 10.5.0
*/
-class PushTokenNotFoundException extends Exception {
+class PushTokenNotFoundException extends WC_Data_Exception {
/**
- * Default exception message.
+ * Constructor.
*
- * @var string
+ * @since 10.6.0
*/
- protected $message = 'Push token could not be found.';
+ public function __construct() {
+ parent::__construct(
+ 'woocommerce_invalid_push_token',
+ 'Push token could not be found.',
+ WP_Http::NOT_FOUND
+ );
+ }
}
diff --git a/plugins/woocommerce/tests/php/src/Internal/PushNotifications/Controllers/PushTokenRestControllerTest.php b/plugins/woocommerce/tests/php/src/Internal/PushNotifications/Controllers/PushTokenRestControllerTest.php
index 626b8b2db1..ffc8360a5e 100644
--- a/plugins/woocommerce/tests/php/src/Internal/PushNotifications/Controllers/PushTokenRestControllerTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/PushNotifications/Controllers/PushTokenRestControllerTest.php
@@ -9,14 +9,15 @@ use Automattic\WooCommerce\Internal\Features\FeaturesController;
use Automattic\WooCommerce\Internal\PushNotifications\Controllers\PushTokenRestController;
use Automattic\WooCommerce\Internal\PushNotifications\DataStores\PushTokensDataStore;
use Automattic\WooCommerce\Internal\PushNotifications\Entities\PushToken;
+use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenInvalidDataException;
use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenNotFoundException;
use Automattic\WooCommerce\Internal\PushNotifications\PushNotifications;
use Automattic\WooCommerce\Proxies\LegacyProxy;
use Exception;
-use InvalidArgumentException;
use RuntimeException;
use PHPUnit\Framework\MockObject\MockObject;
use ReflectionClass;
+use WC_Data_Exception;
use WC_REST_Unit_Test_Case;
use WP_Error;
use WP_Http;
@@ -762,7 +763,7 @@ class PushTokenRestControllerTest extends WC_REST_Unit_Test_Case {
$data = $response->get_data();
- $this->assertEquals( 'woocommerce_rest_invalid_push_token', $data['code'] );
+ $this->assertEquals( 'woocommerce_invalid_push_token', $data['code'] );
$this->assertEquals( 'Push token could not be found.', $data['message'] );
}
@@ -782,7 +783,7 @@ class PushTokenRestControllerTest extends WC_REST_Unit_Test_Case {
$data = $response->get_data();
- $this->assertEquals( 'woocommerce_rest_invalid_push_token', $data['code'] );
+ $this->assertEquals( 'woocommerce_invalid_push_token', $data['code'] );
$this->assertEquals( 'Push token could not be found.', $data['message'] );
}
@@ -957,7 +958,7 @@ class PushTokenRestControllerTest extends WC_REST_Unit_Test_Case {
$result = $method->invoke( $controller, $exception );
$this->assertInstanceOf( WP_Error::class, $result );
- $this->assertEquals( 'woocommerce_rest_internal_error', $result->get_error_code() );
+ $this->assertEquals( 'woocommerce_internal_error', $result->get_error_code() );
$this->assertEquals( 'Internal server error', $result->get_error_message() );
$this->assertEquals( WP_Http::INTERNAL_SERVER_ERROR, $result->get_error_data()['status'] );
}
@@ -977,18 +978,18 @@ class PushTokenRestControllerTest extends WC_REST_Unit_Test_Case {
$result = $method->invoke( $controller, $exception );
$this->assertInstanceOf( WP_Error::class, $result );
- $this->assertEquals( 'woocommerce_rest_invalid_push_token', $result->get_error_code() );
+ $this->assertEquals( 'woocommerce_invalid_push_token', $result->get_error_code() );
$this->assertEquals( 'Push token could not be found.', $result->get_error_message() );
$this->assertEquals( WP_Http::NOT_FOUND, $result->get_error_data()['status'] );
}
/**
* @testdox Test convert_exception_to_wp_error exposes message for
- * InvalidArgumentException.
+ * PushTokenInvalidDataException.
*/
- public function test_it_exposes_message_for_invalid_argument_exception() {
+ public function test_it_exposes_message_for_push_token_invalid_data_exception() {
$controller = new PushTokenRestController();
- $exception = new InvalidArgumentException( 'Invalid argument provided.' );
+ $exception = new PushTokenInvalidDataException( 'Invalid argument provided.' );
$reflection = new ReflectionClass( $controller );
$method = $reflection->getMethod( 'convert_exception_to_wp_error' );
@@ -997,19 +998,46 @@ class PushTokenRestControllerTest extends WC_REST_Unit_Test_Case {
$result = $method->invoke( $controller, $exception );
$this->assertInstanceOf( WP_Error::class, $result );
- $this->assertEquals( 'woocommerce_rest_invalid_argument', $result->get_error_code() );
+ $this->assertEquals( 'woocommerce_invalid_data', $result->get_error_code() );
$this->assertEquals( 'Invalid argument provided.', $result->get_error_message() );
$this->assertEquals( WP_Http::BAD_REQUEST, $result->get_error_data()['status'] );
}
/**
- * @testdox Test convert_exception_to_wp_error hides message for unknown
- * exception subclasses.
+ * @testdox Test convert_exception_to_wp_error correctly handles any non-500
+ * WC_Data_Exception.
*/
- public function test_it_hides_internal_error_message_for_unknown_exception_subclass() {
+ public function test_it_handles_any_non_500_wc_data_exception() {
$controller = new PushTokenRestController();
- // RuntimeException is a subclass of Exception but not in our mapping.
- $exception = new RuntimeException( 'Sensitive runtime error details' );
+ $exception = new WC_Data_Exception(
+ 'custom_error_code',
+ 'Custom error message.',
+ WP_Http::FORBIDDEN
+ );
+
+ $reflection = new ReflectionClass( $controller );
+ $method = $reflection->getMethod( 'convert_exception_to_wp_error' );
+ $method->setAccessible( true );
+
+ $result = $method->invoke( $controller, $exception );
+
+ $this->assertInstanceOf( WP_Error::class, $result );
+ $this->assertEquals( 'custom_error_code', $result->get_error_code() );
+ $this->assertEquals( 'Custom error message.', $result->get_error_message() );
+ $this->assertEquals( WP_Http::FORBIDDEN, $result->get_error_data()['status'] );
+ }
+
+ /**
+ * @testdox Test convert_exception_to_wp_error correctly handles a 500
+ * WC_Data_Exception.
+ */
+ public function test_it_handles_a_500_wc_data_exception() {
+ $controller = new PushTokenRestController();
+ $exception = new WC_Data_Exception(
+ 'custom_error_code',
+ 'Custom error message.',
+ WP_Http::INTERNAL_SERVER_ERROR
+ );
$reflection = new ReflectionClass( $controller );
$method = $reflection->getMethod( 'convert_exception_to_wp_error' );
@@ -1018,7 +1046,7 @@ class PushTokenRestControllerTest extends WC_REST_Unit_Test_Case {
$result = $method->invoke( $controller, $exception );
$this->assertInstanceOf( WP_Error::class, $result );
- $this->assertEquals( 'woocommerce_rest_internal_error', $result->get_error_code() );
+ $this->assertEquals( 'woocommerce_internal_error', $result->get_error_code() );
$this->assertEquals( 'Internal server error', $result->get_error_message() );
$this->assertEquals( WP_Http::INTERNAL_SERVER_ERROR, $result->get_error_data()['status'] );
}
diff --git a/plugins/woocommerce/tests/php/src/Internal/PushNotifications/DataStores/PushTokensDataStoreTest.php b/plugins/woocommerce/tests/php/src/Internal/PushNotifications/DataStores/PushTokensDataStoreTest.php
index 3b17c9568f..a02b31d27f 100644
--- a/plugins/woocommerce/tests/php/src/Internal/PushNotifications/DataStores/PushTokensDataStoreTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/PushNotifications/DataStores/PushTokensDataStoreTest.php
@@ -6,8 +6,8 @@ namespace Automattic\WooCommerce\Tests\Internal\PushNotifications\DataStores;
use Automattic\WooCommerce\Internal\PushNotifications\DataStores\PushTokensDataStore;
use Automattic\WooCommerce\Internal\PushNotifications\Entities\PushToken;
-use Exception;
-use InvalidArgumentException;
+use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenInvalidDataException;
+use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenNotFoundException;
use WC_Unit_Test_Case;
/**
@@ -142,7 +142,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token->set_user_id( 1 );
$push_token->set_token( 'test_token' );
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Can\'t create push token because the push token data provided is invalid.' );
$data_store->create( $push_token );
@@ -157,7 +157,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token = new PushToken();
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Can\'t read push token because the push token data provided is invalid.' );
$data_store->read( $push_token );
@@ -173,7 +173,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token = new PushToken();
$push_token->set_id( 999999 );
- $this->expectException( Exception::class );
+ $this->expectException( PushTokenNotFoundException::class );
$this->expectExceptionMessage( 'Push token could not be found.' );
$data_store->read( $push_token );
@@ -197,7 +197,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token = new PushToken();
$push_token->set_id( $post_id );
- $this->expectException( Exception::class );
+ $this->expectException( PushTokenNotFoundException::class );
$this->expectExceptionMessage( 'Push token could not be found.' );
$data_store->read( $push_token );
@@ -226,7 +226,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token = new PushToken();
$push_token->set_id( $post_id );
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Can\'t read push token because the push token record is malformed.' );
$data_store->read( $push_token );
@@ -243,7 +243,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token->set_id( 1 );
$push_token->set_user_id( 1 );
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Can\'t update push token because the push token data provided is invalid.' );
$data_store->update( $push_token );
@@ -264,7 +264,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token->set_device_uuid( 'device-uuid' );
$push_token->set_origin( PushToken::ORIGIN_WOOCOMMERCE_IOS );
- $this->expectException( Exception::class );
+ $this->expectException( PushTokenNotFoundException::class );
$this->expectExceptionMessage( 'Push token could not be found.' );
$data_store->update( $push_token );
@@ -293,7 +293,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token->set_device_uuid( 'device-uuid' );
$push_token->set_origin( PushToken::ORIGIN_WOOCOMMERCE_IOS );
- $this->expectException( Exception::class );
+ $this->expectException( PushTokenNotFoundException::class );
$this->expectExceptionMessage( 'Push token could not be found.' );
$data_store->update( $push_token );
@@ -307,7 +307,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$data_store = new PushTokensDataStore();
$push_token = new PushToken();
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Can\'t delete push token because the push token data provided is invalid.' );
$data_store->delete( $push_token );
@@ -331,7 +331,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token = new PushToken();
$push_token->set_id( $post_id );
- $this->expectException( Exception::class );
+ $this->expectException( PushTokenNotFoundException::class );
$this->expectExceptionMessage( 'Push token could not be found.' );
$data_store->delete( $push_token );
@@ -551,7 +551,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token->set_token( 'test_token' );
$push_token->set_device_uuid( 'test_device' );
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Can\'t retrieve push token because the push token data provided is invalid.' );
$data_store->get_by_token_or_device_id( $push_token );
@@ -570,7 +570,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token->set_token( 'test_token' );
$push_token->set_device_uuid( 'test_device' );
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Can\'t retrieve push token because the push token data provided is invalid.' );
$data_store->get_by_token_or_device_id( $push_token );
@@ -589,7 +589,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token->set_token( 'test_token' );
$push_token->set_device_uuid( 'test_device' );
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Can\'t retrieve push token because the push token data provided is invalid.' );
$data_store->get_by_token_or_device_id( $push_token );
@@ -607,7 +607,7 @@ class PushTokensDataStoreTest extends WC_Unit_Test_Case {
$push_token->set_platform( PushToken::PLATFORM_APPLE );
$push_token->set_origin( PushToken::ORIGIN_WOOCOMMERCE_IOS );
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Can\'t retrieve push token because the push token data provided is invalid.' );
$data_store->get_by_token_or_device_id( $push_token );
diff --git a/plugins/woocommerce/tests/php/src/Internal/PushNotifications/Entities/PushTokenTest.php b/plugins/woocommerce/tests/php/src/Internal/PushNotifications/Entities/PushTokenTest.php
index 88cd7d11da..cd09e876de 100644
--- a/plugins/woocommerce/tests/php/src/Internal/PushNotifications/Entities/PushTokenTest.php
+++ b/plugins/woocommerce/tests/php/src/Internal/PushNotifications/Entities/PushTokenTest.php
@@ -5,7 +5,7 @@ declare( strict_types = 1 );
namespace Automattic\WooCommerce\Tests\Internal\PushNotifications\Entities;
use Automattic\WooCommerce\Internal\PushNotifications\Entities\PushToken;
-use InvalidArgumentException;
+use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenInvalidDataException;
use WC_Unit_Test_Case;
/**
@@ -388,7 +388,7 @@ class PushTokenTest extends WC_Unit_Test_Case {
public function test_it_throws_exception_when_setting_invalid_platform() {
$push_token = new PushToken();
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Platform for PushToken is invalid.' );
$push_token->set_platform( 'invalid' );
@@ -400,7 +400,7 @@ class PushTokenTest extends WC_Unit_Test_Case {
public function test_it_throws_exception_when_setting_invalid_origin() {
$push_token = new PushToken();
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Origin for PushToken is invalid.' );
$push_token->set_origin( 'com.invalid.app' );
@@ -431,7 +431,7 @@ class PushTokenTest extends WC_Unit_Test_Case {
public function test_it_throws_exception_when_setting_user_id_to_zero() {
$push_token = new PushToken();
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'User ID must be a positive integer.' );
$push_token->set_user_id( 0 );
@@ -443,7 +443,7 @@ class PushTokenTest extends WC_Unit_Test_Case {
public function test_it_throws_exception_when_setting_negative_user_id() {
$push_token = new PushToken();
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'User ID must be a positive integer.' );
$push_token->set_user_id( -1 );
@@ -455,7 +455,7 @@ class PushTokenTest extends WC_Unit_Test_Case {
public function test_it_throws_exception_when_setting_empty_token() {
$push_token = new PushToken();
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Token cannot be empty.' );
$push_token->set_token( '' );
@@ -467,7 +467,7 @@ class PushTokenTest extends WC_Unit_Test_Case {
public function test_it_throws_exception_when_setting_whitespace_only_token() {
$push_token = new PushToken();
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Token cannot be empty.' );
$push_token->set_token( ' ' );
@@ -480,7 +480,7 @@ class PushTokenTest extends WC_Unit_Test_Case {
$push_token = new PushToken();
$long_token = str_repeat( 'A', PushToken::MAX_TOKEN_LENGTH + 1 );
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Token exceeds maximum length of 4096.' );
$push_token->set_token( $long_token );
@@ -573,7 +573,7 @@ class PushTokenTest extends WC_Unit_Test_Case {
* @testdox Tests get_new_instance throws exception for invalid values.
*/
public function test_get_new_instance_throws_exception_for_invalid_platform() {
- $this->expectException( InvalidArgumentException::class );
+ $this->expectException( PushTokenInvalidDataException::class );
$this->expectExceptionMessage( 'Platform for PushToken is invalid.' );
PushToken::get_new_instance(