1

I am trying to enable video thumbnails for posts in my theme. I created a custom post thumbnail media uploader in an editor plugin as follows (This is necessary, because the default uploader can't display videos):

Enqueuing the script in PHP:

function ernst_enqueue_custom_post_meta_plugin() {
    wp_enqueue_script(
        'ernst_custom-post-meta-plugin',
        get_stylesheet_directory_uri() . '/assets/js/editor/custom-post-meta-plugin.js',
        array( 'wp-plugins', 'wp-element', 'wp-edit-post', 'wp-components', 'wp-block-editor', 'wp-data', 'wp-core-data', 'wp-i18n' ),
        time(),
        false
    );
}
add_action( 'enqueue_block_editor_assets', 'ernst_enqueue_custom_post_meta_plugin' );

Adding plugin and media uploader in JS:

( function( plugins, element, editPost, components, blockEditor, data, coreData, i18n ) {
    // Get required dependencies
    const { registerPlugin } = plugins;
    const { PluginDocumentSettingPanel } = editPost;
    const { Fragment } = element;
    const { Button, DropZone, ResponsiveWrapper } = components;
    const { MediaUploadCheck, MediaUpload } = blockEditor;
    const { useSelect } = data;
    const { useEntityProp } = coreData;
    const el = element.createElement;
    const { __ } = i18n;

    // Register custom post meta plugin
    registerPlugin( 'ernst-custom-post-meta-plugin', {
        render: () => {
            // Get current post type
            const postType = useSelect( ( select ) => {
                return( select( 'core/editor' ).getCurrentPostType() );
            }, [] );

            // Get Featured media
            const [ featuredMedia, setFeaturedMedia ] = useEntityProp( 'postType', postType, 'featured_media' );

            // Get meta information for featured media
            const featuredMediaMeta = useSelect( ( select ) => {
                return( featuredMedia ? select( 'core' ).getMedia( featuredMedia ) : undefined );
            } );

            // Prevent component render if featured media meta is not resolved yet:
            if( featuredMedia && typeof( featuredMediaMeta ) === 'undefined' ) {
                return;
            }

            // Check if featured media is video file
            const featuredMediaIsVideo = featuredMedia && featuredMediaMeta.mime_type.includes( 'video' );

            // Check for specific size in featured media meta
            const featuredMediaHasSize = ( size ) => ( featuredMedia && !featuredMediaIsVideo && 'sizes' in featuredMediaMeta.media_details && size in featuredMediaMeta.media_details.sizes );

            console.log( featuredMediaMeta );

            // Render components
            return(
                el( PluginDocumentSettingPanel, {
                    title: __( 'Featured media', 'ernst' ),
                    initialOpen: false
                }, el( 'div', {
                    className: 'editor-post-featured-image'
                }, el( Fragment, {}, featuredMedia != 0 && el( 'div', {
                    id: 'editor-post-featured-image-' + featuredMediaMeta.id + '-describedby',
                    className: 'hidden'
                }, featuredMediaMeta.alt_text === '' ? __( 'The current media has no alternative text. The file name is:', 'ernst' ) + ' ' + featuredMediaMeta.media_details.file.split( '/' ).reverse()[0] : __( 'Current media:', 'ernst' ) + ' ' + featuredMediaMeta.alt_text ), el( 'div', {
                    className: 'editor-post-featured-image__container'
                }, el( Fragment, {}, el( MediaUploadCheck, {}, el( MediaUpload, {
                    title: __( 'Featured media', 'ernst' ),
                    allowedTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'video/mp4'],
                    render: ( { open } ) => el( Button, {
                        className: 'editor-post-featured-image__' + ( featuredMedia ? 'preview' : 'toggle' ),
                        label: featuredMedia ? 'Edit or update featured media' : null,
                        'aria-describedby': featuredMedia ? 'editor-post-featured-image-' + featuredMediaMeta.id + '-describedby' : null,
                        onClick: open
                    }, featuredMedia ? el( ResponsiveWrapper, {
                        isInline: true,
                        naturalWidth: featuredMediaMeta.media_details.width,
                        naturalHeight: featuredMediaMeta.media_details.height
                    }, featuredMediaIsVideo ? el( 'video', {}, el( 'source', {
                        src: featuredMediaMeta.source_url
                    } ) ) : el( 'img', {
                        src: featuredMediaHasSize( 'large' ) ? featuredMediaMeta.media_details.sizes.large.source_url : featuredMediaMeta.source_url
                    } ) ) : __( 'Set featured media', 'ernst' ) ),
                    onSelect: ( newFeaturedMedia ) => setFeaturedMedia( newFeaturedMedia.id )
                } ) ), el( DropZone, {} ) ) ), featuredMedia != 0 && el( MediaUploadCheck, {}, el( MediaUpload, {
                    title: __( 'Featured media', 'ernst' ),
                    allowedTypes: ['image/jpeg', 'image/png', 'image/gif', 'image/svg+xml', 'video/mp4'],
                    render: ( { open } ) => el( Button, {
                        variant: 'secondary',
                        onClick: open
                    }, __( 'Replace Media', 'ernst' ) ),
                    onSelect: ( newFeaturedMedia ) => setFeaturedMedia( newFeaturedMedia.id )
                } ) ), el( Button, {
                    variant: 'link',
                    isDestructive: true,
                    onClick: () => setFeaturedMedia( 0 )
                }, __( 'Remove featured media', 'ernst' ) ) ) ) )
            );
        }
    } );
} )(
    window.wp.plugins,
    window.wp.element,
    window.wp.editPost,
    window.wp.components,
    window.wp.blockEditor,
    window.wp.data,
    window.wp.coreData,
    window.wp.i18n
);

This works great so far, but every time i save the post, the thumbnail gets deleted (if it's a video). Is it possible to change that sanitization behavior? I'd like to hook into post_thumbnail_html and adjust the returned html if a post thumbnail is a video. This way I'd be able to keep all the functionality of the_post_thumbnail and could just continue working on my theme.

The current workaround is to register a new post meta for my featured media and display this instead of the default thumbnail which isn't that elegant in my opinion, especially, because it creates a whole lot of additional metadata entries in the database.

Thanks for your help!

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.