Ticket #6772: 6772.06.patch
File 6772.06.patch, 48.7 KB (added by , 9 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.4+ 18 if ( bp_get_major_wp_version() >= 4.4 && 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.4. 6 * 7 * @since 2.5.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.5.0 20 */ 21 function bp_activity_setup_oembed() { 22 if ( bp_get_major_wp_version() >= 4.4 && 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.5.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.5.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.5.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 129 /** 130 * bp_activity_truncate_entry() includes the 'Read More' link, which is why 131 * we're using this instead of bp_create_excerpt(). 132 */ 133 $content = html_entity_decode( $content ); 134 $content = bp_activity_truncate_entry( $content, array( 135 'html' => false, 136 'filter_shortcodes' => true, 137 'strip_tags' => true, 138 'force_truncate' => true 139 ) ); 140 141 /** 142 * Filter the activity embed excerpt. 143 * 144 * @since 2.5.0 145 * 146 * @var string $content Embed Excerpt. 147 * @var string $unmodified_content Unmodified activity content. 148 */ 149 return apply_filters( 'bp_activity_get_embed_excerpt', $content, $GLOBALS['activities_template']->activity->content ); 150 } 151 152 /** 153 * Outputs the first embedded item in the activity oEmbed template. 154 * 155 * @since 2.5.0 156 */ 157 function bp_activity_embed_response_display_media() { 158 // Bail if oEmbed request explicitly hides media. 159 if ( isset( $_REQUEST['hide_media'] ) && true == wp_validate_boolean( $_REQUEST['hide_media'] ) ) { 160 return; 161 } 162 163 // Find all embeds for the activity item. 164 $embeds = bp_core_extract_media_from_content( $GLOBALS['activities_template']->activity->content, 'embeds' ); 165 166 /** 167 * Should we display media in the oEmbed template? 168 * 169 * @since 2.5.0 170 * 171 * @param bool $retval Defaults to true. 172 */ 173 $allow_embeds = apply_filters( 'bp_activity_embed_display_media', true ); 174 175 // Only embed the first embedded item. 176 if ( $embeds && $allow_embeds ) { 177 // Call BP_Embed if it hasn't already loaded. 178 bp_embed_init(); 179 180 // Autoembed first URL. 181 $content = buddypress()->embed->autoembed( $embeds['embeds'][0]['url'] ); 182 183 // Wrap content around a custom DIV. 184 echo '<div class="bp-activity-embed-display-media">' . $content . '</div>'; 185 186 // Add fluidvids.js for responsive IFRAMEs / OBJECTs. 187 if ( false !== strpos( $content, '<iframe' ) || false !== strpos( $content, '<object' ) ) { 188 ?> 189 190 <script> 191 /*! fluidvids.js v2.4.1 | (c) 2014 @toddmotto | License: MIT | https://github.com/toddmotto/fluidvids */ 192 !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}); 193 194 // init 195 fluidvids.init({ 196 selector: ['iframe', 'object'], 197 players: ['.'] // remove default youtube / vimeo restriction. 198 }); 199 </script> 200 201 <?php 202 } 203 } 204 } 205 add_action( 'bp_activity_embed_after_content', 'bp_activity_embed_response_display_media' ); -
src/bp-activity/bp-activity-filters.php
391 391 * This method can only be used inside the Activity loop. 392 392 * 393 393 * @since 1.5.0 394 * 395 * @uses bp_is_single_activity() 396 * @uses apply_filters() To call the 'bp_activity_excerpt_append_text' hook. 397 * @uses apply_filters() To call the 'bp_activity_excerpt_length' hook. 398 * @uses bp_create_excerpt() 399 * @uses bp_get_activity_id() 400 * @uses bp_get_activity_thread_permalink() 401 * @uses apply_filters() To call the 'bp_activity_truncate_entry' hook. 394 * @since 2.5.0 Added $args parameter. 402 395 * 403 396 * @param string $text The original activity entry text. 404 397 * @return string $excerpt The truncated text. 405 398 */ 406 function bp_activity_truncate_entry( $text ) {399 function bp_activity_truncate_entry( $text, $args = array() ) { 407 400 global $activities_template; 408 401 409 402 /** … … 419 412 ); 420 413 421 414 // The full text of the activity update should always show on the single activity screen. 422 if ( ! $maybe_truncate_text || bp_is_single_activity() ) {415 if ( empty( $args['force_truncate'] ) && ( ! $maybe_truncate_text || bp_is_single_activity() ) ) { 423 416 return $text; 424 417 } 425 418 … … 441 434 */ 442 435 $excerpt_length = apply_filters( 'bp_activity_excerpt_length', 358 ); 443 436 437 $args = wp_parse_args( $args, array( 'ending' => __( '…', 'buddypress' ) ) ); 438 444 439 // Run the text through the excerpt function. If it's too short, the original text will be returned. 445 $excerpt = bp_create_excerpt( $text, $excerpt_length, array( 'ending' => __( '…', 'buddypress' ) ));440 $excerpt = bp_create_excerpt( $text, $excerpt_length, $args ); 446 441 447 442 /* 448 443 * If the text returned by bp_create_excerpt() is different from the original text (ie it's 449 444 * been truncated), add the "Read More" link. Note that bp_create_excerpt() is stripping 450 445 * shortcodes, so we have strip them from the $text before the comparison. 451 446 */ 452 if ( $excerpt != strip_shortcodes( $text) ) {447 if ( strlen( $excerpt ) > strlen( strip_shortcodes( $text ) ) ) { 453 448 $id = !empty( $activities_template->activity->current_comment->id ) ? 'acomment-read-more-' . $activities_template->activity->current_comment->id : 'activity-read-more-' . bp_get_activity_id(); 454 449 455 450 $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
2802 2802 } 2803 2803 2804 2804 // Generate a text excerpt for this activity item (and remove any oEmbeds URLs). 2805 $summary = strip_shortcodes( html_entity_decode( strip_tags( $content ) ) ); 2806 $summary = bp_create_excerpt( preg_replace( '#^\s*(https?://[^\s"]+)\s*$#im', '', $summary ) ); 2805 $summary = bp_create_excerpt( html_entity_decode( $content ), 225, array( 2806 'html' => false, 2807 'filter_shortcodes' => true, 2808 'strip_tags' => true, 2809 'remove_links' => true 2810 ) ); 2807 2811 2808 2812 if ( $use_media_type === 'embeds' ) { 2809 2813 $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 } … … 68 69 $includes[] = 'akismet'; 69 70 } 70 71 72 // Embeds - only applicable for WP 4.4+ 73 if ( bp_get_major_wp_version() >= 4.4 && bp_is_active( $this->id, 'embeds' ) ) { 74 $includes[] = 'embeds'; 75 } 76 71 77 if ( is_admin() ) { 72 78 $includes[] = 'admin'; 73 79 } -
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.5.0 18 */ 19 class BP_Activity_oEmbed_Component extends BP_oEmbed_Component { 20 /** 21 * Custom oEmbed slug endpoint. 22 * 23 * @since 2.5.0 24 * 25 * @var string 26 */ 27 public $slug_endpoint = 'activity'; 28 29 /** 30 * Custom hooks. 31 * 32 * @since 2.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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 * @since 2.5.0 294 */ 295 public function embed_comments_button() { 296 if ( ! bp_is_single_activity() ) { 297 return; 298 } 299 300 // Make sure our custom permalink shows up in the 'WordPress Embed' block. 301 add_filter( 'the_permalink', array( $this, 'filter_embed_url' ) ); 302 303 // Only show comment bubble if we have some activity comments. 304 $count = bp_activity_get_comment_count(); 305 if ( empty( $count ) ) { 306 return; 307 } 308 ?> 309 310 <div class="wp-embed-comments"> 311 <a href="<?php bp_activity_thread_permalink(); ?>"> 312 <span class="dashicons dashicons-admin-comments"></span> 313 <?php 314 printf( 315 _n( 316 '%s <span class="screen-reader-text">Comment</span>', 317 '%s <span class="screen-reader-text">Comments</span>', 318 $count, 319 'buddypress' 320 ), 321 number_format_i18n( $count ) 322 ); 323 ?> 324 </a> 325 </div> 326 327 <?php 328 } 329 } -
src/bp-core/bp-core-actions.php
39 39 add_action( 'setup_theme', 'bp_setup_theme', 10 ); 40 40 add_action( 'after_setup_theme', 'bp_after_setup_theme', 100 ); // After WP themes. 41 41 add_action( 'wp_enqueue_scripts', 'bp_enqueue_scripts', 10 ); 42 add_action( 'enqueue_embed_scripts', 'bp_enqueue_embed_scripts', 10 ); 42 43 add_action( 'admin_bar_menu', 'bp_setup_admin_bar', 20 ); // After WP core. 43 44 add_action( 'template_redirect', 'bp_template_redirect', 10 ); 44 45 add_action( 'widgets_init', 'bp_widgets_init', 10 ); -
src/bp-core/bp-core-dependency.php
459 459 } 460 460 461 461 /** 462 * Fires the 'bp_enqueue_embed_scripts' action in the <head> for BP oEmbeds. 463 * 464 * @since 2.5.0 465 */ 466 function bp_enqueue_embed_scripts() { 467 if ( ! is_buddypress() ) { 468 return; 469 } 470 471 /** 472 * Enqueue CSS and JS files for BuddyPress embeds. 473 * 474 * @since 2.5.0 475 */ 476 do_action ( 'bp_enqueue_embed_scripts' ); 477 } 478 479 /** 462 480 * Fire the 'bp_add_rewrite_tag' action, where BP adds its custom rewrite tags. 463 481 * 464 482 * @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.5.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.5.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.5.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
545 545 } 546 546 547 547 /** 548 * Create a dummy WP_Post object. 549 * 550 * @since 2.5.0 551 * 552 * @param array $args Array of optional arguments. Arguments parallel the properties 553 * of {@link WP_Post}; see that class for more details. 554 * @return WP_Post 555 */ 556 function bp_theme_compat_create_dummy_post( $args = array() ) { 557 $args = wp_parse_args( $args, array( 558 'ID' => -9999, 559 'post_status' => 'public', 560 'post_author' => 0, 561 'post_parent' => 0, 562 'post_type' => 'page', 563 'post_date' => 0, 564 'post_date_gmt' => 0, 565 'post_modified' => 0, 566 'post_modified_gmt' => 0, 567 'post_content' => '', 568 'post_title' => '', 569 'post_excerpt' => '', 570 'post_content_filtered' => '', 571 'post_mime_type' => '', 572 'post_password' => '', 573 'post_name' => '', 574 'guid' => '', 575 'menu_order' => 0, 576 'pinged' => '', 577 'to_ping' => '', 578 'ping_status' => '', 579 'comment_status' => 'closed', 580 'comment_count' => 0, 581 'filter' => 'raw', 582 583 'is_404' => false, 584 'is_page' => false, 585 'is_single' => false, 586 'is_archive' => false, 587 'is_tax' => false, 588 ) ); 589 590 // Create the dummy post. 591 $post = new WP_Post( (object) $args ); 592 593 return $post; 594 } 595 596 /** 548 597 * Populate various WordPress globals with dummy data to prevent errors. 549 598 * 550 599 * This dummy data is necessary because theme compatibility essentially fakes … … 565 614 566 615 // Switch defaults if post is set. 567 616 if ( isset( $wp_query->post ) ) { 568 $ dummy= wp_parse_args( $args, array(617 $args = wp_parse_args( $args, array( 569 618 'ID' => $wp_query->post->ID, 570 619 'post_status' => $wp_query->post->post_status, 571 620 'post_author' => $wp_query->post->post_author, … … 590 639 'comment_status' => $wp_query->post->comment_status, 591 640 'comment_count' => $wp_query->post->comment_count, 592 641 'filter' => $wp_query->post->filter, 593 594 'is_404' => false,595 'is_page' => false,596 'is_single' => false,597 'is_archive' => false,598 'is_tax' => false,599 ) );600 } else {601 $dummy = wp_parse_args( $args, array(602 'ID' => -9999,603 'post_status' => 'public',604 'post_author' => 0,605 'post_parent' => 0,606 'post_type' => 'page',607 'post_date' => 0,608 'post_date_gmt' => 0,609 'post_modified' => 0,610 'post_modified_gmt' => 0,611 'post_content' => '',612 'post_title' => '',613 'post_excerpt' => '',614 'post_content_filtered' => '',615 'post_mime_type' => '',616 'post_password' => '',617 'post_name' => '',618 'guid' => '',619 'menu_order' => 0,620 'pinged' => '',621 'to_ping' => '',622 'ping_status' => '',623 'comment_status' => 'closed',624 'comment_count' => 0,625 'filter' => 'raw',626 627 'is_404' => false,628 'is_page' => false,629 'is_single' => false,630 'is_archive' => false,631 'is_tax' => false,632 642 ) ); 633 643 } 634 644 635 645 // Bail if dummy post is empty. 636 if ( empty( $ dummy) ) {646 if ( empty( $args ) ) { 637 647 return; 638 648 } 639 649 640 650 // Set the $post global. 641 $post = new WP_Post( (object) $dummy);651 $post = bp_theme_compat_create_dummy_post( $args ); 642 652 643 653 // Copy the new post global into the main $wp_query. 644 654 $wp_query->post = $post; … … 646 656 647 657 // Prevent comments form from appearing. 648 658 $wp_query->post_count = 1; 649 $wp_query->is_404 = $dummy['is_404']; 650 $wp_query->is_page = $dummy['is_page']; 651 $wp_query->is_single = $dummy['is_single']; 652 $wp_query->is_archive = $dummy['is_archive']; 653 $wp_query->is_tax = $dummy['is_tax']; 654 655 // Clean up the dummy post. 656 unset( $dummy ); 659 $wp_query->is_404 = $post->is_404; 660 $wp_query->is_page = $post->is_page; 661 $wp_query->is_single = $post->is_single; 662 $wp_query->is_archive = $post->is_archive; 663 $wp_query->is_tax = $post->is_tax; 657 664 658 665 /** 659 666 * Force the header back to 200 status if not a deliberate 404 -
src/bp-core/classes/class-bp-admin.php
783 783 <a href="https://bbpress.org">bbPress</a>, 784 784 <a href="https://github.com/ichord/Caret.js">Caret.js</a>, 785 785 <a href="http://tedgoas.github.io/Cerberus/">Cerberus</a>, 786 <a href="https://github.com/toddmotto/fluidvids">fluidvids.js</a>, 786 787 <a href="https://github.com/carhartl/jquery-cookie">jquery.cookie</a>, 787 788 <a href="https://www.mediawiki.org/wiki/MediaWiki">MediaWiki</a>, 788 789 <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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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.5.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 * @since 2.5.0 190 */ 191 protected function setup_hooks() { 192 add_action( 'rest_api_init', array( $this, 'register_route' ) ); 193 add_action( 'bp_embed_content', array( $this, 'inject_content' ) ); 194 195 add_filter( 'embed_template', array( $this, 'filter_template' ) ); 196 add_filter( 'post_embed_url', array( $this, 'filter_embed_url' ) ); 197 add_filter( 'embed_html', array( $this, 'filter_embed_html' ) ); 198 add_filter( 'oembed_discovery_links', array( $this, 'add_oembed_discovery_links' ) ); 199 } 200 201 /** HOOKS ***************************************************************/ 202 203 /** 204 * Register the oEmbed REST API route. 205 * 206 * @since 2.5.0 207 */ 208 public function register_route() { 209 /** This filter is documented in wp-includes/class-wp-oembed-controller.php */ 210 $maxwidth = apply_filters( 'oembed_default_width', 600 ); 211 212 // Required arguments. 213 $args = array( 214 'url' => array( 215 'required' => true, 216 'sanitize_callback' => 'esc_url_raw', 217 ), 218 'format' => array( 219 'default' => 'json', 220 'sanitize_callback' => 'wp_oembed_ensure_format', 221 ), 222 'maxwidth' => array( 223 'default' => $maxwidth, 224 'sanitize_callback' => 'absint', 225 ) 226 ); 227 228 // Merge custom arguments here. 229 $args = $args + (array) $this->set_route_args(); 230 231 register_rest_route( 'oembed/1.0', "/embed/{$this->slug_endpoint}", array( 232 array( 233 'methods' => WP_REST_Server::READABLE, 234 'callback' => array( $this, 'get_item' ), 235 'args' => $args 236 ), 237 ) ); 238 } 239 240 /** 241 * Filters the embed template. 242 * 243 * Override if needed. 244 * 245 * @since 2.5.0 246 * 247 * @param string $template File path to current embed template. 248 * @return string 249 */ 250 public function filter_template( $template ) { 251 if ( ! $this->is_page() || is_404() ) { 252 return $template; 253 } 254 255 // Embed template hierarchy! 256 return bp_locate_template( array( 257 'assets/embeds/template.php' 258 ) ); 259 } 260 261 /** 262 * Adds oEmbed discovery links on single activity pages. 263 * 264 * @since 2.5.0 265 * 266 * @param string $retval Current discovery links. 267 * @return string 268 */ 269 public function add_oembed_discovery_links( $retval ) { 270 if ( ! $this->is_page() ) { 271 return $retval; 272 } 273 274 $permalink = $this->set_permalink(); 275 if ( empty( $permalink ) ) { 276 return $retval; 277 } 278 279 add_filter( 'rest_url' , array( $this, 'filter_rest_url' ) ); 280 281 $retval = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink ) ) . '" />' . "\n"; 282 283 if ( class_exists( 'SimpleXMLElement' ) ) { 284 $retval .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink, 'xml' ) ) . '" />' . "\n"; 285 } 286 287 remove_filter( 'rest_url' , array( $this, 'filter_rest_url' ) ); 288 289 return $retval; 290 } 291 292 /** 293 * Callback for the API endpoint. 294 * 295 * Returns the JSON object for the item. 296 * 297 * @since 2.5.0 298 * 299 * @param WP_REST_Request $request Full data about the request. 300 * @return WP_Error|array oEmbed response data or WP_Error on failure. 301 */ 302 public function get_item( $request ) { 303 $url = $request['url']; 304 305 $data = false; 306 307 $item_id = (int) $this->validate_url_to_item_id( $url ); 308 309 if ( ! empty( $item_id ) ) { 310 $item = $this->set_oembed_response_data( $item_id ); 311 312 // Create dummy post to piggyback off of get_oembed_response_data() 313 $post = bp_theme_compat_create_dummy_post( array( 314 'post_author' => $item['user_id'], 315 'post_title' => $item['title'], 316 'post_content' => $item['content'], 317 318 // This passes the get_oembed_response_data() check. 319 'post_status' => 'publish' 320 ) ); 321 322 // Add markers to tell that we're embedding a single activity. 323 // This is needed for various oEmbed response data filtering. 324 if ( empty( buddypress()->{$this->slug_endpoint} ) ) { 325 buddypress()->{$this->slug_endpoint} = new stdClass; 326 } 327 buddypress()->{$this->slug_endpoint}->embedurl_in_progress = $url; 328 buddypress()->{$this->slug_endpoint}->embedid_in_progress = $item_id; 329 330 // Save custom route args as well. 331 $custom_args = array_keys( (array) $this->set_route_args() ); 332 if ( ! empty( $custom_args ) ) { 333 buddypress()->{$this->slug_endpoint}->embedargs_in_progress = array(); 334 335 foreach( $custom_args as $arg ) { 336 if ( isset( $request[ $arg ] ) ) { 337 buddypress()->{$this->slug_endpoint}->embedargs_in_progress[ $arg ] = $request[ $arg ]; 338 } 339 } 340 } 341 342 // Use WP's oEmbed response data function. 343 $data = get_oembed_response_data( $post, $request['maxwidth'] ); 344 345 // Set custom 'author_url' if we have one. 346 if ( ! empty( $item['author_url'] ) ) { 347 $data['author_url'] = $item['author_url']; 348 } 349 } 350 351 if ( ! $data ) { 352 return new WP_Error( 'oembed_invalid_url', get_status_header_desc( 404 ), array( 'status' => 404 ) ); 353 } 354 355 return $data; 356 } 357 358 /** 359 * Pass our BuddyPress activity permalink for embedding. 360 * 361 * @since 2.5.0 362 * 363 * @see bp_activity_embed_rest_route_callback() 364 * 365 * @param string $retval Current embed URL 366 * @return string 367 */ 368 public function filter_embed_url( $retval ) { 369 if ( false === isset( buddypress()->{$this->slug_endpoint}->embedurl_in_progress ) && ! $this->is_page() ) { 370 return $retval; 371 } 372 373 $url = $this->is_page() ? $this->set_permalink() : buddypress()->{$this->slug_endpoint}->embedurl_in_progress; 374 $url = trailingslashit( $url ); 375 376 // This is for the 'WordPress Embed' block 377 // @see bp_activity_embed_comments_button() 378 if ( 'the_permalink' !== current_filter() ) { 379 $url = add_query_arg( 'embed', 'true', trailingslashit( $url ) ); 380 381 // Add custom route args to iframe. 382 if ( ! empty( buddypress()->{$this->slug_endpoint}->embedargs_in_progress ) ) { 383 foreach( buddypress()->{$this->slug_endpoint}->embedargs_in_progress as $key => $value ) { 384 $url = add_query_arg( $key, $value, $url ); 385 } 386 } 387 } 388 389 return $url; 390 } 391 392 /** 393 * Filters the embed HTML for our BP oEmbed endpoint. 394 * 395 * @since 2.5.0 396 * 397 * @param string $retval Current embed HTML 398 * @return string 399 */ 400 public function filter_embed_html( $retval ) { 401 if ( false === isset( buddypress()->{$this->slug_endpoint}->embedurl_in_progress ) && ! $this->is_page() ) { 402 return $retval; 403 } 404 405 $url = $this->set_permalink(); 406 407 $item_id = $this->is_page() ? $this->validate_url_to_item_id( $url ) : buddypress()->{$this->slug_endpoint}->embedid_in_progress; 408 409 // Change 'Embedded WordPress Post' to custom title. 410 $custom_title = $this->set_iframe_title( $item_id ); 411 if ( ! empty( $custom_title ) ) { 412 $title_pos = strpos( $retval, 'title=' ) + 7; 413 $title_end_pos = strpos( $retval, '"', $title_pos ); 414 415 $retval = substr_replace( $retval, esc_attr( $custom_title ), $title_pos, $title_end_pos - $title_pos ); 416 } 417 418 // Add 'max-width' CSS attribute to IFRAME. 419 // This will make our oEmbeds responsive. 420 if ( false === strpos( $retval, 'style="max-width' ) ) { 421 $retval = str_replace( '<iframe', '<iframe style="max-width:100%"', $retval ); 422 } 423 424 // Remove default <blockquote> 425 $retval = substr( $retval, strpos( $retval, '</blockquote>' ) + 13 ); 426 427 // Set up new fallback HTML 428 // @todo Maybe use KSES? 429 $fallback_html = $this->set_fallback_html( $item_id ); 430 431 /** 432 * Dynamic filter to return BP oEmbed HTML. 433 * 434 * @since 2.5.0 435 * 436 * @var string $retval 437 */ 438 return apply_filters( "bp_{$this->slug_endpoint}_embed_html", $fallback_html . $retval ); 439 } 440 441 /** 442 * Append our custom slug endpoint to oEmbed endpoint URL. 443 * 444 * Meant to be used as a filter on 'rest_url' before any call to 445 * {@link get_oembed_endpoint_url()} is used. 446 * 447 * @since 2.5.0 448 * 449 * @see add_oembed_discovery_links() 450 * 451 * @param string $retval Current oEmbed endpoint URL 452 * @return string 453 */ 454 function filter_rest_url( $retval = '' ) { 455 return $retval . "/{$this->slug_endpoint}"; 456 } 457 458 /** 459 * Inject activity content into the embed template. 460 * 461 * @since 2.5.0 462 */ 463 public function inject_content() { 464 if ( ! $this->is_page() ) { 465 return; 466 } 467 468 $this->content(); 469 } 470 } 471 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 <div class="wp-embed-site-title"> 3 <?php 4 $site_title = sprintf( 5 '<a href="%s"><img src="%s" srcset="%s 2x" width="32" height="32" alt="" class="wp-embed-site-icon"/><span>%s</span></a>', 6 esc_url( home_url() ), 7 esc_url( get_site_icon_url( 32, admin_url( 'images/w-logo-blue.png' ) ) ), 8 esc_url( get_site_icon_url( 64, admin_url( 'images/w-logo-blue.png' ) ) ), 9 esc_html( get_bloginfo( 'name' ) ) 10 ); 11 12 /** This filter is documented in wp-includes/embed-template.php */ 13 echo apply_filters( 'embed_site_title_html', $site_title ); 14 ?> 15 </div> 16 17 <div class="wp-embed-meta"> 18 <?php 19 /** This action is documented in wp-includes/embed-template.php */ 20 do_action( 'embed_content_meta'); 21 ?> 22 </div> 23 </div> 24 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> -
new file src/bp-templates/bp-legacy/buddypress/assets/embeds/template.php
new file mode 100644
- + 1 <?php 2 /** 3 * Generic embed template used by BuddyPress. 4 * 5 * When a BuddyPress item is embedded in an iframe, this file is used to 6 * create the output. 7 * 8 * This is a modified version of the bundled WordPress embed template 9 * included in WordPress 4.4+. 10 * 11 * @since 2.5.0 12 * 13 * @package BuddyPress 14 * @subpackage Embeds 15 */ 16 17 if ( ! headers_sent() ) { 18 header( 'X-WP-embed: true' ); 19 } 20 21 ?> 22 <!DOCTYPE html> 23 <html <?php language_attributes(); ?> class="no-js"> 24 <head> 25 <title><?php echo wp_get_document_title(); ?></title> 26 <meta http-equiv="X-UA-Compatible" content="IE=edge"> 27 <base target="_top" /> 28 <?php 29 /** This action is documented in wp-includes/embed-template.php */ 30 do_action( 'embed_head' ); ?> 31 </head> 32 <body <?php body_class(); ?>> 33 <div <?php post_class( 'wp-embed' ); ?>> 34 <?php 35 bp_get_asset_template_part( 'embeds/header', bp_current_component() ); 36 37 /** 38 * Inject BuddyPress embed content on this hook. 39 * 40 * You shouldn't really need to use this if you extend the 41 * {@link BP_oEmbed_Component} class. 42 * 43 * @since 2.5.0 44 */ 45 do_action( 'bp_embed_content' ); 46 47 bp_get_asset_template_part( 'embeds/footer', bp_current_component() ); 48 ?> 49 50 </div> 51 52 <?php 53 /** This action is documented in wp-includes/embed-template.php */ 54 do_action( 'embed_footer' ); 55 ?> 56 </body> 57 </html> 58 No newline at end of file