benecaster_episode_item_output
Unified per-item render filter that fires once per rendered item across all three episode-listing shortcodes: [benecaster_episodes] (once per list item), [benecaster_latest_episode] (once for the featured card), and [benecaster_related_episodes] (once per related item). One callback covers all three surfaces — no need to hook each shortcode separately.
Return an empty string "" to suppress the item entirely (the slot is skipped; the surrounding list does not leave a blank gap). Return any other string to replace the default markup wholesale. Return $html unchanged to pass through.
$is_locked is computed via benecaster_user_can_access_episode() on the Latest and Related surfaces, so third-party access rules registered on benecaster_episode_is_accessible flow through to all three shortcodes automatically. $user_tier is resolved via benecaster_get_user_tier_for_show().
Interaction with the show_locked attribute on [benecaster_episodes]: show_locked="false" fast-paths locked items out of the render loop before this filter fires — locked episodes are skipped entirely and the filter never sees them (attribute wins for the no-code case). show_locked="true" (the default) lets the filter see every item; returning "" from the filter then suppresses selectively (filter wins when both are active together).
Parameters
| Name | Type | Default | Description |
|---|---|---|---|
$html |
string |
— | The fully-rendered default markup for this item or card. |
$episode_id |
int |
— | WordPress post ID of the episode being rendered. |
$show_id |
int |
— | WordPress post ID of the show the episode belongs to. |
$user_tier |
string |
— | The current user's active tier slug for this show, or an empty string when the user has no active subscription. |
$is_locked |
bool |
— | true when the current user cannot access this episode under the active access rules. false when the episode is accessible (free, or the user holds the required tier or higher). |
Returns:
string
Examples
Hide all locked episodes site-wide
add_filter( 'benecaster_episode_item_output', function ( string $html, int $episode_id, int $show_id, string $user_tier, bool $is_locked ): string {
return $is_locked ? '' : $html;
}, 10, 5 );
Replace locked items with a teaser card
add_filter( 'benecaster_episode_item_output', function ( string $html, int $episode_id, int $show_id, string $user_tier, bool $is_locked ): string {
if ( ! $is_locked ) {
return $html;
}
$title = get_the_title( $episode_id );
$excerpt = wp_trim_words( get_the_excerpt( $episode_id ), 20 );
return sprintf(
'<div class="my-episode-teaser"><h3>%s</h3><p>%s</p><a href="%s" class="my-subscribe-cta">%s</a></div>',
esc_html( $title ),
esc_html( $excerpt ),
esc_url( get_permalink( $show_id ) ),
esc_html__( 'Subscribe to listen', 'my-theme' )
);
}, 10, 5 );
Notes
The filter fires for every rendered item, including accessible ones — check $is_locked before replacing markup to avoid altering content the user can already see. For a suppress-locked pattern, this filter is preferable to setting show_locked="false" on [benecaster_episodes] because it works across all three shortcodes with a single callback and remains in effect when new listing shortcodes are added in future releases.
[benecaster_recipe name="unified-episode-item-output-hide-locked"] [benecaster_recipe name="unified-episode-item-output-teaser"]