[buddypress-trac] [BuddyPress Trac] #9329: Enhancement Request: Add filter hook to `bp_email_get_type_schema()`

buddypress-trac noreply at wordpress.org
Sun Feb 8 11:58:37 UTC 2026


#9329: Enhancement Request: Add filter hook to `bp_email_get_type_schema()`
-------------------------+-----------------------------
 Reporter:  indigetal    |      Owner:  (none)
     Type:  enhancement  |     Status:  new
 Priority:  normal       |  Milestone:  Awaiting Review
Component:  Emails       |    Version:
 Severity:  normal       |   Keywords:
-------------------------+-----------------------------
 == The Gap

 BuddyPress's email system has two schema functions that work in tandem:

 1. `bp_email_get_schema()` — returns email content (subject, HTML body,
 plain text). '''Has a filter:''' `bp_email_get_schema` (applied at line
 4109 of `bp-core-functions.php`). Plugins CAN extend this.
 2. `bp_email_get_type_schema( $field )` — returns email type metadata
 (description, `named_salutation`, unsubscribe config). '''No filter.'''
 Returns a hardcoded `$types` array directly (lines 4310–4518 of `bp-core-
 functions.php`).

 The content schema is filterable; the type schema is not. This creates a
 gap: plugins can register new email types into the content schema, but
 cannot register the corresponding type metadata.

 The install function `bp_core_install_emails()` in `bp-core-admin-
 schema.php` (lines 504–544) consumes both:

 {{{#!php
 $emails       = bp_email_get_schema();                      // ← filtered,
 plugin types included
 $descriptions = bp_email_get_type_schema( 'description' );  // ← NOT
 filtered, plugin types missing
 }}}

 Then for each email it sets the taxonomy term description from
 `$descriptions[$id]` (line 540). For plugin-registered email types,
 `$descriptions[$id]` is undefined — the email post IS created (because the
 content schema filter works), but the taxonomy term description is empty.

 The only filtered code path that touches type schema data is
 `bp_email_get_unsubscribe_type_schema()` (lines 4718–4730), which filters
 the return of `bp_email_get_type_schema('all')` via the
 `bp_email_get_unsubscribe_type_schema` hook. However, this filter is NOT
 consumed by `bp_core_install_emails()` — it's only used by the unsubscribe
 handler.

 This means:

 1. **Inconsistent schema extensibility** — `bp_email_get_schema()` is
 filterable, `bp_email_get_type_schema()` is not. Plugin developers who
 follow the documented pattern of filtering `bp_email_get_schema` to
 register custom emails find that their type metadata has no equivalent
 entry point.
 2. **Empty term descriptions after "Reinstall Emails"** — Email posts are
 created successfully, but their taxonomy term descriptions are blank
 because `$descriptions[$id]` is undefined for plugin types.
 3. **Incomplete enumeration** — Any admin UI or utility code that calls
 `bp_email_get_type_schema('description')` or
 `bp_email_get_type_schema('all')` directly will miss plugin-registered
 types entirely.

 == Proposed Change

 Add `apply_filters( 'bp_email_get_type_schema', $types )` before the
 return in `bp_email_get_type_schema()`, matching the pattern established
 by `bp_email_get_schema()`.

 In `bp-core-functions.php`, before the field check at line 4513:

 {{{#!php
 /**
  * Filters the email type schema, allowing anyone to add/update email type
 metadata.
  *
  * @since {next_version}
  *
  * @param array $types The array of email type metadata.
  */
 $types = apply_filters( 'bp_email_get_type_schema', $types );

 if ( $field !== 'all' ) {
     return wp_list_pluck( $types, $field );
 } else {
     return $types;
 }
 }}}

 == Scope

  * ~1 line of functional code added to one function in `bp-core-
 functions.php`
  * Zero behavioral change — the filter passes through existing values by
 default
  * Brings `bp_email_get_type_schema()` into parity with
 `bp_email_get_schema()`
  * The existing `bp_email_get_unsubscribe_type_schema` filter continues to
 work as-is
 [[br]]
 == What This Enables for Addons

 With this hook, addon plugins can register their custom email type
 metadata (description, `named_salutation`, unsubscribe config) alongside
 their email content schema. This means:

  * '''Complete email registration''' — Plugins that filter
 `bp_email_get_schema` to add email content can also filter
 `bp_email_get_type_schema` to add the corresponding metadata, keeping both
 schemas in sync.
  * '''Correct "Reinstall Emails" behavior''' — `bp_core_install_emails()`
 will pick up plugin type descriptions, so taxonomy terms are populated
 correctly.
  * '''Full enumeration support''' — Admin tools, settings pages, or any
 code that calls `bp_email_get_type_schema()` will include plugin-
 registered types.

 == Prior Art

 BuddyBoss Platform independently added exactly this filter to their fork.
 In `bp-core-functions.php` (line 4047 in BuddyBoss 2.19.0):

 {{{#!php
 /**
  * Filters Email type schema
  *
  * @param array $types Types array.
  *
  * @since BuddyBoss 1.5.4
  */
 $types = apply_filters( 'bp_email_get_type_schema', $types );
 }}}

 Their notification abstract class (`BP_Core_Notification_Abstract`) hooks
 both schema filters at priority 999 in its `start()` method:

 {{{#!php
 add_filter( 'bp_email_get_schema', array( $this, 'email_schema' ), 999 );
 add_filter( 'bp_email_get_type_schema', array( $this, 'email_type_schema'
 ), 999 );
 }}}

 The fact that BuddyBoss independently arrived at the same 1-line solution
 (and has shipped it since version 1.5.4) validates the need. If this
 filter had existed in BuddyPress core, plugins could register complete
 email type metadata without relying on platform-specific workarounds.

 I'm happy to submit a patch for this change.

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


More information about the buddypress-trac mailing list