Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the admin notification mechanics contextually aware (of the user and of the admin screen) #767

Merged
merged 8 commits into from
Jan 22, 2025

Conversation

barryhughes
Copy link
Member

@barryhughes barryhughes commented Jan 16, 2025

If an admin notice is added via the wcs_add_admin_notice() function, then it will display on the next request for an admin screen—regardless of who the current user is or what screen they are viewing. Here's a hypothetical example:

  • Merchant changes the subscription end date in the editor.
  • In response, we add an admin notice to tell them the change was successful (or possibly to inform them that there was a problem of some kind).
  • If some other user, like a contributor, just happens to request a different admin page at approximately the same time (and immediately before the admin's instance of the subscription editor finishes reloading), then that is the user who will, quite unexpectedly, see the admin notice.
  • Additionally, these operate as "flash" messages by default—and so, once they've been consumed, they are gone: in other words, in this hypothetical scenario, the merchant would never see the message. Only the contributor would see it, and they'd probably be a little confused by it.

In this change, we tighten things up a little such that:

  • If a notice is enqueued, we assume its intended audience is the current user (and that's the only person that will see it). We also make it possible to explicitly specify the intended recipient.
  • Additionally, it can be 'locked' to a specific context, by specifying the relevant screen ID (this would mean we can constrain certain notices so they only render in the subscription editor, to pick an example).

How can this code break?

We previously stored these notices in a transient named _wcs_admin_notices, but will now use one or more transients named _wcs_admin_notices_<user_id>. So, an enqueued notice could be lost upon update (I think this is acceptable, and would be a very temporary problem that probably would impact very few users indeed ... but we could soften the landing if we think it's necessary to do so).

Updates http://github.com/woocommerce/woocommerce-subscriptions/issues/4776

How to test this PR

Let's first test that existing admin notices continue work as expected. To do this, select an existing subscription and contrive a problem in which the subscription end date is earlier than the next payment date:

Subscription payment dates meta box

Normally it's not possible to do this, so setting it up will require direct edits to the relevant row of the wc_orders_meta table (assuming you are using HPOS). Find the _schedule_end entry, and alter the date manually as needed.

With that done, return to the editor and click update. Upon reload, you should see that an admin notice is present on the page telling you that the end date is incorrect:

Admin notices at the top of the subscription editor screen

On to the real testing! Let's confirm that admin notices are 'constrained' to the current user. Probably the easiest way to do this is to have two separate browser contexts: in one, you should be logged in as an admin user or shop manager, in the other you should be logged in as a contributor (or other less privileged user). You also need to add the following snippet to a suitable location, such as wp-content/mu-plugins/test-pr-767.php:

<?php

add_action( 'admin_footer', function () {
	if (
		! isset( $_GET[ 'create-wcs-message' ] )
		|| ! function_exists( 'wcs_add_admin_notice' )
	) {
		return;
	}

	$user = wp_get_current_user();

	$username = $user instanceof WP_User ? $user->display_name : '&lt;unknown&gt;';
	wcs_add_admin_notice( "Hey there, $username! Time for a coffee?", 'success');
} );
  • As the admin user, visit example.com/wp-admin?create-wcs-message=1. This triggers the code in the snippet.
  • When the page finishes loading you should see ... nothing new (or, at least, you should not see an admin notice, unless perhaps WordPress adds one that is unrelated to the scenario we are testing).
  • Now switch to the other browser context, where you are logged in as a contributor. Load or refresh one of the admin pages:
    • Without this fix, you should see a message reading something like Hey there, admin user! Time for a coffee?
    • If you repeat but with this fix, you should not see any admin notice message.
  • Switch back to the original browser context, where you are logged in as an admin user. Load or refresh another admin page, but make sure ?create-wcs-message=1 is no longer in the URL.
    • Without this fix, you will not see an admin notice (it was consumed by the contributor).
    • With this fix, you should see the admin notice.

Tip

In case it isn't clear, note that you need to run through the whole set of testing steps once without this fix, and then again with the fix. You can't flip between branches as you go along, or you will get unexpected results.

Note

The change goes beyond what these testing instructions describe. For example, as noted earlier, it now becomes possible to lock a message to a specific screen. I have not detailed testing steps for this but will probably do so in a further PR that takes advantage of that functionality. Nonetheless, feel free to explore this area now if you feel so inclined!

Product impact

  • Added changelog entry (or does not apply)
  • Will this PR affect WooCommerce Subscriptions? Yes → #4776
  • Will this PR affect WooCommerce Payments? No
  • Added deprecated functions, hooks or classes to the spreadsheet None

@barryhughes barryhughes marked this pull request as ready for review January 17, 2025 02:47
@barryhughes barryhughes requested a review from mattallan January 17, 2025 03:24
Copy link
Contributor

@mattallan mattallan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for including unit tests and nice work on this one @barryhughes !!
Also amazing PR description :)

I've left a few initial comments, but so far these change look good!

includes/admin/wcs-admin-functions.php Outdated Show resolved Hide resolved
includes/admin/wcs-admin-functions.php Outdated Show resolved Hide resolved
includes/admin/wcs-admin-functions.php Outdated Show resolved Hide resolved
changelog.txt Outdated Show resolved Hide resolved
barryhughes and others added 5 commits January 21, 2025 08:11
Co-authored-by: Matt Allan <[email protected]>
If a plugin tries to call wcs_add_admin_notice() and no user is currently logged in, then a transient will be created and (if this happens periodically) it will A) not expire B) continue to grow in size. This change guards against that possibility.
@barryhughes
Copy link
Member Author

@mattallan requesting your further review. I think I addressed all of your concerns, but of course let me know if I missed anything/if any of the adjustments are off-key. Thanks again for all the great feedback!

@barryhughes barryhughes requested a review from mattallan January 21, 2025 19:36
Copy link
Contributor

@mattallan mattallan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great @barryhughes !

I tested:

  • existing uses of wcs_display_admin_notices() throughout subscriptions are still working as expected
  • transient is properly cleared after noticed is displayed
  • tested user specific notices and screen specific:
wcs_add_admin_notice( 'This is a test notice.', 'error' );
wcs_add_admin_notice( 'Show this to user 2.', 'error', 2 );
wcs_add_admin_notice( 'Only show this notice on subscription list.', 'success', 1, 'edit-shop_subscription' );
wcs_add_admin_notice( 'Invalid guest notice.', 'success', 0 );

All appears to be working as expected 💯 I've left a small comment to fix a typo but apart from that this is good !
Thanks again

includes/admin/wcs-admin-functions.php Outdated Show resolved Hide resolved
Co-authored-by: Matt Allan <[email protected]>
@barryhughes barryhughes merged commit d5fbefc into trunk Jan 22, 2025
9 checks passed
@barryhughes barryhughes deleted the fix/4776-admin-notices branch January 22, 2025 14:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants