Core Features
- Front-end Editing: Users can edit their activity posts directly from the activity stream
- Time-based Restrictions: Admins can set time limits for how long users can edit their posts
- Seamless Integration: Works with standard BuddyPress themes and templates
- Visual Feedback: Shows “(edited)” indicator on posts that have been modified
- Security: Only post authors and admins can edit content
Technical Architecture
The plugin follows the WordPress plugin architecture pattern with separate admin and public-facing components:
buddypress-edit-activity/
├── admin/ # Admin-specific functionality
├── includes/ # Core plugin files
├── public/ # Front-end functionality
├── languages/ # Internationalization
└── edd-license/ # Licensing system
Available Hooks
Filters
buddypress_edit_activity_duration- Purpose: Modify the duration (in minutes) during which users can edit their activities
- Parameters:
$duration(int) - Default: Varies based on admin settings (Forever, 30 days, 7 days, 1 day, 1 hour, or 10 minutes)
- Example:
function custom_edit_duration($duration) { return 60 * 3; // 3 hours in minutes } add_filter('buddypress_edit_activity_duration', 'custom_edit_duration');
bp_editable_types_activity- Purpose: Define which activity types can be edited
- Parameters:
$editable_types(array) - Default:
['activity_update'] - Example:
function custom_editable_types($types) { $types[] = 'activity_comment'; return $types; } add_filter('bp_editable_types_activity', 'custom_editable_types');
buddypress_can_edit_activity- Purpose: Determine if a user can edit a specific activity
- Parameters:
$can_edit(boolean),$activity(object) - Example:
function custom_edit_permissions($can_edit, $activity) { // Allow group moderators to edit any activity in their groups if (bp_is_active('groups') && $activity->component == 'groups') { $group_id = $activity->item_id; if (groups_is_user_mod(get_current_user_id(), $group_id)) { return true; } } return $can_edit; } add_filter('buddypress_can_edit_activity', 'custom_edit_permissions', 10, 2);
buddypress_get_edit_activity_content- Purpose: Filter the activity content before displaying it in the edit form
- Parameters:
$content(string),$activity(object) - Example:
function prepare_activity_for_editing($content, $activity) { // Remove any special formatting before editing $content = preg_replace('/[special_format](.*?)[/special_format]/s', '$1', $content); return $content; } add_filter('buddypress_get_edit_activity_content', 'prepare_activity_for_editing', 10, 2);
buddypress_edit_activity_content- Purpose: Modify the activity content before saving the edited version
- Parameters:
$content(string),$activity_id(int) - Example:
function process_edited_content($content, $activity_id) { // Add formatting or process hashtags $content = parse_hashtags($content); return $content; } add_filter('buddypress_edit_activity_content', 'process_edited_content', 10, 2);
buddypress_bp_edit_activity_action- Purpose: Modify the activity action text with the “(edited)” indicator
- Parameters:
$action(string),$activity(object) - Example:
function custom_edited_indicator($action, $activity) { // Add timestamp to edited indicator if (bp_activity_get_meta($activity->id, '_bp_edit_activity', true)) { $edit_time = bp_activity_get_meta($activity->id, '_bp_edit_timestamp', true); if ($edit_time) { $time_diff = human_time_diff($edit_time, current_time('timestamp')); return $action . ' <span class="bp-activity-edited-text">(edited ' . $time_diff . ' ago)</span>'; } } return $action; } add_filter('buddypress_bp_edit_activity_action', 'custom_edited_indicator', 10, 2);
Actions
bp_before_edit_activity_template- Purpose: Add content before the edit activity form
- Example:
function add_edit_form_notice() { echo '<div class="bp-edit-notice">Editing your post will notify all participants.</div>'; } add_action('bp_before_edit_activity_template', 'add_edit_form_notice');
bp_after_edit_activity_template- Purpose: Add content after the edit activity form
- Example:
function add_edit_form_guidelines() { echo '<div class="bp-edit-guidelines">Please follow community guidelines when editing.</div>'; } add_action('bp_after_edit_activity_template', 'add_edit_form_guidelines');
bp_edit_activity_fields- Purpose: Add custom fields to the edit activity form
- Example:
function add_custom_edit_fields() { ?> <div class="custom-activity-field"> <label for="activity-category">Category:</label> <select name="activity_category" id="activity-category"> <option value="general">General</option> <option value="question">Question</option> <option value="announcement">Announcement</option> </select> </div> <?php } add_action('bp_edit_activity_fields', 'add_custom_edit_fields');
bp_get_addition_activity_content- Purpose: Add additional content to the activity when retrieving it for editing
- Parameters:
$activity(object) - Example:
function load_custom_activity_data($activity) { // Get saved category $category = bp_activity_get_meta($activity->id, 'activity_category', true); if ($category) { ?> <script> jQuery(document).ready(function($) { $('#activity-category').val('<?php echo esc_js($category); ?>'); }); </script> <?php } } add_action('bp_get_addition_activity_content', 'load_custom_activity_data');
buddypress_edit_activity_before_save_activity_content- Purpose: Execute actions before saving the edited activity content
- Parameters:
$activity_id(int) - Example:
function before_save_activity($activity_id) { // Log edit action bp_activity_add_meta($activity_id, '_edit_started', time()); } add_action('buddypress_edit_activity_before_save_activity_content', 'before_save_activity');
buddypress_edit_activity_after_save_activity_content- Purpose: Execute actions after saving the edited activity content
- Parameters:
$activity_id(int),$activity(object) - Example:
function after_save_activity($activity_id, $activity) { // Save edit timestamp bp_activity_update_meta($activity_id, '_bp_edit_timestamp', time()); // Save custom fields if (isset($_POST['activity_category'])) { $category = sanitize_text_field($_POST['activity_category']); bp_activity_update_meta($activity_id, 'activity_category', $category); } // Create notification about edit if (function_exists('bp_notifications_add_notification')) { // Notify original mentioned users about update $mentioned_users = bp_activity_get_meta($activity_id, 'mentioned_users', true); if (!empty($mentioned_users) && is_array($mentioned_users)) { foreach ($mentioned_users as $user_id) { bp_notifications_add_notification(array( 'user_id' => $user_id, 'item_id' => $activity_id, 'component_name' => 'activity', 'component_action' => 'activity_edited', )); } } } } add_action('buddypress_edit_activity_after_save_activity_content', 'after_save_activity', 10, 2);
Implementation Examples
1. Add Character Counter to Edit Form
function add_character_counter() {
?>
<div class="character-count">
<span id="char-count">0</span> characters
</div>
<script>
jQuery(document).ready(function($) {
var textarea = $('#whats-new');
var counter = $('#char-count');
// Update on load
counter.text(textarea.val().length);
// Update on keyup
textarea.on('keyup', function() {
counter.text($(this).val().length);
});
});
</script>
<?php
}
add_action('bp_before_edit_activity_template', 'add_character_counter');
2. Extend Editing Time for Certain Groups
function extend_edit_time_for_groups($duration, $activity) {
// Check if activity is from specific groups
if (!empty($activity->component) && $activity->component === 'groups') {
// Get array of group IDs with extended edit time
$extended_groups = [5, 10, 15]; // Replace with your group IDs
if (in_array($activity->item_id, $extended_groups)) {
// Allow 7 days for these groups instead of default
return 60 * 24 * 7; // 7 days in minutes
}
}
return $duration;
}
add_filter('buddypress_edit_activity_duration', 'extend_edit_time_for_groups', 10, 2);
3. Custom Activity History Tracking
function track_activity_edit_history($activity_id, $activity) {
// Get previous content versions
$history = bp_activity_get_meta($activity_id, '_edit_history', true);
if (!$history) {
$history = array();
}
// Add new entry to history
$history[] = array(
'content' => $activity->content,
'time' => current_time('timestamp'),
'user_id' => bp_loggedin_user_id()
);
// Store up to 5 recent edits
if (count($history) > 5) {
$history = array_slice($history, -5);
}
// Save history
bp_activity_update_meta($activity_id, '_edit_history', $history);
}
add_action('buddypress_edit_activity_after_save_activity_content', 'track_activity_edit_history', 10, 2);
4. Adding Toggle Privacy Option During Edit
function add_privacy_toggle_field() {
?>
<div class="edit-activity-privacy">
<label>
<input type="checkbox" name="make_private" id="make-activity-private" />
Make this activity visible only to friends
</label>
</div>
<?php
}
add_action('bp_edit_activity_fields', 'add_privacy_toggle_field');
function process_privacy_toggle($activity_id, $activity) {
if (isset($_POST['make_private']) && $_POST['make_private'] == 'on') {
// Set activity to private (only visible to friends)
bp_activity_update_meta($activity_id, 'privacy', 'friends');
// This requires additional filtering of activity visibility elsewhere
} else {
// Set activity to public
bp_activity_delete_meta($activity_id, 'privacy');
}
}
add_action('buddypress_edit_activity_after_save_activity_content', 'process_privacy_toggle', 10, 2);
5. Customize Edit Button for Specific Activity Types
function customize_edit_button($buttons, $activity_id) {
$activity = new BP_Activity_Activity($activity_id);
// Change button text/appearance for photo updates
if ($activity->type == 'activity_update' && strpos($activity->content, '<img') !== false) {
$buttons['activity_bp_edit']['button_attr']['data-bp-tooltip'] = __('Edit Photo', 'my-plugin');
$buttons['activity_bp_edit']['link_text'] = sprintf('<span class="bp-screen-reader-text">%s</span>', __('Edit Photo', 'my-plugin'));
}
return $buttons;
}
add_filter('bb_nouveau_get_activity_entry_dropdown_toggle_buttons', 'customize_edit_button', 20, 2);
Troubleshooting
Common Issues and Solutions
- Activity Not Editable When Expected
- Check if the activity type is included in the
bp_editable_types_activityfilter - Verify user permissions with the
buddypress_can_edit_activityfilter - Ensure the edit duration hasn’t expired
- Check if the activity type is included in the
- Custom Fields Not Saving
- Ensure proper nonce verification in your code
- Check that you’re hooking into
buddypress_edit_activity_after_save_activity_content - Verify proper sanitization of form inputs
- Modal Dialog Styling Issues
- Use browser developer tools to inspect the modal
- Add specific CSS targeting the
.bp-activity-edit-model-wrapand its children - Ensure your theme’s styles aren’t overriding the plugin’s modal styles
- JavaScript Not Working
- Check browser console for JavaScript errors
- Ensure jQuery is properly loaded
- Verify AJAX URLs are correctly configured
Best Practices
- Security
- Always sanitize and validate user inputs
- Use nonce verification for AJAX requests
- Check user capabilities before allowing edits
- Performance
- Minimize database queries in your hooks
- Cache expensive operations where appropriate
- Use transients for temporary data storage
- Compatibility
- Test your customizations with different BuddyPress themes
- Ensure compatibility with popular BuddyPress plugins
- Follow WordPress coding standards
- User Experience
- Provide clear feedback when activities are edited
- Keep the editing interface simple and intuitive
- Consider mobile users when adding UI elements
Support
For additional support or to report issues:
- Visit our Documentation
- Contact our Support Team
