[ Index ]

PHP Cross Reference of BuddyPress

title

Body

[close]

/src/bp-activity/ -> bp-activity-embeds.php (source)

   1  <?php
   2  /**
   3   * Functions related to embedding single activity items externally.
   4   *
   5   * @since 2.6.0
   6   *
   7   * @package BuddyPress
   8   * @subpackage ActivityEmbeds
   9   */
  10  
  11  // Exit if accessed directly.
  12  defined( 'ABSPATH' ) || exit;
  13  
  14  /**
  15   * Loads our activity oEmbed component.
  16   *
  17   * @since 2.6.0
  18   */
  19  function bp_activity_setup_oembed() {
  20      buddypress()->activity->oembed = new BP_Activity_oEmbed_Extension;
  21  }
  22  add_action( 'bp_loaded', 'bp_activity_setup_oembed' );
  23  
  24  /**
  25   * Catch links in embed excerpt so top.location.href can be added.
  26   *
  27   * Due to <iframe sandbox="allow-top-navigation">, links in embeds can only be
  28   * clicked if invoked with top.location.href via JS.
  29   *
  30   * @since 2.6.0
  31   *
  32   * @param  string $text Embed excerpt
  33   * @return string
  34   */
  35  function bp_activity_embed_excerpt_onclick_location_filter( $text ) {
  36      return preg_replace_callback( '/<a\s+[^>]*href=\"([^\"]*)\"/iU', 'bp_activity_embed_excerpt_onclick_location_filter_callback', $text );
  37  }
  38      /**
  39       * Add onclick="top.location.href" to a link.
  40       *
  41       * @since 2.6.0
  42       *
  43       * @param  array $matches Items matched by bp_activity_embed_excerpt_onclick_location_filter().
  44       * @return string
  45       */
  46      function bp_activity_embed_excerpt_onclick_location_filter_callback( $matches ) {
  47          return sprintf( '<a href="%1$s" onclick="top.location.href=\'%1$s\'"', $matches[1] );
  48      }
  49  
  50  /**
  51   * Add inline styles for BP activity embeds.
  52   *
  53   * @since  2.6.0
  54   */
  55  function bp_activity_embed_add_inline_styles() {
  56      if ( false === bp_is_single_activity() ) {
  57          return;
  58      }
  59  
  60      $min = bp_core_get_minified_asset_suffix();
  61  
  62      if ( is_rtl() ) {
  63          $css = bp_locate_template_asset( "css/embeds-activity-rtl{$min}.css" );
  64      } else {
  65          $css = bp_locate_template_asset( "css/embeds-activity{$min}.css" );
  66      }
  67  
  68      // Bail if file wasn't found.
  69      if ( false === $css ) {
  70          return;
  71      }
  72  
  73      // Grab contents of CSS file and do some rudimentary CSS protection.
  74      $css = file_get_contents( $css['file'] );
  75      $css = wp_kses( $css, array( "\'", '\"' ) );
  76  
  77      printf( '<style type="text/css">%s</style>', $css );
  78  }
  79  add_action( 'embed_head', 'bp_activity_embed_add_inline_styles', 20 );
  80  
  81  /**
  82   * Query for the activity item on the activity embed template.
  83   *
  84   * Basically a wrapper for {@link bp_has_activities()}, but allows us to
  85   * use the activity loop without requerying for it again.
  86   *
  87   * @since 2.6.0
  88   *
  89   * @param  int $activity_id The activity ID.
  90   * @return bool
  91   */
  92  function bp_activity_embed_has_activity( $activity_id = 0 ) {
  93      global $activities_template;
  94  
  95      if ( empty( $activity_id ) ) {
  96          return false;
  97      }
  98  
  99      if ( ! empty( $activities_template->activities ) ) {
 100          $activity = (array) $activities_template->activities;
 101          $activity = reset( $activity );
 102  
 103          // No need to requery if we already got the embed activity.
 104          if ( (int) $activity_id === $activity->id ) {
 105              return $activities_template->has_activities();
 106          }
 107      }
 108  
 109      return bp_has_activities( array(
 110          'display_comments' => 'threaded',
 111          'show_hidden'      => true,
 112          'include'          => (int) $activity_id,
 113      ) );
 114  }
 115  
 116  /**
 117   * Outputs excerpt for an activity embed item.
 118   *
 119   * @since 2.6.0
 120   */
 121  function bp_activity_embed_excerpt( $content = '' ) {
 122      echo bp_activity_get_embed_excerpt( $content );
 123  }
 124  
 125      /**
 126       * Generates excerpt for an activity embed item.
 127       *
 128       * @since 2.6.0
 129       *
 130       * @param  string $content The content to generate an excerpt for.
 131       * @return string
 132       */
 133  	function bp_activity_get_embed_excerpt( $content = '' ) {
 134          if ( empty( $content ) && ! empty( $GLOBALS['activities_template']->in_the_loop ) ) {
 135              $content = $GLOBALS['activities_template']->activity->content;
 136          }
 137  
 138          /*
 139           * bp_activity_truncate_entry() includes the 'Read More' link, which is why
 140           * we're using this instead of bp_create_excerpt().
 141           */
 142          $content = html_entity_decode( $content );
 143          $content = bp_activity_truncate_entry( $content, array(
 144              'html' => false,
 145              'filter_shortcodes' => true,
 146              'strip_tags'        => true,
 147              'force_truncate'    => true
 148          ) );
 149  
 150          /**
 151           * Filter the activity embed excerpt.
 152           *
 153           * @since 2.6.0
 154           *
 155           * @var string $content Embed Excerpt.
 156           * @var string $unmodified_content Unmodified activity content.
 157           */
 158          return apply_filters( 'bp_activity_get_embed_excerpt', $content, $GLOBALS['activities_template']->activity->content );
 159      }
 160  
 161  /**
 162   * Outputs the first embedded item in the activity oEmbed template.
 163   *
 164   * @since 2.6.0
 165   */
 166  function bp_activity_embed_media() {
 167      // Bail if oEmbed request explicitly hides media.
 168      if ( isset( $_GET['hide_media'] ) && true == wp_validate_boolean( $_GET['hide_media'] ) ) {
 169          /**
 170           * Do something after media is rendered for an activity oEmbed item.
 171           *
 172           * @since 2.6.0
 173           */
 174          do_action( 'bp_activity_embed_after_media' );
 175  
 176          return;
 177      }
 178  
 179      /**
 180       * Should we display media in the oEmbed template?
 181       *
 182       * @since 2.6.0
 183       *
 184       * @param bool $retval Defaults to true.
 185       */
 186      $allow_media = apply_filters( 'bp_activity_embed_display_media', true );
 187  
 188      // Find oEmbeds from only WP registered providers.
 189      bp_remove_all_filters( 'oembed_providers' );
 190      $media = bp_core_extract_media_from_content( $GLOBALS['activities_template']->activity->content, 'embeds' );
 191      bp_restore_all_filters( 'oembed_providers' );
 192  
 193      // oEmbeds have precedence over inline video / audio.
 194      if ( isset( $media['embeds'] ) && true === $allow_media ) {
 195          // Autoembed first URL.
 196          $oembed_defaults = wp_embed_defaults();
 197          $oembed_args = array(
 198              'width'    => $oembed_defaults['width'],
 199              'height'   => $oembed_defaults['height'],
 200              'discover' => true
 201          );
 202          $url      = $media['embeds'][0]['url'];
 203          $cachekey = '_oembed_response_' . md5( $url . serialize( $oembed_args ) );
 204  
 205          // Try to fetch oEmbed response from meta.
 206          $oembed = bp_activity_get_meta( bp_get_activity_id(), $cachekey );
 207  
 208          // No cache, so fetch full oEmbed response now!
 209          if ( '' === $oembed ) {
 210              $o = _wp_oembed_get_object();
 211              $oembed = $o->fetch( $o->get_provider( $url, $oembed_args ), $url, $oembed_args );
 212  
 213              // Cache oEmbed response.
 214              bp_activity_update_meta( bp_get_activity_id(), $cachekey, $oembed );
 215          }
 216  
 217          $content = '';
 218  
 219          /**
 220           * Filters the default embed display max width.
 221           *
 222           * This is used if the oEmbed response does not return a thumbnail width.
 223           *
 224           * @since 2.6.0
 225           *
 226           * @param int $width.
 227           */
 228          $width = (int) apply_filters( 'bp_activity_embed_display_media_width', 550 );
 229  
 230          // Set thumbnail.
 231          if ( 'photo' === $oembed->type ) {
 232              $thumbnail = $oembed->url;
 233          } elseif ( isset( $oembed->thumbnail_url ) ) {
 234              $thumbnail = $oembed->thumbnail_url;
 235  
 236          /* Non-oEmbed standard attributes */
 237          // Mixcloud.
 238          } elseif ( isset( $oembed->image ) ) {
 239              $thumbnail = $oembed->image;
 240          // ReverbNation.
 241          } elseif ( isset( $oembed->{'thumbnail-url'} ) ) {
 242              $thumbnail = $oembed->{'thumbnail-url'};
 243          }
 244  
 245          // Display thumb and related oEmbed meta.
 246          if ( true === isset ( $thumbnail ) ) {
 247              $play_icon = $caption = '';
 248  
 249              // Add play icon for non-photos.
 250              if ( 'photo' !== $oembed->type ) {
 251                  /**
 252                   * ion-play icon from Ionicons.
 253                   *
 254                   * @link    http://ionicons.com/
 255                   * @license MIT
 256                   */
 257                  $play_icon = <<<EOD
 258  <svg id="Layer_1" style="enable-background:new 0 0 512 512;" version="1.1" viewBox="0 0 512 512" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path d="M405.2,232.9L126.8,67.2c-3.4-2-6.9-3.2-10.9-3.2c-10.9,0-19.8,9-19.8,20H96v344h0.1c0,11,8.9,20,19.8,20  c4.1,0,7.5-1.4,11.2-3.4l278.1-165.5c6.6-5.5,10.8-13.8,10.8-23.1C416,246.7,411.8,238.5,405.2,232.9z"/></svg>
 259  EOD;
 260  
 261                  $play_icon = sprintf( '<a rel="nofollow" class="play-btn" href="%1$s" onclick="top.location.href=\'%1$s\'">%2$s</a>', esc_url( $url ), $play_icon );
 262              }
 263  
 264              // Thumb width.
 265              $thumb_width = isset( $oembed->thumbnail_width ) && 'photo' !== $oembed->type && (int) $oembed->thumbnail_width < 550 ? (int) $oembed->thumbnail_width : $width;
 266  
 267              $float_width = 350;
 268  
 269              // Set up thumb.
 270              $content = sprintf( '<div class="thumb" style="max-width:%1$spx">%2$s<a href="%3$s" rel="nofollow" onclick="top.location.href=\'%3$s\'"><img loading="lazy" src="%4$s" alt="" /></a></div>', $thumb_width, $play_icon, esc_url( $url ), esc_url( $thumbnail ) );
 271  
 272              // Show title.
 273              if ( isset( $oembed->title ) ) {
 274                  $caption .= sprintf( '<p class="caption-title"><strong>%s</strong></p>', apply_filters( 'single_post_title', $oembed->title ) );
 275              }
 276  
 277              // Show description (non-oEmbed standard).
 278              if ( isset( $oembed->description ) ) {
 279                  $caption .= sprintf( '<div class="caption-description">%s</div>', apply_filters( 'bp_activity_get_embed_excerpt', $oembed->description ) );
 280              }
 281  
 282              // Show author info.
 283              if ( isset( $oembed->provider_name ) && isset( $oembed->author_name ) ) {
 284                  /* translators: 1: oEmbed author. 2: oEmbed provider. eg. By BuddyPress on YouTube. */
 285                  $anchor_text = sprintf( __( 'By %1$s on %2$s', 'buddypress' ), $oembed->author_name, $oembed->provider_name );
 286  
 287              } elseif ( isset( $oembed->provider_name ) ) {
 288                  /* translators: %s: oEmbed provider. */
 289                  $anchor_text = sprintf( __( 'View on %s', 'buddypress' ), $oembed->provider_name );
 290              }
 291  
 292              if ( true === isset( $anchor_text ) )  {
 293                  $caption .= sprintf( '<a rel="nofollow" href="%1$s" onclick="top.location.href=\'%1$s\'">%2$s</a>', esc_url( $url ), apply_filters( 'the_title', $anchor_text ) );
 294              }
 295  
 296              // Set up caption.
 297              if ( '' !== $caption ) {
 298                  $css_class = isset( $oembed->provider_name ) ? sprintf( ' provider-%s', sanitize_html_class( strtolower( $oembed->provider_name ) ) ) : '';
 299                  $caption = sprintf( '<div class="caption%1$s" style="width:%2$s">%3$s</div>',
 300                      $css_class,
 301                      $thumb_width > $float_width ? 100 . '%' : round( ( $width - (int) $thumb_width ) / $width * 100 ) . '%',
 302                      $caption
 303                  );
 304  
 305                  $content .= $caption;
 306              }
 307          }
 308  
 309          // Print rich content.
 310          if ( '' !== $content ) {
 311              printf( '<div class="bp-activity-embed-display-media %s" style="max-width:%spx">%s</div>',
 312                  $thumb_width < $float_width ? 'two-col' : 'one-col',
 313                  $thumb_width < $float_width ? $width : $thumb_width,
 314                  $content
 315              );
 316          }
 317  
 318      // Video / audio.
 319      } elseif ( true === $allow_media ) {
 320          // Call BP_Embed if it hasn't already loaded.
 321          bp_embed_init();
 322  
 323          // Run shortcode and embed routine.
 324          $content = buddypress()->embed->run_shortcode( $GLOBALS['activities_template']->activity->content );
 325          $content = buddypress()->embed->autoembed( $content );
 326  
 327          // Try to find inline video / audio.
 328          $media = bp_core_extract_media_from_content( $content, 96 );
 329  
 330          // Video takes precedence. HTML5-only.
 331          if ( isset( $media['videos'] ) && 'shortcodes' === $media['videos'][0]['source'] ) {
 332              printf( '<video controls preload="metadata"><source src="%1$s"><p>%2$s</p></video>',
 333                  esc_url( $media['videos'][0]['url'] ),
 334                  esc_html__( 'Your browser does not support HTML5 video', 'buddypress' )
 335              );
 336  
 337          // No video? Try audio. HTML5-only.
 338          } elseif ( isset( $media['audio'] ) && 'shortcodes' === $media['audio'][0]['source'] ) {
 339              printf( '<audio controls preload="metadata"><source src="%1$s"><p>%2$s</p></audio>',
 340                  esc_url( $media['audio'][0]['url'] ),
 341                  esc_html__( 'Your browser does not support HTML5 audio', 'buddypress' )
 342              );
 343          }
 344  
 345      }
 346  
 347      /** This hook is documented in /bp-activity/bp-activity-embeds.php */
 348      do_action( 'bp_activity_embed_after_media' );
 349  }


Generated: Thu Nov 21 01:00:57 2024 Cross-referenced by PHPXref 0.7.1