Fix: Custom avatar not shown if set default avatar - #411
Conversation
Verify that the set_avatar_url filter runs at priority 11 (after the set_default_avatar filter at priority 10), ensuring custom avatars take precedence over the site-wide default avatar. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Fixes an execution-order bug in WPUM’s avatar URL filtering so that a user’s uploaded (custom) avatar reliably overrides the site-wide default avatar when both are configured.
Changes:
- Change
WPUM_Avatars::set_avatar_urlfilter registration priority from10to11so it runs afterset_default_avatar. - Add WPUnit coverage asserting the expected
get_avatar_urlfilter priorities and their ordering.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
includes/admin/class-wpum-avatars.php |
Bumps custom avatar filter priority to ensure it wins over the default avatar filter. |
tests/wpunit/Avatars/AvatarPriorityTest.php |
Adds WPUnit tests to confirm filter priorities/order for custom vs default avatar behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| public function _tearDown() { | ||
| // Remove filters that our fresh instance added, so they don't leak | ||
| // into other tests. | ||
| remove_all_filters( 'get_avatar_url' ); | ||
|
|
There was a problem hiding this comment.
remove_all_filters( 'get_avatar_url' ) removes every callback on that hook (including core/other plugin/test callbacks), which can cause cross-test pollution. Prefer removing only the WPUM_Avatars callbacks you added (e.g., iterate current callbacks and remove_filter where the callable object is a WPUM_Avatars instance), or snapshot/restore the prior callbacks in _tearDown().
| * Tests for the WPUM_Avatars filter priority fix (#411). | ||
| * | ||
| * When both a custom avatar and a site-wide default avatar are configured, | ||
| * the custom avatar filter (set_avatar_url) must run AFTER the default avatar | ||
| * filter (set_default_avatar) so the custom avatar takes precedence. | ||
| * | ||
| * @see https://github.com/WPUserManager/wp-user-manager/pull/411 |
There was a problem hiding this comment.
The test header hard-codes PR references (#411 / pull/411). This is brittle and can become incorrect when cherry-picked or backported; prefer referencing the tracked issue (e.g., #403) or describing the behavior without linking to a specific PR number.
| * Tests for the WPUM_Avatars filter priority fix (#411). | |
| * | |
| * When both a custom avatar and a site-wide default avatar are configured, | |
| * the custom avatar filter (set_avatar_url) must run AFTER the default avatar | |
| * filter (set_default_avatar) so the custom avatar takes precedence. | |
| * | |
| * @see https://github.com/WPUserManager/wp-user-manager/pull/411 | |
| * Tests for the WPUM_Avatars filter priority behavior. | |
| * | |
| * When both a custom avatar and a site-wide default avatar are configured, | |
| * the custom avatar filter (set_avatar_url) must run AFTER the default avatar | |
| * filter (set_default_avatar) so the custom avatar takes precedence. |
| /** | ||
| * Helper: return the WPUM_Avatars instance that was created in _setUp. | ||
| * | ||
| * We retrieve it from the filter registry rather than storing a reference, | ||
| * so the test truly reflects what WordPress sees. | ||
| * | ||
| * @return WPUM_Avatars | ||
| */ | ||
| private function get_avatars_instance() { | ||
| global $wp_filter; | ||
|
|
||
| if ( ! isset( $wp_filter['get_avatar_url'] ) ) { | ||
| $this->fail( 'get_avatar_url filter is not registered.' ); | ||
| } | ||
|
|
||
| foreach ( $wp_filter['get_avatar_url']->callbacks as $priority => $callbacks ) { | ||
| foreach ( $callbacks as $callback ) { | ||
| if ( | ||
| is_array( $callback['function'] ) && | ||
| $callback['function'][0] instanceof WPUM_Avatars | ||
| ) { | ||
| return $callback['function'][0]; |
There was a problem hiding this comment.
get_avatars_instance() reaches into the $wp_filter internals (WP_Hook::$callbacks) and returns the first WPUM_Avatars instance it finds. This is brittle across WP versions and also doesn’t guarantee it returns the instance created in _setUp() if another WPUM_Avatars instance is already registered. Consider storing the instance created in _setUp() on the test class (and using has_filter on that), or making the helper explicitly select the most recently added callback.
Resolves #403
Summary
Changes the
get_avatar_urlfilter priority for custom avatars from10to11so that a user's uploaded avatar takes precedence over the site-wide default avatar set in WPUM settings.Root cause: Both
set_avatar_url(custom avatar) andset_default_avatar(default avatar) were registered at priority 10. WordPress executes same-priority filters in registration order, meaning the default avatar could overwrite the custom one.Fix: Bump
set_avatar_urlto priority 11 so it always runs afterset_default_avatar.Manual Test Plan
Prerequisites
1. Setup default avatar
2. Upload a custom avatar for a user
3. Verify custom avatar overrides default
/profile/{username}/)4. Verify default avatar still works for other users
5. Verify Gravatar fallback
WPUnit Test Coverage
4 tests in
tests/wpunit/Avatars/AvatarPriorityTest.php:set_avatar_urlregistered at priority 11set_default_avatarregistered at priority 10WPUM_Avatarsclass exists🤖 Generated with Claude Code