Skip to content

Instantly share code, notes, and snippets.

@vapvarun
Last active September 4, 2025 13:35
Show Gist options
  • Select an option

  • Save vapvarun/2ba5caba76856038a1622861ab313abe to your computer and use it in GitHub Desktop.

Select an option

Save vapvarun/2ba5caba76856038a1622861ab313abe to your computer and use it in GitHub Desktop.
WP Stories - Separate PUBLIC Stories on Activity Pages (Complete Solution with Plugin Modifications)
<?php
/**
* Plugin Name: WP Stories - Separate PUBLIC Stories on Activity Pages
* Description: Display PUBLIC stories as separate circles on activity pages instead of grouping by user
* Version: 1.0.0
*
* This code ensures that PUBLIC type stories are displayed separately on BuddyPress/PeepSo activity pages,
* while SINGLE type stories remain grouped by user as normal.
*/
if (!defined('ABSPATH')) {
exit;
}
/**
* Remove default WP Stories hooks for activity pages
*/
add_action('plugins_loaded', function() {
// Remove default hooks after they're added
add_action('init', function() {
global $wp_filter;
// Remove PeepSo hooks
if (isset($wp_filter['peepso_action_before_exec_template'])) {
foreach ($wp_filter['peepso_action_before_exec_template']->callbacks as $priority => $hooks) {
foreach ($hooks as $key => $hook) {
if (is_array($hook['function']) &&
is_object($hook['function'][0]) &&
get_class($hook['function'][0]) === 'Wp_Stories_Public' &&
$hook['function'][1] === 'wp_story_display_peepso_stories') {
remove_action('peepso_action_before_exec_template', $hook['function'], $priority);
}
}
}
}
// Remove BuddyPress hooks
if (isset($wp_filter['bp_before_directory_activity_content'])) {
foreach ($wp_filter['bp_before_directory_activity_content']->callbacks as $priority => $hooks) {
foreach ($hooks as $key => $hook) {
if (is_array($hook['function']) &&
is_object($hook['function'][0]) &&
get_class($hook['function'][0]) === 'Wp_Stories_Public' &&
$hook['function'][1] === 'wp_story_display_activity_stories') {
remove_action('bp_before_directory_activity_content', $hook['function'], $priority);
}
}
}
}
}, 999);
}, 1);
/**
* Add custom display for PeepSo activity pages
*/
add_action('peepso_action_before_exec_template', function($section, $template, $data, $return_output) {
static $stories_displayed = false;
// Only display on activity stream
if ($section === 'activity' && $template === 'activity' && !$stories_displayed) {
$stories_displayed = true;
// Get all users who have stories
global $wpdb;
// Get users with PUBLIC stories
$users_with_public_stories = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT p.post_author
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE p.post_type = %s
AND p.post_status = %s
AND pm.meta_key = %s
AND pm.meta_value = %s
ORDER BY p.post_date DESC",
'wb-user-story',
'publish',
'user_story_type',
'public'
)
);
// Get users with SINGLE stories
$users_with_single_stories = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT p.post_author
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE p.post_type = %s
AND p.post_status = %s
AND pm.meta_key = %s
AND pm.meta_value = %s
ORDER BY p.post_date DESC",
'wb-user-story',
'publish',
'user_story_type',
'single'
)
);
?>
<div class="wb-stories-user-activities">
<div class="wp-stories-user-stories">
<?php
// Display PUBLIC stories - each user gets their own circle
foreach ($users_with_public_stories as $user_id) {
echo do_shortcode('[wb-story-user-stories id="' . $user_id . '" type="public"]');
}
// Display SINGLE stories - grouped by user
if (!empty($users_with_single_stories)) {
echo do_shortcode('[wb-story-user-stories id="' . $users_with_single_stories[0] . '" type="single" subs="' . implode(',', array_slice($users_with_single_stories, 1)) . '"]');
}
?>
</div>
</div>
<?php
}
}, 10, 4);
/**
* Add custom display for BuddyPress activity pages
*/
add_action('bp_before_directory_activity_content', function() {
// Get all users who have stories
global $wpdb;
// Get users with PUBLIC stories
$users_with_public_stories = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT p.post_author
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE p.post_type = %s
AND p.post_status = %s
AND pm.meta_key = %s
AND pm.meta_value = %s
ORDER BY p.post_date DESC",
'wb-user-story',
'publish',
'user_story_type',
'public'
)
);
// Get users with SINGLE stories
$users_with_single_stories = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT p.post_author
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE p.post_type = %s
AND p.post_status = %s
AND pm.meta_key = %s
AND pm.meta_value = %s
ORDER BY p.post_date DESC",
'wb-user-story',
'publish',
'user_story_type',
'single'
)
);
?>
<div class="wb-stories-user-activities">
<div class="wp-stories-user-stories">
<?php
// Display PUBLIC stories - each user gets their own circle
foreach ($users_with_public_stories as $user_id) {
echo do_shortcode('[wb-story-user-stories id="' . $user_id . '" type="public"]');
}
// Display SINGLE stories - grouped by user
if (!empty($users_with_single_stories)) {
echo do_shortcode('[wb-story-user-stories id="' . $users_with_single_stories[0] . '" type="single" subs="' . implode(',', array_slice($users_with_single_stories, 1)) . '"]');
}
?>
</div>
</div>
<?php
}, 10);
<?php
/**
* WP Stories Plugin Modifications
*
* These modifications add a setting to control how PUBLIC stories are displayed on activity pages.
*
* FILES TO MODIFY:
* 1. /wp-content/plugins/wp-stories/admin/inc/wp-stories-integrations-tab.php (Add settings)
* 2. /wp-content/plugins/wp-stories/public/class-wp-stories-public.php (Modify display logic)
*/
// ==============================================================================
// FILE 1: ADD TO wp-stories-integrations-tab.php
// Add this after line 85 (after the "Enable Story Collections" setting)
// ==============================================================================
?>
<div class="wbcom-settings-section-wrap buddypress_integration">
<div class="wbcom-settings-section-options-heading">
<label for="activity_story_display_mode"><?php esc_html_e( 'Activity Page Story Display Mode', 'wp-stories' ); ?></label>
<p class="description"><?php esc_html_e( 'Choose how stories are displayed on activity pages.', 'wp-stories' ); ?></p>
</div>
<div class="wbcom-settings-section-options">
<select id="activity_story_display_mode" name="wp_stories_integrations[activity_story_display_mode]">
<option value="grouped" <?php selected( 'grouped', isset($integrations['activity_story_display_mode']) ? $integrations['activity_story_display_mode'] : 'grouped' ); ?>>
<?php esc_html_e( 'Grouped by User (Default)', 'wp-stories' ); ?>
</option>
<option value="separate_public" <?php selected( 'separate_public', isset($integrations['activity_story_display_mode']) ? $integrations['activity_story_display_mode'] : '' ); ?>>
<?php esc_html_e( 'Separate PUBLIC Stories', 'wp-stories' ); ?>
</option>
</select>
<p class="description" style="margin-top: 10px;">
<strong><?php esc_html_e( 'Grouped by User:', 'wp-stories' ); ?></strong> <?php esc_html_e( 'All stories from same user appear as one circle (Instagram style).', 'wp-stories' ); ?><br>
<strong><?php esc_html_e( 'Separate PUBLIC Stories:', 'wp-stories' ); ?></strong> <?php esc_html_e( 'Each PUBLIC story appears as its own circle with cover image, while SINGLE stories remain grouped.', 'wp-stories' ); ?>
</p>
</div>
</div>
<?php
// Also add the same setting for PeepSo after line 173
?>
<div class="wbcom-settings-section-wrap peepso_integration">
<div class="wbcom-settings-section-options-heading">
<label for="peepso_activity_story_display_mode"><?php esc_html_e( 'Activity Page Story Display Mode', 'wp-stories' ); ?></label>
<p class="description"><?php esc_html_e( 'Choose how stories are displayed on activity pages.', 'wp-stories' ); ?></p>
</div>
<div class="wbcom-settings-section-options">
<select id="peepso_activity_story_display_mode" name="wp_stories_integrations[peepso_activity_story_display_mode]">
<option value="grouped" <?php selected( 'grouped', isset($integrations['peepso_activity_story_display_mode']) ? $integrations['peepso_activity_story_display_mode'] : 'grouped' ); ?>>
<?php esc_html_e( 'Grouped by User (Default)', 'wp-stories' ); ?>
</option>
<option value="separate_public" <?php selected( 'separate_public', isset($integrations['peepso_activity_story_display_mode']) ? $integrations['peepso_activity_story_display_mode'] : '' ); ?>>
<?php esc_html_e( 'Separate PUBLIC Stories', 'wp-stories' ); ?>
</option>
</select>
<p class="description" style="margin-top: 10px;">
<strong><?php esc_html_e( 'Grouped by User:', 'wp-stories' ); ?></strong> <?php esc_html_e( 'All stories from same user appear as one circle (Instagram style).', 'wp-stories' ); ?><br>
<strong><?php esc_html_e( 'Separate PUBLIC Stories:', 'wp-stories' ); ?></strong> <?php esc_html_e( 'Each PUBLIC story appears as its own circle with cover image, while SINGLE stories remain grouped.', 'wp-stories' ); ?>
</p>
</div>
</div>
<?php
// ==============================================================================
// FILE 2: MODIFY class-wp-stories-public.php
// Replace the wp_story_display_peepso_stories function (around line 887)
// ==============================================================================
?>
/**
* Display PeepSo stories.
*
* @since 1.0.0
*/
public function wp_story_display_peepso_stories( $section, $template, $data, $return_output ) {
static $stories_displayed = false;
$integrations = get_option( 'wp_stories_integrations' );
$current_user_id = get_current_user_id();
if ( ! empty( $integrations ) && isset( $integrations['peepso'] ) ) {
if ( ( 'profile' === $section && 'focus' === $template ) ) {
global $GLOBALS;
// ... existing profile code ...
} elseif ( 'activity' === $section && 'activity' === $template && ! $stories_displayed ) {
$stories_displayed = true;
// Check display mode setting
$display_mode = isset( $integrations['peepso_activity_story_display_mode'] ) ? $integrations['peepso_activity_story_display_mode'] : 'grouped';
if ( $display_mode === 'separate_public' ) {
// New behavior: Separate PUBLIC stories
echo $this->wp_story_display_activity_stories_separated( 'peepso' );
} else {
// Default behavior: Grouped by user
echo $this->wp_story_display_activity_stories( 'peepso' );
}
}
}
}
/**
* Display activity stories with PUBLIC stories separated.
*
* @param string $integration The integration type (buddypress or peepso).
* @return string
* @since 1.0.0
*/
public function wp_story_display_activity_stories_separated( $integration = 'buddypress' ) {
global $wpdb;
// Get users with PUBLIC stories
$users_with_public_stories = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT p.post_author
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE p.post_type = %s
AND p.post_status = %s
AND pm.meta_key = %s
AND pm.meta_value = %s
ORDER BY p.post_date DESC",
'wb-user-story',
'publish',
'user_story_type',
'public'
)
);
// Get users with SINGLE stories
$users_with_single_stories = $wpdb->get_col(
$wpdb->prepare(
"SELECT DISTINCT p.post_author
FROM {$wpdb->posts} p
INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
WHERE p.post_type = %s
AND p.post_status = %s
AND pm.meta_key = %s
AND pm.meta_value = %s
ORDER BY p.post_date DESC",
'wb-user-story',
'publish',
'user_story_type',
'single'
)
);
ob_start();
$integrations = get_option( 'wp_stories_integrations' );
$show_form = false;
if ( $integration === 'peepso' && isset( $integrations['peepso_activities_form'] ) ) {
$show_form = $integrations['peepso_activities_form'];
} elseif ( $integration === 'buddypress' && isset( $integrations['buddypress_activities_form'] ) ) {
$show_form = $integrations['buddypress_activities_form'];
}
?>
<div class="wb-stories-user-activities">
<div class="wp-stories-user-stories">
<?php if ( $show_form && is_user_logged_in() ) : ?>
<a href="#" class="wp-stories-add-stories" data-type="single" data-id="activity-stories">
<span class="wp-stories-add-image">
<?php echo get_avatar( get_current_user_id(), 80 ); ?>
<span class="wp-stories-add-icon">
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24">
<path d="M0 0h24v24H0z" fill="none"/>
<path fill="#64B5F6" d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/>
</svg>
</span>
</span>
<span class="wp-stories-add-title"><?php esc_html_e( 'Add story', 'wp-stories' ); ?></span>
</a>
<?php endif; ?>
<?php
// Display PUBLIC stories - each user gets their own circle
foreach ( $users_with_public_stories as $user_id ) {
echo do_shortcode( '[wb-story-user-stories id="' . $user_id . '" type="public"]' );
}
// Display SINGLE stories - grouped by user
if ( ! empty( $users_with_single_stories ) ) {
$first_user = array_shift( $users_with_single_stories );
$subs = ! empty( $users_with_single_stories ) ? implode( ',', $users_with_single_stories ) : '';
echo do_shortcode( '[wb-story-user-stories id="' . $first_user . '" type="single" subs="' . $subs . '"]' );
}
?>
</div>
</div>
<?php
if ( $show_form ) {
wp_stories_user_story_submit_form( 'single', 'activity-stories' );
}
return ob_get_clean();
}
<?php
// ==============================================================================
// Also update the BuddyPress display function similarly
// Around line 493 in class-wp-stories-public.php
// ==============================================================================
?>
/**
* Display BuddyPress activity stories.
*
* @param string $integration Integration type.
* @since 1.0.0
*/
public function wp_story_display_activity_stories( $integration = 'buddypress' ) {
$integrations = get_option( 'wp_stories_integrations' );
// Check display mode setting
$display_mode = isset( $integrations['activity_story_display_mode'] ) ? $integrations['activity_story_display_mode'] : 'grouped';
if ( $display_mode === 'separate_public' && $integration === 'buddypress' ) {
// New behavior: Separate PUBLIC stories
return $this->wp_story_display_activity_stories_separated( $integration );
}
// ... rest of existing function code for default behavior ...
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment