Skip to:
Content

BuddyPress.org

Ticket #6772: 6772.03.patch

File 6772.03.patch, 30.4 KB (added by r-a-y, 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() { 
    744744        $bp->activity->akismet = new BP_Akismet();
    745745}
    746746
     747
     748/**
     749 * Loads our activity oEmbed component.
     750 *
     751 * @since 2.5.0
     752 */
     753function 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
    747759/**
    748760 * AJAX endpoint for Suggestions API lookups.
    749761 *
  • 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 { 
    3131                        array(
    3232                                'adminbar_myaccount_order' => 10,
    3333                                'search_query_arg' => 'activity_search',
     34                                'features' => array( 'embeds' )
    3435                        )
    3536                );
    3637        }
    class BP_Activity_Component extends BP_Component { 
    6768                        $includes[] = 'akismet';
    6869                }
    6970
     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
    7076                if ( is_admin() ) {
    7177                        $includes[] = 'admin';
    7278                }
    class BP_Activity_Component extends BP_Component { 
    365371                // Spam prevention.
    366372                add_action( 'bp_include', 'bp_activity_setup_akismet' );
    367373
     374                // oEmbed handler.
     375                add_action( 'bp_loaded', 'bp_activity_setup_oembed' );
     376
    368377                parent::setup_actions();
    369378        }
    370379
  • 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..95d174d
    - +  
     1<?php
     2/**
     3 * BuddyPress Activity Classes.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Embeds
     7 */
     8
     9// Exit if accessed directly.
     10defined( 'ABSPATH' ) || exit;
     11
     12require_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 */
     19class 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         * Conditional function to determine if we're on our activity page.
     31         *
     32         * @since 2.5.0
     33         *
     34         * @var string
     35         */
     36        protected $page_conditional_fn = 'bp_is_single_activity';
     37
     38        /**
     39         * Custom hooks.
     40         *
     41         * @since 2.5.0
     42         */
     43        protected function custom_hooks() {
     44                add_action( 'embed_content_meta', array( $this, 'embed_comments_button' ), 5 );
     45        }
     46
     47        /**
     48         * Output our custom embed template part.
     49         *
     50         * @since 2.5.0
     51         */
     52        protected function content() {
     53                bp_get_template_part( 'embeds/activity' );
     54        }
     55
     56        /**
     57         * Validates the URL to determine if the activity item is valid.
     58         *
     59         * @since 2.5.0
     60         *
     61         * @param  string   $url The URL to check.
     62         * @return int|bool Activity ID on success; boolean false on failure.
     63         */
     64        protected function validate_url_to_item_id( $url ) {
     65                if ( bp_core_enable_root_profiles() ) {
     66                        $domain = bp_get_root_domain();
     67                } else {
     68                        $domain = bp_get_members_directory_permalink();
     69                }
     70
     71                // Check the URL to see if this is a single activity URL.
     72                if ( 0 !== strpos( $url, $domain ) ) {
     73                        return false;
     74                }
     75
     76                // Check for activity slug.
     77                if ( false === strpos( $url, '/' . bp_get_activity_slug() . '/' ) ) {
     78                        return false;
     79                }
     80
     81                // Do more checks.
     82                $url = trim( untrailingslashit( $url ) );
     83
     84                // Grab the activity ID.
     85                $activity_id = (int) substr(
     86                        $url,
     87                        strrpos( $url, '/' ) + 1
     88                );
     89
     90                if ( ! empty( $activity_id ) ) {
     91                        // Check if activity item still exists.
     92                        $activity = new BP_Activity_Activity( $activity_id );
     93
     94                        // Okay, we're good to go!
     95                        if ( ! empty( $activity->component ) && 0 === (int) $activity->is_spam ) {
     96                                return $activity_id;
     97                        }
     98                }
     99
     100                return false;
     101        }
     102
     103        /**
     104         * Sets the oEmbed response data for our activity item.
     105         *
     106         * @since 2.5.0
     107         *
     108         * @param  int $item_id The activity ID.
     109         * @return array
     110         */
     111        protected function set_oembed_response_data( $item_id ) {
     112                $activity = new BP_Activity_Activity( $item_id );
     113
     114                return array(
     115                        'user_id'    => $activity->user_id,
     116                        'content'    => $activity->content,
     117                        'title'      => __( 'Activity', 'buddypress' ),
     118                        'author_url' => bp_core_get_user_domain( $activity->user_id )
     119                );
     120        }
     121
     122        /**
     123         * Sets a custom <blockquote> for our oEmbed fallback HTML.
     124         *
     125         * @since 2.5.0
     126         *
     127         * @param  int $item_id The activity ID.
     128         * @return string
     129         */
     130        protected function set_fallback_html( $item_id ) {
     131                $activity    = new BP_Activity_Activity( $item_id );
     132                $mentionname = bp_activity_do_mentions() ? ' (@' . bp_activity_get_user_mentionname( $activity->user_id ) . ')' : '';
     133                $date        = date_i18n( get_option( 'date_format' ), strtotime( $activity->date_recorded ) );
     134
     135                // 'wp-embedded-content' CSS class is necessary due to how the embed JS works.
     136                $blockquote = sprintf( '<blockquote class="wp-embedded-content bp-activity-item">%1$s%2$s %3$s</blockquote>',
     137                        apply_filters( 'bp_get_activity_content_body', $activity->content ),
     138                        '- ' . bp_core_get_user_displayname( $activity->user_id ) . $mentionname,
     139                        '<a href="' . esc_url( bp_activity_get_permalink( $item_id ) ) . '">' . $date . '</a>'
     140                );
     141
     142                /**
     143                 * Filters the fallback HTML used when embedding a BP activity item.
     144                 *
     145                 * @since 2.5.0
     146                 *
     147                 * @param string               $blockquote Current fallback HTML
     148                 * @param BP_Activity_Activity $activity   Activity object
     149                 */
     150                return apply_filters( 'bp_activity_embed_fallback_html', $blockquote, $activity );
     151        }
     152
     153        /**
     154         * Sets a custom <iframe> title for our oEmbed item.
     155         *
     156         * @since 2.5.0
     157         *
     158         * @param  int $item_id The activity ID
     159         * @return string
     160         */
     161        protected function set_iframe_title( $item_id ) {
     162                return __( 'Embedded Activity Item', 'buddypress' );
     163        }
     164
     165        /**
     166         * Prints the markup for the activity embed comments button.
     167         *
     168         * @since 2.5.0
     169         */
     170        public function embed_comments_button() {
     171                if ( ! bp_is_single_activity() ) {
     172                        return;
     173                }
     174
     175                // Make sure our custom permalink shows up in the 'WordPress Embed' block.
     176                add_filter( 'the_permalink', array( $this, 'filter_embed_url' ) );
     177
     178                // Only show comment bubble if we have some activity comments.
     179                $count = bp_activity_get_comment_count();
     180                if ( empty( $count ) ) {
     181                        return;
     182                }
     183        ?>
     184
     185                <div class="wp-embed-comments">
     186                        <a href="<?php bp_activity_thread_permalink(); ?>">
     187                                <span class="dashicons dashicons-admin-comments"></span>
     188                                <?php
     189                                printf(
     190                                        _n(
     191                                                '%s <span class="screen-reader-text">Comment</span>',
     192                                                '%s <span class="screen-reader-text">Comments</span>',
     193                                                $count
     194                                        ),
     195                                        number_format_i18n( $count )
     196                                );
     197                                ?>
     198                        </a>
     199                </div>
     200
     201        <?php
     202        }
     203}
  • 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..8bb63e5 100644
    function bp_use_embed_in_private_messages() { 
    16661666        return apply_filters( 'bp_use_embed_in_private_messages', !defined( 'BP_EMBED_DISABLE_PRIVATE_MESSAGES' ) || !BP_EMBED_DISABLE_PRIVATE_MESSAGES );
    16671667}
    16681668
     1669/**
     1670 * Checks a given content to see if a certain media type exists.
     1671 *
     1672 * @since 2.5.0
     1673 *
     1674 * @param  string $content The content to check.
     1675 * @param  string $type    The type to check. See the class constants in the BP_Media_Extractor class.
     1676 * @return bool
     1677 */
     1678function bp_core_check_content_for_media_type( $content = '', $type = 'all' ) {
     1679        $retval = false;
     1680
     1681        $class = new ReflectionClass( 'BP_Media_Extractor' );
     1682        $bitmask = $class->getConstant( strtoupper( $type ) );
     1683
     1684        // Type isn't valid, so bail.
     1685        if ( empty( $bitmask ) ) {
     1686                return false;
     1687        }
     1688
     1689        $x = new BP_Media_Extractor;
     1690        $media = $x->extract( $content, $bitmask );
     1691
     1692        if ( 'all' === $type ) {
     1693                unset( $media['has'] );
     1694                $media = array_filter( $media );
     1695                if ( ! empty( $media ) ) {
     1696                        $retval = true;
     1697                }
     1698        }
     1699
     1700        if ( ! empty( $media[ $type ] ) ) {
     1701                $retval = true;
     1702        }
     1703
     1704        return $retval;
     1705}
     1706
    16691707/** Admin *********************************************************************/
    16701708
    16711709/**
  • 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 ) { 
    650650}
    651651
    652652/**
     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 */
     661function 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/**
    653702 * Populate various WordPress globals with dummy data to prevent errors.
    654703 *
    655704 * This dummy data is necessary because theme compatibility essentially fakes
    function bp_theme_compat_reset_post( $args = array() ) { 
    670719
    671720        // Switch defaults if post is set.
    672721        if ( isset( $wp_query->post ) ) {
    673                 $dummy = wp_parse_args( $args, array(
     722                $args = wp_parse_args( $args, array(
    674723                        'ID'                    => $wp_query->post->ID,
    675724                        'post_status'           => $wp_query->post->post_status,
    676725                        'post_author'           => $wp_query->post->post_author,
    function bp_theme_compat_reset_post( $args = array() ) { 
    695744                        'comment_status'        => $wp_query->post->comment_status,
    696745                        'comment_count'         => $wp_query->post->comment_count,
    697746                        '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,
    737747                ) );
    738748        }
    739749
    740750        // Bail if dummy post is empty.
    741         if ( empty( $dummy ) ) {
     751        if ( empty( $args ) ) {
    742752                return;
    743753        }
    744754
    745755        // Set the $post global.
    746         $post = new WP_Post( (object) $dummy );
     756        $post = bp_theme_compat_create_dummy_post( $args );
    747757
    748758        // Copy the new post global into the main $wp_query.
    749759        $wp_query->post       = $post;
    function bp_theme_compat_reset_post( $args = array() ) { 
    751761
    752762        // Prevent comments form from appearing.
    753763        $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;
    762769
    763770        /**
    764771         * 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..52dd9c5
    - +  
     1<?php
     2/**
     3 * Core component classes.
     4 *
     5 * @package BuddyPress
     6 * @subpackage Core
     7 */
     8
     9// Exit if accessed directly.
     10defined( 'ABSPATH' ) || exit;
     11
     12/**
     13 * API for responding and returning a custom oEmbed request.
     14 *
     15 * @since 2.5.0
     16 */
     17abstract 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         * (required) Callback to determine if you're on the page requiring oEmbed.
     32         *
     33         * eg. bp_is_single_activity() without the brackets - 'bp_is_single_activity'.
     34         *
     35         * @var string
     36         */
     37        protected $page_conditional_fn = '';
     38
     39        /**
     40         * (optional) Embed template hierarchy.
     41         *
     42         * Define the template hierarchy for your oEmbed rendering.
     43         *
     44         * @var array
     45         */
     46        protected $template_hierarchy = array();
     47
     48        /** END PROPERTIES ******************************************************/
     49
     50        /**
     51         * Constructor.
     52         */
     53        final public function __construct() {
     54                $this->setup_properties();
     55
     56                // Some rudimentary logic checking.
     57                if ( empty( $this->slug_endpoint ) ) {
     58                        $class = get_class( $this );
     59                        throw new \LogicException( $class . ' class must define $slug_endpoint property' );
     60                } elseif ( empty( $this->page_conditional_fn ) || false === is_callable( $this->page_conditional_fn ) ) {
     61                        $child = get_class( $this );
     62                        throw new \LogicException( $class . ' class must define $page_conditional_fn property or must be callable' );
     63                }
     64
     65                $this->setup_hooks();
     66                $this->custom_hooks();
     67        }
     68
     69        /** REQUIRED METHODS ****************************************************/
     70
     71        /**
     72         * Add content for your oEmbed response here.
     73         *
     74         * @since 2.5.0
     75         */
     76        abstract protected function content();
     77
     78        /**
     79         * Validate the URL to see if it matches your item ID.
     80         *
     81         * @since 2.5.0
     82         *
     83         * @return int Your item ID
     84         */
     85        abstract protected function validate_url_to_item_id( $url );
     86
     87        /**
     88         * Set the oEmbed response data.
     89         *
     90         * @since 2.5.0
     91         *
     92         * @param  int   $item_id Your item ID to do checks against.
     93         * @return array Should contain 'user_id', 'content', 'title', 'author_url' as array keys.
     94         *               'author_url' is optional; the rest are required.
     95         */
     96        abstract protected function set_oembed_response_data( $item_id );
     97
     98        /**
     99         * Sets the fallback HTML for the oEmbed response.
     100         *
     101         * In a WordPress oEmbed item, the fallback HTML is a <blockquote>.  This is
     102         * usually hidden after the <iframe> is loaded.
     103         *
     104         * @since 2.5.0
     105         *
     106         * @param  int    $item_id Your item ID to do checks against.
     107         * @return string Fallback HTML you want to output.
     108         */
     109        abstract protected function set_fallback_html( $item_id );
     110
     111        /** OPTIONAL METHODS ****************************************************/
     112
     113        /**
     114         * Set permalink for oEmbed link discovery.
     115         *
     116         * This method will be called on the page we want to oEmbed.  Override in your
     117         * extended class method if needed.
     118         *
     119         * @since 2.5.0
     120         */
     121        protected function set_permalink() {
     122                return 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                $conditional = $this->page_conditional_fn;
     213
     214                if ( ! $conditional() || is_404() ) {
     215                        return $template;
     216                }
     217
     218                // Embed template hierarchy!
     219                return bp_locate_template( array(
     220                        'embeds/template.php'
     221                ) );
     222        }
     223
     224        /**
     225         * Adds oEmbed discovery links on single activity pages.
     226         *
     227         * @since 2.5.0
     228         *
     229         * @param  string $retval Current discovery links.
     230         * @return string
     231         */
     232        public function add_oembed_discovery_links( $retval ) {
     233                $conditional = $this->page_conditional_fn;
     234                if ( ! $conditional() ) {
     235                        return $retval;
     236                }
     237
     238                $permalink = $this->set_permalink();
     239                if ( empty( $permalink ) ) {
     240                        return $retval;
     241                }
     242
     243                add_filter( 'rest_url' , array( $this, 'filter_rest_url' ) );
     244
     245                $retval = '<link rel="alternate" type="application/json+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink ) ) . '" />' . "\n";
     246
     247                if ( class_exists( 'SimpleXMLElement' ) ) {
     248                        $retval .= '<link rel="alternate" type="text/xml+oembed" href="' . esc_url( get_oembed_endpoint_url( $permalink, 'xml' ) ) . '" />' . "\n";
     249                }
     250
     251                remove_filter( 'rest_url' , array( $this, 'filter_rest_url' ) );
     252
     253                return $retval;
     254        }
     255
     256        /**
     257         * Callback for the API endpoint.
     258         *
     259         * Returns the JSON object for the item.
     260         *
     261         * @since 2.5.0
     262         *
     263         * @param  WP_REST_Request $request Full data about the request.
     264         * @return WP_Error|array oEmbed response data or WP_Error on failure.
     265         */
     266        public function get_item( $request ) {
     267                $url = $request['url'];
     268
     269                $data = false;
     270
     271                $item_id = (int) $this->validate_url_to_item_id( $url );
     272
     273                if ( ! empty( $item_id ) ) {
     274                        $item = $this->set_oembed_response_data( $item_id );
     275
     276                        // Create dummy post to piggyback off of get_oembed_response_data()
     277                        $post = bp_theme_compat_create_dummy_post( array(
     278                                'post_author'  => $item['user_id'],
     279                                'post_title'   => $item['title'],
     280                                'post_content' => $item['content'],
     281
     282                                // This passes the get_oembed_response_data() check.
     283                                'post_status'  => 'publish'
     284                        ) );
     285
     286                        // Add markers to tell that we're embedding a single activity.
     287                        // This is needed for various oEmbed response data filtering.
     288                        if ( empty( buddypress()->{$this->slug_endpoint} ) ) {
     289                                buddypress()->$this->slug_endpoint = new stdClass;
     290                        }
     291                        buddypress()->{$this->slug_endpoint}->embedurl_in_progress = $url;
     292                        buddypress()->{$this->slug_endpoint}->embedid_in_progress  = $item_id;
     293
     294                        // Use WP's oEmbed response data function.
     295                        $data = get_oembed_response_data( $post, $request['maxwidth'] );
     296
     297                        // Set custom 'author_url' if we have one.
     298                        if ( ! empty( $item['author_url'] ) ) {
     299                                $data['author_url'] = $item['author_url'];
     300                        }
     301                }
     302
     303                if ( ! $data ) {
     304                        return new WP_Error( 'oembed_invalid_url', get_status_header_desc( 404 ), array( 'status' => 404 ) );
     305                }
     306
     307                return $data;
     308        }
     309
     310        /**
     311         * Pass our BuddyPress activity permalink for embedding.
     312         *
     313         * @since 2.5.0
     314         *
     315         * @see bp_activity_embed_rest_route_callback()
     316         *
     317         * @param  string $retval Current embed URL
     318         * @return string
     319         */
     320        public function filter_embed_url( $retval ) {
     321                $conditional = $this->page_conditional_fn;
     322                if ( false === isset( buddypress()->{$this->slug_endpoint}->embedurl_in_progress ) && ! $conditional() ) {
     323                        return $retval;
     324                }
     325
     326                $url = $conditional() ? $this->set_permalink() : buddypress()->{$this->slug_endpoint}->embedurl_in_progress;
     327                $url = trailingslashit( $url );
     328
     329                // This is for the 'WordPress Embed' block
     330                // @see bp_activity_embed_comments_button()
     331                if ( 'the_permalink' !== current_filter() ) {
     332                        $url = add_query_arg( 'embed', 'true', trailingslashit( $url ) );
     333                }
     334
     335                return $url;
     336        }
     337
     338        /**
     339         * Filters the embed HTML for the default oEmbed fallback HTML.
     340         *
     341         * @since 2.5.0
     342         *
     343         * @param  string $retval Current embed HTML
     344         * @return string
     345         */
     346        public function filter_embed_html( $retval ) {
     347                $conditional = $this->page_conditional_fn;
     348                if ( false === isset( buddypress()->{$this->slug_endpoint}->embedurl_in_progress ) && ! $conditional() ) {
     349                        return $retval;
     350                }
     351
     352                // Remove querystring from URL
     353                $url = substr( bp_get_requested_url(), 0, strpos( bp_get_requested_url(), '?' ) );
     354
     355                $item_id = $conditional() ? $this->validate_url_to_item_id( $url ) : buddypress()->{$this->slug_endpoint}->embedid_in_progress;
     356
     357                // Change 'Embedded WordPress Post' to custom title.
     358                $custom_title = $this->set_iframe_title( $item_id );
     359                if ( ! empty( $custom_title ) ) {
     360                        $retval = str_replace( __( 'Embedded WordPress Post' ), esc_attr( $custom_title ), $retval );
     361                }
     362
     363                // Remove default <blockquote>
     364                $retval = substr( $retval, strpos( $retval, '</blockquote>' ) + 13 );
     365
     366                // Set up new fallback HTML
     367                // @todo Maybe use KSES?
     368                $fallback_html = $this->set_fallback_html( $item_id );
     369
     370                // Add our custom <blockquote>
     371                return $fallback_html . $retval;
     372        }
     373
     374        /**
     375         * Append our custom slug endpoint to oEmbed endpoint URL.
     376         *
     377         * Meant to be used as a filter on 'rest_url' before any call to
     378         * {@link get_oembed_endpoint_url()} is used.
     379         *
     380         * @since 2.5.0
     381         *
     382         * @see add_oembed_discovery_links()
     383         *
     384         * @param  string $retval Current oEmbed endpoint URL
     385         * @return string
     386         */
     387        function filter_rest_url( $retval = '' ) {
     388                return $retval . "/{$this->slug_endpoint}";
     389        }
     390
     391        /**
     392         * Inject activity content into the embed template.
     393         *
     394         * @since 2.5.0
     395         */
     396        public function inject_content() {
     397                $conditional = $this->page_conditional_fn;
     398                if ( ! $conditional() ) {
     399                        return;
     400                }
     401
     402                $this->content();
     403        }
     404}
     405 No newline at end of file
  • new file src/bp-templates/bp-legacy/buddypress/embeds/activity.php

    diff --git src/bp-templates/bp-legacy/buddypress/embeds/activity.php src/bp-templates/bp-legacy/buddypress/embeds/activity.php
    new file mode 100644
    index 0000000..589fad2
    - +  
     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_content_body(); ?></div>
     6
     7                                <p><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                                // Add inline JS for responsive IFRAMES if an embed is detected.
     11                                if ( bp_core_check_content_for_media_type( $GLOBALS['activities_template']->activity->content, 'embeds' ) ) {
     12                                ?>
     13
     14<script>
     15/*! fluidvids.js v1.2.0 | (c) 2013 @toddmotto | https://github.com/toddmotto/fluidvids */
     16window.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);
     17</script>
     18
     19                                <?php
     20                                }
     21                                ?>
     22
     23                        <?php endwhile; ?>
     24
     25                <?php endif; ?>
     26
  • new file src/bp-templates/bp-legacy/buddypress/embeds/css.php

    diff --git src/bp-templates/bp-legacy/buddypress/embeds/css.php src/bp-templates/bp-legacy/buddypress/embeds/css.php
    new file mode 100644
    index 0000000..129c877
    - +  
     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
     14p.wp-embed-heading {
     15        font-size: 16px;
     16        margin-bottom: 0;
     17}
     18
     19.wp-embed-excerpt {
     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/embeds/footer.php

    diff --git src/bp-templates/bp-legacy/buddypress/embeds/footer.php src/bp-templates/bp-legacy/buddypress/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/embeds/header.php

    diff --git src/bp-templates/bp-legacy/buddypress/embeds/header.php src/bp-templates/bp-legacy/buddypress/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/embeds/template.php

    diff --git src/bp-templates/bp-legacy/buddypress/embeds/template.php src/bp-templates/bp-legacy/buddypress/embeds/template.php
    new file mode 100644
    index 0000000..cb681df
    - +  
     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
     17if ( ! 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_template_part( 'embeds/css' );
     34        ?>
     35</head>
     36<body <?php body_class(); ?>>
     37<div <?php post_class( 'wp-embed' ); ?>>
     38<?php
     39bp_get_template_part( 'embeds/header', bp_current_component() );
     40
     41/** This action is documented in wp-includes/embed-template.php */
     42do_action( 'embed_content' );
     43
     44bp_get_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 */
     51do_action( 'embed_footer' );
     52?>
     53</body>
     54</html>
     55 No newline at end of file