[ Index ]

WordPress Cross Reference

title

Body

[close]

/wp-includes/ -> class-oembed.php (source)

   1  <?php
   2  /**
   3   * API for fetching the HTML to embed remote content based on a provided URL.
   4   * Used internally by the {@link WP_Embed} class, but is designed to be generic.
   5   *
   6   * @link http://codex.wordpress.org/oEmbed oEmbed Codex Article
   7   * @link http://oembed.com/ oEmbed Homepage
   8   *
   9   * @package WordPress
  10   * @subpackage oEmbed
  11   */
  12  
  13  /**
  14   * oEmbed class.
  15   *
  16   * @package WordPress
  17   * @subpackage oEmbed
  18   * @since 2.9.0
  19   */
  20  class WP_oEmbed {
  21      var $providers = array();
  22  
  23      /**
  24       * Constructor
  25       *
  26       * @uses apply_filters() Filters a list of pre-defined oEmbed providers.
  27       */
  28  	function __construct() {
  29          $providers = array(
  30              '#https?://(www\.)?youtube\.com/watch.*#i'           => array( 'http://www.youtube.com/oembed',                     true  ),
  31              'http://youtu.be/*'                                  => array( 'http://www.youtube.com/oembed',                     false ),
  32              'http://blip.tv/*'                                   => array( 'http://blip.tv/oembed/',                            false ),
  33              '#https?://(www\.)?vimeo\.com/.*#i'                  => array( 'http://vimeo.com/api/oembed.{format}',              true  ),
  34              '#https?://(www\.)?dailymotion\.com/.*#i'            => array( 'http://www.dailymotion.com/services/oembed',        true  ),
  35              'http://dai.ly/*'                                    => array( 'http://www.dailymotion.com/services/oembed',        false ),
  36              '#https?://(www\.)?flickr\.com/.*#i'                 => array( 'http://www.flickr.com/services/oembed/',            true  ),
  37              'http://flic.kr/*'                                   => array( 'http://www.flickr.com/services/oembed/',            false ),
  38              '#https?://(.+\.)?smugmug\.com/.*#i'                 => array( 'http://api.smugmug.com/services/oembed/',           true  ),
  39              '#https?://(www\.)?hulu\.com/watch/.*#i'             => array( 'http://www.hulu.com/api/oembed.{format}',           true  ),
  40              '#https?://(www\.)?viddler\.com/.*#i'                => array( 'http://lab.viddler.com/services/oembed/',           true  ),
  41              'http://qik.com/*'                                   => array( 'http://qik.com/api/oembed.{format}',                false ),
  42              'http://revision3.com/*'                             => array( 'http://revision3.com/api/oembed/',                  false ),
  43              'http://i*.photobucket.com/albums/*'                 => array( 'http://photobucket.com/oembed',                     false ),
  44              'http://gi*.photobucket.com/groups/*'                => array( 'http://photobucket.com/oembed',                     false ),
  45              '#https?://(www\.)?scribd\.com/.*#i'                 => array( 'http://www.scribd.com/services/oembed',             true  ),
  46              'http://wordpress.tv/*'                              => array( 'http://wordpress.tv/oembed/',                       false ),
  47              '#https?://(.+\.)?polldaddy\.com/.*#i'               => array( 'http://polldaddy.com/oembed/',                      true  ),
  48              '#https?://(www\.)?funnyordie\.com/videos/.*#i'      => array( 'http://www.funnyordie.com/oembed',                  true  ),
  49              '#https?://(www\.)?twitter\.com/.+?/status(es)?/.*#i'=> array( 'https://api.twitter.com/1/statuses/oembed.{format}', true ),
  50               '#https?://(www\.)?soundcloud\.com/.*#i'             => array( 'http://soundcloud.com/oembed',                      true  ),
  51              '#https?://(www\.)?slideshare\.net/*#'               => array( 'http://www.slideshare.net/api/oembed/2',            true  ),
  52              '#http://instagr(\.am|am\.com)/p/.*#i'               => array( 'http://api.instagram.com/oembed',                   true  ),
  53              '#https?://(www\.)?rdio\.com/.*#i'                   => array( 'http://www.rdio.com/api/oembed/',                   true  ),
  54              '#https?://rd\.io/x/.*#i'                            => array( 'http://www.rdio.com/api/oembed/',                   true  ),
  55              '#https?://(open|play)\.spotify\.com/.*#i'           => array( 'https://embed.spotify.com/oembed/',                 true  ),
  56          );
  57          /**
  58           * Filter the list of oEmbed providers.
  59           *
  60           * Discovery is disabled for users lacking the unfiltered_html capability.
  61           * Only providers in this array will be used for those users.
  62           *
  63           * @see wp_oembed_add_provider()
  64           *
  65           * @since 2.9.0
  66           *
  67           * @param array $providers An array of popular oEmbed providers.
  68           */
  69          $this->providers = apply_filters( 'oembed_providers', $providers );
  70  
  71          // Fix any embeds that contain new lines in the middle of the HTML which breaks wpautop().
  72          add_filter( 'oembed_dataparse', array($this, '_strip_newlines'), 10, 3 );
  73      }
  74  
  75      /**
  76       * The do-it-all function that takes a URL and attempts to return the HTML.
  77       *
  78       * @see WP_oEmbed::discover()
  79       * @see WP_oEmbed::fetch()
  80       * @see WP_oEmbed::data2html()
  81       *
  82       * @param string $url The URL to the content that should be attempted to be embedded.
  83       * @param array $args Optional arguments. Usually passed from a shortcode.
  84       * @return bool|string False on failure, otherwise the UNSANITIZED (and potentially unsafe) HTML that should be used to embed.
  85       */
  86  	function get_html( $url, $args = '' ) {
  87          $provider = false;
  88  
  89          if ( !isset($args['discover']) )
  90              $args['discover'] = true;
  91  
  92          foreach ( $this->providers as $matchmask => $data ) {
  93              list( $providerurl, $regex ) = $data;
  94  
  95              // Turn the asterisk-type provider URLs into regex
  96              if ( !$regex ) {
  97                  $matchmask = '#' . str_replace( '___wildcard___', '(.+)', preg_quote( str_replace( '*', '___wildcard___', $matchmask ), '#' ) ) . '#i';
  98                  $matchmask = preg_replace( '|^#http\\\://|', '#https?\://', $matchmask );
  99              }
 100  
 101              if ( preg_match( $matchmask, $url ) ) {
 102                  $provider = str_replace( '{format}', 'json', $providerurl ); // JSON is easier to deal with than XML
 103                  break;
 104              }
 105          }
 106  
 107          if ( !$provider && $args['discover'] )
 108              $provider = $this->discover( $url );
 109  
 110          if ( !$provider || false === $data = $this->fetch( $provider, $url, $args ) )
 111              return false;
 112  
 113          /**
 114           * Filter the HTML returned by the oEmbed provider.
 115           *
 116           * @since 2.9.0
 117           *
 118           * @param string $data The returned oEmbed HTML.
 119           * @param string $url  URL of the content to be embedded.
 120           * @param array  $args Optional arguments, usually passed from a shortcode.
 121           */
 122          return apply_filters( 'oembed_result', $this->data2html( $data, $url ), $url, $args );
 123      }
 124  
 125      /**
 126       * Attempts to find oEmbed provider discovery <link> tags at the given URL.
 127       *
 128       * @param string $url The URL that should be inspected for discovery <link> tags.
 129       * @return bool|string False on failure, otherwise the oEmbed provider URL.
 130       */
 131  	function discover( $url ) {
 132          $providers = array();
 133  
 134          // Fetch URL content
 135          if ( $html = wp_remote_retrieve_body( wp_safe_remote_get( $url ) ) ) {
 136  
 137              /**
 138               * Filter the link types that contain oEmbed provider URLs.
 139               *
 140               * @since 2.9.0
 141               *
 142               * @param array $format Array of oEmbed link types. Accepts 'application/json+oembed',
 143               *                      'text/xml+oembed', and 'application/xml+oembed' (incorrect,
 144               *                      used by at least Vimeo).
 145               */
 146              $linktypes = apply_filters( 'oembed_linktypes', array(
 147                  'application/json+oembed' => 'json',
 148                  'text/xml+oembed' => 'xml',
 149                  'application/xml+oembed' => 'xml',
 150              ) );
 151  
 152              // Strip <body>
 153              $html = substr( $html, 0, stripos( $html, '</head>' ) );
 154  
 155              // Do a quick check
 156              $tagfound = false;
 157              foreach ( $linktypes as $linktype => $format ) {
 158                  if ( stripos($html, $linktype) ) {
 159                      $tagfound = true;
 160                      break;
 161                  }
 162              }
 163  
 164              if ( $tagfound && preg_match_all( '/<link([^<>]+)>/i', $html, $links ) ) {
 165                  foreach ( $links[1] as $link ) {
 166                      $atts = shortcode_parse_atts( $link );
 167  
 168                      if ( !empty($atts['type']) && !empty($linktypes[$atts['type']]) && !empty($atts['href']) ) {
 169                          $providers[$linktypes[$atts['type']]] = $atts['href'];
 170  
 171                          // Stop here if it's JSON (that's all we need)
 172                          if ( 'json' == $linktypes[$atts['type']] )
 173                              break;
 174                      }
 175                  }
 176              }
 177          }
 178  
 179          // JSON is preferred to XML
 180          if ( !empty($providers['json']) )
 181              return $providers['json'];
 182          elseif ( !empty($providers['xml']) )
 183              return $providers['xml'];
 184          else
 185              return false;
 186      }
 187  
 188      /**
 189       * Connects to a oEmbed provider and returns the result.
 190       *
 191       * @param string $provider The URL to the oEmbed provider.
 192       * @param string $url The URL to the content that is desired to be embedded.
 193       * @param array $args Optional arguments. Usually passed from a shortcode.
 194       * @return bool|object False on failure, otherwise the result in the form of an object.
 195       */
 196  	function fetch( $provider, $url, $args = '' ) {
 197          $args = wp_parse_args( $args, wp_embed_defaults() );
 198  
 199          $provider = add_query_arg( 'maxwidth', (int) $args['width'], $provider );
 200          $provider = add_query_arg( 'maxheight', (int) $args['height'], $provider );
 201          $provider = add_query_arg( 'url', urlencode($url), $provider );
 202  
 203          /**
 204           * Filter the oEmbed URL to be fetched.
 205           *
 206           * @since 2.9.0
 207           *
 208           * @param string $provider URL of the oEmbed provider.
 209           * @param string $url      URL of the content to be embedded.
 210           * @param array  $args     Optional arguments, usually passed from a shortcode.
 211           */
 212          $provider = apply_filters( 'oembed_fetch_url', $provider, $url, $args );
 213  
 214          foreach( array( 'json', 'xml' ) as $format ) {
 215              $result = $this->_fetch_with_format( $provider, $format );
 216              if ( is_wp_error( $result ) && 'not-implemented' == $result->get_error_code() )
 217                  continue;
 218              return ( $result && ! is_wp_error( $result ) ) ? $result : false;
 219          }
 220          return false;
 221      }
 222  
 223      /**
 224       * Fetches result from an oEmbed provider for a specific format and complete provider URL
 225       *
 226       * @since 3.0.0
 227       * @access private
 228       * @param string $provider_url_with_args URL to the provider with full arguments list (url, maxheight, etc.)
 229       * @param string $format Format to use
 230       * @return bool|object False on failure, otherwise the result in the form of an object.
 231       */
 232  	function _fetch_with_format( $provider_url_with_args, $format ) {
 233          $provider_url_with_args = add_query_arg( 'format', $format, $provider_url_with_args );
 234          $response = wp_safe_remote_get( $provider_url_with_args );
 235          if ( 501 == wp_remote_retrieve_response_code( $response ) )
 236              return new WP_Error( 'not-implemented' );
 237          if ( ! $body = wp_remote_retrieve_body( $response ) )
 238              return false;
 239          $parse_method = "_parse_$format";
 240          return $this->$parse_method( $body );
 241      }
 242  
 243      /**
 244       * Parses a json response body.
 245       *
 246       * @since 3.0.0
 247       * @access private
 248       */
 249  	function _parse_json( $response_body ) {
 250          return ( ( $data = json_decode( trim( $response_body ) ) ) && is_object( $data ) ) ? $data : false;
 251      }
 252  
 253      /**
 254       * Parses an XML response body.
 255       *
 256       * @since 3.0.0
 257       * @access private
 258       */
 259  	function _parse_xml( $response_body ) {
 260          if ( ! function_exists( 'libxml_disable_entity_loader' ) )
 261              return false;
 262  
 263          $loader = libxml_disable_entity_loader( true );
 264          $errors = libxml_use_internal_errors( true );
 265  
 266          $return = $this->_parse_xml_body( $response_body );
 267  
 268          libxml_use_internal_errors( $errors );
 269          libxml_disable_entity_loader( $loader );
 270  
 271          return $return;
 272      }
 273  
 274      /**
 275       * Helper function for parsing an XML response body.
 276       *
 277       * @since 3.6.0
 278       * @access private
 279       */
 280  	private function _parse_xml_body( $response_body ) {
 281          if ( ! function_exists( 'simplexml_import_dom' ) || ! class_exists( 'DOMDocument' ) )
 282              return false;
 283  
 284          $dom = new DOMDocument;
 285          $success = $dom->loadXML( $response_body );
 286          if ( ! $success )
 287              return false;
 288  
 289          if ( isset( $dom->doctype ) )
 290              return false;
 291  
 292          foreach ( $dom->childNodes as $child ) {
 293              if ( XML_DOCUMENT_TYPE_NODE === $child->nodeType )
 294                  return false;
 295          }
 296  
 297          $xml = simplexml_import_dom( $dom );
 298          if ( ! $xml )
 299              return false;
 300  
 301          $return = new stdClass;
 302          foreach ( $xml as $key => $value ) {
 303              $return->$key = (string) $value;
 304          }
 305  
 306          return $return;
 307      }
 308  
 309      /**
 310       * Converts a data object from {@link WP_oEmbed::fetch()} and returns the HTML.
 311       *
 312       * @param object $data A data object result from an oEmbed provider.
 313       * @param string $url The URL to the content that is desired to be embedded.
 314       * @return bool|string False on error, otherwise the HTML needed to embed.
 315       */
 316  	function data2html( $data, $url ) {
 317          if ( ! is_object( $data ) || empty( $data->type ) )
 318              return false;
 319  
 320          $return = false;
 321  
 322          switch ( $data->type ) {
 323              case 'photo':
 324                  if ( empty( $data->url ) || empty( $data->width ) || empty( $data->height ) )
 325                      break;
 326                  if ( ! is_string( $data->url ) || ! is_numeric( $data->width ) || ! is_numeric( $data->height ) )
 327                      break;
 328  
 329                  $title = ! empty( $data->title ) && is_string( $data->title ) ? $data->title : '';
 330                  $return = '<a href="' . esc_url( $url ) . '"><img src="' . esc_url( $data->url ) . '" alt="' . esc_attr($title) . '" width="' . esc_attr($data->width) . '" height="' . esc_attr($data->height) . '" /></a>';
 331                  break;
 332  
 333              case 'video':
 334              case 'rich':
 335                  if ( ! empty( $data->html ) && is_string( $data->html ) )
 336                      $return = $data->html;
 337                  break;
 338  
 339              case 'link':
 340                  if ( ! empty( $data->title ) && is_string( $data->title ) )
 341                      $return = '<a href="' . esc_url( $url ) . '">' . esc_html( $data->title ) . '</a>';
 342                  break;
 343  
 344              default:
 345                  $return = false;
 346          }
 347  
 348          /**
 349           * Filter the returned oEmbed HTML.
 350           *
 351           * Use this filter to add support for custom data types, or to filter the result.
 352           *
 353           * @since 2.9.0
 354           *
 355           * @param string $return The returned oEmbed HTML.
 356           * @param object $data   A data object result from an oEmbed provider.
 357           * @param string $url    The URL of the content to be embedded.
 358           */
 359          return apply_filters( 'oembed_dataparse', $return, $data, $url );
 360      }
 361  
 362      /**
 363       * Strip any new lines from the HTML.
 364       *
 365       * @access private
 366       * @param string $html Existing HTML.
 367       * @param object $data Data object from WP_oEmbed::data2html()
 368       * @param string $url The original URL passed to oEmbed.
 369       * @return string Possibly modified $html
 370       */
 371  	function _strip_newlines( $html, $data, $url ) {
 372          if ( false !== strpos( $html, "\n" ) )
 373              $html = str_replace( array( "\r\n", "\n" ), '', $html );
 374  
 375          return $html;
 376      }
 377  }
 378  
 379  /**
 380   * Returns the initialized {@link WP_oEmbed} object
 381   *
 382   * @since 2.9.0
 383   * @access private
 384   *
 385   * @see WP_oEmbed
 386   * @uses WP_oEmbed
 387   *
 388   * @return WP_oEmbed object.
 389   */
 390  function _wp_oembed_get_object() {
 391      static $wp_oembed;
 392  
 393      if ( is_null($wp_oembed) )
 394          $wp_oembed = new WP_oEmbed();
 395  
 396      return $wp_oembed;
 397  }


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu