Yoast] This currently stops at the first video (=old behaviour). Is this correct * and as intended ? What about adding the potential secondary videos to the sitemap as well ? * and what about wrapping them in schema.org info in the content ? * This would impact the saving of metadata, how the metadata is presented to the user in the metabox * as the user should be able to edit info on all videos (should they get a choice which is the main * video to use for header info ? ), how the schema.org data is added and how the sitemap is generated. * Adding the 'matched' string to the saved metadata would help with the schema.org data * (str_replace on the correct video) */ class WPSEO_Video_Analyse_Post { /** * Whether or not the DOM extension is enabled. * * @var bool */ public static $dom_enabled = false; /** * Array of supported plugins to take into account when analysing a post. * * Format: key = class name suffix, value = plugin basename. * * {@internal Changing the order of this array will change the priority with which the plugin * is treated. * The current order is based on the number of plugin downloads as stated in the * WP repository per 2014-07-25.} * * {@internal To add (or remove) support for a plugin: * - Create a class file in the supported-plugins folder (see other files and template for examples). * - Add the plugin to the below list. * - Add the class file to the autoload list in video-seo.php. * - Add one of more unit test file(s) for the features supported by the plugin. * - Add the plugin to travis.yml for download via git/svn.} * * @var array */ public static $supported_plugins = array( 'Jetpack' => 'jetpack/jetpack.php', 'Smart_Youtube' => 'smart-youtube/smartyoutube.php', 'Cincopa_Media' => 'video-playlist-and-gallery-plugin/wp-media-cincopa.php', 'JW_Player' => 'jw-player-plugin-for-wordpress/jwplayermodule.php', 'Youtube_Embed_Plus' => 'youtube-embed-plus/youtube.php', 'Tubepress' => 'tubepress/tubepress.php', 'Media_Element_Player' => 'media-element-html5-video-and-audio-player/mediaelement-js-wp.php', 'Youtube_Embed' => 'youtube-embed/youtube-embed.php', 'Featured_Video_Plus' => 'featured-video-plus/featured-video-plus.php', 'FV_WordPress_Flowplayer' => 'fv-wordpress-flowplayer/flowplayer.php', 'WP_Youtube_Lyte' => 'wp-youtube-lyte/wp-youtube-lyte.php', 'WP_Video_Lightbox' => 'wp-video-lightbox/wp-video-lightbox.php', 'Advanced_Responsive_Video_Embedder' => 'advanced-responsive-video-embedder/advanced-responsive-video-embedder.php', 'Flowplayer5' => 'flowplayer5/flowplayer.php', 'Ustudio' => 'ustudio/plugin.php', ); /** * Array of active plugins - subset of the supported plugins. * * Format: key = class name suffix, value = object instance. * * @var array */ protected static $active_plugins = array(); /** * Array of supported shortcodes with their handler methods. * * Format: key = shortcode, value = array of handler methods, i.e. if several plugins * use the same shortcode, each handler method will be used in turn. * * @var array */ protected static $shortcodes = array(); /** * Array of additional supported post_types with their handler methods. * * Format: key = post_type, value = array of handler methods, i.e. if several plugins * use the same post_type, each handler method will be used in turn. * * @var array */ protected static $post_types = array(); /** * Array of additional supported custom post meta fields with their handler methods. * * Format: key = meta_key, value = array of handler methods, i.e. if several plugins * use the same meta_key, each handler method will be used in turn. * * @var array */ protected static $meta_keys = array(); /** * Array of alternative protocol schemes to take into account. * * @var array */ protected static $alt_protocols = array(); /** * Array of video embeds to take into account. * * @var array */ protected static $video_autoembeds = array(); /** * Array of video OEmbeds to take into account. * * @var array */ protected static $video_oembeds = array(); /** * The video info array. * * @var array */ protected $vid = array( 'id' => null, 'type' => null, 'url' => null, ); /** * The video array with all the data of the previous "fetch", if available. * * @var array */ protected $old_vid = array(); /** * The content of the post to analyse. * * @var string */ protected $content = ''; /** * The post object for the post to analyse. * * @var object */ protected $post; /** * Use embedly as a fall back method for video detail retrieval? * * @var bool */ protected static $use_embedly; /** * Initialize the class * * @param string $content The content to parse for videos. * @param array $vid The video array to update. * @param array $old_vid The former video array. * @param mixed $post The post object or the post id of the post to analyse. * * @return \WPSEO_Video_Analyse_Post */ public function __construct( $content, $vid, $old_vid = array(), $post = null ) { $this->vid = array_merge( $this->vid, $vid ); $this->old_vid = $old_vid; // Set up post object if needed. if ( ! empty( $post ) && ! is_object( $post ) ) { $post = get_post( $post ); } if ( is_object( $post ) ) { $this->post = $post; } elseif ( ! empty( $GLOBALS['post'] ) ) { // Default to the current post - @todo probably wrong as it might be a term which is being analysed. $this->post = $GLOBALS['post']; } /** * Filter: 'wpseo_video_index_content' - Allow changing the content of a post before indexation. * * @api string $content The content to analyze. * * @param array $vid Array with video info, usually empty. * @param \WP_Post $post Post object. */ $content = apply_filters( 'wpseo_video_index_content', $content, $this->vid, $this->post ); // Deal with alternative protocols. if ( in_array( 'youtube::', self::$alt_protocols, true ) ) { // Very specific to the YouTube Embed plugin - maybe should be moved to plugin methods. $content = str_replace( 'youtube::', 'http://www.youtube.com/watch?v=', $content ); } $this->content = str_replace( self::$alt_protocols, 'http://', $content ); // Can we use Embedly? if ( ! isset( self::$use_embedly ) ) { // Check if we have an Embedly api key. if ( WPSEO_Options::get( 'video_embedly_api_key', '' ) !== '' ) { self::$use_embedly = true; } else { self::$use_embedly = false; } } $this->analyse(); } /** * Reset statics */ public static function reset_statics() { self::$dom_enabled = false; self::$active_plugins = array(); self::$shortcodes = array(); self::$post_types = array(); self::$meta_keys = array(); self::$alt_protocols = array(); self::$video_autoembeds = array(); self::$video_oembeds = array(); } /** * Set statics */ public static function set_statics() { // Reset just in case this method is called more than once (like when we're testing). self::reset_statics(); if ( extension_loaded( 'dom' ) && class_exists( 'domxpath' ) ) { self::$dom_enabled = true; } /* * Add WP core to 'active plugins' as the first (highest prio) item * Add this plugin as the second */ self::$active_plugins['wp_core'] = new WPSEO_Video_Support_Core(); self::$active_plugins['videoseo'] = new WPSEO_Video_Plugin_Yoast_Videoseo(); /* * @todo It might be better if we can figure out if the plugin is installed rather than active * Also - this will give issues with plugins in the mu-plugins directory as is_plugin_active() * incorrectly returns false (should be fixed in WP4 ?) */ if ( ! function_exists( 'is_plugin_active' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } foreach ( self::$supported_plugins as $name => $plugin_basenames ) { $plugin_basenames = (array) $plugin_basenames; foreach ( $plugin_basenames as $plugin_basename ) { if ( is_plugin_active( $plugin_basename ) ) { $classname = 'WPSEO_Video_Plugin_' . $name; self::$active_plugins[ $name ] = new $classname(); break; } } } unset( $name, $plugin_basenames, $plugin_basename, $classname ); // Add the plugin features for all active plugins. if ( is_array( self::$active_plugins ) && self::$active_plugins !== array() ) { foreach ( self::$active_plugins as $name => $instance ) { // Add known shortcodes. $shortcodes = $instance->get_shortcodes(); if ( is_array( $shortcodes ) && $shortcodes !== array() ) { foreach ( $shortcodes as $sc ) { self::$shortcodes[ $sc ][] = array( $instance, 'get_info_from_shortcode' ); } } unset( $shortcodes, $sc ); // Add known additional post_types. $post_types = $instance->get_post_types(); if ( is_array( $post_types ) && $post_types !== array() ) { foreach ( $post_types as $pt ) { self::$post_types[ $pt ][] = array( $instance, 'get_info_for_post_type' ); } } unset( $post_types, $pt ); // Add known additional meta_keys. $meta_keys = $instance->get_meta_keys(); if ( is_array( $meta_keys ) && $meta_keys !== array() ) { foreach ( $meta_keys as $key ) { self::$meta_keys[ $key ][] = array( $instance, 'get_info_from_post_meta' ); } } unset( $meta_keys, $key ); // Add alternative protocols. $alt_protocols = $instance->get_alt_protocols(); if ( is_array( $alt_protocols ) && $alt_protocols !== array() ) { self::$alt_protocols = array_unique( array_merge( self::$alt_protocols, $alt_protocols ) ); } unset( $alt_protocols ); // Add autoembed information. $video_autoembeds = $instance->get_video_autoembeds(); if ( is_array( $video_autoembeds ) && $video_autoembeds !== array() ) { /* * {@internal Merge order reversed, if there is a handler name conflict * between plugins, defer to the more popular plugin which will * have been added first.} */ self::$video_autoembeds = array_unique( array_merge( $video_autoembeds, self::$video_autoembeds ) ); } unset( $video_autoembeds ); // Add oembed information. $video_oembeds = $instance->get_video_oembeds(); if ( is_array( $video_oembeds ) && $video_oembeds !== array() ) { /* * {@internal Merge order reversed, if there is a handler name conflict * between plugins, defer to the more popular plugin which will * have been added first.} */ self::$video_oembeds = array_unique( array_merge( $video_oembeds, self::$video_oembeds ) ); } unset( $video_oembeds ); } unset( $name, $instance ); } } /** * Get the video info * * @return array|string Return video array or 'none' */ public function get_vid_info() { if ( isset( $this->vid['content_loc'] ) || isset( $this->vid['player_loc'] ) ) { $this->normalize_values(); $vid = apply_filters( 'wpseo_video_' . $this->vid['type'] . '_details', $this->vid ); return array_filter( $vid ); } else { return 'none'; } } /** * Make sure all duration, view_count, height and width values are integers */ protected function normalize_values() { $keys = array( 'duration', 'height', 'view_count', 'width', ); foreach ( $keys as $key ) { if ( isset( $this->vid[ $key ] ) ) { $this->vid[ $key ] = absint( round( $this->vid[ $key ] ) ); } } } /** * Analyse the post for video content */ protected function analyse() { $methods = array( 'get_video_from_post_type', 'get_video_from_post_meta', 'get_video_from_attachment', 'get_video_from_shortcode', 'get_video_from_auto_embeds', 'get_video_through_old_methods', ); foreach ( $methods as $method ) { if ( is_callable( array( $this, $method ) ) ) { $vid = call_user_func( array( $this, $method ) ); // Check for video. if ( $vid !== array() && ( isset( $vid['content_loc'] ) || isset( $vid['player_loc'] ) ) ) { $this->vid = array_merge( $this->vid, $vid ); break; } } } } /** * Check if the current post type is a video post type and if we can find usable info through it */ protected function get_video_from_post_type() { $vid = array(); if ( ( is_array( self::$post_types ) && self::$post_types !== array() ) && ( is_object( $this->post ) && isset( self::$post_types[ $this->post->post_type ] ) ) ) { foreach ( self::$post_types[ $this->post->post_type ] as $function ) { if ( is_callable( $function ) ) { $vid = call_user_func( $function, $this->post->ID, $this->post->post_type, $this->post ); if ( is_array( $vid ) && $vid !== array() ) { $vid = $this->get_video_details( $vid ); if ( ! empty( $vid['player_loc'] ) || ! empty( $vid['content_loc'] ) ) { // Stop on the first function which delivers results. break; } else { // Reset $vid if no usable info was found. $vid = array(); } } } } } return $vid; } /** * Check if any custom fields are video fields and if they contain usable info */ protected function get_video_from_post_meta() { $vid = array(); if ( is_array( self::$meta_keys ) && self::$meta_keys !== array() && ! empty( $this->post->ID ) ) { foreach ( self::$meta_keys as $key => $callables ) { $meta_values = $this->get_normalized_meta_values( $key, $this->post->ID ); if ( is_array( $meta_values ) && $meta_values !== array() ) { foreach ( $meta_values as $single_meta_value ) { foreach ( $callables as $function ) { if ( is_callable( $function ) ) { $vid = call_user_func( $function, $single_meta_value, $key, $this->post->ID ); if ( is_array( $vid ) && $vid !== array() ) { $vid = $this->get_video_details( $vid ); if ( ! empty( $vid['player_loc'] ) || ! empty( $vid['content_loc'] ) ) { // Stop on the first function which deliveres results. unset( $vid['__add_to_content'] ); break 3; } elseif ( ! empty( $vid['__add_to_content'] ) ) { $this->content = $vid['__add_to_content'] . "\n" . $this->content; $vid = array(); } else { // Reset $vid if no usable info was found. $vid = array(); } } } } } } } } return $vid; } /** * Get post meta values to analyse for video content * * @param string $key Meta key to get the values for. * @param int $post_id Post to get the values for. * * @return array Single dimensional array with already entity normalized potentially usable meta values. */ protected function get_normalized_meta_values( $key, $post_id ) { $real_values = array(); $meta_values = get_post_custom_values( $key, $post_id ); if ( is_array( $meta_values ) && $meta_values !== array() ) { foreach ( $meta_values as $meta_value ) { $meta_value = maybe_unserialize( $meta_value ); if ( is_scalar( $meta_value ) && ! empty( $meta_value ) ) { $real_values[] = $meta_value; } elseif ( is_array( $meta_value ) && $meta_value !== array() ) { foreach ( $meta_value as $value ) { if ( is_scalar( $value ) && ! empty( $value ) ) { $real_values[] = $value; } elseif ( is_array( $value ) && ! empty( $value[0] ) && is_scalar( $value[0] ) ) { /* * Ignore deeper meta values which are multi-dim arrays as we really * don't know what we need from it them */ $real_values[] = $value[0]; } } } } } unset( $meta_values, $meta_value, $value ); /* * Silly, silly themes _encode_ the value of the post meta field. Yeah it's ridiculous. * But this fixes it. * * ^ Helpful comment, thanks! */ $real_values = array_map( array( $this, 'normalize_entities' ), $real_values ); $real_values = array_map( 'trim', $real_values ); // Remove empties. $real_values = array_filter( $real_values ); return $real_values; } /** * Get all video attachments and see if we can find one we can use */ protected function get_video_from_attachment() { $vid = array(); if ( ! empty( $this->post->ID ) ) { $media = get_attached_media( 'video', $this->post->ID ); if ( is_array( $media ) && $media !== array() ) { foreach ( $media as $video ) { $vid['type'] = 'localfile'; $vid['maybe_local'] = true; $vid['attachment_id'] = $video->ID; $vid['url'] = $video->guid; $vid = $this->get_video_details( $vid ); if ( ! empty( $vid['player_loc'] ) || ! empty( $vid['content_loc'] ) ) { // Stop on the first video which delivers results (i.e. has a usable extension). break; } else { // Reset $vid if no usable info was found. $vid = array(); } } } } return $vid; } /** * Get all the shortcodes, check for any video shortcodes and see if we can parse them to useable info */ protected function get_video_from_shortcode() { $vid = array(); if ( false !== strpos( $this->content, '[' ) && is_array( self::$shortcodes ) && self::$shortcodes !== array() ) { $old_shortcode_tags = $GLOBALS['shortcode_tags']; $GLOBALS['shortcode_tags'] = self::$shortcodes; // WPCS: override ok. /* * 1 - An extra [ to allow for escaping shortcodes with double [[]] * 2 - The shortcode name * 3 - The shortcode argument list * 4 - The self closing / * 5 - The content of a shortcode when it wraps some content. * 6 - An extra ] to allow for escaping shortcodes with double [[]] */ if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $this->content, $matches, PREG_SET_ORDER ) ) { foreach ( $matches as $match ) { // No need to do anything is it's an escaped shortcode. if ( $match[1] !== '[' && $match[6] !== ']' ) { $full = $match[0]; $tag = trim( $match[2] ); $sc_content = $match[5]; $atts = shortcode_parse_atts( $match[3] ); // Handle WordPress.com shortcode format. if ( isset( $atts[0] ) && $sc_content === '' ) { $atts = $this->fix_sc_attributes( $atts ); $sc_content = trim( $atts[0] ); unset( $atts[0] ); } $sc_content = $this->normalize_entities( $sc_content ); if ( is_array( $atts ) && $atts !== array() ) { $atts = array_map( array( $this, 'normalize_entities' ), $atts ); } $thumb = ''; if ( isset( $atts['image'] ) && ( is_string( $atts['image'] ) && $atts['images'] !== '' ) ) { $thumb = $atts['image']; } foreach ( self::$shortcodes[ $tag ] as $function ) { if ( is_callable( $function ) ) { $vid = call_user_func( $function, $full, $tag, $atts, $sc_content ); if ( is_array( $vid ) && $vid !== array() ) { if ( ! isset( $vid['thumbnail_loc'] ) && $thumb !== '' ) { $vid['thumbnail_loc'] = $thumb; } $vid = $this->get_video_details( $vid ); if ( ! empty( $vid['player_loc'] ) || ! empty( $vid['content_loc'] ) ) { // Stop on the first function which delivers results. break 2; } elseif ( ! empty( $vid['__add_to_content'] ) ) { $this->content = $vid['__add_to_content'] . "\n" . $this->content; $vid = array(); } else { // Reset $vid if no usable info was found. $vid = array(); } } } } } } } $GLOBALS['shortcode_tags'] = $old_shortcode_tags; // WPCS: override ok. } return $vid; } /** * Grab all urls which are on their own line and check if any are registered video urls * and if so, grab usable info */ protected function get_video_from_auto_embeds() { $vid = array(); /* * Get all the embeddable urls * Use the same regex as in WP_Embed::autoembed() */ if ( preg_match_all( '`^(?:\s*)(https?://[^\s<>"]+)(?:\s*)$`im', $this->content, $matches, PREG_PATTERN_ORDER ) ) { // Only interested in the real url matches. $urls = $matches[1]; foreach ( $urls as $url ) { // Follow WP. $url = str_replace( '&', '&', $url ); if ( ! empty( $GLOBALS['wp_embed']->handlers ) && is_array( $GLOBALS['wp_embed']->handlers ) ) { // Go through the embed handlers. foreach ( $GLOBALS['wp_embed']->handlers as $handler_array ) { foreach ( $handler_array as $name => $details ) { if ( isset( self::$video_autoembeds[ $name ] ) && preg_match( $details['regex'], $url ) ) { $vid['url'] = $url; if ( self::$video_autoembeds[ $name ] !== '' ) { $vid['type'] = self::$video_autoembeds[ $name ]; } $vid = $this->get_video_details( $vid ); if ( ! empty( $vid['player_loc'] ) || ! empty( $vid['content_loc'] ) ) { // Stop on the first function which delivers results. break 3; } else { // Reset $vid if no usable info was found. $vid = array(); } } } unset( $name, $details ); } unset( $handler_array ); } /* * Go through the Oembed handlers */ $oembed = _wp_oembed_get_object(); $providerurl = $oembed->get_provider( $url, array( 'discover' => false ) ); if ( ( is_string( $providerurl ) && $providerurl !== '' ) && ! empty( self::$video_oembeds ) ) { foreach ( self::$video_oembeds as $partial_url => $service ) { if ( stripos( $providerurl, $partial_url ) !== false ) { $vid['url'] = $url; if ( $service !== '' ) { $vid['type'] = $service; } $vid = $this->get_video_details( $vid ); if ( ! empty( $vid['player_loc'] ) || ! empty( $vid['content_loc'] ) ) { // Stop on the first function which delivers results. break 2; } else { // Reset $vid if no usable info was found. $vid = array(); } } } } } } return $vid; } /** * Parse the content of a post or term description. * * {@internal Stripped version of the old function.} * * @since 1.3 * * @return array */ protected function get_video_through_old_methods() { $content = $this->content; $vid = array(); if ( preg_match( '`()`s', $content, $html5vid ) ) { if ( preg_match( '`src=([\'"])(.*?)\.(' . WPSEO_Video_Sitemap::$video_ext_pattern . ')\1`', $html5vid[1], $content_loc ) ) { $vid['content_loc'] = $content_loc[2] . '.' . $content_loc[3]; $vid['maybe_local'] = true; if ( preg_match( '`poster=([\'"])([^\'"\s]+)\1`', $html5vid[1], $thumbnail_loc ) ) { $vid['thumbnail_loc'] = $thumbnail_loc[2]; } $vid['type'] = 'html5vid'; return $this->get_video_details( $vid ); } } $vid = $this->get_wistia_video_through_old_methods( $content ); if ( isset( $vid['content_loc'] ) || isset( $vid['player_loc'] ) ) { return $vid; } else { // Reset vid. $vid = array(); } $oembed = $this->grab_embeddable_urls_xpath( $content ); if ( is_array( $oembed ) && $oembed !== array() ) { foreach ( $oembed as $url ) { $vid['url'] = $url; $vid = $this->get_video_details( $vid ); if ( isset( $vid['content_loc'] ) || isset( $vid['player_loc'] ) ) { return $vid; } else { // Reset vid. $vid = array(); } } } unset( $oembed ); $oembed = $this->grab_embeddable_urls( $content ); if ( is_array( $oembed ) && $oembed !== array() ) { foreach ( $oembed as $url ) { $vid['url'] = $url; $vid = $this->get_video_details( $vid ); if ( isset( $vid['content_loc'] ) || isset( $vid['player_loc'] ) ) { return $vid; } else { // Reset vid. $vid = array(); } } } unset( $oembed ); return $vid; } /** * Analyse post content for typical Wistia embed codes. * * @link https://wistia.com/doc/embedding * * @since 3.9 * * @param string $content Post content. * * @return array Video info array or empty array if no wistia video was matched. */ protected function get_wistia_video_through_old_methods( $content ) { $vid = array(); if ( preg_match( '`<(?:div|span)(?: [a-z]+=\S+)* class=(?:[\'"])wistia_embed wistia_async_([^\'"\s]+)`', $content, $matches ) ) { $vid['id'] = $matches[1]; $vid['type'] = 'wistia'; $vid = $this->get_video_details( $vid ); } elseif ( preg_match( '`
get_video_details( $vid ); } elseif ( preg_match( '`get_video_details( $vid ); } return $vid; } /** * Checks whether there are oembed URLs in the post that should be included in the video sitemap. * * {@internal Look at WP native function `get_media_embedded_in_content( $content, $types = null )`.} * * @since 0.1 * * @param string $content the content of the post. * * @return array|bool returns array $urls with type of video as array key and video URL as content, or false on negative */ protected function grab_embeddable_urls( $content ) { $evs_location = get_option( 'evs_location' ); // Catch both the single line embeds as well as the embeds using the [embed] shortcode. preg_match_all( '`\[embed(?:[^\]]+)?\](http[s]?://[^\s"]+)\s*\[/embed\]`im', $content, $matches ); preg_match_all( '`^\s*(?:

)?(http[s]?://[^\s"]+)\s*$`im', $content, $matches2 ); $matched_urls = array(); if ( isset( $matches[1] ) && is_array( $matches[1] ) ) { $matched_urls = array_merge( $matched_urls, $matches[1] ); } if ( isset( $matches2[1] ) && is_array( $matches2[1] ) ) { $matched_urls = array_merge( $matched_urls, $matches2[1] ); } if ( preg_match_all( '`()`s', $content, $iframes, PREG_SET_ORDER ) ) { foreach ( $iframes as $iframe ) { if ( preg_match( '`src=([\'"])([^\s\'"]+)\1`', $iframe[1], $iframesrc ) ) { $matched_urls[] = $iframesrc[2]; } } } if ( preg_match_all( '`()`s', $content, $objects, PREG_SET_ORDER ) ) { foreach ( $objects as $object ) { if ( preg_match( '``', $content, $matches ) ) { $matched_urls[] = $matches[3]; } $wistia_info = array( 'domain' => 'wistia.com' ); $wistia_domain = WPSEO_Options::get( 'video_wistia_domain', '' ); if ( $wistia_domain !== '' ) { $wistia_info = $this->parse_url( $wistia_domain ); } $evs_info = $this->parse_url( $evs_location ); if ( ! isset( $evs_info ) || ! isset( $evs_info['domain'] ) ) { $evs_info = array( 'domain' => 'easyvideosuite.com' ); } if ( count( $matched_urls ) > 0 ) { $urls = array(); foreach ( $matched_urls as $match ) { $url_info = $this->parse_url( $match ); if ( ! isset( $url_info['domain'] ) ) { continue; } switch ( $url_info['domain'] ) { case 'brightcove.com': if ( preg_match( '`length > 0 ) { foreach ( $objects as $object ) { $value = $object->getAttribute( 'value' ); $matched_urls[] = $value; } } unset( $objects, $object, $value ); // For iframe embeds (i.e. vidyard.com). $iframes = $xpath->query( '//iframe' ); if ( is_object( $iframes ) && $iframes->length > 0 ) { foreach ( $iframes as $iframe ) { $src = $iframe->getAttribute( 'src' ); $matched_urls[] = $src; } } unset( $iframes, $iframe, $src ); // Specific check for vidyard embed with javascript and lightbox. $script = $xpath->query( '//script[contains(@src,"play.vidyard.com")]' ); if ( is_object( $script ) && $script->length > 0 ) { foreach ( $script as $element ) { $src = $element->getAttribute( 'src' ); $matched_urls[] = $src; } } unset( $script, $element, $src ); // Specific check for cincopa embed via javascript. $script = $xpath->query( '//script/text()[contains(.,"cp_load_widget")]' ); if ( is_object( $script ) && $script->length > 0 ) { foreach ( $script as $element ) { // Remove CDATA. $src = preg_replace( '`//\s*?`', '', $element->wholeText ); $src = 'http://cincopa.com?' . $src; $matched_urls[] = $src; } } unset( $script, $element, $src ); // Specific check for brightcove. $script = $xpath->query( '//object/param[contains(@value,"brightcove.com")]/following-sibling::param[@name="flashVars"]' ); if ( is_object( $script ) && $script->length > 0 ) { foreach ( $script as $element ) { $src = $element->getAttribute( 'value' ); $src = 'http://brightcove.com?' . $src; $matched_urls[] = $src; } } unset( $script, $element, $src ); // Specific check for screenr. $script = $xpath->query( '//object/param[contains(@value,"screenr.com")]/following-sibling::param[@name="flashvars"]' ); if ( is_object( $script ) && $script->length > 0 ) { foreach ( $script as $element ) { $flashvars = $element->getAttribute( 'value' ); if ( preg_match( '`