OwlCyberSecurity - MANAGER
Edit File: PushToken.php
<?php declare( strict_types = 1 ); namespace Automattic\WooCommerce\Internal\PushNotifications\Entities; defined( 'ABSPATH' ) || exit; use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenInvalidDataException; use Automattic\WooCommerce\Internal\PushNotifications\Validators\PushTokenValidator; /** * Object representation of a push token. * * @since 10.4.0 */ class PushToken { /** * WordPress post type for storing push tokens. */ const POST_TYPE = 'wc_push_token'; /** * The locale to use for tokens when the locale is not set, e.g. for tokens * created before `device_locale` was added. */ const DEFAULT_DEVICE_LOCALE = 'en_US'; /** * Platform identifier for Apple devices. */ const PLATFORM_APPLE = 'apple'; /** * Platform identifier for Android devices. */ const PLATFORM_ANDROID = 'android'; /** * Platform identifier for web browsers. */ const PLATFORM_BROWSER = 'browser'; /** * Origin identifier for WooCommerce Android app. */ const ORIGIN_WOOCOMMERCE_ANDROID = 'com.woocommerce.android'; /** * Origin identifier for WooCommerce Android app development builds. */ const ORIGIN_WOOCOMMERCE_ANDROID_DEV = 'com.woocommerce.android:dev'; /** * Origin identifier for WooCommerce iOS app. */ const ORIGIN_WOOCOMMERCE_IOS = 'com.automattic.woocommerce'; /** * Origin identifier for WooCommerce iOS app development builds. */ const ORIGIN_WOOCOMMERCE_IOS_DEV = 'com.automattic.woocommerce:dev'; /** * Origin identifier for browsers. */ const ORIGIN_BROWSER = 'browser'; /** * List of valid platforms. */ const PLATFORMS = array( self::PLATFORM_APPLE, self::PLATFORM_ANDROID, self::PLATFORM_BROWSER, ); /** * List of valid origins. */ const ORIGINS = array( self::ORIGIN_BROWSER, self::ORIGIN_WOOCOMMERCE_ANDROID, self::ORIGIN_WOOCOMMERCE_ANDROID_DEV, self::ORIGIN_WOOCOMMERCE_IOS, self::ORIGIN_WOOCOMMERCE_IOS_DEV, ); /** * The ID of the token post. * * @var int|null */ private ?int $id = null; /** * The ID of the user who owns the token. * * @var int|null */ private ?int $user_id = null; /** * The token representing a device we can send a push notification to. * * @var string|null */ private ?string $token = null; /** * The UUID of the device that generated the token. * * @var string|null */ private ?string $device_uuid = null; /** * The platform the token was generated by. * * @var string|null */ private ?string $platform = null; /** * The origin the token belongs to. * * @var string|null */ private ?string $origin = null; /** * The locale of the device the token belongs to. * * @var string|null */ private ?string $device_locale = null; /** * An array of metadata for the token. * * @var array|null */ private ?array $metadata = null; /** * Creates a new PushToken instance with the given data. * * @param array $data Optional array with keys: id, user_id, token, device_uuid, platform, origin. * @throws PushTokenInvalidDataException If any of the provided values fail validation. * * @since 10.6.0 */ public function __construct( array $data = array() ) { if ( array_key_exists( 'id', $data ) ) { $this->set_id( (int) $data['id'] ); } if ( array_key_exists( 'user_id', $data ) ) { $this->set_user_id( (int) $data['user_id'] ); } if ( array_key_exists( 'token', $data ) ) { $this->set_token( (string) $data['token'] ); } if ( array_key_exists( 'device_uuid', $data ) ) { $this->set_device_uuid( (string) $data['device_uuid'] ); } if ( array_key_exists( 'platform', $data ) ) { $this->set_platform( (string) $data['platform'] ); } if ( array_key_exists( 'origin', $data ) ) { $this->set_origin( (string) $data['origin'] ); } if ( array_key_exists( 'device_locale', $data ) ) { $this->set_device_locale( (string) $data['device_locale'] ); } if ( array_key_exists( 'metadata', $data ) ) { $this->set_metadata( (array) $data['metadata'] ); } } /** * Validates and sets the ID. * * @param int $id The ID of the token post. * @throws PushTokenInvalidDataException If ID is not valid. * @return void * * @since 10.4.0 */ public function set_id( int $id ): void { $result = PushTokenValidator::validate( compact( 'id' ), array( 'id' ) ); if ( is_wp_error( $result ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new PushTokenInvalidDataException( $result->get_error_message() ); } $this->id = $id; } /** * Validates and sets the user ID. * * @param int $user_id The ID of the user who owns the token. * @throws PushTokenInvalidDataException If user ID is not valid. * @return void * * @since 10.4.0 */ public function set_user_id( int $user_id ): void { $result = PushTokenValidator::validate( compact( 'user_id' ), array( 'user_id' ) ); if ( is_wp_error( $result ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new PushTokenInvalidDataException( $result->get_error_message() ); } $this->user_id = $user_id; } /** * Validates and sets the token. * * @param string $token The token representing a device we can send a push notification to. * @throws PushTokenInvalidDataException If token is not valid. * @return void * * @since 10.4.0 */ public function set_token( string $token ): void { $result = PushTokenValidator::validate( compact( 'token' ), array( 'token' ) ); if ( is_wp_error( $result ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new PushTokenInvalidDataException( $result->get_error_message() ); } $this->token = trim( $token ); } /** * Validates and sets the device UUID, normalize empty (non-null) values to null. * * @param string|null $device_uuid The UUID of the device that generated the token. * @throws PushTokenInvalidDataException If device UUID is not valid. * @return void * * @since 10.4.0 */ public function set_device_uuid( ?string $device_uuid ): void { $result = PushTokenValidator::validate( compact( 'device_uuid' ), array( 'device_uuid' ) ); if ( is_wp_error( $result ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new PushTokenInvalidDataException( $result->get_error_message() ); } if ( null !== $device_uuid ) { $device_uuid = trim( $device_uuid ); } $this->device_uuid = $device_uuid ? $device_uuid : null; } /** * Validates and sets the device locale. * * @param string $device_locale The locale of the device the token belongs to. * @throws PushTokenInvalidDataException If device locale is not valid. * @return void * * @since 10.6.0 */ public function set_device_locale( string $device_locale ): void { $result = PushTokenValidator::validate( compact( 'device_locale' ), array( 'device_locale' ) ); if ( is_wp_error( $result ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new PushTokenInvalidDataException( $result->get_error_message() ); } $this->device_locale = trim( $device_locale ); } /** * Validates and sets the platform. * * @param string $platform The platform the token was generated by. * @throws PushTokenInvalidDataException If platform is not valid. * @return void * * @since 10.4.0 */ public function set_platform( string $platform ): void { $result = PushTokenValidator::validate( compact( 'platform' ), array( 'platform' ) ); if ( is_wp_error( $result ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new PushTokenInvalidDataException( $result->get_error_message() ); } $this->platform = trim( $platform ); } /** * Validates and sets the origin. * * @param string $origin The origin of the token, e.g. the app it came from. * @throws PushTokenInvalidDataException If origin is not valid. * @return void * * @since 10.4.0 */ public function set_origin( string $origin ): void { $result = PushTokenValidator::validate( compact( 'origin' ), array( 'origin' ) ); if ( is_wp_error( $result ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new PushTokenInvalidDataException( $result->get_error_message() ); } $this->origin = trim( $origin ); } /** * Validates and sets the metadata. * * @param array $metadata An array of metadata for the token, e.g. the app version, device OS etc. * @throws PushTokenInvalidDataException If metadata is not valid. * @return void * * @since 10.6.0 */ public function set_metadata( array $metadata ): void { $result = PushTokenValidator::validate( compact( 'metadata' ), array( 'metadata' ) ); if ( is_wp_error( $result ) ) { // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped throw new PushTokenInvalidDataException( $result->get_error_message() ); } if ( ! empty( $metadata ) ) { $keys = array_map( 'sanitize_key', array_keys( $metadata ) ); $values = array_map( 'sanitize_text_field', array_values( $metadata ) ); /** * Typehint for PHPStan, as it can't infer the $keys and $values are * the same length therefore array_combine won't return false. * * @var array<string, string> $metadata */ $metadata = array_combine( $keys, $values ); } $this->metadata = $metadata; } /** * Gets the ID. * * @return int|null * * @since 10.4.0 */ public function get_id(): ?int { return $this->id; } /** * Gets the user ID. * * @return int|null * * @since 10.4.0 */ public function get_user_id(): ?int { return $this->user_id; } /** * Gets the token. * * @return string|null * * @since 10.4.0 */ public function get_token(): ?string { return $this->token; } /** * Gets the device UUID. * * @return string|null * * @since 10.4.0 */ public function get_device_uuid(): ?string { return $this->device_uuid; } /** * Gets the platform. * * @return string|null * * @since 10.4.0 */ public function get_platform(): ?string { return $this->platform; } /** * Gets the origin. * * @return string|null * * @since 10.4.0 */ public function get_origin(): ?string { return $this->origin; } /** * Gets the device locale. * * @return string|null * * @since 10.6.0 */ public function get_device_locale(): ?string { return $this->device_locale; } /** * Gets the metadata. * * @return array|null * * @since 10.6.0 */ public function get_metadata(): ?array { return $this->metadata; } /** * Determines whether this token can be created. * * @return bool * * @since 10.4.0 */ public function can_be_created(): bool { return ! $this->get_id() && $this->has_required_parameters(); } /** * Determines whether this token can be updated. * * @return bool * * @since 10.4.0 */ public function can_be_updated(): bool { return $this->get_id() && $this->has_required_parameters(); } /** * Determines whether this token can be read. * * @return bool * * @since 10.4.0 */ public function can_be_read(): bool { return (bool) $this->get_id(); } /** * Determines whether this token can be deleted. * * @return bool * * @since 10.4.0 */ public function can_be_deleted(): bool { return (bool) $this->get_id(); } /** * Determines whether all the required non-ID parameters are filled. * * @return bool * * @since 10.4.0 */ private function has_required_parameters(): bool { return $this->get_user_id() && $this->get_token() && $this->get_platform() && $this->get_origin() && $this->get_device_locale() && ( $this->get_device_uuid() || $this->get_platform() === self::PLATFORM_BROWSER ); } }