Skip to:
Content
Pages
Categories
Search
Top
Bottom

Add `privacy` column to `bp_activity` for per-item visibility control

  • @indigetal

    Participant

    BuddyPress activities have a single visibility control: hide_sitewide (0 or 1). This provides binary visibility — shown everywhere, or hidden from sitewide feeds. There’s no way to express:

    – **”Only me”** — private activity visible only to the author
    – **”Friends only”** — visible only to the author’s friends
    – **”Logged-in users”** — hidden from anonymous visitors
    – **”Group members only”** — visible only within the group context where it was posted

    Per-item privacy is a foundational social platform feature. Facebook has had it since 2009. LinkedIn, Twitter/X (with protected tweets), Instagram, and every major social network support some form of per-post audience control. It’s as fundamental to a social platform as hide_sitewide is — just multi-valued instead of binary.

    This is not a request for any specific addon’s needs. It’s a request for the same kind of infrastructure that hide_sitewide provides — a first-class column that any addon can use to implement privacy-aware features.

    #### Current State

    BuddyPress 14.4.0’s activity query system is well-designed for extensibility:

    bp_activity_get_where_conditions lets addons inject WHERE clauses
    bp_activity_get_join_sql lets addons add JOINs
    – Data hydration uses SELECT * (in populate() and the cache-miss path of get()), so any column added to the table is automatically returned to calling code
    bp_activity_before_save / bp_activity_after_save provide save-time hooks

    An addon **can** add a privacy column via dbDelta and filter queries via bp_activity_get_where_conditions. However, the save() method has a hardcoded column list in its INSERT/UPDATE SQL (in BP_Activity_Activity::save()), meaning an addon must do a separate $wpdb->update() after every save — a double-write on every activity creation. This works but is suboptimal, and the column’s general-purpose nature (used by media addons, document addons, moderation addons, group addons — not just one feature) argues for core inclusion.

    #### Proposed Change

    **Schema:** Add one column + index to bp_activity in bp_core_install_activity_streams() (in bp-core-admin-schema.php). dbDelta() handles adding the column on upgrade automatically:

    sql

    
    -- Added after the existing <code>is_spam</code> column in the CREATE TABLE definition:
    privacy varchar(75) NOT NULL DEFAULT 'public',
    -- Added to the KEY list:
    KEY privacy (privacy)
    

    **Model class (BP_Activity_Activity):**

    1. Add public $privacy = 'public'; property
    2. In save() — add privacy to the INSERT/UPDATE column list alongside the existing columns (user_id, component, type, action, content, etc.)
    3. In get() — add 'privacy' to the $r defaults (default false, meaning no filtering). When set, add AND a.privacy IN (...) to the WHERE conditions.

    **REST API (BP_REST_Activity_Endpoint):**

    4. In prepare_item_for_response() — expose privacy in the response object (paralleling how hide_sitewide is currently exposed as hidden)
    5. In prepare_item_for_database() — accept privacy as a writable field on create/update

    **Migration:** dbDelta() runs on every upgrade via bp_core_install(), so modifying the CREATE TABLE definition is sufficient for the schema change. A DB version bump in bp-core-update.php tracks the upgrade.

    #### Scope

    – ~40 lines of changes across 4 files (bp-core-admin-schema.php, class-bp-activity-activity.php, class-bp-rest-activity-endpoint.php, bp-core-update.php)
    – Default value 'public' — 100% backward compatible
    – Existing queries that don’t pass privacy return all activities as before
    hide_sitewide continues to work as-is (orthogonal — hide_sitewide controls directory listing, privacy controls per-item access)

    #### What Core Provides vs. What Addons Handle

    To be explicit about scope: this proposal adds **storage and query filtering only**. Core would:

    – Store the privacy value on each activity row
    – Allow get() callers to filter by privacy value(s)
    – Expose/accept the field through the REST API

    Core would **not** need to:

    – Define a fixed set of allowed values (addons register the values they need — e.g., 'onlyme', 'friends', 'loggedin')
    – Enforce access control based on privacy values (addons hook into bp_activity_get_where_conditions to inject viewer-aware WHERE clauses, exactly as they would today for any custom filtering)
    – Provide UI for selecting privacy (addon/theme territory)

    This mirrors how hide_sitewide works today — core stores the flag and filters on it; the decision of *when* to set it is made by callers (groups component, plugins, etc.).

    #### Prior Art

    BuddyBoss Platform (a BuddyPress-derived platform) implemented this exact column. Their bp_activity schema includes privacy varchar(75) NOT NULL DEFAULT 'public', and their media, document, video, and moderation subsystems all depend on it for privacy filtering. The column is referenced in their activity save/query paths, REST API, and template layer — making it one of the most cross-cutting additions they made to the activity table. The fact that an independent platform needed this to build standard social features demonstrates both the demand and the general-purpose nature of the column.

    I’m happy to submit a PR for this change.

Viewing 2 replies - 1 through 2 (of 2 total)
  • @emaralive

    Moderator

    You should submit a ticket with the type set to “enhancement”, with the details you have expressed here, such that your proposal can be considered and dispatched accordingly.

    Afterwards, if you decide to submit a PR, the ticket can be referenced which will attach the PR to the ticket.

    @emaralive

    Moderator

    For reference, see Trac ticket #9327.

Viewing 2 replies - 1 through 2 (of 2 total)
  • You must be logged in to reply to this topic.
Skip to toolbar