HEX
Server: Apache/2.4.65 (Debian)
System: Linux 88f31f35b0b8 6.1.0-38-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.147-1 (2025-08-02) x86_64
User: www-data (33)
PHP: 8.2.29
Disabled: NONE
Upload Files
File: /var/www/html/wp-content/plugins/wpseo-video/classes/class-wpseo-video-embed.php
<?php
/**
 * All functionality for speeding up YouTube embeds by not loading them immediately.
 *
 * @package    WordPress SEO
 * @subpackage WordPress SEO Video
 */

/**
 * WPSEO_Video_Embed class.
 *
 * @package WordPress SEO Video
 */
class WPSEO_Video_Embed {

	/**
	 * Constructor for the WPSEO_Video_Embed class.
	 */
	public function __construct() {
		add_filter( 'render_block', [ $this, 'replace_youtube_block_html' ], 10, 2 );
		add_action( 'wp_head', [ $this, 'set_high_res_default_image' ] );
	}

	/**
	 * Replaces the YouTube embed HTML with our custom HTML.
	 *
	 * @return void
	 */
	public function set_high_res_default_image() {
		/*
		 * Light YouTube Embeds by @labnol.
		 * Web: https://www.labnol.org/internet/light-youtube-embeds/27941/
		 * Adapted by Yoast to use the max res default image when available,
		 * load the play image locally, and make it keyboard-accessible.
		 */
		echo '<script>
			document.addEventListener( "DOMContentLoaded", function() {
				var div, i,
					youtubePlayers = document.getElementsByClassName( "video-seo-youtube-player" );
				for ( i = 0; i < youtubePlayers.length; i++ ) {
					div = document.createElement( "div" );
					div.className = "video-seo-youtube-embed-loader";
					div.setAttribute( "data-id", youtubePlayers[ i ].dataset.id );
					div.setAttribute( "tabindex", "0" );
					div.setAttribute( "role", "button" );
					div.setAttribute(
						"aria-label", "'
						/* translators: Hidden accessibility text. */
						. esc_attr__( 'Load YouTube video', 'yoast-video-seo' )
						. '"
					);
					div.innerHTML = videoSEOGenerateYouTubeThumbnail( youtubePlayers[ i ].dataset.id );
					div.addEventListener( "click", videoSEOGenerateYouTubeIframe );
					div.addEventListener( "keydown", videoSEOYouTubeThumbnailHandleKeydown );
					div.addEventListener( "keyup", videoSEOYouTubeThumbnailHandleKeyup );
					youtubePlayers[ i ].appendChild( div );
				}
			} );

			function videoSEOGenerateYouTubeThumbnail( id ) {
				var thumbnail = \'<picture class="video-seo-youtube-picture">\n\' +
					\'<source class="video-seo-source-to-maybe-replace" media="(min-width: 801px)" srcset="https://i.ytimg.com/vi/\' + id + \'/maxresdefault.jpg" >\n\' +
					\'<source class="video-seo-source-hq" media="(max-width: 800px)" srcset="https://i.ytimg.com/vi/\' + id + \'/hqdefault.jpg">\n\' +
					\'<img onload="videoSEOMaybeReplaceMaxResSourceWithHqSource( event );" src="https://i.ytimg.com/vi/\' + id + \'/hqdefault.jpg" width="480" height="360" loading="eager" alt="">\n\' +
					\'</picture>\n\',
					play = \'<div class="video-seo-youtube-player-play"></div>\';
				return thumbnail.replace( "ID", id ) + play;
			}

			function videoSEOMaybeReplaceMaxResSourceWithHqSource( event ) {
				var sourceMaxRes,
					sourceHighQuality,
					loadedThumbnail = event.target,
					parent = loadedThumbnail.parentNode;

				if ( loadedThumbnail.naturalWidth < 150 ) {
					sourceMaxRes = parent.querySelector(".video-seo-source-to-maybe-replace");
					sourceHighQuality = parent.querySelector(".video-seo-source-hq");
					sourceMaxRes.srcset = sourceHighQuality.srcset;
					parent.className = "video-seo-youtube-picture video-seo-youtube-picture-replaced-srcset";
				}
			}

			function videoSEOYouTubeThumbnailHandleKeydown( event ) {
				if ( event.keyCode !== 13 && event.keyCode !== 32 ) {
					return;
				}

				if ( event.keyCode === 13 ) {
					videoSEOGenerateYouTubeIframe( event );
				}

				if ( event.keyCode === 32 ) {
					event.preventDefault();
				}
			}

			function videoSEOYouTubeThumbnailHandleKeyup( event ) {
				if ( event.keyCode !== 32 ) {
					return;
				}

				videoSEOGenerateYouTubeIframe( event );
			}

			function videoSEOGenerateYouTubeIframe( event ) {
				var el = ( event.type === "click" ) ? this : event.target,
					iframe = document.createElement( "iframe" );

				iframe.setAttribute( "src", "https://www.youtube.com/embed/" + el.dataset.id + "?autoplay=1&enablejsapi=1&origin=' . rawurlencode( home_url() ) . '" );
				iframe.setAttribute( "frameborder", "0" );
				iframe.setAttribute( "allowfullscreen", "1" );
				iframe.setAttribute( "allow", "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" );
				el.parentNode.replaceChild( iframe, el );
			}
		</script>';
	}

	/**
	 * Replaces the YouTube block HTML with our custom HTML.
	 *
	 * @param string $block_content The block content.
	 * @param array  $block         The full block, including name and attributes.
	 *
	 * @return string The filtered block content.
	 */
	public function replace_youtube_block_html( $block_content, $block ) {
		/*
		 * In WordPress 5.6 the YouTube block name changed from `core-embed/youtube`
		 * to `core/embed` as the embed block was refactored to use only one block
		 * type with variations. The old name `core-embed/youtube` is used here
		 * for backwards compatibility.
		 */
		if (
			( $block['blockName'] === 'core/embed' || $block['blockName'] === 'core-embed/youtube' )
			&& $block['attrs']['providerNameSlug'] === 'youtube'
		) {
			wp_enqueue_style(
				'videoseo-youtube-embed-css',
				plugins_url( 'css/dist/videoseo-youtube-embed.css', WPSEO_VIDEO_FILE ),
				[],
				WPSEO_VIDEO_VERSION
			);

			if ( strpos( $block['attrs']['url'], 'youtu.be' ) ) {
				$data_id = str_replace( 'https://youtu.be/', '', $block['attrs']['url'] );
			}
			else {
				$data_id = str_replace( 'https://www.youtube.com/watch?v=', '', $block['attrs']['url'] );
			}

			$class = '';
			if ( isset( $block['attrs']['align'] ) ) {
				$class = 'align' . $block['attrs']['align'] . ' ';
			}

			if ( isset( $block['attrs']['className'] ) ) {
				$class .= $block['attrs']['className'] . ' ';
			}

			$block_content  = '<figure class="wp-block-embed ' . $class . ' is-type-video is-provider-youtube wp-block-embed-youtube">';
			$block_content .= '<div class="wp-block-embed__wrapper video-seo-youtube-embed-wrapper">';
			$block_content .= '<div class="video-seo-youtube-player" data-id="' . $data_id . '"></div>';
			$block_content .= '</div></figure>';

			return $block_content;
		}

		return $block_content;
	}
}