diff --git a/admin/class-yoast-notification-center.php b/admin/class-yoast-notification-center.php index e5b9fb0baa5..404e00e346f 100644 --- a/admin/class-yoast-notification-center.php +++ b/admin/class-yoast-notification-center.php @@ -716,7 +716,6 @@ private static function get_user_input( $key ) { * @return void */ private function retrieve_notifications_from_storage( $user_id ) { - if ( $this->notifications_retrieved ) { return; } @@ -732,6 +731,7 @@ private function retrieve_notifications_from_storage( $user_id ) { if ( is_array( $stored_notifications ) ) { $notifications = array_map( [ $this, 'array_to_notification' ], $stored_notifications ); + // Apply array_values to ensure we get a 0-indexed array. $notifications = array_values( array_filter( $notifications, [ $this, 'filter_notification_current_user' ] ) ); @@ -841,6 +841,13 @@ private function array_to_notification( $notification_data ) { $notification_data['message'] = $notification_data['message']->present(); } + if ( isset( $notification_data['options']['user'] ) ) { + $notification_data['options']['user_id'] = $notification_data['options']['user']->ID; + unset( $notification_data['options']['user'] ); + + $this->notifications_need_storage = true; + } + return new Yoast_Notification( $notification_data['message'], $notification_data['options'] diff --git a/admin/class-yoast-notification.php b/admin/class-yoast-notification.php index d4b1ea7090b..6b0182ed3d4 100644 --- a/admin/class-yoast-notification.php +++ b/admin/class-yoast-notification.php @@ -72,7 +72,7 @@ class Yoast_Notification { private $defaults = [ 'type' => self::UPDATED, 'id' => '', - 'user' => null, + 'user_id' => null, 'nonce' => null, 'priority' => 0.5, 'data_json' => [], @@ -112,10 +112,14 @@ public function get_id() { /** * Retrieve the user to show the notification for. * + * @deprecated 21.6 + * @codeCoverageIgnore + * * @return WP_User The user to show this notification for. */ public function get_user() { - return $this->options['user']; + \_deprecated_function( __METHOD__, 'Yoast SEO 21.6' ); + return null; } /** @@ -126,10 +130,7 @@ public function get_user() { * @return int The user id */ public function get_user_id() { - if ( $this->get_user() !== null ) { - return $this->get_user()->ID; - } - return get_current_user_id(); + return ( $this->options['user_id'] ?? get_current_user_id() ); } /** @@ -220,7 +221,7 @@ public function display_for_current_user() { */ public function match_capabilities() { // Super Admin can do anything. - if ( is_multisite() && is_super_admin( $this->options['user']->ID ) ) { + if ( is_multisite() && is_super_admin( $this->options['user_id'] ) ) { return true; } @@ -280,7 +281,15 @@ public function match_capabilities() { * @return bool */ private function has_capability( $capability ) { - $user = $this->options['user']; + $user_id = $this->options['user_id']; + if ( ! is_numeric( $user_id ) ) { + return false; + } + $user = get_user_by( 'id', $user_id ); + if ( ! $user ) { + return false; + } + return $user->has_cap( $capability ); } @@ -396,9 +405,9 @@ private function normalize_options( $options ) { $options['capabilities'] = [ 'wpseo_manage_options' ]; } - // Set to the current user if not supplied. - if ( $options['user'] === null ) { - $options['user'] = wp_get_current_user(); + // Set to the id of the current user if not supplied. + if ( $options['user_id'] === null ) { + $options['user_id'] = get_current_user_id(); } return $options; diff --git a/tests/integration/notifications/test-class-yoast-notification-center.php b/tests/integration/notifications/test-class-yoast-notification-center.php index a35920a3f5e..e526016530f 100644 --- a/tests/integration/notifications/test-class-yoast-notification-center.php +++ b/tests/integration/notifications/test-class-yoast-notification-center.php @@ -800,13 +800,16 @@ public function test_add_notifications_for_multiple_users() { $instance = $this->get_notification_center(); - $user_mock_1 = $this->mock_wp_user( 1, [ 'wpseo_manage_options' => true ] ); - $user_mock_2 = $this->mock_wp_user( 2, [ 'wpseo_manage_options' => true ] ); + $user_1 = $this->factory->user->create_and_get(); + $user_1->add_cap( 'wpseo_manage_options' ); + + $user_2 = $this->factory->user->create_and_get(); + $user_2->add_cap( 'wpseo_manage_options' ); $notification_for_user_1 = new Yoast_Notification( 'Hello, user 1!', [ - 'user' => $user_mock_1, + 'user_id' => $user_1->ID, 'capabilities' => [ 'wpseo_manage_options' ], ] ); @@ -814,7 +817,7 @@ public function test_add_notifications_for_multiple_users() { $notification_for_user_2 = new Yoast_Notification( 'Hello, user 2!', [ - 'user' => $user_mock_2, + 'user_id' => $user_2->ID, 'capabilities' => [ 'wpseo_manage_options' ], ] ); @@ -823,10 +826,10 @@ public function test_add_notifications_for_multiple_users() { $instance->add_notification( $notification_for_user_2 ); $expected_for_user_1 = [ $notification_for_user_1 ]; - $actual_for_user_1 = $instance->get_notifications_for_user( 1 ); + $actual_for_user_1 = $instance->get_notifications_for_user( $user_1->ID ); $expected_for_user_2 = [ $notification_for_user_2 ]; - $actual_for_user_2 = $instance->get_notifications_for_user( 2 ); + $actual_for_user_2 = $instance->get_notifications_for_user( $user_2->ID ); $this->assertEquals( $expected_for_user_1, $actual_for_user_1 ); $this->assertEquals( $expected_for_user_2, $actual_for_user_2 ); @@ -841,13 +844,14 @@ public function test_add_notifications_only_once_for_user() { $instance = $this->get_notification_center(); - $user_mock = $this->mock_wp_user( 3, [ 'wpseo_manage_options' => true ] ); + $user = $this->factory->user->create_and_get(); + $user->add_cap( 'wpseo_manage_options' ); $notification = new Yoast_Notification( 'Hello, user 3!', [ 'id' => 'Yoast_Notification_Test', - 'user' => $user_mock, + 'user_id' => $user->ID, 'capabilities' => [ 'wpseo_manage_options' ], ] ); @@ -856,7 +860,7 @@ public function test_add_notifications_only_once_for_user() { $instance->add_notification( $notification ); $expected = [ $notification ]; - $actual = $instance->get_notifications_for_user( 3 ); + $actual = $instance->get_notifications_for_user( $user->ID ); $this->assertEquals( $expected, $actual ); } @@ -917,35 +921,4 @@ private function get_notification_center() { return $notification_center; } - - /** - * Creates a mock WordPress user. - * - * @param int $user_id The ID of the user. - * @param array $caps A map, mapping capabilities to `true` (user has capability) or `false` ( user has not). - * - * @return PHPUnit_Framework_MockObject_Invocation_Object | WP_User - */ - private function mock_wp_user( $user_id, $caps ) { - $user_mock = $this - ->getMockBuilder( 'WP_User' ) - ->setMethods( [ 'has_cap' ] ) - ->getMock(); - - $user_mock - ->expects( $this->any() ) - ->method( 'has_cap' ) - ->with( $this->isType( 'string' ) ) - ->willReturn( - $this->returnCallback( - static function( $argument ) use ( $caps ) { - return isset( $caps[ $argument ] ) ? $caps[ $argument ] : false; - } - ) - ); - - $user_mock->ID = $user_id; - - return $user_mock; - } } diff --git a/tests/integration/notifications/test-class-yoast-notification.php b/tests/integration/notifications/test-class-yoast-notification.php index fbb45d5c450..855d79a9ee8 100644 --- a/tests/integration/notifications/test-class-yoast-notification.php +++ b/tests/integration/notifications/test-class-yoast-notification.php @@ -26,6 +26,18 @@ class Yoast_Notification_Test extends WPSEO_UnitTestCase { */ private $verify_capability_match_filter_args = []; + /** + * Create user with proper caps. + */ + public function set_up() { + parent::set_up(); + + $user = $this->factory->user->create_and_get(); + $user->add_cap( 'wpseo_manage_options' ); + + wp_set_current_user( $user->ID ); + } + /** * No ID is not persistent. */ @@ -40,12 +52,13 @@ public function test_not_persistent() { public function test_set_defaults() { $subject = new Yoast_Notification( 'message', [] ); $test = $subject->to_array(); + $user = wp_get_current_user(); $this->assertEquals( [ 'type' => 'updated', 'id' => '', - 'user' => wp_get_current_user(), + 'user_id' => $user->ID, 'nonce' => null, 'priority' => 0.5, 'data_json' => [], @@ -168,6 +181,7 @@ public function test_match_any_pass() { ] ); + $this->assertTrue( $subject->display_for_current_user() ); $this->remove_cap( 'bla' ); diff --git a/tests/unit/admin/admin-features-test.php b/tests/unit/admin/admin-features-test.php index 9763e2de3c4..1713c85cf46 100644 --- a/tests/unit/admin/admin-features-test.php +++ b/tests/unit/admin/admin-features-test.php @@ -38,9 +38,12 @@ private function get_admin_with_expectations() { ->with( 'https://example.org', 'dismiss-5star-upsell' ) ->andReturn( 'https://example.org?_wpnonce=test-nonce' ); - Monkey\Functions\expect( 'wp_get_current_user' ) - ->once() - ->andReturn( Mockery::mock( WP_User::class ) ); + $admin_user = Mockery::mock( WP_User::class ); + $admin_user->ID = 1; + + Monkey\Functions\expect( 'get_current_user_id' ) + ->once() + ->andReturn( $admin_user->ID ); return new WPSEO_Admin(); } diff --git a/tests/unit/admin/admin-gutenberg-compatibility-notification-test.php b/tests/unit/admin/admin-gutenberg-compatibility-notification-test.php index e001285cf77..930bd19403e 100644 --- a/tests/unit/admin/admin-gutenberg-compatibility-notification-test.php +++ b/tests/unit/admin/admin-gutenberg-compatibility-notification-test.php @@ -22,6 +22,13 @@ */ class WPSEO_Admin_Gutenberg_Compatibility_Notification_Test extends TestCase { + /** + * Holds the admin user mock instance. + * + * @var WP_User + */ + private $admin_user; + /** * Holds the WPSEO_Gutenberg_Compatibility mock instance. * @@ -49,6 +56,11 @@ class WPSEO_Admin_Gutenberg_Compatibility_Notification_Test extends TestCase { public function set_up() { parent::set_up(); + $this->stubTranslationFunctions(); + + $this->admin_user = Mockery::mock( WP_User::class ); + $this->admin_user->ID = 1; + $this->gutenberg_compatibility_mock = Mockery::mock( WPSEO_Gutenberg_Compatibility::class )->makePartial(); $this->notification_center_mock = Mockery::mock( Yoast_Notification_Center::class ); @@ -120,15 +132,6 @@ public function data_provider_manage_notification_remove_notification() { * @covers WPSEO_Gutenberg_Compatibility::get_installed_version */ public function test_manage_notification_gutenberg_show_notification() { - Monkey\Functions\stubs( - [ - '__' => null, - 'wp_get_current_user' => static function() { - return null; - }, - ] - ); - $this->gutenberg_compatibility_mock->allows( [ 'is_installed' => true, @@ -136,6 +139,10 @@ public function test_manage_notification_gutenberg_show_notification() { ] ); + Monkey\Functions\expect( 'get_current_user_id' ) + ->once() + ->andReturn( $this->admin_user->ID ); + $this->notification_center_mock->expects( 'add_notification' )->once()->withArgs( static function ( $arg ) { // Verify that the added notification is a Yoast_Notification object and has the correct id. diff --git a/tests/unit/content-type-visibility/application/content-type-visibility-watcher-actions-test.php b/tests/unit/content-type-visibility/application/content-type-visibility-watcher-actions-test.php index ea3d524b836..f14a7d9accf 100644 --- a/tests/unit/content-type-visibility/application/content-type-visibility-watcher-actions-test.php +++ b/tests/unit/content-type-visibility/application/content-type-visibility-watcher-actions-test.php @@ -21,6 +21,13 @@ */ class Content_Type_Visibility_Watcher_Actions_Test extends TestCase { + /** + * Holds the admin user mock instance. + * + * @var WP_User + */ + private $admin_user; + /** * Holds the Options_Helper instance. * @@ -57,6 +64,9 @@ protected function set_up() { $this->stubTranslationFunctions(); + $this->admin_user = Mockery::mock( WP_User::class ); + $this->admin_user->ID = 1; + $this->options = Mockery::mock( Options_Helper::class ); $this->notification_center = Mockery::mock( Yoast_Notification_Center::class ); $this->content_type_dismiss_notifications = Mockery::mock( Content_Type_Visibility_Dismiss_Notifications::class ); @@ -310,10 +320,13 @@ public function test_maybe_add_notification() { [ 'esc_url' => 'https://yoa.st/3.0-content-types', 'admin_url' => 'admin.php?page=wpseo_page_settings', - 'wp_get_current_user' => Mockery::mock( WP_User::class ), ] ); + Monkey\Functions\expect( 'get_current_user_id' ) + ->once() + ->andReturn( $this->admin_user->ID ); + $this->notification_center ->expects( 'add_notification' ) ->once(); diff --git a/tests/unit/inc/addon-manager-test.php b/tests/unit/inc/addon-manager-test.php index 9cddf533cde..c54ff990974 100644 --- a/tests/unit/inc/addon-manager-test.php +++ b/tests/unit/inc/addon-manager-test.php @@ -1157,8 +1157,12 @@ public function test_create_notification( $product_name, $short_link ) { ] ); - Monkey\Functions\expect( 'wp_get_current_user' ) - ->twice(); + $admin_user = Mockery::mock( WP_User::class ); + $admin_user->ID = 1; + + Monkey\Functions\expect( 'get_current_user_id' ) + ->twice() + ->andReturn( $admin_user->ID ); Monkey\Functions\expect( 'YoastSEO' ) ->once() diff --git a/tests/unit/integrations/admin/indexing-notification-integration-test.php b/tests/unit/integrations/admin/indexing-notification-integration-test.php index 7466eefedd8..1ff4a5b5709 100644 --- a/tests/unit/integrations/admin/indexing-notification-integration-test.php +++ b/tests/unit/integrations/admin/indexing-notification-integration-test.php @@ -344,8 +344,10 @@ public function test_maybe_create_notification_with_indexing_failed_reason() { ->once() ->andReturn( Indexing_Reasons::REASON_INDEXING_FAILED ); - Monkey\Functions\expect( 'wp_get_current_user' ) - ->andReturn( 'user' ); + $admin_user = Mockery::mock( WP_User::class ); + $admin_user->ID = 1; + Monkey\Functions\expect( 'get_current_user_id' ) + ->andReturn( $admin_user->ID ); $this->notification_helper ->expects( 'restore_notification' ) @@ -400,8 +402,10 @@ public function test_maybe_create_notification_with_indexing_reasons( $reason ) ->once() ->andReturn( $reason ); - Monkey\Functions\expect( 'wp_get_current_user' ) - ->andReturn( 'user' ); + $admin_user = Mockery::mock( WP_User::class ); + $admin_user->ID = 1; + Monkey\Functions\expect( 'get_current_user_id' ) + ->andReturn( $admin_user->ID ); $this->notification_helper ->expects( 'restore_notification' ) diff --git a/tests/unit/integrations/third-party/wpml-wpseo-notification-test.php b/tests/unit/integrations/third-party/wpml-wpseo-notification-test.php index d4799c20903..7f6ec5faabf 100644 --- a/tests/unit/integrations/third-party/wpml-wpseo-notification-test.php +++ b/tests/unit/integrations/third-party/wpml-wpseo-notification-test.php @@ -120,8 +120,10 @@ public function test_notifies_when_not_installed() { // Mock that the Yoast SEO Multilingual plugin is not installed and activated. $this->wpml_wpseo_conditional->expects( 'is_met' )->andReturnFalse(); - Monkey\Functions\expect( 'wp_get_current_user' ) - ->andReturn( 'user' ); + $admin_user = Mockery::mock( WP_User::class ); + $admin_user->ID = 1; + Monkey\Functions\expect( 'get_current_user_id' ) + ->andReturn( $admin_user->ID ); $this->notification_center ->expects( 'add_notification' ) diff --git a/tests/unit/integrations/watchers/search-engines-discouraged-watcher-test.php b/tests/unit/integrations/watchers/search-engines-discouraged-watcher-test.php index f0ed0bad2bb..705e57de20b 100644 --- a/tests/unit/integrations/watchers/search-engines-discouraged-watcher-test.php +++ b/tests/unit/integrations/watchers/search-engines-discouraged-watcher-test.php @@ -22,6 +22,13 @@ */ class Search_Engines_Discouraged_Watcher_Test extends TestCase { + /** + * Holds the admin user mock instance. + * + * @var WP_User + */ + private $admin_user; + /** * Yoast_Notification_Center mock. * @@ -70,6 +77,9 @@ class Search_Engines_Discouraged_Watcher_Test extends TestCase { public function set_up() { parent::set_up(); + $this->admin_user = Mockery::mock( WP_User::class ); + $this->admin_user->ID = 1; + $this->notification_center = Mockery::mock( Yoast_Notification_Center::class ); $this->notification_helper = Mockery::mock( Notification_Helper::class ); $this->current_page_helper = Mockery::mock( Current_Page_Helper::class ); @@ -338,9 +348,9 @@ public function test_manage_search_engines_discouraged_notification( $blog_publi ->expects( 'restore_notification' ); $this->notification_center ->expects( 'add_notification' ); - Monkey\Functions\expect( 'wp_get_current_user' ) + Monkey\Functions\expect( 'get_current_user_id' ) ->once() - ->andReturn( null ); + ->andReturn( $this->admin_user->ID ); } else { $this->notification_helper