Skip to content

Commit 7bbda35

Browse files
reygcalantaolpolevaultwebclaude
authored
Fix: Custom avatar not shown if set default avatar (#411)
* Fix: Custom avatar not shown if set default avatar Resolves #403 @polevaultweb * Add WPUnit tests for avatar priority fix (#411) 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> --------- Co-authored-by: Iain Poulson <iain@polevaultweb.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 51f867b commit 7bbda35

2 files changed

Lines changed: 123 additions & 1 deletion

File tree

includes/admin/class-wpum-avatars.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,9 @@ public function __construct() {
3636

3737
if ( wpum_get_option( 'custom_avatars' ) ) {
3838
add_action( 'carbon_fields_register_fields', array( $this, 'avatar_field' ) );
39-
add_filter( 'get_avatar_url', array( $this, 'set_avatar_url' ), 10, 3 );
39+
40+
// Set user uploaded avatar a higher priority than the default avatar.
41+
add_filter( 'get_avatar_url', array( $this, 'set_avatar_url' ), 11, 3 );
4042
}
4143

4244
if ( ! wpum_get_option( 'disable_profile_cover' ) ) {
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
<?php
2+
/**
3+
* Tests for the WPUM_Avatars filter priority fix (#411).
4+
*
5+
* When both a custom avatar and a site-wide default avatar are configured,
6+
* the custom avatar filter (set_avatar_url) must run AFTER the default avatar
7+
* filter (set_default_avatar) so the custom avatar takes precedence.
8+
*
9+
* @see https://github.com/WPUserManager/wp-user-manager/pull/411
10+
*/
11+
12+
require_once dirname( __DIR__ ) . '/WPUMTestCase.php';
13+
14+
class AvatarPriorityTest extends WPUMTestCase {
15+
16+
public function _setUp() {
17+
parent::_setUp();
18+
19+
// Enable the custom_avatars and default_avatar WPUM options so both
20+
// code paths in the WPUM_Avatars constructor are entered.
21+
global $wpum_options;
22+
if ( ! is_array( $wpum_options ) ) {
23+
$wpum_options = array();
24+
}
25+
$wpum_options['custom_avatars'] = true;
26+
$wpum_options['default_avatar'] = 'http://example.com/default-avatar.jpg';
27+
28+
// Instantiate a fresh WPUM_Avatars so both filters are registered.
29+
new WPUM_Avatars();
30+
}
31+
32+
public function _tearDown() {
33+
// Remove filters that our fresh instance added, so they don't leak
34+
// into other tests.
35+
remove_all_filters( 'get_avatar_url' );
36+
37+
global $wpum_options;
38+
if ( is_array( $wpum_options ) ) {
39+
unset( $wpum_options['custom_avatars'], $wpum_options['default_avatar'] );
40+
}
41+
42+
parent::_tearDown();
43+
}
44+
45+
/**
46+
* Verify the WPUM_Avatars class exists and is loadable.
47+
*/
48+
public function test_wpum_avatars_class_exists() {
49+
$this->assertTrue( class_exists( 'WPUM_Avatars' ), 'WPUM_Avatars class should be loaded.' );
50+
}
51+
52+
/**
53+
* The set_avatar_url callback (custom avatar) must be registered at priority 11.
54+
*/
55+
public function test_set_avatar_url_registered_at_priority_11() {
56+
$priority = has_filter( 'get_avatar_url', array( $this->get_avatars_instance(), 'set_avatar_url' ) );
57+
58+
$this->assertNotFalse( $priority, 'set_avatar_url should be registered on get_avatar_url.' );
59+
$this->assertSame( 11, $priority, 'set_avatar_url must be registered at priority 11.' );
60+
}
61+
62+
/**
63+
* The set_default_avatar callback must be registered at priority 10 (the default).
64+
*/
65+
public function test_set_default_avatar_registered_at_priority_10() {
66+
$priority = has_filter( 'get_avatar_url', array( $this->get_avatars_instance(), 'set_default_avatar' ) );
67+
68+
$this->assertNotFalse( $priority, 'set_default_avatar should be registered on get_avatar_url.' );
69+
$this->assertSame( 10, $priority, 'set_default_avatar must be registered at priority 10.' );
70+
}
71+
72+
/**
73+
* The custom avatar filter priority must be strictly greater than the
74+
* default avatar filter priority, so the custom avatar wins.
75+
*/
76+
public function test_custom_avatar_priority_is_higher_than_default() {
77+
$instance = $this->get_avatars_instance();
78+
79+
$custom_priority = has_filter( 'get_avatar_url', array( $instance, 'set_avatar_url' ) );
80+
$default_priority = has_filter( 'get_avatar_url', array( $instance, 'set_default_avatar' ) );
81+
82+
$this->assertNotFalse( $custom_priority, 'set_avatar_url should be registered.' );
83+
$this->assertNotFalse( $default_priority, 'set_default_avatar should be registered.' );
84+
85+
$this->assertGreaterThan(
86+
$default_priority,
87+
$custom_priority,
88+
'Custom avatar filter (set_avatar_url) must run after the default avatar filter (set_default_avatar).'
89+
);
90+
}
91+
92+
/**
93+
* Helper: return the WPUM_Avatars instance that was created in _setUp.
94+
*
95+
* We retrieve it from the filter registry rather than storing a reference,
96+
* so the test truly reflects what WordPress sees.
97+
*
98+
* @return WPUM_Avatars
99+
*/
100+
private function get_avatars_instance() {
101+
global $wp_filter;
102+
103+
if ( ! isset( $wp_filter['get_avatar_url'] ) ) {
104+
$this->fail( 'get_avatar_url filter is not registered.' );
105+
}
106+
107+
foreach ( $wp_filter['get_avatar_url']->callbacks as $priority => $callbacks ) {
108+
foreach ( $callbacks as $callback ) {
109+
if (
110+
is_array( $callback['function'] ) &&
111+
$callback['function'][0] instanceof WPUM_Avatars
112+
) {
113+
return $callback['function'][0];
114+
}
115+
}
116+
}
117+
118+
$this->fail( 'Could not find a WPUM_Avatars instance in the get_avatar_url filter.' );
119+
}
120+
}

0 commit comments

Comments
 (0)