<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[BuddyPress][4709] trunk: Add oembed support to activity stream items and forum posts.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg > ul, #logmsg > ol { margin-left: 0; margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://buddypress.trac.wordpress.org/changeset/4709">4709</a></dd>
<dt>Author</dt> <dd>djpaul</dd>
<dt>Date</dt> <dd>2011-07-18 22:43:22 +0000 (Mon, 18 Jul 2011)</dd>
</dl>

<h3>Log Message</h3>
<pre>Add oembed support to activity stream items and forum posts. Fixes <a href="http://buddypress.trac.wordpress.org/ticket/2707">#2707</a>, massive props r-a-y</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkbpactivitybpactivityfunctionsphp">trunk/bp-activity/bp-activity-functions.php</a></li>
<li><a href="#trunkbpcorebpcoreclassesphp">trunk/bp-core/bp-core-classes.php</a></li>
<li><a href="#trunkbpcorebpcorefunctionsphp">trunk/bp-core/bp-core-functions.php</a></li>
<li><a href="#trunkbpforumsbpforumsfunctionsphp">trunk/bp-forums/bp-forums-functions.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkbpactivitybpactivityfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-activity/bp-activity-functions.php (4708 => 4709)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-activity/bp-activity-functions.php        2011-07-18 22:37:22 UTC (rev 4708)
+++ trunk/bp-activity/bp-activity-functions.php        2011-07-18 22:43:22 UTC (rev 4709)
</span><span class="lines">@@ -116,7 +116,7 @@
</span><span class="cx">  * @param int $item_id The activity id
</span><span class="cx">  * @param int $secondary_item_id In the case of at-mentions, this is the mentioner's id
</span><span class="cx">  * @param int $total_items The total number of notifications to format
</span><del>- * @param str $format 'string' to get a BuddyBar-compatible notification, 'array' otherwise 
</del><ins>+ * @param str $format 'string' to get a BuddyBar-compatible notification, 'array' otherwise
</ins><span class="cx">  */
</span><span class="cx"> function bp_activity_format_notifications( $action, $item_id, $secondary_item_id, $total_items, $format = 'string' ) {
</span><span class="cx">         global $bp;
</span><span class="lines">@@ -138,7 +138,7 @@
</span><span class="cx">                         }
</span><span class="cx">                 break;
</span><span class="cx">         }
</span><del>-                                
</del><ins>+
</ins><span class="cx">         if ( 'string' == $format ) {
</span><span class="cx">                 $return = apply_filters( $filter, '&lt;a href=&quot;' . $at_mention_link . '&quot; title=&quot;' . $at_mention_title . '&quot;&gt;' . $text . '&lt;/a&gt;', $at_mention_link, (int)$total_items, $activity_id, $poster_user_id );
</span><span class="cx">         } else {
</span><span class="lines">@@ -993,4 +993,44 @@
</span><span class="cx">         return apply_filters( 'bp_activity_thumbnail_content_images', $content, $matches );
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-?&gt;
</del><ins>+/** Embeds *******************************************************************/
+
+/**
+ * Grabs the activity ID and attempts to retrieve the oEmbed cache (if it exists)
+ * during the activity loop.  If no cache and link is embeddable, cache it.
+ *
+ * @see BP_Embed
+ * @see bp_embed_activity_cache()
+ * @see bp_embed_activity_save_cache()
+ * @package BuddyPress Activity
+ * @since 1.3
+ */
+function bp_activity_embed() {
+        add_filter( 'embed_post_id',         'bp_get_activity_id'                  );
+        add_filter( 'bp_embed_get_cache',    'bp_embed_activity_cache',      10, 3 );
+        add_action( 'bp_embed_update_cache', 'bp_embed_activity_save_cache', 10, 3 );
+}
+add_action( 'activity_loop_start', 'bp_activity_embed' );
+
+/**
+ * Wrapper function for {@link bp_activity_get_meta()}.
+ * Used during {@link BP_Embed::parse_oembed()} via {@link bp_activity_embed()}.
+ *
+ * @package BuddyPress Activity
+ * @since 1.3
+ */
+function bp_embed_activity_cache( $cache, $id, $cachekey ) {
+        return bp_activity_get_meta( $id, $cachekey );
+}
+
+/**
+ * Wrapper function for {@link bp_activity_update_meta()}.
+ * Used during {@link BP_Embed::parse_oembed()} via {@link bp_activity_embed()}.
+ *
+ * @package BuddyPress Activity
+ * @since 1.3
+ */
+function bp_embed_activity_save_cache( $cache, $cachekey, $id ) {
+        bp_activity_update_meta( $id, $cachekey, $cache );
+}
+?&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkbpcorebpcoreclassesphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-core/bp-core-classes.php (4708 => 4709)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-core/bp-core-classes.php        2011-07-18 22:37:22 UTC (rev 4708)
+++ trunk/bp-core/bp-core-classes.php        2011-07-18 22:43:22 UTC (rev 4709)
</span><span class="lines">@@ -1082,4 +1082,156 @@
</span><span class="cx">         }
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-?&gt;
</del><ins>+/**
+ * BP_Embed
+ *
+ * Extends WP_Embed class for use with BuddyPress.
+ *
+ * @package BuddyPress Core
+ * @since 1.3
+ * @see WP_Embed
+ */
+class BP_Embed extends WP_Embed {
+        /**
+         * Constructor
+         *
+         * @global unknown $wp_embed
+         */
+        function __construct() {
+                global $wp_embed;
+
+                // Make sure we populate the WP_Embed handlers array.
+                // These are providers that use a regex callback on the URL in question.
+                // Do not confuse with oEmbed providers, which require an external ping.
+                // Used in WP_Embed::shortcode()
+                $this-&gt;handlers = $wp_embed-&gt;handlers;
+
+                if ( bp_use_embed_in_activity() ) {
+                        add_filter( 'bp_get_activity_content_body', array( &amp;$this, 'autoembed' ), 8 );
+                        add_filter( 'bp_get_activity_content_body', array( &amp;$this, 'run_shortcode' ), 7 );
+                }
+
+                if ( bp_use_embed_in_activity_replies() ) {
+                        add_filter( 'bp_get_activity_content', array( &amp;$this, 'autoembed' ), 8 );
+                        add_filter( 'bp_get_activity_content', array( &amp;$this, 'run_shortcode' ), 7 );
+                }
+
+                if ( bp_use_embed_in_forum_posts() ) {
+                        add_filter( 'bp_get_the_topic_post_content', array( &amp;$this, 'autoembed' ), 8 );
+                        add_filter( 'bp_get_the_topic_post_content', array( &amp;$this, 'run_shortcode' ), 7 );
+                }
+        }
+
+        /**
+         * The {@link do_shortcode()} callback function.
+         *
+         * Attempts to convert a URL into embed HTML. Starts by checking the URL against the regex of the registered embed handlers.
+         * Next, checks the URL against the regex of registered {@link WP_oEmbed} providers if oEmbed discovery is false.
+         * If none of the regex matches and it's enabled, then the URL will be passed to {@link BP_Embed::parse_oembed()} for oEmbed parsing.
+         *
+         * @uses wp_parse_args()
+         * @uses wp_embed_defaults()
+         * @uses current_user_can()
+         * @uses _wp_oembed_get_object()
+         * @uses WP_Embed::maybe_make_link()
+         *
+         * @param array $attr Shortcode attributes.
+         * @param string $url The URL attempting to be embeded.
+         * @return string The embed HTML on success, otherwise the original URL.
+         */
+        function shortcode( $attr, $url = '' ) {
+                if ( empty( $url ) )
+                        return '';
+
+                $rawattr = $attr;
+                $attr = wp_parse_args( $attr, wp_embed_defaults() );
+
+                // kses converts &amp; into &amp;amp; and we need to undo this
+                // See http://core.trac.wordpress.org/ticket/11311
+                $url = str_replace( '&amp;amp;', '&amp;', $url );
+
+                // Look for known internal handlers
+                ksort( $this-&gt;handlers );
+                foreach ( $this-&gt;handlers as $priority =&gt; $handlers ) {
+                        foreach ( $handlers as $id =&gt; $handler ) {
+                                if ( preg_match( $handler['regex'], $url, $matches ) &amp;&amp; is_callable( $handler['callback'] ) ) {
+                                        if ( false !== $return = call_user_func( $handler['callback'], $matches, $attr, $url, $rawattr ) )
+                                                return apply_filters( 'embed_handler_html', $return, $url, $attr );
+                                }
+                        }
+                }
+
+                // Get object ID
+                $id = apply_filters( 'embed_post_id', $id );
+
+                // Is oEmbed discovery on?
+                $attr['discover'] = ( apply_filters( 'bp_embed_oembed_discover', false ) &amp;&amp; current_user_can( 'unfiltered_html' ) );
+
+                // Set up a new WP oEmbed object to check URL with registered oEmbed providers
+                require_once( ABSPATH . WPINC . '/class-oembed.php' );
+                $oembed_obj = _wp_oembed_get_object();
+
+                // If oEmbed discovery is true, skip oEmbed provider check
+                $is_oembed_link = false;
+                if ( !$attr['discover'] ) {
+                        foreach ( (array)$oembed_obj-&gt;providers as $provider_matchmask =&gt; $provider ) {
+                                $regex = ( $is_regex = $provider[1] ) ? $provider_matchmask : '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $provider_matchmask ), '#' ) ) . '#i';
+
+                                if ( preg_match( $regex, $url ) )
+                                        $is_oembed_link = true;
+                        }
+
+                        // If url doesn't match a WP oEmbed provider, stop parsing
+                        if ( !$is_oembed_link )
+                                return $this-&gt;maybe_make_link( $url );
+                }
+
+                return $this-&gt;parse_oembed( $id, $url, $attr, $rawattr );
+        }
+
+        /**
+         * Base function so BP components / plugins can parse links to be embedded.
+         * View an example to add support in {@link bp_activity_embed()}.
+         *
+         * @uses apply_filters() Filters cache.
+         * @uses do_action() To save cache.
+         * @uses wp_oembed_get() Connects to oEmbed provider and returns HTML on success.
+         * @uses WP_Embed::maybe_make_link() Process URL for hyperlinking on oEmbed failure.
+         * @param int $id ID to do the caching for.
+         * @param string $url The URL attempting to be embedded.
+         * @param array $attr Shortcode attributes from {@link WP_Embed::shortcode()}.
+         * @param array $rawattr Untouched shortcode attributes from {@link WP_Embed::shortcode()}.
+         * @return string The embed HTML on success, otherwise the original URL.
+         */
+        function parse_oembed( $id, $url, $attr, $rawattr ) {
+                if ( $id ) {
+                        // Setup the cachekey
+                        $cachekey = '_oembed_' . md5( $url . serialize( $attr ) );
+
+                        // Let components / plugins grab their cache
+                        $cache = '';
+                        $cache = apply_filters( 'bp_embed_get_cache', $cache, $id, $cachekey, $url, $attr, $rawattr );
+
+                        // Grab cache and return it if available
+                        if ( !empty( $cache ) ) {
+                                return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $rawattr );
+
+                        // If no cache, ping the oEmbed provider and cache the result
+                        } else {
+                                $html = wp_oembed_get( $url, $attr );
+                                $cache = ( $html ) ? $html : $url;
+
+                                // Let components / plugins save their cache
+                                do_action( 'bp_embed_update_cache', $cache, $cachekey, $id );
+
+                                // If there was a result, return it
+                                if ( $html )
+                                        return apply_filters( 'bp_embed_oembed_html', $html, $url, $attr, $rawattr );
+                        }
+                }
+
+                // Still unknown
+                return $this-&gt;maybe_make_link( $url );
+        }
+}
+?&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre></div>
<a id="trunkbpcorebpcorefunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-core/bp-core-functions.php (4708 => 4709)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-core/bp-core-functions.php        2011-07-18 22:37:22 UTC (rev 4708)
+++ trunk/bp-core/bp-core-functions.php        2011-07-18 22:43:22 UTC (rev 4709)
</span><span class="lines">@@ -18,7 +18,7 @@
</span><span class="cx">  */
</span><span class="cx"> function bp_get_option( $option_name, $default = '' ) {
</span><span class="cx">         $value = get_blog_option( bp_get_root_blog_id(), $option_name, $default );
</span><del>-        
</del><ins>+
</ins><span class="cx">         return apply_filters( 'bp_get_option', $value );
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -78,9 +78,9 @@
</span><span class="cx">  */
</span><span class="cx"> function bp_core_get_page_meta() {
</span><span class="cx">         $page_ids = bp_get_option( 'bp-pages' );
</span><del>-  
</del><ins>+
</ins><span class="cx">           // Upgrading from an earlier version of BP pre-1.3
</span><del>-        if ( !isset( $page_ids['members'] ) &amp;&amp; $ms_page_ids = get_site_option( 'bp-pages' ) ) {  
</del><ins>+        if ( !isset( $page_ids['members'] ) &amp;&amp; $ms_page_ids = get_site_option( 'bp-pages' ) ) {
</ins><span class="cx">                 $page_blog_id = bp_is_multiblog_mode() ? get_current_blog_id() : bp_get_root_blog_id();
</span><span class="cx"> 
</span><span class="cx">                 if ( isset( $ms_page_ids[$page_blog_id] ) ) {
</span><span class="lines">@@ -89,7 +89,7 @@
</span><span class="cx">                         bp_update_option( 'bp-pages', $page_ids );
</span><span class="cx">                 }
</span><span class="cx">           }
</span><del>-          
</del><ins>+
</ins><span class="cx">         return apply_filters( 'bp_core_get_page_meta', $page_ids );
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -697,12 +697,12 @@
</span><span class="cx">  */
</span><span class="cx"> function bp_core_record_activity() {
</span><span class="cx">         global $bp;
</span><del>-        
</del><ins>+
</ins><span class="cx">         if ( !is_user_logged_in() )
</span><span class="cx">                 return false;
</span><del>-        
</del><ins>+
</ins><span class="cx">         $user_id = $bp-&gt;loggedin_user-&gt;id;
</span><del>-        
</del><ins>+
</ins><span class="cx">         if ( bp_core_is_user_spammer( $user_id ) || bp_core_is_user_deleted( $user_id ) )
</span><span class="cx">                 return false;
</span><span class="cx"> 
</span><span class="lines">@@ -913,6 +913,21 @@
</span><span class="cx"> add_action( 'bp_init', 'bp_core_add_ajax_hook' );
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Initializes {@link BP_Embed} after everything is loaded.
+ *
+ * @global object $bp BuddyPress global settings
+ * @package BuddyPress Core
+ * @since 1.3
+ */
+function bp_embed_init() {
+        global $bp;
+
+        if ( empty( $bp-&gt;embed ) )
+                $bp-&gt;embed = new BP_Embed();
+}
+add_action( 'bp_init', 'bp_embed_init' );
+
+/**
</ins><span class="cx">  * When switching from single to multisite we need to copy blog options to
</span><span class="cx">  * site options.
</span><span class="cx">  *
</span><span class="lines">@@ -1074,7 +1089,6 @@
</span><span class="cx">  * @return bool $is_root_blog Returns true if this is bp_get_root_blog_id().
</span><span class="cx">  */
</span><span class="cx"> function bp_is_root_blog( $blog_id = 0 ) {
</span><del>-        
</del><span class="cx">         // Assume false
</span><span class="cx">         $is_root_blog = false;
</span><span class="cx"> 
</span><span class="lines">@@ -1118,7 +1132,7 @@
</span><span class="cx">                 }
</span><span class="cx"> 
</span><span class="cx">                 define( 'BP_ROOT_BLOG', $root_blog_id );
</span><del>-                
</del><ins>+
</ins><span class="cx">         // Root blog is defined
</span><span class="cx">         } else {
</span><span class="cx">                 $root_blog_id = BP_ROOT_BLOG;
</span><span class="lines">@@ -1220,7 +1234,7 @@
</span><span class="cx">  * @since 1.3
</span><span class="cx">  *
</span><span class="cx">  * @uses apply_filters() Filter 'bp_is_username_compatibility_mode' to alter
</span><del>- * @return bool False when compatibility mode is disabled (default); true when enabled 
</del><ins>+ * @return bool False when compatibility mode is disabled (default); true when enabled
</ins><span class="cx">  */
</span><span class="cx"> function bp_is_username_compatibility_mode() {
</span><span class="cx">         return apply_filters( 'bp_is_username_compatibility_mode', defined( 'BP_ENABLE_USERNAME_COMPATIBILITY_MODE' ) &amp;&amp; BP_ENABLE_USERNAME_COMPATIBILITY_MODE );
</span><span class="lines">@@ -1231,7 +1245,7 @@
</span><span class="cx">  *
</span><span class="cx">  * Note that BP_ENABLE_MULTIBLOG is different from (but dependent on) WP Multisite. &quot;Multiblog&quot; is
</span><span class="cx">  * a BP setup that allows BP content to be viewed in the theme, and with the URL, of every blog
</span><del>- * on the network. Thus, instead of having all 'boonebgorges' links go to 
</del><ins>+ * on the network. Thus, instead of having all 'boonebgorges' links go to
</ins><span class="cx">  *   http://example.com/members/boonebgorges
</span><span class="cx">  * on the root blog, each blog will have its own version of the same profile content, eg
</span><span class="cx">  *   http://site2.example.com/members/boonebgorges (for subdomains)
</span><span class="lines">@@ -1244,7 +1258,7 @@
</span><span class="cx">  * @since 1.3
</span><span class="cx">  *
</span><span class="cx">  * @uses apply_filters() Filter 'bp_is_multiblog_mode' to alter
</span><del>- * @return bool False when multiblog mode is disabled (default); true when enabled 
</del><ins>+ * @return bool False when multiblog mode is disabled (default); true when enabled
</ins><span class="cx">  */
</span><span class="cx"> function bp_is_multiblog_mode() {
</span><span class="cx">         return apply_filters( 'bp_is_multiblog_mode', is_multisite() &amp;&amp; defined( 'BP_ENABLE_MULTIBLOG' ) &amp;&amp; BP_ENABLE_MULTIBLOG );
</span><span class="lines">@@ -1263,13 +1277,43 @@
</span><span class="cx">  * @since 1.3
</span><span class="cx">  *
</span><span class="cx">  * @uses apply_filters() Filter 'bp_use_wp_admin_bar' to alter
</span><del>- * @return bool False when WP Admin Bar support is disabled (default); true when enabled 
</del><ins>+ * @return bool False when WP Admin Bar support is disabled (default); true when enabled
</ins><span class="cx">  */
</span><span class="cx"> function bp_use_wp_admin_bar() {
</span><span class="cx">         return apply_filters( 'bp_use_wp_admin_bar', defined( 'BP_USE_WP_ADMIN_BAR' ) &amp;&amp; BP_USE_WP_ADMIN_BAR );
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * Are oembeds allowed in activity items?
+ *
+ * @return bool False when activity embed support is disabled; true when enabled (default)
+ * @since 1.3
+ */
+function bp_use_embed_in_activity() {
+        return apply_filters( 'bp_use_oembed_in_activity', !defined( 'BP_EMBED_DISABLE_ACTIVITY' ) || !BP_EMBED_DISABLE_ACTIVITY );
+}
+
+/**
+ * Are oembeds allwoed in acitivity replies?
+ *
+ * @return bool False when activity replies embed support is disabled; true when enabled (default)
+ * @since 1.3
+ */
+function bp_use_embed_in_activity_replies() {
+        return apply_filters( 'bp_use_embed_in_activity_replies', !defined( 'BP_EMBED_DISABLE_ACTIVITY_REPLIES' ) || !BP_EMBED_DISABLE_ACTIVITY_REPLIES );
+}
+
+/**
+ * Are oembeds allowed on forum posts?
+ *
+ * @return bool False when form post embed support is disabled; true when enabled (default)
+ * @since 1.3
+ */
+function bp_use_embed_in_forum_posts() {
+        return apply_filters( 'bp_use_embed_in_forum_posts', !defined( 'BP_EMBED_DISABLE_FORUM_POSTS' ) || !BP_EMBED_DISABLE_FORUM_POSTS );
+}
+
+/**
</ins><span class="cx">  * Output the correct URL based on BuddyPress and WordPress configuration
</span><span class="cx">  *
</span><span class="cx">  * @package BuddyPress
</span><span class="lines">@@ -1372,8 +1416,8 @@
</span><span class="cx"> 
</span><span class="cx">         do_action( 'bp_do_404', $redirect );
</span><span class="cx"> 
</span><del>-        $wp_query-&gt;set_404(); 
-        status_header( 404 ); 
</del><ins>+        $wp_query-&gt;set_404();
+        status_header( 404 );
</ins><span class="cx">         nocache_headers();
</span><span class="cx"> 
</span><span class="cx">         if ( 'remove_canonical_direct' == $redirect )
</span></span></pre></div>
<a id="trunkbpforumsbpforumsfunctionsphp"></a>
<div class="modfile"><h4>Modified: trunk/bp-forums/bp-forums-functions.php (4708 => 4709)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/bp-forums/bp-forums-functions.php        2011-07-18 22:37:22 UTC (rev 4708)
+++ trunk/bp-forums/bp-forums-functions.php        2011-07-18 22:43:22 UTC (rev 4709)
</span><span class="lines">@@ -514,4 +514,45 @@
</span><span class="cx"> add_action( 'bp_forums_new_topic', 'bp_core_clear_cache' );
</span><span class="cx"> add_action( 'bp_forums_new_post',  'bp_core_clear_cache' );
</span><span class="cx"> 
</span><del>-?&gt;
</del><ins>+
+/** Embeds *******************************************************************/
+
+/**
+ * Grabs the topic post ID and attempts to retrieve the oEmbed cache (if it exists)
+ * during the forum topic loop.  If no cache and link is embeddable, cache it.
+ *
+ * @see BP_Embed
+ * @see bp_embed_forum_cache()
+ * @see bp_embed_forum_save_cache()
+ * @package BuddyPress_Forums
+ * @since 1.3
+ */
+function bp_forums_embed() {
+        add_filter( 'embed_post_id',         'bp_get_the_topic_post_id'         );
+        add_filter( 'bp_embed_get_cache',    'bp_embed_forum_cache',      10, 3 );
+        add_action( 'bp_embed_update_cache', 'bp_embed_forum_save_cache', 10, 3 );
+}
+add_action( 'topic_loop_start', 'bp_forums_embed' );
+
+/**
+ * Wrapper function for {@link bb_get_postmeta()}.
+ * Used during {@link BP_Embed::parse_oembed()} via {@link bp_forums_embed()}.
+ *
+ * @package BuddyPress_Forums
+ * @since 1.3
+ */
+function bp_embed_forum_cache( $cache, $id, $cachekey ) {
+        return bb_get_postmeta( $id, $cachekey );
+}
+
+/**
+ * Wrapper function for {@link bb_update_postmeta()}.
+ * Used during {@link BP_Embed::parse_oembed()} via {@link bp_forums_embed()}.
+ *
+ * @package BuddyPress_Forums
+ * @since 1.3
+ */
+function bp_embed_forum_save_cache( $cache, $cachekey, $id ) {
+        bb_update_postmeta( $id, $cachekey, $cache );
+}
+?&gt;
</ins><span class="cx">\ No newline at end of file
</span></span></pre>
</div>
</div>

</body>
</html>