94 lines
3.9 KiB
PHP
94 lines
3.9 KiB
PHP
<?php
|
|
/**
|
|
* Avatars utilisateurs — chaîne de fallback
|
|
* Simple Local Avatar → Gravatar (cache préchauffé par cron) → chaîne vide
|
|
* (initiales côté template).
|
|
*
|
|
* Le rendu ne fait JAMAIS de requête réseau : l'existence du Gravatar est
|
|
* vérifiée par un cron quotidien (thalim_warm_gravatar_cache) qui remplit
|
|
* les transients. En cas de cache manquant (nouvel utilisateur, transient
|
|
* expiré), on renvoie '' (initiales) et on planifie un réchauffage unitaire.
|
|
*/
|
|
|
|
/**
|
|
* Returns the avatar URL for a user:
|
|
* 1. Simple Local Avatar (media library upload) if set
|
|
* 2. Gravatar if the user has one (transient rempli par cron)
|
|
* 3. Empty string → templates fall back to initials/placeholder
|
|
*/
|
|
function thalim_get_user_avatar_url( int $user_id ): string {
|
|
// 1. Simple Local Avatar plugin
|
|
$meta = get_user_meta( $user_id, 'simple_local_avatar', true );
|
|
if ( is_array( $meta ) && ! empty( $meta['full'] ) ) {
|
|
// Use media_id for a dynamic URL that works across environments
|
|
if ( ! empty( $meta['media_id'] ) ) {
|
|
$url = wp_get_attachment_url( (int) $meta['media_id'] );
|
|
if ( $url ) return $url;
|
|
}
|
|
// Fallback: rewrite stored URL to current site domain
|
|
$pos = strpos( $meta['full'], '/wp-content/' );
|
|
if ( $pos !== false ) {
|
|
return rtrim( site_url(), '/' ) . substr( $meta['full'], $pos );
|
|
}
|
|
return $meta['full'];
|
|
}
|
|
|
|
// 2. Gravatar — uniquement depuis le cache (pas de HEAD dans le rendu)
|
|
$cached = get_transient( 'thalim_gravatar_' . $user_id );
|
|
if ( $cached !== false ) return $cached;
|
|
|
|
// Cache manquant : fallback initiales tout de suite, réchauffage en différé
|
|
if ( ! wp_next_scheduled( 'thalim_warm_gravatar_user', [ $user_id ] ) ) {
|
|
wp_schedule_single_event( time() + 60, 'thalim_warm_gravatar_user', [ $user_id ] );
|
|
}
|
|
return '';
|
|
}
|
|
|
|
/**
|
|
* Vérifie l'existence du Gravatar d'un utilisateur (HEAD avec d=404) et met
|
|
* le résultat (positif ou négatif) en transient. Appelé uniquement en cron.
|
|
*/
|
|
function thalim_refresh_gravatar_cache( int $user_id ): void {
|
|
$user = get_userdata( $user_id );
|
|
if ( ! $user ) return;
|
|
|
|
$hash = md5( strtolower( trim( $user->user_email ) ) );
|
|
$response = wp_remote_head(
|
|
'https://www.gravatar.com/avatar/' . $hash . '?d=404',
|
|
[ 'timeout' => 3 ]
|
|
);
|
|
|
|
// Erreur réseau : ne pas mettre en cache un faux négatif, retenter plus tard
|
|
if ( is_wp_error( $response ) ) return;
|
|
|
|
$url = wp_remote_retrieve_response_code( $response ) === 200
|
|
? 'https://www.gravatar.com/avatar/' . $hash . '?s=300'
|
|
: '';
|
|
set_transient( 'thalim_gravatar_' . $user_id, $url, WEEK_IN_SECONDS );
|
|
}
|
|
add_action( 'thalim_warm_gravatar_user', 'thalim_refresh_gravatar_cache' );
|
|
|
|
// Cron quotidien : réchauffe le cache Gravatar des utilisateurs sans avatar
|
|
// local, avant expiration des transients (1 semaine) — le premier rendu de
|
|
// /membres ne paie plus jamais N requêtes HEAD de 3 s.
|
|
add_action( 'init', function () {
|
|
if ( ! wp_next_scheduled( 'thalim_warm_gravatar_cache' ) ) {
|
|
wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'thalim_warm_gravatar_cache' );
|
|
}
|
|
} );
|
|
|
|
add_action( 'thalim_warm_gravatar_cache', function () {
|
|
$users = get_users( [ 'fields' => 'ID' ] );
|
|
foreach ( $users as $user_id ) {
|
|
$user_id = (int) $user_id;
|
|
// Avatar local → pas besoin de Gravatar
|
|
$meta = get_user_meta( $user_id, 'simple_local_avatar', true );
|
|
if ( is_array( $meta ) && ! empty( $meta['full'] ) ) continue;
|
|
// Transient encore frais (posé il y a < 1 semaine) : on le rafraîchit
|
|
// quand même s'il expire dans moins de 2 jours, sinon on saute.
|
|
$timeout = (int) get_option( '_transient_timeout_thalim_gravatar_' . $user_id );
|
|
if ( $timeout && $timeout - time() > 2 * DAY_IN_SECONDS ) continue;
|
|
thalim_refresh_gravatar_cache( $user_id );
|
|
}
|
|
} );
|