Ticket #6772: 6772.07.patch
File 6772.07.patch, 49.1 KB (added by , 8 years ago) |
---|
-
src/bp-activity/bp-activity-classes.php
13 13 require dirname( __FILE__ ) . '/classes/class-bp-activity-activity.php'; 14 14 require dirname( __FILE__ ) . '/classes/class-bp-activity-feed.php'; 15 15 require dirname( __FILE__ ) . '/classes/class-bp-activity-query.php'; 16 17 // Embeds - only applicable for WP 4.5+ 18 if ( bp_get_major_wp_version() >= 4.5 && bp_is_active( 'activity', 'embeds' ) ) { 19 require dirname( __FILE__ ) . '/classes/class-bp-activity-oembed-component.php'; 20 } 21 No newline at end of file -
new file src/bp-activity/bp-activity-embeds.php
new file mode 100644
- + 1 <?php 2 /** 3 * Functions related to embedding single activity items externally. 4 * 5 * Relies on WordPress 4.5. 6 * 7 * @since 2.6.0 8 * 9 * @package BuddyPress 10 * @subpackage ActivityEmbeds 11 */ 12 13 // Exit if accessed directly. 14 defined( 'ABSPATH' ) || exit; 15 16 /** 17 * Loads our activity oEmbed component. 18 * 19 * @since 2.6.0 20 */ 21 function bp_activity_setup_oembed() { 22 if ( bp_get_major_wp_version() >= 4.5 && bp_is_active( 'activity', 'embeds' ) ) { 23 buddypress()->activity->oembed = new BP_Activity_oEmbed_Component; 24 } 25 26 add_filter( 'bp_activity_get_embed_excerpt', 'wptexturize' ); 27 add_filter( 'bp_activity_get_embed_excerpt', 'convert_chars' ); 28 add_filter( 'bp_activity_get_embed_excerpt', 'make_clickable', 9 ); 29 add_filter( 'bp_activity_get_embed_excerpt', 'bp_activity_at_name_filter' ); 30 add_filter( 'bp_activity_get_embed_excerpt', 'convert_smilies', 20 ); 31 add_filter( 'bp_activity_get_embed_excerpt', 'wpautop', 30 ); 32 } 33 add_action( 'bp_loaded', 'bp_activity_setup_oembed' ); 34 35 /** 36 * Add inline styles for BP activity embeds. 37 * 38 * This is subject to change or be removed entirely for a different system. 39 * See PHPDoc for BP_Legacy::locate_asset_in_stack(). 40 * 41 * @since 2.6.0 42 * @access private 43 */ 44 function _bp_activity_embed_add_inline_styles() { 45 $inline_css = <<<EOD 46 47 #wp-embed-header:after { 48 clear: both; 49 content: ""; 50 display: table; 51 margin-bottom: 1em; 52 } 53 54 .wp-embed-avatar { 55 float: left; 56 margin: 0 .75em 0 0; 57 } 58 59 p.wp-embed-heading { 60 font-size: 16px; 61 margin-bottom: 0; 62 } 63 64 .wp-embed-excerpt, p.wp-embed-timestamp { 65 margin-bottom: .5em; 66 } 67 68 .wp-embed-excerpt a { 69 color: #21759b; 70 display: inline-block; 71 overflow: hidden; 72 text-overflow: ellipsis; 73 vertical-align: top; 74 white-space: nowrap; 75 max-width: 250px; 76 } 77 78 .bp-activity-embed-display-media { 79 height: auto; 80 max-width: 550px; 81 } 82 83 .bp-activity-embed-display-media img { 84 height: auto; 85 max-width: 100%; 86 } 87 88 .activity-read-more { 89 margin-left: .5em; 90 } 91 92 .activity-read-more a { 93 color: #b4b9be; 94 } 95 96 .wp-embed-footer { 97 margin-top: 20px; 98 } 99 100 EOD; 101 102 // Piggyback off of 'open-sans' handle so we can use our inline CSS. 103 wp_add_inline_style( 'open-sans', $inline_css ); 104 } 105 add_action( 'bp_enqueue_embed_scripts', '_bp_activity_embed_add_inline_styles' ); 106 107 /** 108 * Outputs excerpt for an activity embed item. 109 * 110 * @since 2.6.0 111 */ 112 function bp_activity_embed_excerpt( $content = '' ) { 113 echo bp_activity_get_embed_excerpt( $content = '' ); 114 } 115 116 /** 117 * Generates excerpt for an activity embed item. 118 * 119 * @since 2.6.0 120 * 121 * @param string $content The content to generate an excerpt for. 122 * @return string 123 */ 124 function bp_activity_get_embed_excerpt( $content = '' ) { 125 if ( empty( $content ) && ! empty( $GLOBALS['activities_template']->in_the_loop ) ) { 126 $content = $GLOBALS['activities_template']->activity->content; 127 128 // No content, so use action value. 129 if ( empty( $content ) ) { 130 $action = bp_activity_get_action( bp_get_activity_object_name(), bp_get_activity_type() ); 131 $content = false !== $action ? $action['value'] : ''; 132 } 133 } 134 135 /** 136 * bp_activity_truncate_entry() includes the 'Read More' link, which is why 137 * we're using this instead of bp_create_excerpt(). 138 */ 139 $content = html_entity_decode( $content ); 140 $content = bp_activity_truncate_entry( $content, array( 141 'html' => false, 142 'filter_shortcodes' => true, 143 'strip_tags' => true, 144 'force_truncate' => true 145 ) ); 146 147 /** 148 * Filter the activity embed excerpt. 149 * 150 * @since 2.6.0 151 * 152 * @var string $content Embed Excerpt. 153 * @var string $unmodified_content Unmodified activity content. 154 */ 155 return apply_filters( 'bp_activity_get_embed_excerpt', $content, $GLOBALS['activities_template']->activity->content ); 156 } 157 158 /** 159 * Outputs the first embedded item in the activity oEmbed template. 160 * 161 * @since 2.6.0 162 */ 163 function bp_activity_embed_response_display_media() { 164 // Bail if oEmbed request explicitly hides media. 165 if ( isset( $_REQUEST['hide_media'] ) && true == wp_validate_boolean( $_REQUEST['hide_media'] ) ) { 166 return; 167 } 168 169 // Find all embeds for the activity item. 170 $embeds = bp_core_extract_media_from_content( $GLOBALS['activities_template']->activity->content, 'embeds' ); 171 172 /** 173 * Should we display media in the oEmbed template? 174 * 175 * @since 2.6.0 176 * 177 * @param bool $retval Defaults to true. 178 */ 179 $allow_embeds = apply_filters( 'bp_activity_embed_display_media', true ); 180 181 // Only embed the first embedded item. 182 if ( $embeds && $allow_embeds ) { 183 // Call BP_Embed if it hasn't already loaded. 184 bp_embed_init(); 185 186 // Autoembed first URL. 187 $content = buddypress()->embed->autoembed( $embeds['embeds'][0]['url'] ); 188 189 // Wrap content around a custom DIV. 190 echo '<div class="bp-activity-embed-display-media">' . $content . '</div>'; 191 192 // Add fluidvids.js for responsive IFRAMEs / OBJECTs. 193 if ( false !== strpos( $content, '<iframe' ) || false !== strpos( $content, '<object' ) ) { 194 ?> 195 196 <script> 197 /*! fluidvids.js v2.4.1 | (c) 2014 @toddmotto | License: MIT | https://github.com/toddmotto/fluidvids */ 198 !function(e,t){"function"==typeof define&&define.amd?define(t):"object"==typeof exports?module.exports=t:e.fluidvids=t()}(this,function(){"use strict";function e(e){return new RegExp("^(https?:)?//(?:"+d.players.join("|")+").*$","i").test(e)}function t(e,t){return parseInt(e,10)/parseInt(t,10)*100+"%"}function i(i){if((e(i.src)||e(i.data))&&!i.getAttribute("data-fluidvids")){var n=document.createElement("div");i.parentNode.insertBefore(n,i),i.className+=(i.className?" ":"")+"fluidvids-item",i.setAttribute("data-fluidvids","loaded"),n.className+="fluidvids",n.style.paddingTop=t(i.height,i.width),n.appendChild(i)}}function n(){var e=document.createElement("div");e.innerHTML="<p>x</p><style>"+o+"</style>",r.appendChild(e.childNodes[1])}var d={selector:["iframe","object"],players:["www.youtube.com","player.vimeo.com"]},o=[".fluidvids {","width: 100%; max-width: 100%; position: relative;","}",".fluidvids-item {","position: absolute; top: 0px; left: 0px; width: 100%; height: 100%;","}"].join(""),r=document.head||document.getElementsByTagName("head")[0];return d.render=function(){for(var e=document.querySelectorAll(d.selector.join()),t=e.length;t--;)i(e[t])},d.init=function(e){for(var t in e)d[t]=e[t];d.render(),n()},d}); 199 200 // init 201 fluidvids.init({ 202 selector: ['iframe', 'object'], 203 players: ['.'] // remove default youtube / vimeo restriction. 204 }); 205 </script> 206 207 <?php 208 } 209 } 210 } 211 add_action( 'bp_activity_embed_after_content', 'bp_activity_embed_response_display_media' ); -
src/bp-activity/bp-activity-filters.php
395 395 * This method can only be used inside the Activity loop. 396 396 * 397 397 * @since 1.5.0 398 * 399 * @uses bp_is_single_activity() 400 * @uses apply_filters() To call the 'bp_activity_excerpt_append_text' hook. 401 * @uses apply_filters() To call the 'bp_activity_excerpt_length' hook. 402 * @uses bp_create_excerpt() 403 * @uses bp_get_activity_id() 404 * @uses bp_get_activity_thread_permalink() 405 * @uses apply_filters() To call the 'bp_activity_truncate_entry' hook. 398 * @since 2.6.0 Added $args parameter. 406 399 * 407 400 * @param string $text The original activity entry text. 408 401 * @return string $excerpt The truncated text. 409 402 */ 410 function bp_activity_truncate_entry( $text ) {403 function bp_activity_truncate_entry( $text, $args = array() ) { 411 404 global $activities_template; 412 405 413 406 /** … … 423 416 ); 424 417 425 418 // The full text of the activity update should always show on the single activity screen. 426 if ( ! $maybe_truncate_text || bp_is_single_activity() ) {419 if ( empty( $args['force_truncate'] ) && ( ! $maybe_truncate_text || bp_is_single_activity() ) ) { 427 420 return $text; 428 421 } 429 422 … … 445 438 */ 446 439 $excerpt_length = apply_filters( 'bp_activity_excerpt_length', 358 ); 447 440 441 $args = wp_parse_args( $args, array( 'ending' => __( '…', 'buddypress' ) ) ); 442 448 443 // Run the text through the excerpt function. If it's too short, the original text will be returned. 449 $excerpt = bp_create_excerpt( $text, $excerpt_length, array( 'ending' => __( '…', 'buddypress' ) ));444 $excerpt = bp_create_excerpt( $text, $excerpt_length, $args ); 450 445 451 446 /* 452 447 * If the text returned by bp_create_excerpt() is different from the original text (ie it's 453 448 * been truncated), add the "Read More" link. Note that bp_create_excerpt() is stripping 454 449 * shortcodes, so we have strip them from the $text before the comparison. 455 450 */ 456 if ( $excerpt != strip_shortcodes( $text) ) {451 if ( strlen( $excerpt ) > strlen( strip_shortcodes( $text ) ) ) { 457 452 $id = !empty( $activities_template->activity->current_comment->id ) ? 'acomment-read-more-' . $activities_template->activity->current_comment->id : 'activity-read-more-' . bp_get_activity_id(); 458 453 459 454 $excerpt = sprintf( '%1$s<span class="activity-read-more" id="%2$s"><a href="%3$s" rel="nofollow">%4$s</a></span>', $excerpt, $id, bp_get_activity_thread_permalink(), $append_text ); -
src/bp-activity/bp-activity-functions.php
3337 3337 } 3338 3338 3339 3339 // Generate a text excerpt for this activity item (and remove any oEmbeds URLs). 3340 $summary = strip_shortcodes( html_entity_decode( strip_tags( $content ) ) ); 3341 $summary = bp_create_excerpt( preg_replace( '#^\s*(https?://[^\s"]+)\s*$#im', '', $summary ) ); 3340 $summary = bp_create_excerpt( html_entity_decode( $content ), 225, array( 3341 'html' => false, 3342 'filter_shortcodes' => true, 3343 'strip_tags' => true, 3344 'remove_links' => true 3345 ) ); 3342 3346 3343 3347 if ( $use_media_type === 'embeds' ) { 3344 3348 $summary .= PHP_EOL . PHP_EOL . $extracted_media['url']; -
src/bp-activity/classes/class-bp-activity-component.php
32 32 array( 33 33 'adminbar_myaccount_order' => 10, 34 34 'search_query_arg' => 'activity_search', 35 'features' => array( 'embeds' ) 35 36 ) 36 37 ); 37 38 } … … 72 73 $includes[] = 'akismet'; 73 74 } 74 75 76 // Embeds - only applicable for WP 4.5+ 77 if ( bp_get_major_wp_version() >= 4.5 && bp_is_active( $this->id, 'embeds' ) ) { 78 $includes[] = 'embeds'; 79 } 80 75 81 if ( is_admin() ) { 76 82 $includes[] = 'admin'; 77 83 } -
new file src/bp-activity/classes/class-bp-activity-oembed-component.php
new file mode 100644
- + 1 <?php 2 /** 3 * BuddyPress Activity Classes. 4 * 5 * @package BuddyPress 6 * @subpackage Embeds 7 */ 8 9 // Exit if accessed directly. 10 defined( 'ABSPATH' ) || exit; 11 12 require_once( buddypress()->plugin_dir . '/bp-core/classes/class-bp-oembed-component.php' ); 13 14 /** 15 * oEmbed handler to respond and render single activity items. 16 * 17 * @since 2.6.0 18 */ 19 class BP_Activity_oEmbed_Component extends BP_oEmbed_Component { 20 /** 21 * Custom oEmbed slug endpoint. 22 * 23 * @since 2.6.0 24 * 25 * @var string 26 */ 27 public $slug_endpoint = 'activity'; 28 29 /** 30 * Custom hooks. 31 * 32 * @since 2.6.0 33 */ 34 protected function custom_hooks() { 35 add_action( 'embed_content_meta', array( $this, 'embed_comments_button' ), 5 ); 36 37 add_filter( 'bp_activity_embed_html', array( $this, 'modify_iframe' ) ); 38 } 39 40 /** 41 * Add custom endpoint arguments. 42 * 43 * Currently, includes 'hide_media'. 44 * 45 * @since 2.6.0 46 * 47 * @return array 48 */ 49 protected function set_route_args() { 50 return array( 51 'hide_media' => array( 52 'default' => false, 53 'sanitize_callback' => 'wp_validate_boolean' 54 ) 55 ); 56 } 57 58 /** 59 * Output our custom embed template part. 60 * 61 * @since 2.6.0 62 */ 63 protected function content() { 64 bp_get_asset_template_part( 'embeds/activity' ); 65 } 66 67 /** 68 * Check if we're on our single activity page. 69 * 70 * @since 2.6.0 71 * 72 * @return bool 73 */ 74 protected function is_page() { 75 return bp_is_single_activity(); 76 } 77 78 /** 79 * Validates the URL to determine if the activity item is valid. 80 * 81 * @since 2.6.0 82 * 83 * @param string $url The URL to check. 84 * @return int|bool Activity ID on success; boolean false on failure. 85 */ 86 protected function validate_url_to_item_id( $url ) { 87 if ( bp_core_enable_root_profiles() ) { 88 $domain = bp_get_root_domain(); 89 } else { 90 $domain = bp_get_members_directory_permalink(); 91 } 92 93 // Check the URL to see if this is a single activity URL. 94 if ( 0 !== strpos( $url, $domain ) ) { 95 return false; 96 } 97 98 // Check for activity slug. 99 if ( false === strpos( $url, '/' . bp_get_activity_slug() . '/' ) ) { 100 return false; 101 } 102 103 // Do more checks. 104 $url = trim( untrailingslashit( $url ) ); 105 106 // Grab the activity ID. 107 $activity_id = (int) substr( 108 $url, 109 strrpos( $url, '/' ) + 1 110 ); 111 112 if ( ! empty( $activity_id ) ) { 113 // Check if activity item still exists. 114 $activity = new BP_Activity_Activity( $activity_id ); 115 116 // Okay, we're good to go! 117 if ( ! empty( $activity->component ) && 0 === (int) $activity->is_spam ) { 118 return $activity_id; 119 } 120 } 121 122 return false; 123 } 124 125 /** 126 * Sets the oEmbed response data for our activity item. 127 * 128 * @since 2.6.0 129 * 130 * @param int $item_id The activity ID. 131 * @return array 132 */ 133 protected function set_oembed_response_data( $item_id ) { 134 $activity = new BP_Activity_Activity( $item_id ); 135 136 return array( 137 'user_id' => $activity->user_id, 138 'content' => $activity->content, 139 'title' => __( 'Activity', 'buddypress' ), 140 'author_url' => bp_core_get_user_domain( $activity->user_id ) 141 ); 142 } 143 144 /** 145 * Sets a custom <blockquote> for our oEmbed fallback HTML. 146 * 147 * @since 2.6.0 148 * 149 * @param int $item_id The activity ID. 150 * @return string 151 */ 152 protected function set_fallback_html( $item_id ) { 153 $activity = new BP_Activity_Activity( $item_id ); 154 $mentionname = bp_activity_do_mentions() ? ' (@' . bp_activity_get_user_mentionname( $activity->user_id ) . ')' : ''; 155 $date = date_i18n( get_option( 'date_format' ), strtotime( $activity->date_recorded ) ); 156 157 // Make sure we can use some activity functions that depend on the loop. 158 $GLOBALS['activities_template'] = new stdClass; 159 $GLOBALS['activities_template']->activity = $activity; 160 161 // 'wp-embedded-content' CSS class is necessary due to how the embed JS works. 162 $blockquote = sprintf( '<blockquote class="wp-embedded-content bp-activity-item">%1$s%2$s %3$s</blockquote>', 163 '<p>' . bp_activity_get_embed_excerpt( $activity->content ) . '</p>', 164 '- ' . bp_core_get_user_displayname( $activity->user_id ) . $mentionname, 165 '<a href="' . esc_url( bp_activity_get_permalink( $item_id ) ) . '">' . $date . '</a>' 166 ); 167 168 // Clean up. 169 unset( $GLOBALS['activities_template'] ); 170 171 /** 172 * Filters the fallback HTML used when embedding a BP activity item. 173 * 174 * @since 2.6.0 175 * 176 * @param string $blockquote Current fallback HTML 177 * @param BP_Activity_Activity $activity Activity object 178 */ 179 return apply_filters( 'bp_activity_embed_fallback_html', $blockquote, $activity ); 180 } 181 182 /** 183 * Sets a custom <iframe> title for our oEmbed item. 184 * 185 * @since 2.6.0 186 * 187 * @param int $item_id The activity ID 188 * @return string 189 */ 190 protected function set_iframe_title( $item_id ) { 191 return __( 'Embedded Activity Item', 'buddypress' ); 192 } 193 194 /** 195 * Modify various IFRAME-related items if embeds are allowed. 196 * 197 * IFRAME attributes added: 198 * - sandbox="allow-same-origin" - Only added for Twitter and Soundcloud 199 * embeds to allow them to work. 200 * - allowfullscreen="true" - Allows users to view embed content fullscreen. 201 * 202 * JS modified: 203 * - remove IFRAME height restriction of 1000px. Fixes long embed items being 204 * truncated. 205 * - delay IFRAME onload script by 550ms. Fixes resize issues with Tumblr embeds. 206 * 207 * @since 2.6.0 208 * 209 * @param string $retval Current embed HTML. 210 * @return string 211 */ 212 public function modify_iframe( $retval ) { 213 // Bail if oEmbed request explicitly hides media. 214 if ( isset( $_REQUEST['hide_media'] ) && true == wp_validate_boolean( $_REQUEST['hide_media'] ) ) { 215 return $retval; 216 } 217 218 // Check filter-configured value. 219 if ( false == apply_filters( 'bp_activity_embed_display_media', true ) ) { 220 return $retval; 221 } 222 223 // Add 'allow-same-origin' sandbox attribute to IFRAME. 224 // This is only applicable for Twitter and Soundcloud embeds. 225 if ( false === strpos( $retval, 'allow-same-origin' ) ) { 226 // Grab activity meta for this item. 227 $meta = bp_activity_get_meta( $this->get_item_id() ); 228 229 $checked = false; 230 foreach( $meta as $key => $val ) { 231 if ( $checked ) { 232 break; 233 } 234 235 // Not an oEmbed meta item. 236 if ( false === strpos( $key, '_oembed' ) ) { 237 continue; 238 } 239 240 $checked = true; 241 242 // See if the first embed is a Soundcloud or Twitter item. 243 if ( false === strpos( $val[0], 'soundcloud.com' ) && false === strpos( $val[0], 'twitter.com' ) ) { 244 continue; 245 } 246 247 // Add the 'allow-same-origin' attribute. 248 $retval = str_replace( 'sandbox="', 'sandbox="allow-same-origin ', $retval ); 249 } 250 } 251 252 // Add 'allowfullscreen' attribute to IFRAME. 253 if ( false === strpos( $retval, 'allowfullscreen=' ) ) { 254 $retval = str_replace( '<iframe', '<iframe allowfullscreen="true"', $retval ); 255 } 256 257 // See /wp-includes/js/wp-embed.js. 258 if ( SCRIPT_DEBUG ) { 259 // Removes WP's hardcoded IFRAME height restriction. 260 $retval = str_replace( 'height = 1000;', 'height = height;', $retval ); 261 262 // Delay IFRAME postMessage script so Tumblr embeds are not truncated. 263 $retval = str_replace( 264 "window.addEventListener( 'message', window.wp.receiveEmbedMessage, false );", 265 "window.addEventListener( 'message', function(e) { 266 if ( e.source.frameElement.contentDocument.querySelector('iframe.tumblr-embed') ) { 267 setTimeout( function() { 268 window.wp.receiveEmbedMessage(e); 269 }, 550 ); 270 } else { 271 window.wp.receiveEmbedMessage(e); 272 } 273 }, false );", 274 $retval 275 ); 276 277 // This is for the WP build minified version. 278 } else { 279 $retval = str_replace( 'g=1e3', 'g=g', $retval ); 280 $retval = str_replace( 281 'a.addEventListener("message",a.wp.receiveEmbedMessage,!1)', 282 'a.addEventListener("message",function(e){if(e.source.frameElement.contentDocument.querySelector("iframe.tumblr-embed")){setTimeout(function(){a.wp.receiveEmbedMessage(e);},550);}else{a.wp.receiveEmbedMessage(e);}},!1)', 283 $retval 284 ); 285 } 286 287 return $retval; 288 } 289 290 /** 291 * Prints the markup for the activity embed comments button. 292 * 293 * Basically a copy of {@link print_embed_comments_button()}, but modified for 294 * the BP activity component. 295 * 296 * @since 2.6.0 297 */ 298 public function embed_comments_button() { 299 if ( ! bp_is_single_activity() ) { 300 return; 301 } 302 303 // Make sure our custom permalink shows up in the 'WordPress Embed' block. 304 add_filter( 'the_permalink', array( $this, 'filter_embed_url' ) ); 305 306 // Only show comment bubble if we have some activity comments. 307 $count = bp_activity_get_comment_count(); 308 if ( empty( $count ) ) { 309 return; 310 } 311 ?> 312 313 <div class="wp-embed-comments"> 314 <a href="<?php bp_activity_thread_permalink(); ?>"> 315 <span class="dashicons dashicons-admin-comments"></span> 316 <?php 317 printf( 318 _n( 319 '%s <span class="screen-reader-text">Comment</span>', 320 '%s <span class="screen-reader-text">Comments</span>', 321 $count, 322 'buddypress' 323 ), 324 number_format_i18n( $count ) 325 ); 326 ?> 327 </a> 328 </div> 329 330 <?php 331 } 332 } -
src/bp-core/bp-core-actions.php
40 40 add_action( 'setup_theme', 'bp_setup_theme', 10 ); 41 41 add_action( 'after_setup_theme', 'bp_after_setup_theme', 100 ); // After WP themes. 42 42 add_action( 'wp_enqueue_scripts', 'bp_enqueue_scripts', 10 ); 43 add_action( 'enqueue_embed_scripts', 'bp_enqueue_embed_scripts', 10 ); 43 44 add_action( 'admin_bar_menu', 'bp_setup_admin_bar', 20 ); // After WP core. 44 45 add_action( 'template_redirect', 'bp_template_redirect', 10 ); 45 46 add_action( 'widgets_init', 'bp_widgets_init', 10 ); -
src/bp-core/bp-core-dependency.php
477 477 } 478 478 479 479 /** 480 * Fires the 'bp_enqueue_embed_scripts' action in the <head> for BP oEmbeds. 481 * 482 * @since 2.6.0 483 */ 484 function bp_enqueue_embed_scripts() { 485 if ( ! is_buddypress() ) { 486 return; 487 } 488 489 /** 490 * Enqueue CSS and JS files for BuddyPress embeds. 491 * 492 * @since 2.6.0 493 */ 494 do_action ( 'bp_enqueue_embed_scripts' ); 495 } 496 497 /** 480 498 * Fire the 'bp_add_rewrite_tag' action, where BP adds its custom rewrite tags. 481 499 * 482 500 * @since 1.8.0 -
src/bp-core/bp-core-functions.php
1666 1666 return apply_filters( 'bp_use_embed_in_private_messages', !defined( 'BP_EMBED_DISABLE_PRIVATE_MESSAGES' ) || !BP_EMBED_DISABLE_PRIVATE_MESSAGES ); 1667 1667 } 1668 1668 1669 /** 1670 * Extracts media metadata from a given content. 1671 * 1672 * @since 2.6.0 1673 * 1674 * @param string $content The content to check. 1675 * @param string|int $type The type to check. Can also use a bitmask. See the class constants in the 1676 * BP_Media_Extractor class for more info. 1677 * @return array|bool If media exists, will return array of media metadata. Else, boolean false. 1678 */ 1679 function bp_core_extract_media_from_content( $content = '', $type = 'all' ) { 1680 if ( is_string( $type ) ) { 1681 $class = new ReflectionClass( 'BP_Media_Extractor' ); 1682 $bitmask = $class->getConstant( strtoupper( $type ) ); 1683 } else { 1684 $bitmask = (int) $type; 1685 } 1686 1687 // Type isn't valid, so bail. 1688 if ( empty( $bitmask ) ) { 1689 return false; 1690 } 1691 1692 $x = new BP_Media_Extractor; 1693 $media = $x->extract( $content, $bitmask ); 1694 1695 unset( $media['has'] ); 1696 $retval = array_filter( $media ); 1697 1698 return ! empty( $retval ) ? $retval : false; 1699 } 1700 1669 1701 /** Admin *********************************************************************/ 1670 1702 1671 1703 /** -
src/bp-core/bp-core-template-loader.php
66 66 } 67 67 68 68 /** 69 * Get an asset template part. 70 * 71 * Basically the same as {@link bp_get_template_part()}, but with 'assets/' 72 * prepended to the slug. 73 * 74 * @since 2.6.0 75 * 76 * @see bp_get_template_part() for full documentation. 77 */ 78 function bp_get_asset_template_part( $slug, $name = null ) { 79 return bp_get_template_part( "assets/{$slug}", $name ); 80 } 81 82 /** 69 83 * Retrieve the name of the highest priority template file that exists. 70 84 * 71 85 * Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which -
src/bp-core/bp-core-template.php
769 769 * This function is borrowed from CakePHP v2.0, under the MIT license. See 770 770 * http://book.cakephp.org/view/1469/Text#truncate-1625 771 771 * 772 * @since 2.6.0 Added 'strip_tags' and 'remove_links' as $options args. 773 * 772 774 * ### Options: 773 775 * 774 776 * - `ending` Will be used as Ending and appended to the trimmed string. … … 791 793 * excerpt length. Default: true. 792 794 * @type bool $filter_shortcodes If true, shortcodes will be stripped. 793 795 * Default: true. 796 * @type bool $strip_tags If true, HTML tags will be stripped. Default: false. 797 * Only applicable if $html is set to false. 798 * @type bool $remove_links If true, URLs will be stripped. Default: false. 799 * Only applicable if $html is set to false. 794 800 * } 795 801 * @return string Trimmed string. 796 802 */ … … 803 809 'ending' => __( ' […]', 'buddypress' ), 804 810 'exact' => false, 805 811 'html' => true, 806 'filter_shortcodes' => $filter_shortcodes_default 812 'filter_shortcodes' => $filter_shortcodes_default, 813 'strip_tags' => false, 814 'remove_links' => false, 807 815 ), 'create_excerpt' ); 808 816 809 817 // Save the original text, to be passed along to the filter. … … 889 897 } 890 898 } 891 899 } else { 900 // Strip HTML tags if necessary. 901 if ( ! empty( $r['strip_tags'] ) ) { 902 $text = strip_tags( $text ); 903 } 904 905 // Remove links if necessary. 906 if ( ! empty( $r['remove_links'] ) ) { 907 $text = preg_replace( '#^\s*(https?://[^\s"]+)\s*$#im', '', $text ); 908 } 909 892 910 if ( mb_strlen( $text ) <= $length ) { 893 return $text; 911 /** 912 * Filters the final generated excerpt. 913 * 914 * @since 1.1.0 915 * 916 * @param string $truncate Generated excerpt. 917 * @param string $original_text Original text provided. 918 * @param int $length Length of returned string, including ellipsis. 919 * @param array $options Array of HTML attributes and options. 920 */ 921 return apply_filters( 'bp_create_excerpt', $text, $original_text, $length, $options ); 894 922 } else { 895 923 $truncate = mb_substr( $text, 0, $length - mb_strlen( $ending ) ); 896 924 } -
src/bp-core/bp-core-theme-compatibility.php
547 547 } 548 548 549 549 /** 550 * Create a dummy WP_Post object. 551 * 552 * @since 2.6.0 553 * 554 * @param array $args Array of optional arguments. Arguments parallel the properties 555 * of {@link WP_Post}; see that class for more details. 556 * @return WP_Post 557 */ 558 function bp_theme_compat_create_dummy_post( $args = array() ) { 559 $args = wp_parse_args( $args, array( 560 'ID' => -9999, 561 'post_status' => 'public', 562 'post_author' => 0, 563 'post_parent' => 0, 564 'post_type' => 'page', 565 'post_date' => 0, 566 'post_date_gmt' => 0, 567 'post_modified' => 0, 568 'post_modified_gmt' => 0, 569 'post_content' => '', 570 'post_title' => '', 571 'post_excerpt' => '', 572 'post_content_filtered' => '', 573 'post_mime_type' => '', 574 'post_password' => '', 575 'post_name' => '', 576 'guid' => '', 577 'menu_order' => 0, 578 'pinged' => '', 579 'to_ping' => '', 580 'ping_status' => '', 581 'comment_status' => 'closed', 582 'comment_count' => 0, 583 'filter' => 'raw', 584 585 'is_404' => false, 586 'is_page' => false, 587 'is_single' => false, 588 'is_archive' => false, 589 'is_tax' => false, 590 ) ); 591 592 // Create the dummy post. 593 $post = new WP_Post( (object) $args ); 594 595 return $post; 596 } 597 598 /** 550 599 * Populate various WordPress globals with dummy data to prevent errors. 551 600 * 552 601 * This dummy data is necessary because theme compatibility essentially fakes … … 567 616 568 617 // Switch defaults if post is set. 569 618 if ( isset( $wp_query->post ) ) { 570 $ dummy= wp_parse_args( $args, array(619 $args = wp_parse_args( $args, array( 571 620 'ID' => $wp_query->post->ID, 572 621 'post_status' => $wp_query->post->post_status, 573 622 'post_author' => $wp_query->post->post_author, … … 592 641 'comment_status' => $wp_query->post->comment_status, 593 642 'comment_count' => $wp_query->post->comment_count, 594 643 'filter' => $wp_query->post->filter, 595 596 'is_404' => false,597 'is_page' => false,598 'is_single' => false,599 'is_archive' => false,600 'is_tax' => false,601 ) );602 } else {603 $dummy = wp_parse_args( $args, array(604 'ID' => -9999,605 'post_status' => 'public',606 'post_author' => 0,607 'post_parent' => 0,608 'post_type' => 'page',609 'post_date' => 0,610 'post_date_gmt' => 0,611 'post_modified' => 0,612 'post_modified_gmt' => 0,613 'post_content' => '',614 'post_title' => '',615 'post_excerpt' => '',616 'post_content_filtered' => '',617 'post_mime_type' => '',618 'post_password' => '',619 'post_name' => '',620 'guid' => '',621 'menu_order' => 0,622 'pinged' => '',623 'to_ping' => '',624 'ping_status' => '',625 'comment_status' => 'closed',626 'comment_count' => 0,627 'filter' => 'raw',628 629 'is_404' => false,630 'is_page' => false,631 'is_single' => false,632 'is_archive' => false,633 'is_tax' => false,634 644 ) ); 635 645 } 636 646 637 647 // Bail if dummy post is empty. 638 if ( empty( $ dummy) ) {648 if ( empty( $args ) ) { 639 649 return; 640 650 } 641 651 642 652 // Set the $post global. 643 $post = new WP_Post( (object) $dummy);653 $post = bp_theme_compat_create_dummy_post( $args ); 644 654 645 655 // Copy the new post global into the main $wp_query. 646 656 $wp_query->post = $post; … … 648 658 649 659 // Prevent comments form from appearing. 650 660 $wp_query->post_count = 1; 651 $wp_query->is_404 = $dummy['is_404']; 652 $wp_query->is_page = $dummy['is_page']; 653 $wp_query->is_single = $dummy['is_single']; 654 $wp_query->is_archive = $dummy['is_archive']; 655 $wp_query->is_tax = $dummy['is_tax']; 656 657 // Clean up the dummy post. 658 unset( $dummy ); 661 $wp_query->is_404 = $post->is_404; 662 $wp_query->is_page = $post->is_page; 663 $wp_query->is_single = $post->is_single; 664 $wp_query->is_archive = $post->is_archive; 665 $wp_query->is_tax = $post->is_tax; 659 666 660 667 /** 661 668 * Force the header back to 200 status if not a deliberate 404 … … 700 707 * @return string $template Template name. 701 708 */ 702 709 function bp_template_include_theme_compat( $template = '' ) { 710 // If embed template, bail. 711 if ( is_embed() ) { 712 return $template; 713 } 703 714 704 715 // If the current theme doesn't need theme compat, bail at this point. 705 716 if ( ! bp_use_theme_compat_with_current_theme() ) { -
src/bp-core/classes/class-bp-admin.php
836 836 <a href="https://bbpress.org">bbPress</a>, 837 837 <a href="https://github.com/ichord/Caret.js">Caret.js</a>, 838 838 <a href="http://tedgoas.github.io/Cerberus/">Cerberus</a>, 839 <a href="https://github.com/toddmotto/fluidvids">fluidvids.js</a>, 839 840 <a href="https://github.com/carhartl/jquery-cookie">jquery.cookie</a>, 840 841 <a href="https://www.mediawiki.org/wiki/MediaWiki">MediaWiki</a>, 841 842 <a href="https://wordpress.org">WordPress</a>. -
new file src/bp-core/classes/class-bp-oembed-component.php
new file mode 100644
- + 1 <?php 2 /** 3 * Core component classes. 4 * 5 * @package BuddyPress 6 * @subpackage Core 7 */ 8 9 // Exit if accessed directly. 10 defined( 'ABSPATH' ) || exit; 11 12 /** 13 * API for responding and returning a custom oEmbed request. 14 * 15 * @since 2.6.0 16 */ 17 abstract class BP_oEmbed_Component { 18 19 /** START PROPERTIES ****************************************************/ 20 21 /** 22 * (required) The slug endpoint. 23 * 24 * Should be your component id. 25 * 26 * @var string 27 */ 28 public $slug_endpoint = ''; 29 30 /** 31 * (optional) Embed template hierarchy. 32 * 33 * Define the template hierarchy for your oEmbed rendering. 34 * 35 * @var array 36 */ 37 protected $template_hierarchy = array(); 38 39 /** END PROPERTIES ******************************************************/ 40 41 /** 42 * Constructor. 43 */ 44 final public function __construct() { 45 $this->setup_properties(); 46 47 // Some rudimentary logic checking. 48 if ( empty( $this->slug_endpoint ) ) { 49 $class = get_class( $this ); 50 throw new LogicException( $class . ' class must define $slug_endpoint property' ); 51 } 52 53 $this->setup_hooks(); 54 $this->custom_hooks(); 55 } 56 57 /** REQUIRED METHODS ****************************************************/ 58 59 /** 60 * Add content for your oEmbed response here. 61 * 62 * @since 2.6.0 63 */ 64 abstract protected function content(); 65 66 /** 67 * Add a check for when you are on the page you want to oEmbed. 68 * 69 * You'll want to return a boolean here. eg. bp_is_single_activity(). 70 * 71 * @since 2.6.0 72 * 73 * @return bool 74 */ 75 abstract protected function is_page(); 76 77 /** 78 * Validate the URL to see if it matches your item ID. 79 * 80 * @since 2.6.0 81 * 82 * @return int Your item ID 83 */ 84 abstract protected function validate_url_to_item_id( $url ); 85 86 /** 87 * Set the oEmbed response data. 88 * 89 * @since 2.6.0 90 * 91 * @param int $item_id Your item ID to do checks against. 92 * @return array Should contain 'user_id', 'content', 'title', 'author_url' as array keys. 93 * 'author_url' is optional; the rest are required. 94 */ 95 abstract protected function set_oembed_response_data( $item_id ); 96 97 /** 98 * Sets the fallback HTML for the oEmbed response. 99 * 100 * In a WordPress oEmbed item, the fallback HTML is a <blockquote>. This is 101 * usually hidden after the <iframe> is loaded. 102 * 103 * @since 2.6.0 104 * 105 * @param int $item_id Your item ID to do checks against. 106 * @return string Fallback HTML you want to output. 107 */ 108 abstract protected function set_fallback_html( $item_id ); 109 110 /** OPTIONAL METHODS ****************************************************/ 111 112 /** 113 * If your oEmbed endpoint requires additional arguments, set them here. 114 * 115 * @see register_rest_route() View the $args parameter for more info. 116 * 117 * @since 2.6.0 118 * 119 * @return array 120 */ 121 protected function set_route_args() { 122 return array(); 123 } 124 125 /** 126 * Set the iframe title. 127 * 128 * If not set, this will fallback to WP's 'Embedded WordPress Post'. 129 * 130 * @param int $item_id The item ID to do checks for. 131 * @return string 132 */ 133 protected function set_iframe_title( $item_id ) {} 134 135 /** 136 * Do what you need to do here to initialize any custom hooks. 137 * 138 * @since 2.6.0 139 */ 140 protected function custom_hooks() {} 141 142 /** 143 * Set permalink for oEmbed link discovery. 144 * 145 * This method will be called on the page we want to oEmbed. In most cases, 146 * you will not need to override this method. However, if you need to, do 147 * override in your extended class. 148 * 149 * @since 2.6.0 150 */ 151 protected function set_permalink() { 152 $url = bp_get_requested_url(); 153 154 // Remove querystring from bp_get_requested_url() 155 if ( false !== strpos( bp_get_requested_url(), '?' ) ) { 156 $url = substr( bp_get_requested_url(), 0, strpos( bp_get_requested_url(), '?' ) ); 157 } 158 159 return $url; 160 } 161 162 /** HELPERS *************************************************************/ 163 164 /** 165 * Get the item ID when filtering the oEmbed HTML. 166 * 167 * Should only be used during the 'embed_html' hook. 168 * 169 * @since 2.6.0 170 */ 171 protected function get_item_id() { 172 return $this->is_page() ? $this->validate_url_to_item_id( $this->set_permalink() ) : buddypress()->{$this->slug_endpoint}->embedid_in_progress; 173 } 174 175 /** SET UP **************************************************************/ 176 177 /** 178 * Set up properties. 179 * 180 * @since 2.6.0 181 */ 182 protected function setup_properties() { 183 $this->slug_endpoint = sanitize_title( $this->slug_endpoint ); 184 } 185 186 /** 187 * Hooks! We do the dirty work here, so you don't have to! :) 188 * 189 * More hooks are available in the setup_template_parts() method. 190 * 191 * @since 2.6.0 192 */ 193 protected function setup_hooks() { 194 add_action( 'rest_api_init', array( $this, 'register_route' ) ); 195 add_action( 'bp_embed_content', array( $this, 'inject_content' ) ); 196 197 add_filter( 'embed_template', array( $this, 'setup_template_parts' ) ); 198 add_filter( 'post_embed_url', array( $this, 'filter_embed_url' ) ); 199 add_filter( 'embed_html', array( $this, 'filter_embed_html' ) ); 200 add_filter( 'oembed_discovery_links', array( $this, 'add_oembed_discovery_links' ) ); 201 } 202 203 /** HOOKS ***************************************************************/ 204 205 /** 206 * Register the oEmbed REST API route. 207 * 208 * @since 2.6.0 209 */ 210 public function register_route() { 211 /** This filter is documented in wp-includes/class-wp-oembed-controller.php */ 212 $maxwidth = apply_filters( 'oembed_default_width', 600 ); 213 214 // Required arguments. 215 $args = array( 216 'url' => array( 217 'required' => true, 218 'sanitize_callback' => 'esc_url_raw', 219 ), 220 'format' => array( 221 'default' => 'json', 222 'sanitize_callback' => 'wp_oembed_ensure_format', 223 ), 224 'maxwidth' => array( 225 'default' => $maxwidth, 226 'sanitize_callback' => 'absint', 227 ) 228 ); 229 230 // Merge custom arguments here. 231 $args = $args + (array) $this->set_route_args(); 232 233 register_rest_route( 'oembed/1.0', "/embed/{$this->slug_endpoint}", array( 234 array( 235 'methods' => WP_REST_Server::READABLE, 236 'callback' => array( $this, 'get_item' ), 237 'args' => $args 238 ), 239 ) ); 240 } 241 242 /** 243 * Set up custom embed template parts for BuddyPress use. 244 * 245 * @since 2.6.0 246 * 247 * @param string $template File path to current embed template. 248 * @return string 249 */ 250 public function setup_template_parts( $template ) { 251 // Determine if we're on our BP page. 252 if ( ! $this->is_page() || is_404() ) { 253 return $template; 254 } 255 256 // Set up some BP-specific embed template overrides. 257 add_action( 'embed_head', array( $this, 'add_base_element' ), 1 ); 258 add_action( 'get_template_part_embed', array( $this, 'content_buffer_start' ), -999, 2 ); 259 add_action( 'get_footer', array( $this, 'content_buffer_end' ), -999 ); 260 261 // Return the original WP embed template. 262 return $template; 263 } 264 265 /** 266 * Add <base> element to embed <head>. 267 */ 268 public function add_base_element() { 269 echo '<base target="_top" />'; 270 } 271 272 /** 273 * Start object buffer. 274 * 275 * We're going to override WP's get_template_part( 'embed, 'content' ) call 276 * and inject our own template for BuddyPress use. 277 */ 278 public function content_buffer_start( $slug, $name ) { 279 if ( 'embed' !== $slug || 'content' !== $name ) { 280 return; 281 } 282 283 // Start the buffer to wipe out get_template_part( 'embed, 'content' ). 284 ob_start(); 285 } 286 287 /** 288 * End object buffer. 289 * 290 * We're going to override WP's get_template_part( 'embed, 'content' ) call 291 * and inject our own template for BuddyPress use. 292 */ 293 public function content_buffer_end( $name ) { 294 if ( 'embed' !== $name || is_404() ) { 295 return; 296 } 297 298 // Wipe out get_template_part( 'embed, 'content' ). 299 ob_end_clean(); 300 301 // Start our custom BuddyPress embed template! 302 echo '<div '; 303 post_class( 'wp-embed' ); 304 echo '>'; 305 306 // Template part for our embed header. 307 bp_get_asset_template_part( 'embeds/header', bp_current_component() ); 308 309 /** 310 * Inject BuddyPress embed content on this hook. 311 * 312 * You shouldn't really need to use this if you extend the 313 * {@link BP_oEmbed_Component} class. 314 * 315 * @since 2.6.0 316 */ 317 do_action( 'bp_embed_content' ); 318 319 // Template part for our embed footer. 320 bp_get_asset_template_part( 'embeds/footer', bp_current_component() ); 321 322 echo '</div>'; 323 } 324 325 /** 326 * Adds oEmbed discovery links on single activity pages. 327 * 328 * @since 2.6.0 329 * 330 * @param string $retval Current discovery links. 331 * @return string 332 */ 333 public function add_oembed_discovery_links( $retval ) { 334 if ( ! $this->is_page() ) { 335 return $retval; 336 } 337 338 $permalink = $this->set_permalink(); 339 if ( empty( $permalink ) ) { 340 return $retval; 341 } 342 343 add_filter( 'rest_url' , array( $this, 'filter_rest_url' ) ); 344 345 $retval = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink ) ) . '" />' . "\n"; 346 347 if ( class_exists( 'SimpleXMLElement' ) ) { 348 $retval .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink, 'xml' ) ) . '" />' . "\n"; 349 } 350 351 remove_filter( 'rest_url' , array( $this, 'filter_rest_url' ) ); 352 353 return $retval; 354 } 355 356 /** 357 * Callback for the API endpoint. 358 * 359 * Returns the JSON object for the item. 360 * 361 * @since 2.6.0 362 * 363 * @param WP_REST_Request $request Full data about the request. 364 * @return WP_Error|array oEmbed response data or WP_Error on failure. 365 */ 366 public function get_item( $request ) { 367 $url = $request['url']; 368 369 $data = false; 370 371 $item_id = (int) $this->validate_url_to_item_id( $url ); 372 373 if ( ! empty( $item_id ) ) { 374 $item = $this->set_oembed_response_data( $item_id ); 375 376 // Create dummy post to piggyback off of get_oembed_response_data() 377 $post = bp_theme_compat_create_dummy_post( array( 378 'post_author' => $item['user_id'], 379 'post_title' => $item['title'], 380 'post_content' => $item['content'], 381 382 // This passes the get_oembed_response_data() check. 383 'post_status' => 'publish' 384 ) ); 385 386 // Add markers to tell that we're embedding a single activity. 387 // This is needed for various oEmbed response data filtering. 388 if ( empty( buddypress()->{$this->slug_endpoint} ) ) { 389 buddypress()->{$this->slug_endpoint} = new stdClass; 390 } 391 buddypress()->{$this->slug_endpoint}->embedurl_in_progress = $url; 392 buddypress()->{$this->slug_endpoint}->embedid_in_progress = $item_id; 393 394 // Save custom route args as well. 395 $custom_args = array_keys( (array) $this->set_route_args() ); 396 if ( ! empty( $custom_args ) ) { 397 buddypress()->{$this->slug_endpoint}->embedargs_in_progress = array(); 398 399 foreach( $custom_args as $arg ) { 400 if ( isset( $request[ $arg ] ) ) { 401 buddypress()->{$this->slug_endpoint}->embedargs_in_progress[ $arg ] = $request[ $arg ]; 402 } 403 } 404 } 405 406 // Use WP's oEmbed response data function. 407 $data = get_oembed_response_data( $post, $request['maxwidth'] ); 408 409 // Set custom 'author_url' if we have one. 410 if ( ! empty( $item['author_url'] ) ) { 411 $data['author_url'] = $item['author_url']; 412 } 413 } 414 415 if ( ! $data ) { 416 return new WP_Error( 'oembed_invalid_url', get_status_header_desc( 404 ), array( 'status' => 404 ) ); 417 } 418 419 return $data; 420 } 421 422 /** 423 * Pass our BuddyPress activity permalink for embedding. 424 * 425 * @since 2.6.0 426 * 427 * @see bp_activity_embed_rest_route_callback() 428 * 429 * @param string $retval Current embed URL 430 * @return string 431 */ 432 public function filter_embed_url( $retval ) { 433 if ( false === isset( buddypress()->{$this->slug_endpoint}->embedurl_in_progress ) && ! $this->is_page() ) { 434 return $retval; 435 } 436 437 $url = $this->is_page() ? $this->set_permalink() : buddypress()->{$this->slug_endpoint}->embedurl_in_progress; 438 $url = trailingslashit( $url ); 439 440 // This is for the 'WordPress Embed' block 441 // @see bp_activity_embed_comments_button() 442 if ( 'the_permalink' !== current_filter() ) { 443 $url = add_query_arg( 'embed', 'true', trailingslashit( $url ) ); 444 445 // Add custom route args to iframe. 446 if ( ! empty( buddypress()->{$this->slug_endpoint}->embedargs_in_progress ) ) { 447 foreach( buddypress()->{$this->slug_endpoint}->embedargs_in_progress as $key => $value ) { 448 $url = add_query_arg( $key, $value, $url ); 449 } 450 } 451 } 452 453 return $url; 454 } 455 456 /** 457 * Filters the embed HTML for our BP oEmbed endpoint. 458 * 459 * @since 2.6.0 460 * 461 * @param string $retval Current embed HTML 462 * @return string 463 */ 464 public function filter_embed_html( $retval ) { 465 if ( false === isset( buddypress()->{$this->slug_endpoint}->embedurl_in_progress ) && ! $this->is_page() ) { 466 return $retval; 467 } 468 469 $url = $this->set_permalink(); 470 471 $item_id = $this->is_page() ? $this->validate_url_to_item_id( $url ) : buddypress()->{$this->slug_endpoint}->embedid_in_progress; 472 473 // Change 'Embedded WordPress Post' to custom title. 474 $custom_title = $this->set_iframe_title( $item_id ); 475 if ( ! empty( $custom_title ) ) { 476 $title_pos = strpos( $retval, 'title=' ) + 7; 477 $title_end_pos = strpos( $retval, '"', $title_pos ); 478 479 $retval = substr_replace( $retval, esc_attr( $custom_title ), $title_pos, $title_end_pos - $title_pos ); 480 } 481 482 // Add 'max-width' CSS attribute to IFRAME. 483 // This will make our oEmbeds responsive. 484 if ( false === strpos( $retval, 'style="max-width' ) ) { 485 $retval = str_replace( '<iframe', '<iframe style="max-width:100%"', $retval ); 486 } 487 488 // Remove default <blockquote> 489 $retval = substr( $retval, strpos( $retval, '</blockquote>' ) + 13 ); 490 491 // Set up new fallback HTML 492 // @todo Maybe use KSES? 493 $fallback_html = $this->set_fallback_html( $item_id ); 494 495 /** 496 * Dynamic filter to return BP oEmbed HTML. 497 * 498 * @since 2.6.0 499 * 500 * @var string $retval 501 */ 502 return apply_filters( "bp_{$this->slug_endpoint}_embed_html", $fallback_html . $retval ); 503 } 504 505 /** 506 * Append our custom slug endpoint to oEmbed endpoint URL. 507 * 508 * Meant to be used as a filter on 'rest_url' before any call to 509 * {@link get_oembed_endpoint_url()} is used. 510 * 511 * @since 2.6.0 512 * 513 * @see add_oembed_discovery_links() 514 * 515 * @param string $retval Current oEmbed endpoint URL 516 * @return string 517 */ 518 function filter_rest_url( $retval = '' ) { 519 return $retval . "/{$this->slug_endpoint}"; 520 } 521 522 /** 523 * Inject activity content into the embed template. 524 * 525 * @since 2.6.0 526 */ 527 public function inject_content() { 528 if ( ! $this->is_page() ) { 529 return; 530 } 531 532 $this->content(); 533 } 534 } 535 No newline at end of file -
new file src/bp-templates/bp-legacy/buddypress/assets/embeds/activity.php
new file mode 100644
- + 1 2 <?php if ( bp_has_activities( 'display_comments=threaded&show_hidden=true&include=' . bp_current_action() ) ) : ?> 3 4 <?php while ( bp_activities() ) : bp_the_activity(); ?> 5 <div class="wp-embed-excerpt"><?php bp_activity_embed_excerpt(); ?></div> 6 7 <p class="wp-embed-timestamp"><a href="<?php bp_activity_thread_permalink(); ?>"><?php echo date_i18n( get_option( 'time_format' ) . ' - ' . get_option( 'date_format' ), strtotime( bp_get_activity_date_recorded() ) ); ?></a></p> 8 9 <?php do_action( 'bp_activity_embed_after_content' ); ?> 10 11 <?php endwhile; ?> 12 13 <?php endif; ?> 14 -
new file src/bp-templates/bp-legacy/buddypress/assets/embeds/footer.php
new file mode 100644
- + 1 <div class="wp-embed-footer"> 2 <?php the_embed_site_title() ?> 3 4 <div class="wp-embed-meta"> 5 <?php 6 /** This action is documented in wp-includes/theme-compat/embed-content.php */ 7 do_action( 'embed_content_meta'); ?> 8 </div> 9 </div> 10 No newline at end of file -
new file src/bp-templates/bp-legacy/buddypress/assets/embeds/header.php
new file mode 100644
- + 1 2 <div id="wp-embed-header"> 3 <div class="wp-embed-avatar"> 4 <a href="<?php bp_displayed_user_link(); ?>"> 5 <?php bp_displayed_user_avatar( 'type=thumb&width=36&height=36' ); ?> 6 </a> 7 </div> 8 9 <p class="wp-embed-heading"> 10 <a href="<?php bp_displayed_user_link(); ?>"> 11 <?php bp_displayed_user_fullname(); ?> 12 </a> 13 </p> 14 15 <?php if ( bp_is_active( 'activity' ) && bp_activity_do_mentions() ) : ?> 16 <p class="wp-embed-mentionname">@<?php bp_displayed_user_mentionname(); ?></p> 17 <?php endif; ?> 18 </div>