embed.php (7301B)
1 <?php 2 namespace Elementor; 3 4 if ( ! defined( 'ABSPATH' ) ) { 5 exit; // Exit if accessed directly. 6 } 7 8 /** 9 * Elementor embed. 10 * 11 * Elementor embed handler class is responsible for Elementor embed functionality. 12 * The class holds the supported providers with their embed patters, and handles 13 * their custom properties to create custom HTML with the embeded content. 14 * 15 * @since 1.5.0 16 */ 17 class Embed { 18 19 /** 20 * Provider match masks. 21 * 22 * Holds a list of supported providers with their URL structure in a regex format. 23 * 24 * @since 1.5.0 25 * @access private 26 * @static 27 * 28 * @var array Provider URL structure regex. 29 */ 30 private static $provider_match_masks = [ 31 'youtube' => '/^.*(?:youtu\.be\/|youtube(?:-nocookie)?\.com\/(?:(?:watch)?\?(?:.*&)?vi?=|(?:embed|v|vi|user)\/))([^\?&\"\'>]+)/', 32 'vimeo' => '/^.*vimeo\.com\/(?:[a-z]*\/)*([0-9]{6,11})[?]?.*/', 33 'dailymotion' => '/^.*dailymotion.com\/(?:video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/', 34 ]; 35 36 /** 37 * Embed patterns. 38 * 39 * Holds a list of supported providers with their embed patters. 40 * 41 * @since 1.5.0 42 * @access private 43 * @static 44 * 45 * @var array Embed patters. 46 */ 47 private static $embed_patterns = [ 48 'youtube' => 'https://www.youtube{NO_COOKIE}.com/embed/{VIDEO_ID}?feature=oembed', 49 'vimeo' => 'https://player.vimeo.com/video/{VIDEO_ID}#t={TIME}', 50 'dailymotion' => 'https://dailymotion.com/embed/video/{VIDEO_ID}', 51 ]; 52 53 /** 54 * Get video properties. 55 * 56 * Retrieve the video properties for a given video URL. 57 * 58 * @since 1.5.0 59 * @access public 60 * @static 61 * 62 * @param string $video_url Video URL. 63 * 64 * @return null|array The video properties, or null. 65 */ 66 public static function get_video_properties( $video_url ) { 67 foreach ( self::$provider_match_masks as $provider => $match_mask ) { 68 preg_match( $match_mask, $video_url, $matches ); 69 70 if ( $matches ) { 71 return [ 72 'provider' => $provider, 73 'video_id' => $matches[1], 74 ]; 75 } 76 } 77 78 return null; 79 } 80 81 /** 82 * Get embed URL. 83 * 84 * Retrieve the embed URL for a given video. 85 * 86 * @since 1.5.0 87 * @access public 88 * @static 89 * 90 * @param string $video_url Video URL. 91 * @param array $embed_url_params Optional. Embed parameters. Default is an 92 * empty array. 93 * @param array $options Optional. Embed options. Default is an 94 * empty array. 95 * 96 * @return null|array The video properties, or null. 97 */ 98 public static function get_embed_url( $video_url, array $embed_url_params = [], array $options = [] ) { 99 $video_properties = self::get_video_properties( $video_url ); 100 101 if ( ! $video_properties ) { 102 return null; 103 } 104 105 $embed_pattern = self::$embed_patterns[ $video_properties['provider'] ]; 106 107 $replacements = [ 108 '{VIDEO_ID}' => $video_properties['video_id'], 109 ]; 110 111 if ( 'youtube' === $video_properties['provider'] ) { 112 $replacements['{NO_COOKIE}'] = ! empty( $options['privacy'] ) ? '-nocookie' : ''; 113 } elseif ( 'vimeo' === $video_properties['provider'] ) { 114 $time_text = ''; 115 116 if ( ! empty( $options['start'] ) ) { 117 $time_text = date( 'H\hi\ms\s', $options['start'] ); // PHPCS:Ignore WordPress.DateTime.RestrictedFunctions.date_date 118 } 119 120 $replacements['{TIME}'] = $time_text; 121 } 122 123 $embed_pattern = str_replace( array_keys( $replacements ), $replacements, $embed_pattern ); 124 125 return add_query_arg( $embed_url_params, $embed_pattern ); 126 } 127 128 /** 129 * Get embed HTML. 130 * 131 * Retrieve the final HTML of the embedded URL. 132 * 133 * @since 1.5.0 134 * @access public 135 * @static 136 * 137 * @param string $video_url Video URL. 138 * @param array $embed_url_params Optional. Embed parameters. Default is an 139 * empty array. 140 * @param array $options Optional. Embed options. Default is an 141 * empty array. 142 * @param array $frame_attributes Optional. IFrame attributes. Default is an 143 * empty array. 144 * 145 * @return string The embed HTML. 146 */ 147 public static function get_embed_html( $video_url, array $embed_url_params = [], array $options = [], array $frame_attributes = [] ) { 148 $video_properties = self::get_video_properties( $video_url ); 149 150 $default_frame_attributes = [ 151 'class' => 'elementor-video-iframe', 152 'allowfullscreen', 153 'title' => sprintf( 154 /* translators: %s: Video provider */ 155 __( '%s Video Player', 'elementor' ), 156 $video_properties['provider'] 157 ), 158 ]; 159 160 $video_embed_url = self::get_embed_url( $video_url, $embed_url_params, $options ); 161 if ( ! $video_embed_url ) { 162 return null; 163 } 164 if ( ! $options['lazy_load'] ) { 165 $default_frame_attributes['src'] = $video_embed_url; 166 } else { 167 $default_frame_attributes['data-lazy-load'] = $video_embed_url; 168 } 169 170 $frame_attributes = array_merge( $default_frame_attributes, $frame_attributes ); 171 172 $attributes_for_print = []; 173 174 foreach ( $frame_attributes as $attribute_key => $attribute_value ) { 175 $attribute_value = esc_attr( $attribute_value ); 176 177 if ( is_numeric( $attribute_key ) ) { 178 $attributes_for_print[] = $attribute_value; 179 } else { 180 $attributes_for_print[] = sprintf( '%1$s="%2$s"', $attribute_key, $attribute_value ); 181 } 182 } 183 184 $attributes_for_print = implode( ' ', $attributes_for_print ); 185 186 $iframe_html = "<iframe $attributes_for_print></iframe>"; 187 188 /** This filter is documented in wp-includes/class-oembed.php */ 189 return apply_filters( 'oembed_result', $iframe_html, $video_url, $frame_attributes ); 190 } 191 192 /** 193 * Get oembed data from the cache. 194 * if not exists in the cache it will fetch from provider and then save to the cache. 195 * 196 * @param $oembed_url 197 * @param $cached_post_id 198 * 199 * @return array|null 200 */ 201 public static function get_oembed_data( $oembed_url, $cached_post_id ) { 202 $cached_oembed_data = json_decode( get_post_meta( $cached_post_id, '_elementor_oembed_cache', true ), true ); 203 204 if ( isset( $cached_oembed_data[ $oembed_url ] ) ) { 205 return $cached_oembed_data[ $oembed_url ]; 206 } 207 208 $normalize_oembed_data = self::fetch_oembed_data( $oembed_url ); 209 210 if ( ! $cached_oembed_data ) { 211 $cached_oembed_data = []; 212 } 213 214 update_post_meta( $cached_post_id, '_elementor_oembed_cache', wp_json_encode( array_merge( 215 $cached_oembed_data, 216 [ 217 $oembed_url => $normalize_oembed_data, 218 ] 219 ) ) ); 220 221 return $normalize_oembed_data; 222 } 223 224 /** 225 * Fetch oembed data from oembed provider. 226 * 227 * @param $oembed_url 228 * 229 * @return array|null 230 */ 231 public static function fetch_oembed_data( $oembed_url ) { 232 $oembed_data = _wp_oembed_get_object()->get_data( $oembed_url ); 233 234 if ( ! $oembed_data ) { 235 return null; 236 } 237 238 return [ 239 'thumbnail_url' => $oembed_data->thumbnail_url, 240 'title' => $oembed_data->title, 241 ]; 242 } 243 244 /** 245 * @param $oembed_url 246 * @param null|string|int $cached_post_id 247 * 248 * @return string|null 249 */ 250 public static function get_embed_thumbnail_html( $oembed_url, $cached_post_id = null ) { 251 $oembed_data = self::get_oembed_data( $oembed_url, $cached_post_id ); 252 253 if ( ! $oembed_data ) { 254 return null; 255 } 256 257 return '<div class="elementor-image">' . sprintf( '<img src="%1$s" alt="%2$s" title="%2$s" width="%3$s" />', $oembed_data['thumbnail_url'], esc_attr( $oembed_data['title'] ), '100%' ) . '</div>'; 258 } 259 }