VOOZH about

URL: https://deepwiki.com/Automattic/BuddyPress-VIP-Go/3.1-avatar-management

⇱ Avatar Management | Automattic/BuddyPress-VIP-Go | DeepWiki


Loading...
Menu

Avatar Management

This document describes how the BuddyPress VIP Go plugin handles avatar uploads, cropping, retrieval, and deletion for users and groups. Avatar management is a core component of the plugin's media handling system, implementing a metadata-driven approach that stores only original files in VIP File Hosting Service while using dynamic transformations for display.

For cover image handling, see Cover Image Handling. For the underlying URL transformation system, see Dynamic Image Processing and URL Generation. For overall metadata architecture, see Metadata Storage Architecture.

System Architecture

The avatar system replaces BuddyPress's default filesystem-based avatar management with a VIP Go-compatible approach. Instead of storing multiple image sizes on disk, the plugin stores the original image in VIP FHS and generates URLs with query parameters that instruct the CDN to perform transformations on-demand.

Avatar Upload Flow


Sources: files.php336-464 files.php476-545

The upload process intercepts BuddyPress's standard avatar handling through two pre-filters that return false to shortcircuit default behavior:

  • File uploads are processed by vipbp_handle_avatar_upload() which uses wp_handle_sideload() instead of wp_handle_upload() for consistency with webcam captures and because BuddyPress has already validated the upload upstream in xprofile_screen_change_avatar().

  • Webcam captures are processed by vipbp_handle_avatar_capture() which uses wp_upload_bits() to write base64-decoded PNG data directly to the uploads directory, which is more memory efficient than wp_handle_sideload().

Both processes store placeholder metadata with default crop coordinates (full image) and the original image URL.

Avatar Upload Implementation Details

File Upload Processing

The vipbp_handle_avatar_upload() function files.php336-464 handles uploaded avatar files:

Function Signature:

vipbp_handle_avatar_upload( $_, $file, $upload_dir_filter )

Key Operations:

  1. Blog Switching: If not on root blog, switches to root blog using switch_to_blog(bp_get_root_blog_id()) files.php339-342
  2. Upload Processing: Calls wp_handle_sideload() with test_form: false files.php363-369
  3. Dimension Calculation: Determines crop UI width from $bp->avatar_admin->ui_available_width or defaults to bp_core_avatar_original_max_width() files.php349-392
  4. URL Clamping: Adds w query parameter to prevent image upscaling files.php395
  5. Metadata Storage: Creates placeholder metadata with crop dimensions set to full image size files.php402-434

Metadata Structure for File Uploads:

FieldValuePurpose
urlVIP FHS URL with ?w={width}Original image location
crop_wbp_core_avatar_full_width()Initial crop width (full image)
crop_hbp_core_avatar_full_height()Initial crop height (full image)
crop_x0Initial crop X coordinate
crop_y0Initial crop Y coordinate
ui_widthCalculated widthPrevents upscaling on narrow displays

Sources: files.php336-464

Webcam Capture Processing

The vipbp_handle_avatar_capture() function files.php476-545 handles webcam-captured avatars:

Function Signature:

vipbp_handle_avatar_capture( $_, $data, $item_id )

Key Operations:

  1. Data Validation: Returns false if base64 decoded data is empty files.php478-480
  2. Blog Switching: Switches to root blog if necessary files.php482-487
  3. Direct Upload: Uses wp_upload_bits() with PNG filename format webcam-{item_id}-{random}.png files.php491-492
  4. Memory Management: Unsets $data immediately after upload to free memory files.php495
  5. Metadata Storage: Creates identical metadata structure to file uploads files.php518-529

Sources: files.php476-545

Upload Directory Filter Detection

The function detects avatar type (user vs group) through the $upload_dir_filter parameter files.php400-434:

  • User avatars: xprofile_avatar_upload_dir or bp_members_avatar_upload_dir → stores in user meta
  • Group avatars: groups_avatar_upload_dir → stores in group meta
  • Default group avatar: When item_id=0, stores in BP option vipbp-default-group-avatar

Avatar Metadata Storage

Metadata Keys and Locations


Sources: files.php78-82 files.php114-127 files.php426-434

Metadata Field Structure

Avatar metadata contains comprehensive information for dynamic image processing:

FieldTypeDescriptionRequired
urlstringFull URL to original image on VIP FHSYes
crop_xintHorizontal starting point for crop in pixelsYes
crop_yintVertical starting point for crop in pixelsYes
crop_wintWidth of crop area in pixelsYes
crop_hintHeight of crop area in pixelsYes
ui_widthintMaximum width to prevent upscaling images uploaded on mobileNo

Example metadata after upload:


Example metadata after cropping:


Sources: files.php402-413 files.php518-529

Avatar Cropping

Avatar cropping does not create new image files. Instead, it stores cropping coordinates in metadata that are later used to generate dynamic URLs with crop parameters.

Crop Coordinate Storage Flow


Sources: files.php679-739

Crop Function Implementation

The vipbp_handle_avatar_crop() function files.php679-739 processes crop requests:

Function Signature:

vipbp_handle_avatar_crop( $_, $args )

Args Parameter Structure:

  • object (string): 'user' or 'group'
  • avatar_dir (string): 'avatars' or 'group-avatars'
  • item_id (int): User ID, Group ID, or 0 for default group avatar
  • crop_x (int): Horizontal crop start position
  • crop_y (int): Vertical crop start position
  • crop_w (int): Crop width
  • crop_h (int): Crop height

Key Logic:

  1. Coordinate Extraction: Creates array with only crop coordinates files.php680-685
  2. Meta Retrieval: Fetches existing metadata including URL files.php695-714
  3. Validation: Returns false if no valid URL exists (upload may have failed) files.php698-703 files.php717-722
  4. Meta Merging: Uses wp_parse_args() to merge crop coordinates with existing metadata files.php705-706 files.php724-725
  5. Meta Update: Updates appropriate storage location based on object type files.php706-731

Sources: files.php679-739

Avatar URL Generation and Retrieval

Avatar URLs are generated dynamically when BuddyPress requests an avatar. The plugin intercepts these requests and constructs URLs with transformation parameters.

URL Generation Flow


Sources: files.php70-89 files.php106-136 files.php148-256

User Avatar URL Generation

The vipbp_filter_user_avatar_urls() function files.php70-89 handles user avatar URL generation:

Function Signature:

vipbp_filter_user_avatar_urls( $_, $params )

Params Parameter Structure:

  • item_id (int): User ID
  • object (string): 'user'
  • width (int): Requested width
  • height (int): Requested height
  • email (string): User email for Gravatar fallback
  • scheme (string): URL scheme (http/https)

Process:

  1. Switch to root blog files.php73-76
  2. Retrieve user meta vipbp-avatars files.php78-82
  3. Call vipbp_filter_avatar_urls() helper files.php78-82
  4. Restore current blog files.php84-86

Sources: files.php70-89

Group Avatar URL Generation

The vipbp_filter_group_avatar_urls() function files.php106-136 handles group avatar URL generation with special logic for default group avatars:

Function Signature:

vipbp_filter_group_avatar_urls( $_, $params )

Special Case - Default Group Avatar (item_id=0): When $params['item_id'] === 0, the function retrieves metadata from the vipbp-default-group-avatar option instead of group meta files.php115-117

Fallback Logic: For regular groups, if no group-specific avatar exists, the function falls back to the default group avatar files.php122-126:


Sources: files.php106-136

Avatar URL Helper Function

The vipbp_filter_avatar_urls() function files.php148-256 is the core URL generation logic used by both user and group avatar filters:

No Metadata Path - Gravatar Fallback

When no metadata exists, the function generates a Gravatar URL files.php163-214:

Gravatar Construction:

  1. Determine Gravatar type from $bp->grav_default->{$params['object']} (defaults to 'wavatar') files.php166-170
  2. Get or construct email address files.php173-179
  3. Build Gravatar URL: https://www.gravatar.com/avatar/{md5(email)} files.php182-183
  4. Add query parameters: s (size), f (force default), r (rating), d (default image) files.php185-200

Metadata Exists Path - Dynamic URL Construction

When metadata exists, constructs a VIP FHS URL with transformation parameters files.php221-256:

Query Parameters Added:

ParameterValuePurpose
w$meta['ui_width']Clamps image width (mobile optimization)
crop{crop_x}px,{crop_y}px,{crop_w}px,{crop_h}pxDefines crop region
resize{width},{height}Target display dimensions
stripinfoRemoves EXIF and IPTC data

Width Clamping Logic: The w parameter is only added if $meta['ui_width'] exists and is non-zero files.php242-244 This prevents upscaling images that were uploaded on narrow displays (e.g., mobile phones).

URL Construction Example:

https://example.com/uploads/file.jpg?w=800&crop=125px,75px,200px,200px&resize=150,150&strip=info

Filter Hook: The final URL passes through vipbp_filter_avatar_urls filter files.php248 allowing further customization.

Sources: files.php148-256

Avatar Deletion

Avatar deletion removes both the metadata and the physical file from VIP FHS.

Deletion Flow


Sources: files.php761-836

Deletion Function Implementation

The vipbp_delete_existing_avatar() function files.php761-836 handles avatar deletion:

Function Signature:

vipbp_delete_existing_avatar( $_, $args )

Args Parameter Structure:

  • item_id (int): User/Group ID (0 for default group avatar)
  • object (string): 'user', 'group', or custom
  • avatar_dir (string): Subdirectory name

Key Operations:

  1. Item ID Resolution: If item_id is empty, determines it from context files.php770-786:

    • Users: bp_displayed_user_id()
    • Groups: buddypress()->groups->current_group->id
    • Filtered through bp_core_avatar_item_id
  2. Avatar Directory Resolution: If avatar_dir is empty, determines from object type files.php788-806:

    • User: 'avatars'
    • Group: 'group-avatars'
    • Blog: 'blog-avatars'
    • Filtered through bp_core_avatar_dir
  3. Metadata Retrieval and Deletion: files.php809-822

    • User: get_user_meta() then delete_user_meta()
    • Group (item_id > 0): groups_get_groupmeta() then groups_delete_groupmeta()
    • Default Group (item_id = 0): bp_get_option() then bp_delete_option()
  4. File Deletion: files.php824-827

    • Strips query parameters from URL using strtok($meta['url'], '?')
    • Removes site URL prefix to get relative path
    • Calls wp_delete_file() with relative path
  5. Action Hook: Fires bp_core_delete_existing_avatar action files.php828

Sources: files.php761-836

Special Considerations

Default Group Avatar Handling

The default group avatar (used when a group has no custom avatar) is identified by item_id=0 and requires special storage handling because group meta requires a valid group ID.

Storage Location:

  • Regular group avatars: wp_bp_groups_groupmeta table with group_id={group_id}
  • Default group avatar: wp_options table with option name vipbp-default-group-avatar

Functions with Special Handling:

FunctionDefault Avatar LogicLine Reference
vipbp_filter_group_avatar_urls()Checks item_id === 0 and uses bp_get_option()files.php115-117
vipbp_handle_avatar_upload()Checks object_id === 0 and uses bp_update_option()files.php426-427
vipbp_handle_avatar_crop()Checks item_id === 0 and uses bp_get/update_option()files.php710-711 files.php727-728
vipbp_delete_existing_avatar()Checks item_id === 0 and uses bp_delete_option()files.php815-817

Fallback Behavior: When a group has no custom avatar, vipbp_filter_group_avatar_urls() automatically falls back to the default group avatar files.php122-126

Sources: files.php115-117 files.php122-126 files.php426-427 files.php710-711 files.php727-728 files.php815-817

BuddyBoss Compatibility

BuddyBoss's custom default group avatar functionality uses opendir() which fails on VIP Go. The plugin implements a two-filter workaround:

Filter 1: option_bp-default-custom-group-avatar

The vipbp_filter_default_group_avatar_option() function files.php941-947 returns an empty string when a VIP-stored avatar exists, preventing BuddyBoss from calling bb_get_default_custom_avatar() which would use opendir().

Filter 2: bb_get_default_custom_upload_group_avatar

The vipbp_filter_bb_default_group_avatar() function files.php958-966 provides the actual avatar URL from the stored option.

Logic Flow:

BuddyBoss checks option → Filter returns '' → BuddyBoss skips opendir() call → 
bb_get_default_custom_upload_group_avatar filter → Returns stored URL

Sources: files.php20-21 files.php941-966

Multisite Support

All avatar metadata is stored on the root blog in multisite installations to simplify management and ensure consistency.

Blog Switching Pattern:

Every function that accesses metadata follows this pattern:


Functions Using Blog Switching:

Sources: files.php73-76 files.php84-86 files.php109-112 files.php131-133

Integration with BuddyPress Globals

After upload and capture operations, the plugin sets BuddyPress globals to maintain compatibility with the cropper UI files.php438-446 files.php532-538:


These globals are consumed by BuddyPress's avatar cropping interface to display the uploaded image for cropping.

Sources: files.php438-446 files.php532-538

Hook Registration

Avatar management hooks are registered in the bp_init action at priority 8 files.php23-53:

HookFunctionPurpose
bp_core_default_avatar_uservipbp_filter_user_avatar_urlsGenerate user avatar URLs
bp_core_default_avatar_groupvipbp_filter_group_avatar_urlsGenerate group avatar URLs
bp_core_pre_avatar_handle_uploadvipbp_handle_avatar_uploadOverride file upload handling
bp_avatar_pre_handle_capturevipbp_handle_avatar_captureOverride webcam capture handling
bp_core_pre_avatar_handle_cropvipbp_handle_avatar_cropOverride crop handling
bp_core_pre_delete_existing_avatarvipbp_delete_existing_avatarOverride deletion handling

Early Hooks (before bp_init):

  • bp_disable_avatar_history__return_true files.php12 - Disables BP 10.0+ avatar history feature
  • bp_core_avatar_folder_dir__return_empty_string files.php16 - Prevents filesystem scanning

Sources: files.php12 files.php16 files.php23-53