From 954cb25e14aee9861fd1980cf25378ae5a9c0c3e Mon Sep 17 00:00:00 2001 From: KMchaudhary Date: Mon, 26 Oct 2026 13:45:33 +0530 Subject: [PATCH 1/2] fix(godam): protect activity player markup from content filters The GoDAM player was expanded inline into BuddyPress activity content and then run through make_clickable, the theme hashtag linkifier and wpautop. Those filters turned the #hex colours and URLs inside the player's data-* attributes into tags, shattering the markup so Video.js got no source and the video could not play. Emit a neutral placeholder during normal filtering and swap in the real [godam_video] output on a PHP_INT_MAX pass, after every other bp_get_activity_content_body filter has run. Covers the activity-video and activity-comment paths; surrounding activity text keeps its formatting. Closes #2386 Co-Authored-By: Claude Opus 4.8 --- templates/media/godam-integration.php | 84 ++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 8 deletions(-) diff --git a/templates/media/godam-integration.php b/templates/media/godam-integration.php index 616e64ef0..7b393a1a0 100644 --- a/templates/media/godam-integration.php +++ b/templates/media/godam-integration.php @@ -135,14 +135,14 @@ function ( $content ) { $godam_videos = ''; - // Build Godam player shortcodes for videos. + // Build neutral placeholders for videos. The real player markup is + // injected later by godam_rtmedia_expand_player_placeholders(), after + // BuddyPress/theme content filters have run, so make_clickable, the + // hashtag linkifier and wpautop cannot corrupt the player attributes. if ( ! empty( $grouped_media['video'] ) ) { foreach ( $grouped_media['video'] as $index => $video ) { $player_id = 'godam-activity-' . esc_attr( $activity->id ) . '-' . $index; - $godam_videos .= do_shortcode( - '[godam_video id="' . esc_attr( $video->media_id ) . - '" context="buddypress" player_id="' . esc_attr( $player_id ) . '"]' - ); + $godam_videos .= godam_rtmedia_build_player_placeholder( $video->media_id, $player_id ); } } @@ -159,9 +159,7 @@ function ( $content ) { foreach ( $child_media as $index => $video ) { $player_id = 'godam-comment-' . esc_attr( $child->id ) . '-' . $index; - $child_videos .= do_shortcode( - '[godam_video id="' . esc_attr( $video->media_id ) . '"]' - ); + $child_videos .= godam_rtmedia_build_player_placeholder( $video->media_id, $player_id ); } if ( $child_videos ) { @@ -188,6 +186,76 @@ function ( $content ) { 10 ); + /** + * Build a neutral placeholder for a GoDAM activity player. + * + * The placeholder deliberately carries no URL and no "#" so the activity + * content filters (make_clickable, the hashtag linkifier, wpautop) leave it + * untouched. It is swapped for the real player markup by + * godam_rtmedia_expand_player_placeholders() on a final, late-priority pass. + * + * @param int|string $media_id rtMedia media id for the video. + * @param string $player_id Unique player id for this activity/comment. + * @param string $context Player context passed to the shortcode. + * @return string Placeholder HTML. + */ + function godam_rtmedia_build_player_placeholder( $media_id, $player_id = '', $context = 'buddypress' ) { + return sprintf( + '
', + esc_attr( $media_id ), + esc_attr( $player_id ), + esc_attr( $context ) + ); + } + + /** + * Expand GoDAM player placeholders into real player markup. + * + * Runs at the last possible priority on bp_get_activity_content_body so every + * other activity content filter (kses, make_clickable, the hashtag linkifier, + * wptexturize, wpautop, nofollow, …) has already finished. The player HTML — + * which carries #hex colours and URLs inside its data-* attributes — is + * therefore never seen by those filters and cannot be corrupted into broken + * tags. Surrounding activity text keeps its normal formatting. + * + * @param string $content Activity content, already fully filtered. + * @return string Content with placeholders replaced by GoDAM players. + */ + function godam_rtmedia_expand_player_placeholders( $content ) { + if ( ! is_string( $content ) || false === strpos( $content, 'godam-activity-player-placeholder' ) ) { + return $content; + } + + return preg_replace_callback( + '#]*class="[^"]*godam-activity-player-placeholder[^"]*"[^>]*>\s*#i', + function ( $matches ) { + $tag = $matches[0]; + + $media_id = preg_match( '/data-media-id="([^"]*)"/', $tag, $m ) ? $m[1] : ''; + $player_id = preg_match( '/data-player-id="([^"]*)"/', $tag, $m ) ? $m[1] : ''; + $context = preg_match( '/data-context="([^"]*)"/', $tag, $m ) ? $m[1] : ''; + + if ( '' === $media_id ) { + return ''; + } + + $shortcode = '[godam_video id="' . esc_attr( $media_id ) . '"'; + if ( '' !== $context ) { + $shortcode .= ' context="' . esc_attr( $context ) . '"'; + } + if ( '' !== $player_id ) { + $shortcode .= ' player_id="' . esc_attr( $player_id ) . '"'; + } + $shortcode .= ']'; + + return do_shortcode( $shortcode ); + }, + $content + ); + } + + add_filter( 'bp_get_activity_content_body', 'godam_rtmedia_expand_player_placeholders', PHP_INT_MAX ); + /** * Handle AJAX request for loading a single activity comment's HTML. * Note: Only registered for logged-in users (wp_ajax_) for security. From c6bb3140f39338424ee26e75b95099067b400767 Mon Sep 17 00:00:00 2001 From: KMchaudhary Date: Tue, 27 Oct 2026 11:39:40 +0530 Subject: [PATCH 2/2] fix(godam): expand comment-video placeholders on the comment pipeline Activity comments render via bp_get_activity_content + bp_activity_comment_content and never hit bp_get_activity_content_body, so comment-video placeholders were left in the DOM as empty
s. Also register the expansion on bp_activity_comment_content (PHP_INT_MAX) so comment videos expand too. Addresses review feedback on #2387. Co-Authored-By: Claude Opus 4.8 --- templates/media/godam-integration.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/templates/media/godam-integration.php b/templates/media/godam-integration.php index 7b393a1a0..783f2bc55 100644 --- a/templates/media/godam-integration.php +++ b/templates/media/godam-integration.php @@ -254,7 +254,12 @@ function ( $matches ) { ); } + // Activity updates render through bp_get_activity_content_body; activity + // comments render through bp_get_activity_content + bp_activity_comment_content + // and never hit the body filter. Hook both pipelines so comment-video + // placeholders are expanded too (otherwise they stay as empty
s). add_filter( 'bp_get_activity_content_body', 'godam_rtmedia_expand_player_placeholders', PHP_INT_MAX ); + add_filter( 'bp_activity_comment_content', 'godam_rtmedia_expand_player_placeholders', PHP_INT_MAX ); /** * Handle AJAX request for loading a single activity comment's HTML.