[buddypress-trac] [BuddyPress Trac] #9327: Feature Request: Add `privacy` column to `bp_activity` for per-item visibility control

buddypress-trac noreply at wordpress.org
Thu Feb 5 23:59:14 UTC 2026


#9327: Feature Request: Add `privacy` column to `bp_activity` for per-item
visibility control
-------------------------+-----------------------------
 Reporter:  indigetal    |      Owner:  (none)
     Type:  enhancement  |     Status:  new
 Priority:  normal       |  Milestone:  Awaiting Review
Component:  Core         |    Version:  14.4.0
 Severity:  normal       |   Keywords:
-------------------------+-----------------------------
 #### The Need

 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 `is_spam` 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.

-- 
Ticket URL: <https://buddypress.trac.wordpress.org/ticket/9327>
BuddyPress Trac <http://buddypress.org/>
BuddyPress Trac


More information about the buddypress-trac mailing list