Commit 379245925cb for woocommerce
commit 379245925cbb631494ec241a9f7dc3e2411af3bb
Author: Adam Grzybkowski <agrzybkowski@outlook.com>
Date: Fri May 29 20:54:39 2026 +0200
Push notifications: extract auth trait and fix @since tags (#65380)
* Extract authorize_as_authenticated into a shared trait
Moves the duplicated permission callback used by both
NotificationPreferencesRestController and PushTokenRestController into a
new AuthorizesPushNotificationRequests trait, mirroring the existing
ConvertsExceptionsToWpError trait pattern. PushNotifications is now
looked up via the container in one place rather than re-implemented per
controller, and the now-unused dependency injection of PushNotifications
in NotificationPreferencesRestController has been dropped.
Follow-up to https://github.com/woocommerce/woocommerce/pull/64351#discussion_r3218483918.
* Correct @since tags on push notification preference filter methods
PR #64487 was merged after the version bump to 10.9.0-dev, so the
@since 10.8.0 annotations on the two methods it introduced
(Notification::should_send_to_user and
NotificationProcessor::filter_tokens_by_preferences) should be
@since 10.9.0.
Follow-up to https://github.com/woocommerce/woocommerce/pull/64487#issuecomment-4448627834.
diff --git a/plugins/woocommerce/changelog/64351-followup-authorize-trait b/plugins/woocommerce/changelog/64351-followup-authorize-trait
new file mode 100644
index 00000000000..a68b7c1a4aa
--- /dev/null
+++ b/plugins/woocommerce/changelog/64351-followup-authorize-trait
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Extract shared authorize_as_authenticated logic from the push notifications REST controllers into a new AuthorizesPushNotificationRequests trait.
diff --git a/plugins/woocommerce/changelog/64487-followup-since-tags b/plugins/woocommerce/changelog/64487-followup-since-tags
new file mode 100644
index 00000000000..56f6870bae6
--- /dev/null
+++ b/plugins/woocommerce/changelog/64487-followup-since-tags
@@ -0,0 +1,4 @@
+Significance: patch
+Type: dev
+
+Correct @since tags on push notification preference filtering methods introduced in 10.9.0.
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/Controllers/NotificationPreferencesRestController.php b/plugins/woocommerce/src/Internal/PushNotifications/Controllers/NotificationPreferencesRestController.php
index 5478baebc12..db41f8d0d3f 100644
--- a/plugins/woocommerce/src/Internal/PushNotifications/Controllers/NotificationPreferencesRestController.php
+++ b/plugins/woocommerce/src/Internal/PushNotifications/Controllers/NotificationPreferencesRestController.php
@@ -6,8 +6,8 @@ namespace Automattic\WooCommerce\Internal\PushNotifications\Controllers;
defined( 'ABSPATH' ) || exit;
-use Automattic\WooCommerce\Internal\PushNotifications\PushNotifications;
use Automattic\WooCommerce\Internal\PushNotifications\Services\NotificationPreferencesService;
+use Automattic\WooCommerce\Internal\PushNotifications\Traits\AuthorizesPushNotificationRequests;
use Automattic\WooCommerce\Internal\PushNotifications\Traits\ConvertsExceptionsToWpError;
use Automattic\WooCommerce\Internal\RestApiControllerBase;
use Exception;
@@ -24,6 +24,7 @@ use WP_REST_Server;
* @since 10.8.0
*/
class NotificationPreferencesRestController extends RestApiControllerBase {
+ use AuthorizesPushNotificationRequests;
use ConvertsExceptionsToWpError;
/**
@@ -47,29 +48,17 @@ class NotificationPreferencesRestController extends RestApiControllerBase {
*/
private NotificationPreferencesService $preferences_service;
- /**
- * The push notifications module enablement gate.
- *
- * @var PushNotifications
- */
- private PushNotifications $push_notifications;
-
/**
* Initialize injected dependencies.
*
* @internal
*
* @param NotificationPreferencesService $preferences_service The preferences service.
- * @param PushNotifications $push_notifications The push notifications module.
*
* @since 10.8.0
*/
- final public function init(
- NotificationPreferencesService $preferences_service,
- PushNotifications $push_notifications
- ): void {
+ final public function init( NotificationPreferencesService $preferences_service ): void {
$this->preferences_service = $preferences_service;
- $this->push_notifications = $push_notifications;
}
/**
@@ -154,37 +143,6 @@ class NotificationPreferencesRestController extends RestApiControllerBase {
return new WP_REST_Response( $merged, WP_Http::OK );
}
- /**
- * Checks user is authenticated and authorized to access this endpoint.
- *
- * @since 10.8.0
- *
- * @param WP_REST_Request $request The request object.
- * @phpstan-param WP_REST_Request<array<string, mixed>> $request
- * @return bool|WP_Error
- */
- public function authorize_as_authenticated( WP_REST_Request $request ) {
- if ( ! get_current_user_id() ) {
- return new WP_Error(
- 'woocommerce_rest_cannot_view',
- __( 'Sorry, you are not allowed to do that.', 'woocommerce' ),
- array( 'status' => rest_authorization_required_code() )
- );
- }
-
- if ( ! $this->push_notifications->should_be_enabled() ) {
- return false;
- }
-
- $has_valid_role = array_reduce(
- PushNotifications::ROLES_WITH_PUSH_NOTIFICATIONS_ENABLED,
- fn ( $carry, $role ) => $this->check_permission( $request, $role ) === true ? true : $carry,
- false
- );
-
- return $has_valid_role ? true : false;
- }
-
/**
* Get the accepted arguments for the POST request.
*
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/Controllers/PushTokenRestController.php b/plugins/woocommerce/src/Internal/PushNotifications/Controllers/PushTokenRestController.php
index db890d8068a..47e6abb839c 100644
--- a/plugins/woocommerce/src/Internal/PushNotifications/Controllers/PushTokenRestController.php
+++ b/plugins/woocommerce/src/Internal/PushNotifications/Controllers/PushTokenRestController.php
@@ -11,6 +11,7 @@ use Automattic\WooCommerce\Internal\PushNotifications\DataStores\PushTokensDataS
use Automattic\WooCommerce\Internal\PushNotifications\Entities\PushToken;
use Automattic\WooCommerce\Internal\PushNotifications\Exceptions\PushTokenNotFoundException;
use Automattic\WooCommerce\Internal\PushNotifications\PushNotifications;
+use Automattic\WooCommerce\Internal\PushNotifications\Traits\AuthorizesPushNotificationRequests;
use Automattic\WooCommerce\Internal\PushNotifications\Traits\ConvertsExceptionsToWpError;
use Automattic\WooCommerce\Internal\PushNotifications\Validators\PushTokenValidator;
use Automattic\WooCommerce\Internal\RestApiControllerBase;
@@ -29,6 +30,7 @@ use WP_Http;
* @since 10.6.0
*/
class PushTokenRestController extends RestApiControllerBase {
+ use AuthorizesPushNotificationRequests;
use ConvertsExceptionsToWpError;
/**
@@ -293,41 +295,6 @@ class PushTokenRestController extends RestApiControllerBase {
);
}
- /**
- * Checks user is authenticated and authorized to access this endpoint.
- *
- * @since 10.6.0
- *
- * @param WP_REST_Request $request The request object.
- * @phpstan-param WP_REST_Request<array<string, mixed>> $request
- * @return bool|WP_Error
- */
- public function authorize_as_authenticated( WP_REST_Request $request ) {
- if ( ! get_current_user_id() ) {
- return new WP_Error(
- 'woocommerce_rest_cannot_view',
- __( 'Sorry, you are not allowed to do that.', 'woocommerce' ),
- array( 'status' => rest_authorization_required_code() )
- );
- }
-
- if ( ! wc_get_container()->get( PushNotifications::class )->should_be_enabled() ) {
- return false;
- }
-
- $has_valid_role = array_reduce(
- PushNotifications::ROLES_WITH_PUSH_NOTIFICATIONS_ENABLED,
- fn ( $carry, $role ) => $this->check_permission( $request, $role ) === true ? true : $carry,
- false
- );
-
- if ( ! $has_valid_role ) {
- return false;
- }
-
- return true;
- }
-
/**
* Validates that the request is signed with a Jetpack blog token,
* ensuring only WPCOM can access this endpoint.
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/Notifications/Notification.php b/plugins/woocommerce/src/Internal/PushNotifications/Notifications/Notification.php
index 35404ad7445..bfe2b0352f9 100644
--- a/plugins/woocommerce/src/Internal/PushNotifications/Notifications/Notification.php
+++ b/plugins/woocommerce/src/Internal/PushNotifications/Notifications/Notification.php
@@ -196,7 +196,7 @@ abstract class Notification {
* @param mixed $pref_value The user's stored preference value, or null.
* @return bool True if this notification should be sent to that user.
*
- * @since 10.8.0
+ * @since 10.9.0
*/
public function should_send_to_user( $pref_value ): bool {
if ( null === $pref_value ) {
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/Services/NotificationProcessor.php b/plugins/woocommerce/src/Internal/PushNotifications/Services/NotificationProcessor.php
index 058cdb13294..07d553f2a64 100644
--- a/plugins/woocommerce/src/Internal/PushNotifications/Services/NotificationProcessor.php
+++ b/plugins/woocommerce/src/Internal/PushNotifications/Services/NotificationProcessor.php
@@ -208,7 +208,7 @@ class NotificationProcessor {
*
* @return PushToken[] The tokens whose owner wants the notification.
*
- * @since 10.8.0
+ * @since 10.9.0
*/
private function filter_tokens_by_preferences( array $tokens, Notification $notification ): array {
$type = $notification->get_type();
diff --git a/plugins/woocommerce/src/Internal/PushNotifications/Traits/AuthorizesPushNotificationRequests.php b/plugins/woocommerce/src/Internal/PushNotifications/Traits/AuthorizesPushNotificationRequests.php
new file mode 100644
index 00000000000..e83711a7b1a
--- /dev/null
+++ b/plugins/woocommerce/src/Internal/PushNotifications/Traits/AuthorizesPushNotificationRequests.php
@@ -0,0 +1,51 @@
+<?php
+
+declare( strict_types = 1 );
+
+namespace Automattic\WooCommerce\Internal\PushNotifications\Traits;
+
+defined( 'ABSPATH' ) || exit;
+
+use Automattic\WooCommerce\Internal\PushNotifications\PushNotifications;
+use WP_Error;
+use WP_REST_Request;
+
+/**
+ * Shared "is this caller an authenticated push-notifications user?" check for
+ * REST controllers in the PushNotifications module.
+ *
+ * Implementing classes must extend {@see \Automattic\WooCommerce\Internal\RestApiControllerBase}
+ * so that `check_permission()` is available.
+ */
+trait AuthorizesPushNotificationRequests {
+ /**
+ * Checks the user is authenticated, the push notifications module is
+ * enabled, and the user holds at least one role allowed to interact with
+ * push notifications.
+ *
+ * @param WP_REST_Request $request The request object.
+ * @phpstan-param WP_REST_Request<array<string, mixed>> $request
+ * @return bool|WP_Error
+ */
+ public function authorize_as_authenticated( WP_REST_Request $request ) {
+ if ( ! get_current_user_id() ) {
+ return new WP_Error(
+ 'woocommerce_rest_cannot_view',
+ __( 'Sorry, you are not allowed to do that.', 'woocommerce' ),
+ array( 'status' => rest_authorization_required_code() )
+ );
+ }
+
+ if ( ! wc_get_container()->get( PushNotifications::class )->should_be_enabled() ) {
+ return false;
+ }
+
+ $has_valid_role = array_reduce(
+ PushNotifications::ROLES_WITH_PUSH_NOTIFICATIONS_ENABLED,
+ fn ( $carry, $role ) => $this->check_permission( $request, $role ) === true ? true : $carry,
+ false
+ );
+
+ return $has_valid_role ? true : false;
+ }
+}