Ticket #6772: 6772.04.patch
File 6772.04.patch, 32.8 KB (added by , 9 years ago) |
---|
-
src/bp-activity/bp-activity-actions.php
diff --git src/bp-activity/bp-activity-actions.php src/bp-activity/bp-activity-actions.php index f648b41..18ee4c1 100644
function bp_activity_setup_akismet() { 744 744 $bp->activity->akismet = new BP_Akismet(); 745 745 } 746 746 747 748 /** 749 * Loads our activity oEmbed component. 750 * 751 * @since 2.5.0 752 */ 753 function bp_activity_setup_oembed() { 754 if ( bp_get_major_wp_version() >= 4.4 && bp_is_active( 'activity', 'embeds' ) ) { 755 buddypress()->activity->oembed = new BP_Activity_oEmbed_Component; 756 } 757 } 758 747 759 /** 748 760 * AJAX endpoint for Suggestions API lookups. 749 761 * -
src/bp-activity/bp-activity-functions.php
diff --git src/bp-activity/bp-activity-functions.php src/bp-activity/bp-activity-functions.php index e6c101d..a65c0dd 100644
function bp_activity_thumbnail_content_images( $content, $link = false, $args = 2653 2653 } 2654 2654 2655 2655 /** 2656 * Generate a text excerpt for an activity item (and remove any oEmbeds URLs). 2657 * 2658 * @since 2.5.0 2659 * 2660 * @param string $content The content to generate an excerpt for. 2661 * @return string 2662 */ 2663 function bp_activity_create_excerpt( $content = '' ) { 2664 // Use the existing content in the activity loop. 2665 if ( empty( $content ) && ! empty( $GLOBALS['activities_template']->in_the_loop ) ) { 2666 $content = $GLOBALS['activities_template']->activity->content; 2667 } 2668 2669 $content = strip_shortcodes( html_entity_decode( strip_tags( $content ) ) ); 2670 return bp_create_excerpt( preg_replace( '#^\s*(https?://[^\s"]+)\s*$#im', '', $content ) ); 2671 } 2672 2673 /** 2656 2674 * Create a rich summary of an activity item for the activity stream. 2657 2675 * 2658 2676 * More than just a simple excerpt, the summary could contain oEmbeds and other types of media. … … function bp_activity_create_summary( $content, $activity ) { 2789 2807 } 2790 2808 2791 2809 // Generate a text excerpt for this activity item (and remove any oEmbeds URLs). 2792 $summary = strip_shortcodes( html_entity_decode( strip_tags( $content ) ) ); 2793 $summary = bp_create_excerpt( preg_replace( '#^\s*(https?://[^\s"]+)\s*$#im', '', $summary ) ); 2810 $summary = bp_activity_create_excerpt( $content ); 2794 2811 2795 2812 if ( $use_media_type === 'embeds' ) { 2796 2813 $summary .= PHP_EOL . PHP_EOL . $extracted_media['url']; -
src/bp-activity/bp-activity-loader.php
diff --git src/bp-activity/bp-activity-loader.php src/bp-activity/bp-activity-loader.php index dfdf325..ff8dd0f 100644
class BP_Activity_Component extends BP_Component { 31 31 array( 32 32 'adminbar_myaccount_order' => 10, 33 33 'search_query_arg' => 'activity_search', 34 'features' => array( 'embeds' ) 34 35 ) 35 36 ); 36 37 } … … class BP_Activity_Component extends BP_Component { 67 68 $includes[] = 'akismet'; 68 69 } 69 70 71 // Embeds - only applicable for WP 4.4+ 72 if ( bp_get_major_wp_version() >= 4.4 && bp_is_active( $this->id, 'embeds' ) ) { 73 $includes[] = 'classes/class-bp-activity-oembed-component'; 74 } 75 70 76 if ( is_admin() ) { 71 77 $includes[] = 'admin'; 72 78 } … … class BP_Activity_Component extends BP_Component { 365 371 // Spam prevention. 366 372 add_action( 'bp_include', 'bp_activity_setup_akismet' ); 367 373 374 // oEmbed handler. 375 add_action( 'bp_loaded', 'bp_activity_setup_oembed' ); 376 368 377 parent::setup_actions(); 369 378 } 370 379 -
new file src/bp-activity/classes/class-bp-activity-oembed-component.php
diff --git src/bp-activity/classes/class-bp-activity-oembed-component.php src/bp-activity/classes/class-bp-activity-oembed-component.php new file mode 100644 index 0000000..d1b9312
- + 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 38 /** 39 * Output our custom embed template part. 40 * 41 * @since 2.5.0 42 */ 43 protected function content() { 44 bp_get_asset_template_part( 'embeds/activity' ); 45 } 46 47 /** 48 * Check if we're on our single activity page. 49 * 50 * @since 2.5.0 51 * 52 * @return bool 53 */ 54 protected function is_page() { 55 return bp_is_single_activity(); 56 } 57 58 /** 59 * Validates the URL to determine if the activity item is valid. 60 * 61 * @since 2.5.0 62 * 63 * @param string $url The URL to check. 64 * @return int|bool Activity ID on success; boolean false on failure. 65 */ 66 protected function validate_url_to_item_id( $url ) { 67 if ( bp_core_enable_root_profiles() ) { 68 $domain = bp_get_root_domain(); 69 } else { 70 $domain = bp_get_members_directory_permalink(); 71 } 72 73 // Check the URL to see if this is a single activity URL. 74 if ( 0 !== strpos( $url, $domain ) ) { 75 return false; 76 } 77 78 // Check for activity slug. 79 if ( false === strpos( $url, '/' . bp_get_activity_slug() . '/' ) ) { 80 return false; 81 } 82 83 // Do more checks. 84 $url = trim( untrailingslashit( $url ) ); 85 86 // Grab the activity ID. 87 $activity_id = (int) substr( 88 $url, 89 strrpos( $url, '/' ) + 1 90 ); 91 92 if ( ! empty( $activity_id ) ) { 93 // Check if activity item still exists. 94 $activity = new BP_Activity_Activity( $activity_id ); 95 96 // Okay, we're good to go! 97 if ( ! empty( $activity->component ) && 0 === (int) $activity->is_spam ) { 98 return $activity_id; 99 } 100 } 101 102 return false; 103 } 104 105 /** 106 * Sets the oEmbed response data for our activity item. 107 * 108 * @since 2.5.0 109 * 110 * @param int $item_id The activity ID. 111 * @return array 112 */ 113 protected function set_oembed_response_data( $item_id ) { 114 $activity = new BP_Activity_Activity( $item_id ); 115 116 return array( 117 'user_id' => $activity->user_id, 118 'content' => $activity->content, 119 'title' => __( 'Activity', 'buddypress' ), 120 'author_url' => bp_core_get_user_domain( $activity->user_id ) 121 ); 122 } 123 124 /** 125 * Sets a custom <blockquote> for our oEmbed fallback HTML. 126 * 127 * @since 2.5.0 128 * 129 * @param int $item_id The activity ID. 130 * @return string 131 */ 132 protected function set_fallback_html( $item_id ) { 133 $activity = new BP_Activity_Activity( $item_id ); 134 $mentionname = bp_activity_do_mentions() ? ' (@' . bp_activity_get_user_mentionname( $activity->user_id ) . ')' : ''; 135 $date = date_i18n( get_option( 'date_format' ), strtotime( $activity->date_recorded ) ); 136 137 // 'wp-embedded-content' CSS class is necessary due to how the embed JS works. 138 $blockquote = sprintf( '<blockquote class="wp-embedded-content bp-activity-item">%1$s%2$s %3$s</blockquote>', 139 apply_filters( 'bp_get_activity_content_body', $activity->content ), 140 '- ' . bp_core_get_user_displayname( $activity->user_id ) . $mentionname, 141 '<a href="' . esc_url( bp_activity_get_permalink( $item_id ) ) . '">' . $date . '</a>' 142 ); 143 144 /** 145 * Filters the fallback HTML used when embedding a BP activity item. 146 * 147 * @since 2.5.0 148 * 149 * @param string $blockquote Current fallback HTML 150 * @param BP_Activity_Activity $activity Activity object 151 */ 152 return apply_filters( 'bp_activity_embed_fallback_html', $blockquote, $activity ); 153 } 154 155 /** 156 * Sets a custom <iframe> title for our oEmbed item. 157 * 158 * @since 2.5.0 159 * 160 * @param int $item_id The activity ID 161 * @return string 162 */ 163 protected function set_iframe_title( $item_id ) { 164 return __( 'Embedded Activity Item', 'buddypress' ); 165 } 166 167 /** 168 * Prints the markup for the activity embed comments button. 169 * 170 * @since 2.5.0 171 */ 172 public function embed_comments_button() { 173 if ( ! bp_is_single_activity() ) { 174 return; 175 } 176 177 // Make sure our custom permalink shows up in the 'WordPress Embed' block. 178 add_filter( 'the_permalink', array( $this, 'filter_embed_url' ) ); 179 180 // Only show comment bubble if we have some activity comments. 181 $count = bp_activity_get_comment_count(); 182 if ( empty( $count ) ) { 183 return; 184 } 185 ?> 186 187 <div class="wp-embed-comments"> 188 <a href="<?php bp_activity_thread_permalink(); ?>"> 189 <span class="dashicons dashicons-admin-comments"></span> 190 <?php 191 printf( 192 _n( 193 '%s <span class="screen-reader-text">Comment</span>', 194 '%s <span class="screen-reader-text">Comments</span>', 195 $count 196 ), 197 number_format_i18n( $count ) 198 ); 199 ?> 200 </a> 201 </div> 202 203 <?php 204 } 205 } -
src/bp-core/bp-core-functions.php
diff --git src/bp-core/bp-core-functions.php src/bp-core/bp-core-functions.php index f865d7c..da8540d 100644
function bp_use_embed_in_private_messages() { 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
diff --git src/bp-core/bp-core-template-loader.php src/bp-core/bp-core-template-loader.php index 91c67ef..8f4b03c 100644
function bp_get_template_part( $slug, $name = null ) { 65 65 } 66 66 67 67 /** 68 * Get an asset template part. 69 * 70 * Basically the same as {@link bp_get_template_part()}, but with 'assets/' 71 * prepended to the slug. 72 * 73 * @since 2.5.0 74 * 75 * @see bp_get_template_part() for full documentation. 76 */ 77 function bp_get_asset_template_part( $slug, $name = null ) { 78 return bp_get_template_part( "assets/{$slug}", $name ); 79 } 80 81 /** 68 82 * Retrieve the name of the highest priority template file that exists. 69 83 * 70 84 * Searches in the STYLESHEETPATH before TEMPLATEPATH so that themes which -
src/bp-core/bp-core-theme-compatibility.php
diff --git src/bp-core/bp-core-theme-compatibility.php src/bp-core/bp-core-theme-compatibility.php index da54dce..0de2895 100644
function bp_register_theme_package( $theme = array(), $override = true ) { 650 650 } 651 651 652 652 /** 653 * Create a dummy WP_Post object. 654 * 655 * @since 2.5.0 656 * 657 * @param array $args Array of optional arguments. Arguments parallel the properties 658 * of {@link WP_Post}; see that class for more details. 659 * @return WP_Post 660 */ 661 function bp_theme_compat_create_dummy_post( $args = array() ) { 662 $args = wp_parse_args( $args, array( 663 'ID' => -9999, 664 'post_status' => 'public', 665 'post_author' => 0, 666 'post_parent' => 0, 667 'post_type' => 'page', 668 'post_date' => 0, 669 'post_date_gmt' => 0, 670 'post_modified' => 0, 671 'post_modified_gmt' => 0, 672 'post_content' => '', 673 'post_title' => '', 674 'post_excerpt' => '', 675 'post_content_filtered' => '', 676 'post_mime_type' => '', 677 'post_password' => '', 678 'post_name' => '', 679 'guid' => '', 680 'menu_order' => 0, 681 'pinged' => '', 682 'to_ping' => '', 683 'ping_status' => '', 684 'comment_status' => 'closed', 685 'comment_count' => 0, 686 'filter' => 'raw', 687 688 'is_404' => false, 689 'is_page' => false, 690 'is_single' => false, 691 'is_archive' => false, 692 'is_tax' => false, 693 ) ); 694 695 // Create the dummy post. 696 $post = new WP_Post( (object) $args ); 697 698 return $post; 699 } 700 701 /** 653 702 * Populate various WordPress globals with dummy data to prevent errors. 654 703 * 655 704 * This dummy data is necessary because theme compatibility essentially fakes … … function bp_theme_compat_reset_post( $args = array() ) { 670 719 671 720 // Switch defaults if post is set. 672 721 if ( isset( $wp_query->post ) ) { 673 $ dummy= wp_parse_args( $args, array(722 $args = wp_parse_args( $args, array( 674 723 'ID' => $wp_query->post->ID, 675 724 'post_status' => $wp_query->post->post_status, 676 725 'post_author' => $wp_query->post->post_author, … … function bp_theme_compat_reset_post( $args = array() ) { 695 744 'comment_status' => $wp_query->post->comment_status, 696 745 'comment_count' => $wp_query->post->comment_count, 697 746 'filter' => $wp_query->post->filter, 698 699 'is_404' => false,700 'is_page' => false,701 'is_single' => false,702 'is_archive' => false,703 'is_tax' => false,704 ) );705 } else {706 $dummy = wp_parse_args( $args, array(707 'ID' => -9999,708 'post_status' => 'public',709 'post_author' => 0,710 'post_parent' => 0,711 'post_type' => 'page',712 'post_date' => 0,713 'post_date_gmt' => 0,714 'post_modified' => 0,715 'post_modified_gmt' => 0,716 'post_content' => '',717 'post_title' => '',718 'post_excerpt' => '',719 'post_content_filtered' => '',720 'post_mime_type' => '',721 'post_password' => '',722 'post_name' => '',723 'guid' => '',724 'menu_order' => 0,725 'pinged' => '',726 'to_ping' => '',727 'ping_status' => '',728 'comment_status' => 'closed',729 'comment_count' => 0,730 'filter' => 'raw',731 732 'is_404' => false,733 'is_page' => false,734 'is_single' => false,735 'is_archive' => false,736 'is_tax' => false,737 747 ) ); 738 748 } 739 749 740 750 // Bail if dummy post is empty. 741 if ( empty( $ dummy) ) {751 if ( empty( $args ) ) { 742 752 return; 743 753 } 744 754 745 755 // Set the $post global. 746 $post = new WP_Post( (object) $dummy);756 $post = bp_theme_compat_create_dummy_post( $args ); 747 757 748 758 // Copy the new post global into the main $wp_query. 749 759 $wp_query->post = $post; … … function bp_theme_compat_reset_post( $args = array() ) { 751 761 752 762 // Prevent comments form from appearing. 753 763 $wp_query->post_count = 1; 754 $wp_query->is_404 = $dummy['is_404']; 755 $wp_query->is_page = $dummy['is_page']; 756 $wp_query->is_single = $dummy['is_single']; 757 $wp_query->is_archive = $dummy['is_archive']; 758 $wp_query->is_tax = $dummy['is_tax']; 759 760 // Clean up the dummy post. 761 unset( $dummy ); 764 $wp_query->is_404 = $post->is_404; 765 $wp_query->is_page = $post->is_page; 766 $wp_query->is_single = $post->is_single; 767 $wp_query->is_archive = $post->is_archive; 768 $wp_query->is_tax = $post->is_tax; 762 769 763 770 /** 764 771 * Force the header back to 200 status if not a deliberate 404 -
new file src/bp-core/classes/class-bp-oembed-component.php
diff --git src/bp-core/classes/class-bp-oembed-component.php src/bp-core/classes/class-bp-oembed-component.php new file mode 100644 index 0000000..bab746f
- + 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 * Set permalink for oEmbed link discovery. 114 * 115 * This method will be called on the page we want to oEmbed. Override in your 116 * extended class method if needed. 117 * 118 * @since 2.5.0 119 */ 120 protected function set_permalink() { 121 // Remove querystring from bp_get_requested_url() 122 return substr( bp_get_requested_url(), 0, strpos( bp_get_requested_url(), '?' ) ); 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 /** SET UP **************************************************************/ 143 144 /** 145 * Set up properties. 146 * 147 * @since 2.5.0 148 */ 149 protected function setup_properties() { 150 $this->slug_endpoint = sanitize_title( $this->slug_endpoint ); 151 } 152 153 /** 154 * Hooks! We do the dirty work here, so you don't have to! :) 155 * 156 * @since 2.5.0 157 */ 158 protected function setup_hooks() { 159 add_action( 'rest_api_init', array( $this, 'register_route' ) ); 160 add_action( 'embed_content', array( $this, 'inject_content' ) ); 161 162 add_filter( 'embed_template', array( $this, 'filter_template' ) ); 163 add_filter( 'post_embed_url', array( $this, 'filter_embed_url' ) ); 164 add_filter( 'embed_html', array( $this, 'filter_embed_html' ) ); 165 add_filter( 'oembed_discovery_links', array( $this, 'add_oembed_discovery_links' ) ); 166 } 167 168 /** HOOKS ***************************************************************/ 169 170 /** 171 * Register the oEmbed REST API route. 172 * 173 * @since 2.5.0 174 */ 175 public function register_route() { 176 /** This filter is documented in wp-includes/class-wp-oembed-controller.php */ 177 $maxwidth = apply_filters( 'oembed_default_width', 600 ); 178 179 register_rest_route( 'oembed/1.0', "/embed/{$this->slug_endpoint}", array( 180 array( 181 'methods' => WP_REST_Server::READABLE, 182 'callback' => array( $this, 'get_item' ), 183 'args' => array( 184 'url' => array( 185 'required' => true, 186 'sanitize_callback' => 'esc_url_raw', 187 ), 188 'format' => array( 189 'default' => 'json', 190 'sanitize_callback' => 'wp_oembed_ensure_format', 191 ), 192 'maxwidth' => array( 193 'default' => $maxwidth, 194 'sanitize_callback' => 'absint', 195 ), 196 ), 197 ), 198 ) ); 199 } 200 201 /** 202 * Filters the embed template. 203 * 204 * Override if needed. 205 * 206 * @since 2.5.0 207 * 208 * @param string $template File path to current embed template. 209 * @return string 210 */ 211 public function filter_template( $template ) { 212 if ( ! $this->is_page() || is_404() ) { 213 return $template; 214 } 215 216 // Embed template hierarchy! 217 return bp_locate_template( array( 218 'assets/embeds/template.php' 219 ) ); 220 } 221 222 /** 223 * Adds oEmbed discovery links on single activity pages. 224 * 225 * @since 2.5.0 226 * 227 * @param string $retval Current discovery links. 228 * @return string 229 */ 230 public function add_oembed_discovery_links( $retval ) { 231 if ( ! $this->is_page() ) { 232 return $retval; 233 } 234 235 $permalink = $this->set_permalink(); 236 if ( empty( $permalink ) ) { 237 return $retval; 238 } 239 240 add_filter( 'rest_url' , array( $this, 'filter_rest_url' ) ); 241 242 $retval = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink ) ) . '" />' . "\n"; 243 244 if ( class_exists( 'SimpleXMLElement' ) ) { 245 $retval .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink, 'xml' ) ) . '" />' . "\n"; 246 } 247 248 remove_filter( 'rest_url' , array( $this, 'filter_rest_url' ) ); 249 250 return $retval; 251 } 252 253 /** 254 * Callback for the API endpoint. 255 * 256 * Returns the JSON object for the item. 257 * 258 * @since 2.5.0 259 * 260 * @param WP_REST_Request $request Full data about the request. 261 * @return WP_Error|array oEmbed response data or WP_Error on failure. 262 */ 263 public function get_item( $request ) { 264 $url = $request['url']; 265 266 $data = false; 267 268 $item_id = (int) $this->validate_url_to_item_id( $url ); 269 270 if ( ! empty( $item_id ) ) { 271 $item = $this->set_oembed_response_data( $item_id ); 272 273 // Create dummy post to piggyback off of get_oembed_response_data() 274 $post = bp_theme_compat_create_dummy_post( array( 275 'post_author' => $item['user_id'], 276 'post_title' => $item['title'], 277 'post_content' => $item['content'], 278 279 // This passes the get_oembed_response_data() check. 280 'post_status' => 'publish' 281 ) ); 282 283 // Add markers to tell that we're embedding a single activity. 284 // This is needed for various oEmbed response data filtering. 285 if ( empty( buddypress()->{$this->slug_endpoint} ) ) { 286 buddypress()->$this->slug_endpoint = new stdClass; 287 } 288 buddypress()->{$this->slug_endpoint}->embedurl_in_progress = $url; 289 buddypress()->{$this->slug_endpoint}->embedid_in_progress = $item_id; 290 291 // Use WP's oEmbed response data function. 292 $data = get_oembed_response_data( $post, $request['maxwidth'] ); 293 294 // Set custom 'author_url' if we have one. 295 if ( ! empty( $item['author_url'] ) ) { 296 $data['author_url'] = $item['author_url']; 297 } 298 } 299 300 if ( ! $data ) { 301 return new WP_Error( 'oembed_invalid_url', get_status_header_desc( 404 ), array( 'status' => 404 ) ); 302 } 303 304 return $data; 305 } 306 307 /** 308 * Pass our BuddyPress activity permalink for embedding. 309 * 310 * @since 2.5.0 311 * 312 * @see bp_activity_embed_rest_route_callback() 313 * 314 * @param string $retval Current embed URL 315 * @return string 316 */ 317 public function filter_embed_url( $retval ) { 318 if ( false === isset( buddypress()->{$this->slug_endpoint}->embedurl_in_progress ) && ! $this->is_page() ) { 319 return $retval; 320 } 321 322 $url = $this->is_page() ? $this->set_permalink() : buddypress()->{$this->slug_endpoint}->embedurl_in_progress; 323 $url = trailingslashit( $url ); 324 325 // This is for the 'WordPress Embed' block 326 // @see bp_activity_embed_comments_button() 327 if ( 'the_permalink' !== current_filter() ) { 328 $url = add_query_arg( 'embed', 'true', trailingslashit( $url ) ); 329 } 330 331 return $url; 332 } 333 334 /** 335 * Filters the embed HTML for the default oEmbed fallback HTML. 336 * 337 * @since 2.5.0 338 * 339 * @param string $retval Current embed HTML 340 * @return string 341 */ 342 public function filter_embed_html( $retval ) { 343 if ( false === isset( buddypress()->{$this->slug_endpoint}->embedurl_in_progress ) && ! $this->is_page() ) { 344 return $retval; 345 } 346 347 $url = $this->set_permalink(); 348 349 $item_id = $this->is_page() ? $this->validate_url_to_item_id( $url ) : buddypress()->{$this->slug_endpoint}->embedid_in_progress; 350 351 // Change 'Embedded WordPress Post' to custom title. 352 $custom_title = $this->set_iframe_title( $item_id ); 353 if ( ! empty( $custom_title ) ) { 354 $retval = str_replace( __( 'Embedded WordPress Post' ), esc_attr( $custom_title ), $retval ); 355 } 356 357 // Remove default <blockquote> 358 $retval = substr( $retval, strpos( $retval, '</blockquote>' ) + 13 ); 359 360 // Set up new fallback HTML 361 // @todo Maybe use KSES? 362 $fallback_html = $this->set_fallback_html( $item_id ); 363 364 // Add our custom <blockquote> 365 return $fallback_html . $retval; 366 } 367 368 /** 369 * Append our custom slug endpoint to oEmbed endpoint URL. 370 * 371 * Meant to be used as a filter on 'rest_url' before any call to 372 * {@link get_oembed_endpoint_url()} is used. 373 * 374 * @since 2.5.0 375 * 376 * @see add_oembed_discovery_links() 377 * 378 * @param string $retval Current oEmbed endpoint URL 379 * @return string 380 */ 381 function filter_rest_url( $retval = '' ) { 382 return $retval . "/{$this->slug_endpoint}"; 383 } 384 385 /** 386 * Inject activity content into the embed template. 387 * 388 * @since 2.5.0 389 */ 390 public function inject_content() { 391 if ( ! $this->is_page() ) { 392 return; 393 } 394 395 $this->content(); 396 } 397 } 398 No newline at end of file -
new file src/bp-templates/bp-legacy/buddypress/assets/embeds/activity.php
diff --git src/bp-templates/bp-legacy/buddypress/assets/embeds/activity.php src/bp-templates/bp-legacy/buddypress/assets/embeds/activity.php new file mode 100644 index 0000000..34264ce
- + 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"><p><?php echo bp_activity_create_excerpt(); ?></p></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 10 $embeds = bp_core_extract_media_from_content( $GLOBALS['activities_template']->activity->content, 'embeds' ); 11 12 // Only embed the first embedded item 13 if ( $embeds ) { 14 echo apply_filters( 'bp_get_activity_content_body', $embeds['embeds'][0]['url'] ); 15 16 // Add inline JS for responsive IFRAMES if an embed is detected. 17 ?> 18 19 <script> 20 /*! fluidvids.js v1.2.0 | (c) 2013 @toddmotto | https://github.com/toddmotto/fluidvids */ 21 window.fluidvids=function(a,b){"use strict";var c=function(a){this.elem=a};c.prototype={init:function(){var a=100*(this.elem.height/this.elem.width);this.elem.style.position="absolute",this.elem.style.top="0",this.elem.style.left="0",this.elem.width="100%",this.elem.height="100%";var c=b.createElement("div");c.className="fluidvids",c.style.width="100%",c.style.position="relative",c.style.paddingTop=a+"%";var d=this.elem.parentNode;d.insertBefore(c,this.elem),c.appendChild(this.elem)}};for(var d=b.getElementsByTagName("iframe"),e=0;e<d.length;e++){d[e].src&&new c(d[e]).init()}}(window,document); 22 </script> 23 24 <?php 25 } 26 ?> 27 28 <?php endwhile; ?> 29 30 <?php endif; ?> 31 -
new file src/bp-templates/bp-legacy/buddypress/assets/embeds/css.php
diff --git src/bp-templates/bp-legacy/buddypress/assets/embeds/css.php src/bp-templates/bp-legacy/buddypress/assets/embeds/css.php new file mode 100644 index 0000000..d946ef6
- + 1 <style type="text/css"> 2 #wp-embed-header:after { 3 clear: both; 4 content: ""; 5 display: table; 6 margin-bottom: 1em; 7 } 8 9 .wp-embed-avatar { 10 float: left; 11 margin: 0 .75em 0 0; 12 } 13 14 p.wp-embed-heading { 15 font-size: 16px; 16 margin-bottom: 0; 17 } 18 19 .wp-embed-excerpt, p.wp-embed-timestamp { 20 margin-bottom: .5em; 21 } 22 23 .wp-embed-footer { 24 margin-top: 20px; 25 } 26 </style> 27 No newline at end of file -
new file src/bp-templates/bp-legacy/buddypress/assets/embeds/footer.php
diff --git src/bp-templates/bp-legacy/buddypress/assets/embeds/footer.php src/bp-templates/bp-legacy/buddypress/assets/embeds/footer.php new file mode 100644 index 0000000..22de696
- + 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 /** 13 * Filter the site title HTML in the embed footer. 14 * 15 * @since 4.4.0 16 * 17 * @param string $site_title The site title HTML. 18 */ 19 echo apply_filters( 'embed_site_title_html', $site_title ); 20 ?> 21 </div> 22 23 <div class="wp-embed-meta"> 24 <?php 25 /** 26 * Print additional meta content in the embed template. 27 * 28 * @since 4.4.0 29 */ 30 do_action( 'embed_content_meta'); 31 ?> 32 </div> 33 </div> 34 No newline at end of file -
new file src/bp-templates/bp-legacy/buddypress/assets/embeds/header.php
diff --git src/bp-templates/bp-legacy/buddypress/assets/embeds/header.php src/bp-templates/bp-legacy/buddypress/assets/embeds/header.php new file mode 100644 index 0000000..7a4bc8a
- + 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
diff --git src/bp-templates/bp-legacy/buddypress/assets/embeds/template.php src/bp-templates/bp-legacy/buddypress/assets/embeds/template.php new file mode 100644 index 0000000..599c283
- + 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 32 // This is used by r-a-y for testing purposes at the moment. 33 bp_get_asset_template_part( 'embeds/css' ); 34 ?> 35 </head> 36 <body <?php body_class(); ?>> 37 <div <?php post_class( 'wp-embed' ); ?>> 38 <?php 39 bp_get_asset_template_part( 'embeds/header', bp_current_component() ); 40 41 /** This action is documented in wp-includes/embed-template.php */ 42 do_action( 'embed_content' ); 43 44 bp_get_asset_template_part( 'embeds/footer', bp_current_component() ); 45 ?> 46 47 </div> 48 49 <?php 50 /** This action is documented in wp-includes/embed-template.php */ 51 do_action( 'embed_footer' ); 52 ?> 53 </body> 54 </html> 55 No newline at end of file