VOOZH about

URL: https://deepwiki.com/Automattic/BuddyPress-VIP-Go/3.5-file-deletion-operations

⇱ File Deletion Operations | Automattic/BuddyPress-VIP-Go | DeepWiki


Loading...
Menu

File Deletion Operations

Purpose and Scope

This document explains the file deletion operations implemented by the BuddyPress VIP Go plugin. Deletion follows a two-phase process: first removing metadata from the WordPress database, then calling wp_delete_file() to remove the actual file from VIP's File Hosting Service (FHS).

For information about file upload operations, see Avatar Management and Cover Image Handling. For metadata storage architecture details, see Metadata Storage Architecture.

Sources: files.php761-875

Deletion Architecture Overview

The plugin implements two separate deletion handlers that follow the same architectural pattern:

Handler FunctionHookPurposeReturns
vipbp_delete_existing_avatar()bp_core_pre_delete_existing_avatarDelete user/group avatarsfalse (shortcircuits BuddyPress)
vipbp_delete_cover_image()bp_attachments_pre_delete_fileDelete user/group cover imagesfalse (shortcircuits BuddyPress)

Both functions intercept BuddyPress's default deletion logic and replace it with VIP-compatible operations. They return false to indicate that the operation has been handled and BuddyPress should not proceed with its default behavior.


Sources: files.php43-44 files.php761-875

Avatar Deletion Process

Function Signature and Hook Integration

The vipbp_delete_existing_avatar() function is registered on the bp_core_pre_delete_existing_avatar filter at priority 10 with 2 accepted arguments:

add_filter( 'bp_core_pre_delete_existing_avatar', 'vipbp_delete_existing_avatar', 10, 2 );

The function receives an $args array containing:

ParameterTypeDescriptionDefault Handling
item_idintID of user or groupFalls back to bp_displayed_user_id() or current group
objectstringObject type: 'user', 'group', 'blog'Used to determine metadata location
avatar_dirstringSubdirectory: 'avatars', 'group-avatars', etc.Auto-detected from object type

Sources: files.php761-786

Metadata Deletion by Object Type

The function handles three distinct metadata storage locations:


Sources: files.php809-822

Default Group Avatar Handling

The plugin implements special handling for the default group avatar (when item_id is 0). This avatar is stored in WordPress options rather than group metadata to avoid associating it with a specific group:

if ( 0 === (int) $args['item_id'] ) {
 $meta = bp_get_option( 'vipbp-default-group-avatar', array() );
 bp_delete_option( 'vipbp-default-group-avatar' );
} else {
 $meta = groups_get_groupmeta( (int) $args['item_id'], 'vipbp-' . $args['avatar_dir'], true );
 groups_delete_groupmeta( (int) $args['item_id'], 'vipbp-' . $args['avatar_dir'] );
}

Sources: files.php814-821

Cover Image Deletion Process

Function Signature and Arguments

The vipbp_delete_cover_image() function is registered on the bp_attachments_pre_delete_file filter:

add_filter( 'bp_attachments_pre_delete_file', 'vipbp_delete_cover_image', 10, 2 );

The $args array contains:

ParameterTypeDescription
object_dirstringObject directory: 'members' or 'groups'
item_idintID of user or group
typestringAttachment type (typically 'cover-image')
filestringFilename (unused in this implementation)

Sources: files.php847-855

Metadata Keys by Object Type

Cover image deletion uses simpler metadata keys than avatars, storing only the URL:


Sources: files.php856-873

URL Processing for File Deletion

Before calling wp_delete_file(), both deletion functions perform identical URL cleanup operations to convert the stored metadata URL into a format acceptable to VIP's file deletion API:


The cleanup process:

  1. Remove query parameters: Uses strtok($meta['url'], '?') to strip Photon-like parameters added during display
  2. Remove site URL prefix: Uses str_replace(get_site_url() . '/', '', $url) to convert absolute URL to relative path
  3. Pass to wp_delete_file(): The cleaned relative path is passed to WordPress's file deletion function

Sources: files.php825-826 files.php866-867

Complete Deletion Sequence Diagram

The following diagram shows the complete flow for deleting a user avatar, including all function calls and database operations:


Sources: files.php761-836

Metadata Keys Reference

The following table documents all metadata keys used during deletion operations:

Metadata KeyStorage LocationObject TypeContentUsed By
vipbp-avatarsUser MetaUserCrop coordinates, URL, ui_widthUser avatar deletion
vipbp-group-avatarsGroup MetaGroupCrop coordinates, URL, ui_widthGroup avatar deletion
vipbp-default-group-avatarOptionsDefault Group (id=0)Crop coordinates, URL, ui_widthDefault group avatar deletion
vipbp-user-coverUser MetaUserURL onlyUser cover image deletion
vipbp-group-coverGroup MetaGroupURL onlyGroup cover image deletion

Sources: files.php810 files.php819-820 files.php816-817 files.php857 files.php861

Multisite Blog Switching Pattern

Both deletion functions implement identical multisite handling to ensure operations occur on the root blog where BuddyPress stores all data:

$switched = false;

if ( ! bp_is_root_blog() ) {
 switch_to_blog( bp_get_root_blog_id() );
 $switched = true;
}

// ... perform deletion operations ...

if ( $switched ) {
 restore_current_blog();
}

This pattern is critical for multisite installations because:

  • BuddyPress stores all user and group data on the root blog
  • Metadata operations must occur in the correct blog context
  • The blog context must be restored after operations complete to avoid side effects

Sources: files.php763-768 files.php831-833 files.php849-854 files.php870-872

Action Hook Integration

After successfully deleting an avatar file, the plugin fires the BuddyPress action hook to maintain compatibility with other plugins:

do_action( 'bp_core_delete_existing_avatar', $args );

This hook is only fired when metadata exists and the file deletion completes. Plugins that listen to this hook can perform cleanup operations or logging when avatars are deleted.

Sources: files.php828

Error Handling and Edge Cases

Missing Item ID

If $args['item_id'] is empty, the function attempts to determine it from the current context:

if ( 'user' === $args['object'] ) {
 $args['item_id'] = bp_displayed_user_id();
} elseif ( 'group' === $args['object'] ) {
 $args['item_id'] = buddypress()->groups->current_group->id;
}

$args['item_id'] = apply_filters( 'bp_core_avatar_item_id', $args['item_id'], $args['object'] );

If no valid item ID can be determined after filtering, the function returns false without performing any operations.

Sources: files.php770-785

Missing Avatar Directory

If $args['avatar_dir'] is empty, the function determines the appropriate directory based on object type:

if ( 'user' === $args['object'] ) {
 $args['avatar_dir'] = 'avatars';
} elseif ( 'group' === $args['object'] ) {
 $args['avatar_dir'] = 'group-avatars';
} elseif ( 'blog' === $args['object'] ) {
 $args['avatar_dir'] = 'blog-avatars';
}

$args['avatar_dir'] = apply_filters( 'bp_core_avatar_dir', $args['avatar_dir'], $args['object'] );

If no valid directory can be determined after filtering, the function returns false.

Sources: files.php788-805

No Metadata Exists

If the metadata retrieval returns empty (no avatar was ever uploaded), the deletion functions skip the wp_delete_file() call and return immediately:

if ( $meta ) {
 $meta['url'] = str_replace( get_site_url() . '/', '', strtok( $meta['url'], '?' ) );
 wp_delete_file( $meta['url'] );
 
 do_action( 'bp_core_delete_existing_avatar', $args );
}

This prevents unnecessary file system operations and ensures the bp_core_delete_existing_avatar action is only fired when actual deletions occur.

Sources: files.php824-829 files.php865-868