Architecture Overview
BuddyPress Moderation Pro overviewPremiumGet BuddyPress Moderation Pro →
Understanding the internal structure and design of BuddyPress Moderation Pro.
What You’ll Learn
Section titled “What You’ll Learn”- Plugin file structure and organization
- Core class responsibilities
- Data flow for moderation actions
- Database schema design
- Hook system architecture
- Performance optimizations
Directory Structure
Section titled “Directory Structure”buddypress-moderation-pro/├── buddypress-moderation-pro.php # Main plugin bootstrap├── includes/ # Core functionality│ ├── class-buddypress-moderation-pro.php│ ├── class-buddypress-moderation-pro-loader.php│ ├── class-buddypress-moderation-pro-i18n.php│ ├── class-buddypress-moderation-pro-activator.php│ ├── class-buddypress-moderation-pro-upgrader.php│ ├── class-bmpro-cli.php│ └── buddypress-moderation-pro-functions.php├── admin/ # Admin functionality│ ├── class-buddypress-moderation-pro-admin.php│ ├── class-buddypress-moderation-pro-cleanup.php│ ├── class-buddypress-moderation-pro-bbpress.php│ ├── inc/ # Settings tabs│ │ ├── bmpro-welcome-setting-tab.php│ │ ├── bmpro-general-setting-tab.php│ │ ├── bmpro-restrictions-setting-tab.php│ │ └── ...│ ├── css/│ └── js/├── public/ # Frontend functionality│ ├── class-buddypress-moderation-pro-public.php│ ├── class-buddypress-activity-moderation.php│ ├── class-buddypress-comments-moderation.php│ ├── class-buddypress-members-moderation.php│ ├── class-buddypress-groups-moderation.php│ ├── class-buddypress-messages-moderation.php│ ├── class-buddypress-topics-moderation.php│ ├── class-buddypress-replies-moderation.php│ ├── class-buddypress-avatar-moderation.php│ ├── class-buddypress-moderation-pro-email-notifications.php│ ├── class-buddypress-moderation-pro-bp-notifications.php│ ├── css/│ └── js/├── templates/ # Overridable templates│ ├── bmpo-bp-moderations.php│ ├── blocking.php│ └── blocked.php├── languages/ # Translations└── docs/ # Documentation ├── user/ └── developer/Core Classes
Section titled “Core Classes”Class Diagram
Section titled “Class Diagram”┌─────────────────────────────────────────────────────────────────┐│ Buddypress_Moderation_Pro ││ (Main Orchestrator) │└────────────────────────────┬────────────────────────────────────┘ │ ▼┌─────────────────────────────────────────────────────────────────┐│ Buddypress_Moderation_Pro_Loader ││ (Hook Registration) │└────────────────────────────┬────────────────────────────────────┘ │ ┌─────────────────┼─────────────────┐ ▼ ▼ ▼┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐│ Admin │ │ Public │ │ i18n ││ (Admin Panel) │ │ (Frontend UI) │ │ (Translations) │└────────┬─────────┘ └────────┬─────────┘ └──────────────────┘ │ │ ▼ ▼┌──────────────────┐ ┌────────────────────────────────────────┐│ - Settings │ │ Content Type Handlers: ││ - Meta Boxes │ │ - Activity Moderation ││ - Cleanup │ │ - Comments Moderation ││ - Post Types │ │ - Members Moderation │└──────────────────┘ │ - Groups Moderation │ │ - Messages Moderation │ │ - Topics/Replies Moderation │ │ - Avatar Moderation │ └────────────────────────────────────────┘Buddypress_Moderation_Pro
Section titled “Buddypress_Moderation_Pro”File: includes/class-buddypress-moderation-pro.php
The main plugin class that orchestrates all functionality.
Responsibilities:
- Define plugin constants
- Load dependencies
- Set locale for i18n
- Initialize admin and public hooks
- Run the loader
class Buddypress_Moderation_Pro {
protected $loader; protected $plugin_name; protected $version;
public function __construct() { $this->plugin_name = 'buddypress-moderation-pro'; $this->version = BMPRO_PLUGIN_VERSION;
$this->load_dependencies(); $this->set_locale(); $this->define_admin_hooks(); $this->define_public_hooks(); }
public function run() { $this->loader->run(); }}Buddypress_Moderation_Pro_Loader
Section titled “Buddypress_Moderation_Pro_Loader”File: includes/class-buddypress-moderation-pro-loader.php
Centralized hook registration system.
Responsibilities:
- Queue action hooks
- Queue filter hooks
- Execute all registered hooks
class Buddypress_Moderation_Pro_Loader {
protected $actions = array(); protected $filters = array();
public function add_action( $hook, $component, $callback, $priority = 10, $args = 1 ) { $this->actions[] = compact( 'hook', 'component', 'callback', 'priority', 'args' ); }
public function add_filter( $hook, $component, $callback, $priority = 10, $args = 1 ) { $this->filters[] = compact( 'hook', 'component', 'callback', 'priority', 'args' ); }
public function run() { foreach ( $this->filters as $hook ) { add_filter( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['args'] ); }
foreach ( $this->actions as $hook ) { add_action( $hook['hook'], array( $hook['component'], $hook['callback'] ), $hook['priority'], $hook['args'] ); } }}Content Type Handlers
Section titled “Content Type Handlers”Each content type has a dedicated handler class:
| Class | File | Purpose |
|---|---|---|
Buddypress_Moderation_Pro_Activity_Moderation |
public/class-buddypress-activity-moderation.php |
Activity stream moderation |
Buddypress_Moderation_Pro_Comments |
public/class-buddypress-comments-moderation.php |
Activity comments |
Buddypress_Moderation_Pro_Members |
public/class-buddypress-members-moderation.php |
Member profiles |
Buddypress_Moderation_Pro_Groups |
public/class-buddypress-groups-moderation.php |
BuddyPress groups |
Buddypress_Moderation_Pro_Messages |
public/class-buddypress-messages-moderation.php |
Private messages |
Buddypress_Moderation_Pro_Topics |
public/class-buddypress-topics-moderation.php |
bbPress topics |
Buddypress_Moderation_Pro_Replies |
public/class-buddypress-replies-moderation.php |
bbPress replies |
Buddypress_Moderation_Pro_Avatar |
public/class-buddypress-avatar-moderation.php |
Profile/group avatars |
Common Handler Pattern:
class Content_Handler {
public function __construct() { // Register hooks }
// Show flag button in UI public function show_flag_button() { }
// AJAX: Show report modal public function ajax_show_report_modal() { }
// AJAX: Process flag submission public function ajax_flag_content() { }
// AJAX: Process unflag public function ajax_unflag_content() { }
// Filter: Hide flagged content public function filter_content_visibility() { }
// Check auto-moderation threshold public function check_auto_moderation() { }}Data Flow
Section titled “Data Flow”Report Submission Flow
Section titled “Report Submission Flow”User Clicks Flag Button │ ▼┌─────────────────────┐│ JavaScript Event ││ (Modal Opens) │└──────────┬──────────┘ │ ▼┌─────────────────────┐│ User Fills Form ││ (Reason + Details) │└──────────┬──────────┘ │ ▼┌─────────────────────┐│ AJAX Request ││ (with nonce) │└──────────┬──────────┘ │ ▼┌─────────────────────┐│ PHP Handler ││ - Verify nonce ││ - Validate input ││ - Check permissions│└──────────┬──────────┘ │ ▼┌─────────────────────┐│ Create Report Post ││ (bmpro_spam) │└──────────┬──────────┘ │ ▼┌─────────────────────┐│ Update Meta Data ││ - Reporter list ││ - Content meta ││ - User meta │└──────────┬──────────┘ │ ▼┌─────────────────────┐│ Fire Action Hook ││ (bpmp_*_flagged) │└──────────┬──────────┘ │ ┌─────┴─────┐ ▼ ▼┌─────────┐ ┌─────────────┐│ Email │ │ BP ││ Notify │ │ Notification│└─────────┘ └─────────────┘ │ ▼┌─────────────────────┐│ Check Auto-Mod ││ Threshold │└──────────┬──────────┘ │ ┌─────┴─────┐ ▼ ▼ Threshold Under Met Threshold │ │ ▼ ▼┌─────────┐ ┌─────────┐│ Hide │ │ Keep ││ Content │ │ Visible │└─────────┘ └─────────┘Content Visibility Flow
Section titled “Content Visibility Flow”Content Query Requested │ ▼┌─────────────────────┐│ Filter Hook Fires ││ (bp_ajax_querystring││ or similar) │└──────────┬──────────┘ │ ▼┌─────────────────────┐│ Get Excluded IDs ││ bmpro_exclude_ ││ moderated_content()│└──────────┬──────────┘ │ ▼┌─────────────────────┐│ Check User Context ││ - Is admin? ││ - Is reporter? ││ - Is content owner?│└──────────┬──────────┘ │ ┌─────┴─────────────────┐ ▼ ▼ Show to Hide Admin/Reporter from User │ │ ▼ ▼┌─────────────────┐ ┌─────────────────┐│ Return Content │ │ Filter Out IDs ││ with Flag │ │ from Query │└─────────────────┘ └─────────────────┘Database Schema
Section titled “Database Schema”Custom Post Types
Section titled “Custom Post Types”bmpro_spam (Report Log)
Section titled “bmpro_spam (Report Log)”-- Uses wp_posts tablepost_type = 'bmpro_spam'
-- Post structureID bigint(20) -- Report IDpost_author bigint(20) -- Reporter user IDpost_title text -- Report titlepost_status varchar(20) -- 'publish'post_date datetime -- Report creation timeMeta Keys:
| Key | Type | Description |
|---|---|---|
bmpro_spam_activity_id |
int | Original content ID |
bmpro_spam_reported_by |
array | Reporter user IDs |
bmpro_spam_status |
string | ‘awaiting_moderation’ / ‘spam’ |
bmpro_hide_mode |
string | ‘reporters’ / ‘all_users’ |
bmpro_member_actions |
array | Actions taken on member |
bmpro_groups_actions |
array | Actions taken on group |
bmpro_lock_member_account |
string | ‘yes’ if locked |
bmpro_avatar_spam (Avatar Moderation)
Section titled “bmpro_avatar_spam (Avatar Moderation)”-- Uses wp_posts tablepost_type = 'bmpro_avatar_spam'Meta Keys:
| Key | Type | Description |
|---|---|---|
_bp_user_id |
int | User ID for profile avatars |
_bp_group_id |
int | Group ID for group avatars |
_bp_user_avatar_flag |
int | 0=pending, 1=approved, 2=rejected |
_bp_group_avatar_flag |
int | 0=pending, 1=approved, 2=rejected |
_bp_is_group_avatar |
bool | True for group avatars |
Taxonomy
Section titled “Taxonomy”-- bmpro_content_type taxonomy-- Terms: activity_update, activity_comment, member, group,-- message, topic, reply, group_avatar, user_avatarUser Meta
Section titled “User Meta”| Key | Description |
|---|---|
bmpro_flagged_activities |
Array tracking user’s flagging activity |
bmpro_member_punish |
Punishment status |
bmpro_flagged_member_meta |
Reporter info |
Content Meta
Section titled “Content Meta”| Location | Key | Description |
|---|---|---|
| Activity | bmpro_flagged_activity_meta |
Reporter list |
| Activity | _bp_moderation |
Auto-moderated flag |
| Comment | bmpro_flagged_comment_meta |
Reporter list |
| Message | bmpro_flagged_message_meta |
Reporter list |
| Group | bmpro_flagged_group_meta |
Reporter list |
| Topic | bmpro_flagged_topic_meta |
Reporter list |
| Reply | bmpro_flagged_reply_meta |
Reporter list |
Hook System
Section titled “Hook System”Action Hook Categories
Section titled “Action Hook Categories”┌──────────────────────────────────────────────────────────────┐│ REPORTING HOOKS │├──────────────────────────────────────────────────────────────┤│ bpmp_members_flagged │ When member reported ││ bpmp_activity_flagged │ When activity reported ││ bpmp_activity_comment_flagged │ When comment reported ││ bpmp_groups_flagged │ When group reported ││ bpmp_message_flagged │ When message reported ││ bpmp_topic_flagged │ When topic reported ││ bpmp_reply_flagged │ When reply reported ││ bpmp_avatar_flagged │ When avatar uploaded │└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐│ MODERATION HOOKS │├──────────────────────────────────────────────────────────────┤│ bmpro_member_suspended │ When member suspended ││ bmpro_member_unsuspended │ When suspension lifted ││ bmpro_user_blocked │ When user blocks another ││ bmpro_user_unblocked │ When user unblocks │└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐│ CLEANUP HOOKS │├──────────────────────────────────────────────────────────────┤│ bmpro_spam_cleanup_filter_function │ When content cleaned │└──────────────────────────────────────────────────────────────┘Filter Hook Categories
Section titled “Filter Hook Categories”┌──────────────────────────────────────────────────────────────┐│ CONTENT FILTERS │├──────────────────────────────────────────────────────────────┤│ bmpro_content_to_flag │ Content types array ││ bmpro_exclude_moderated_content │ Hide content check ││ bmpro_spam_statuses_types │ Status options │└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐│ SETTINGS FILTERS │├──────────────────────────────────────────────────────────────┤│ bmpro_auto_mod_limit_filter │ Threshold number ││ bmpro_auto_moderation_enable │ Auto-mod toggle ││ bmpro_get_moderation_mode_filter │ Visibility mode ││ bmpro_get_flag_unflag_text │ Button text │└──────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────┐│ PERMISSION FILTERS │├──────────────────────────────────────────────────────────────┤│ bmpro_user_can_report │ Report permission ││ bpmp_moderator_users │ Moderator list ││ bmpro_allow_activity_update_user_roles │ Update roles │└──────────────────────────────────────────────────────────────┘Performance Optimizations
Section titled “Performance Optimizations”Caching Strategy
Section titled “Caching Strategy”// Spam data preloading for activity loopsfunction bmpro_preload_spam_data( $activity_ids ) { global $wpdb;
// Single query for all activities $ids_string = implode( ',', array_map( 'intval', $activity_ids ) );
$results = $wpdb->get_results( $wpdb->prepare( "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = 'bmpro_spam_activity_id' AND meta_value IN ($ids_string)" ) );
// Cache results foreach ( $results as $row ) { wp_cache_set( 'bmpro_spam_' . $row->meta_value, $row->post_id, 'bmpro' ); }}
// Individual lookup uses cachefunction bmpro_get_spam_post_id( $activity_id ) { $cached = wp_cache_get( 'bmpro_spam_' . $activity_id, 'bmpro' );
if ( $cached !== false ) { return $cached; }
// Fallback to database query // ...}Query Optimization
Section titled “Query Optimization”// Efficient excluded content queryfunction get_excluded_content_ids( $content_type ) { $cache_key = 'bmpro_excluded_' . $content_type; $excluded = wp_cache_get( $cache_key, 'bmpro' );
if ( $excluded === false ) { global $wpdb;
$excluded = $wpdb->get_col( $wpdb->prepare( "SELECT pm.meta_value FROM {$wpdb->posts} p INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id INNER JOIN {$wpdb->term_relationships} tr ON p.ID = tr.object_id INNER JOIN {$wpdb->term_taxonomy} tt ON tr.term_taxonomy_id = tt.term_taxonomy_id INNER JOIN {$wpdb->terms} t ON tt.term_id = t.term_id WHERE p.post_type = 'bmpro_spam' AND pm.meta_key = 'bmpro_spam_activity_id' AND t.slug = %s AND p.post_status = 'publish'", $content_type ) );
wp_cache_set( $cache_key, $excluded, 'bmpro', HOUR_IN_SECONDS ); }
return $excluded;}Asset Loading
Section titled “Asset Loading”// Only load assets on relevant pagesfunction bmpro_get_is_relevant_buddypress_page() { if ( ! function_exists( 'bp_is_active' ) ) { return false; }
// Check specific BuddyPress pages return bp_is_activity_component() || bp_is_members_component() || bp_is_groups_component() || bp_is_messages_component() || ( function_exists( 'bbp_is_forum' ) && bbp_is_forum() );}
// Conditional enqueueif ( bmpro_get_is_relevant_buddypress_page() ) { wp_enqueue_script( 'bmpro-public' ); wp_enqueue_style( 'bmpro-public' );}Security Architecture
Section titled “Security Architecture”Input Validation
Section titled “Input Validation”// All AJAX handlers follow this patternpublic function ajax_flag_content() { // 1. Verify nonce check_ajax_referer( 'bmpro_ajax_nonce', 'nonce' );
// 2. Verify user is logged in if ( ! is_user_logged_in() ) { wp_send_json_error( 'Not authenticated' ); }
// 3. Verify permissions if ( ! bmpro_user_can_report() ) { wp_send_json_error( 'Not authorized' ); }
// 4. Sanitize input $content_id = absint( $_POST['content_id'] ); $reason = sanitize_text_field( $_POST['reason'] ); $details = sanitize_textarea_field( $_POST['details'] );
// 5. Validate content exists if ( ! $this->content_exists( $content_id ) ) { wp_send_json_error( 'Content not found' ); }
// 6. Process request // ...}Output Escaping
Section titled “Output Escaping”// All output is escapedecho esc_html( $report_reason );echo esc_attr( $content_id );echo esc_url( $profile_url );echo wp_kses_post( $report_details );Capability Checks
Section titled “Capability Checks”// Admin operations require proper capabilitiesif ( ! current_user_can( 'edit_post', $spam_post_id ) ) { wp_die( 'Not authorized' );}
// Moderator role has specific capabilities$caps = array( 'edit_bmpro_spam', 'delete_bmpro_spam', 'read_bmpro_spam', 'bp_moderate',);Extensibility Points
Section titled “Extensibility Points”Adding Custom Content Types
Section titled “Adding Custom Content Types”- Register content type via filter
- Create AJAX handlers for flag/unflag
- Add admin meta box for moderation
- Implement cleanup handler
Adding Custom Actions
Section titled “Adding Custom Actions”- Add action via filter hook
- Implement action handler
- Add UI in admin meta box
Adding Custom Notifications
Section titled “Adding Custom Notifications”- Hook into reporting actions
- Use
bp_notifications_add_notification() - Register notification component
Version Upgrade System
Section titled “Version Upgrade System”class Buddypress_Moderation_Pro_Upgrader {
public function __construct() { add_action( 'admin_init', array( $this, 'check_version' ) ); }
public function check_version() { $current = get_option( 'bmpro_version', '0' );
if ( version_compare( $current, BMPRO_PLUGIN_VERSION, '<' ) ) { $this->upgrade( $current ); update_option( 'bmpro_version', BMPRO_PLUGIN_VERSION ); } }
private function upgrade( $from_version ) { if ( version_compare( $from_version, '3.0', '<' ) ) { $this->upgrade_to_3_0(); }
if ( version_compare( $from_version, '4.0', '<' ) ) { $this->upgrade_to_4_0(); } }}WP-CLI Integration
Section titled “WP-CLI Integration”class BMPRO_CLI extends WP_CLI_Command {
/** * Get moderation status * * ## EXAMPLES * wp bmpro status */ public function status() { // Implementation }
/** * Report a member * * ## OPTIONS * <member_id> * [--reason=<reason>] * [--reporter=<reporter_id>] */ public function report( $args, $assoc_args ) { // Implementation }}
// Register commandif ( class_exists( 'WP_CLI' ) ) { WP_CLI::add_command( 'bmpro', 'BMPRO_CLI' );}Testing Guidelines
Section titled “Testing Guidelines”Unit Test Structure
Section titled “Unit Test Structure”tests/├── bootstrap.php├── test-functions.php├── test-activity-moderation.php├── test-member-moderation.php├── test-auto-moderation.php└── test-permissions.phpExample Test
Section titled “Example Test”class Test_Activity_Moderation extends WP_UnitTestCase {
public function test_flag_activity() { // Setup $user_id = $this->factory->user->create(); $activity_id = bp_activity_add( array( 'user_id' => $user_id, 'content' => 'Test activity', ) );
// Act $result = $this->flag_activity( $activity_id, $user_id );
// Assert $this->assertTrue( $result ); $this->assertEquals( 1, $this->get_report_count( $activity_id ) ); }}Last Updated: 2025-12-20 Plugin Version: 4.x+
See Also:

