![]() |
VOOZH | about |
The files.php module is the central integration layer that redirects all BuddyPress media operations from the local filesystem to WordPress VIP Go's file hosting infrastructure. It intercepts 11+ BuddyPress hooks to handle uploads, crops, retrievals, and deletions for avatars, cover images, and videos.
This document covers the hook interception architecture, media operation workflows, and metadata storage patterns implemented in this file. For information about the plugin's initialization and environment detection, see Plugin Initialization and Environment Detection. For details on the metadata schema structure, see Metadata Storage Architecture.
Sources: files.php1-902
The files.php module registers hooks at three distinct phases to ensure proper integration with BuddyPress:
bp_init action): Register primary interception filtersTwo filters are registered at file load time (before bp_init) to prevent BuddyPress from accessing the filesystem:
| Filter Hook | Handler | Purpose | Line |
|---|---|---|---|
bp_disable_avatar_history | __return_true | Disables BP 10.0+ avatar history feature that requires directory listing | 12 |
bp_core_avatar_folder_dir | __return_empty_string | Returns empty string to prevent bp_core_fetch_avatar() from scanning filesystem | 16 |
The bp_core_avatar_folder_dir filter is particularly critical—it runs during bp_setup_title() at bp_init priority 8, so it must be registered earlier to prevent filesystem iteration before VIP integration is fully initialized.
Sources: files.php11-16
Avatar uploads follow a two-stage process: (1) upload to VIP storage via WordPress core APIs, and (2) store metadata with crop coordinates for later retrieval.
File Storage: The function uses wp_handle_sideload() instead of wp_handle_upload() (line 357) for consistency with webcam captures and because BuddyPress has already validated the upload upstream. The test_form parameter is set to false to bypass WordPress's form validation.
Image Width Clamping: Lines 378-386 implement logic to prevent upscaling issues when avatars are uploaded from narrow displays (e.g., mobile devices). The ui_width value is stored in metadata and later applied as a w query parameter.
Metadata Structure: The initial metadata stored includes placeholder crop coordinates defaulting to the full image dimensions:
{
'crop_w': bp_core_avatar_full_width(), // e.g., 150
'crop_h': bp_core_avatar_full_height(), // e.g., 150
'crop_x': 0,
'crop_y': 0,
'ui_width': <calculated_width>,
'url': <vip_file_url>
}
Default Group Avatar Handling: When object_id is 0 (lines 420-421), the avatar is stored in wp_options as vipbp-default-group-avatar instead of wp_bp_groups_groupmeta, since there is no group ID 0.
Sources: files.php330-458
Webcam captures follow a similar but memory-optimized workflow using wp_upload_bits() instead of wp_handle_sideload().
Memory Efficiency: Line 489 immediately calls unset($data) after uploading to free the base64-decoded image data from memory, which can be several megabytes for high-resolution captures.
Filename Generation: Webcam captures use a predictable naming pattern: webcam-{item_id}-{random}.png where the random component is a 6-character password generated via wp_generate_password(6, false) (line 485).
Sources: files.php470-539
Cover image uploads handle both user and group covers, with simpler metadata (only storing the URL) since covers use standardized cropping dimensions.
Key Differences from Avatar Upload:
Handler Function: Uses wp_handle_upload() (line 573) instead of wp_handle_sideload(), with action parameter set to 'wp_handle_upload' to ensure VIP file service filters are applied.
Simpler Metadata: Only stores {url} (lines 608-609, 617-618) since cover images don't support custom cropping—they use standardized dimensions from bp_attachments_get_cover_image_dimensions().
Global Reset: Lines 583-589 reset BuddyPress globals that were modified by bp_attachments_cover_image_ajax_upload() upstream, passed via the $needs_reset parameter.
Return Value: Unlike avatar functions that return false to shortcircuit, this returns an array with result, feedback_code, name, and url (lines 631-636).
Sources: files.php556-643
Cropping operations store only coordinate adjustments in metadata—no new physical files are created. Dynamic cropping occurs at image retrieval time via URL parameters.
Validation Logic: Lines 692-697 and 711-716 implement a critical validation: if the metadata lacks a url field (indicating a failed upload), the function returns false without updating crop coordinates. This prevents storing crop data for non-existent images.
Metadata Preservation: The function uses wp_parse_args($cropping_meta, $meta) (lines 699, 718) to merge new crop coordinates with existing metadata, preserving the url and ui_width fields from the original upload.
Sources: files.php673-733
Avatar retrieval generates URLs with Photon-like query parameters that instruct VIP's file service to perform on-demand cropping and resizing.
The vipbp_filter_avatar_urls() helper function (lines 142-250) constructs query parameters that implement dynamic image processing:
| Parameter | Purpose | Example Value | Code Reference |
|---|---|---|---|
w | Clamp image width (prevent upscaling from mobile) | 320, 450 | lines 217, 236-238 |
crop | Crop coordinates in pixels | 10px,20px,150px,150px | lines 220-226 |
resize | Target dimensions for final image | 50,50 (thumb) or 150,150 (full) | line 229 |
strip | Remove EXIF/IPTC metadata | info | line 232 |
Example Generated URL:
https://vip-uploads.example.com/2024/01/avatar.jpg
?w=450
&crop=10px,20px,150px,150px
&resize=150,150
&strip=info
When no metadata exists (line 157), the function generates a standard Gravatar URL (lines 159-207) using:
md5(strtolower($params['email']))$bp->grav_default->{$params['object']} or 'wavatar'$params['width']$params['force_default']$params['rating']For groups/blogs without email, a synthetic email is generated: {item_id}-{object}@{root_domain} (line 171).
Sources: files.php64-83 files.php100-130 files.php142-250
Cover images use a simplified URL generation pattern with standardized cropping dimensions.
Standardized Cropping: Unlike avatars which use user-specified crop coordinates, cover images apply a fixed crop pattern (line 301):
crop=0,25,{width}px,{height}px
This crops from the left edge (0), starting 25% down from the top (25), capturing the full width and height specified by bp_attachments_get_cover_image_dimensions().
No Resize Parameter: Cover images omit the resize parameter since they're displayed at their actual dimensions determined by the theme's cover image settings.
Sources: files.php271-318
Deletion operations follow a two-step pattern: (1) retrieve metadata to get the file URL, (2) delete metadata from database, (3) delete physical file from VIP storage.
URL Cleaning: Line 819 performs two critical transformations before deletion:
strtok($meta['url'], '?') - Removes all query parameters (e.g., ?w=450&crop=...)str_replace(get_site_url() . '/', '', ...) - Converts absolute URL to relative pathThis ensures wp_delete_file() receives a path relative to the uploads directory (e.g., 2024/01/avatar.jpg instead of https://site.com/wp-content/uploads/2024/01/avatar.jpg?w=450).
Sources: files.php755-830
Cover image deletion follows the same pattern as avatar deletion but is simpler since there's no default cover image special case.
Sources: files.php841-869
Video handling includes temporary file cleanup and cache flushing after video moves.
Purpose: BuddyPress's default bp_core_remove_temp_directory() uses PHP's rmdir() which is incompatible with VIP's filesystem abstraction. This override (lines 880-891) uses wp_delete_file() instead, which works with VIP's WP_Filesystem implementation.
Targeted Override: The function only overrides when the specific file exists (line 883), returning false otherwise to allow BuddyPress's default directory cleanup logic to run.
Sources: files.php880-891
Cache Invalidation: When a video is moved to an album, line 900 calls bp_core_reset_incrementor('bp_media') to invalidate BuddyPress's media cache group. This ensures cached media queries reflect the new album association.
Hook Priority: Registered at priority 99 (line 45) to ensure it runs after all other video processing is complete.
Sources: files.php899-901
Every function that accesses metadata implements a consistent blog-switching pattern to ensure operations occur on the root blog in multisite installations.
| Function | Blog Switch Lines | Restore Lines | Metadata Access Type |
|---|---|---|---|
vipbp_filter_user_avatar_urls | 67-70 | 78-80 | Read user meta |
vipbp_filter_group_avatar_urls | 103-106 | 125-127 | Read group meta / options |
vipbp_filter_avatar_urls | 146-149 | 203-205, 245-247 | Read (delegated) |
vipbp_filter_get_cover_image | 276-279 | 313-315 | Read user/group meta |
vipbp_handle_avatar_upload | 333-336 | 453-455 | Write user/group meta |
vipbp_handle_avatar_capture | 478-481 | 534-536 | Write user meta |
vip_handle_cover_image_upload | 559-562 | 638-640 | Write user/group meta |
vipbp_handle_avatar_crop | 683-686 | 728-730 | Update user/group meta |
vipbp_delete_existing_avatar | 759-762 | 825-827 | Delete user/group meta |
vipbp_delete_cover_image | 845-848 | 864-866 | Delete user/group meta |
Rationale: BuddyPress stores all media metadata on the root blog (blog ID 1) in multisite networks, regardless of which subsite triggered the operation. The blog-switching pattern ensures metadata is read from and written to the correct database tables.
Performance Consideration: The switched flag prevents redundant restore_current_blog() calls when already on the root blog, avoiding unnecessary overhead.
Sources: Multiple functions throughout files.php1-902
| Function Name | Hook/Filter | Purpose | Return Value | Lines |
|---|---|---|---|---|
vipbp_filter_user_avatar_urls | bp_core_default_avatar_user | Generate avatar URLs for users | String (URL) | 64-83 |
vipbp_filter_group_avatar_urls | bp_core_default_avatar_group | Generate avatar URLs for groups | String (URL) | 100-130 |
vipbp_filter_avatar_urls | Helper function | Build avatar URLs with Photon params | String (URL) | 142-250 |
vipbp_filter_get_cover_image | bp_attachments_pre_get_attachment | Generate cover image URLs | String (URL) or false | 271-318 |
vipbp_handle_avatar_upload | bp_core_pre_avatar_handle_upload | Upload avatars via wp_handle_sideload | false (shortcircuit) | 330-458 |
vipbp_handle_avatar_capture | bp_avatar_pre_handle_capture | Upload webcam captures via wp_upload_bits | false (shortcircuit) | 470-539 |
vip_handle_cover_image_upload | bp_attachments_pre_cover_image_ajax_upload | Upload cover images via wp_handle_upload | Array {result, message, type} | 556-643 |
vipbp_handle_avatar_crop | bp_core_pre_avatar_handle_crop | Store crop coordinates in metadata | false (shortcircuit) | 673-733 |
vipbp_delete_existing_avatar | bp_core_pre_delete_existing_avatar | Delete avatar files and metadata | false (shortcircuit) | 755-830 |
vipbp_delete_cover_image | bp_attachments_pre_delete_file | Delete cover image files and metadata | false (shortcircuit) | 841-869 |
vipbp_override_remove_temp_directory | bp_core_pre_remove_temp_directory | Use wp_delete_file for temp cleanup | true (override) or false (continue) | 880-891 |
vipbp_flush_cache_after_video_move | bp_video_after_save | Invalidate media cache after video move | void | 899-901 |
Shortcircuit Pattern: Most functions return false to indicate they've handled the operation, preventing BuddyPress from executing its default filesystem-based implementation. This is the standard WordPress pre-filter pattern for overriding default behavior.
Sources: files.php1-902
Refresh this wiki