Skip to content

Instantly share code, notes, and snippets.

@ippeiukai
Forked from tilap/functions.php
Last active July 23, 2023 09:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ippeiukai/ee718addb65e9360b9cedac13fc224ea to your computer and use it in GitHub Desktop.
Save ippeiukai/ee718addb65e9360b9cedac13fc224ea to your computer and use it in GitHub Desktop.
Wordpress: How to automatically attache youtube/vimeo thumbnail as a post feature image from a post meta key
<?php
// https://github.com/WebDevStudios/Automatic-Featured-Images-from-Videos/blob/1.2.0/automatic-featured-images-from-videos.php
/**
* If a YouTube or Vimeo video is added in the post content, grab its thumbnail and set it as the featured image.
*
* @since 1.0.0
*
* @param int $post_id ID of the post being saved.
* @param string $video_thumbnail_url URL of the image thumbnail.
* @param string $video_id Video ID from embed.
*/
function wds_set_video_thumbnail_as_featured_image( $post_id, $video_thumbnail_url, $video_id = '' ) {
// Bail if no valid video thumbnail URL.
if ( ! $video_thumbnail_url || is_wp_error( $video_thumbnail_url ) ) {
return;
}
$post_title = sanitize_title( preg_replace( '/[^a-zA-Z0-9\s]/', '-', get_the_title() ) ) . '-' . $video_id;
global $wpdb;
$stmt = "SELECT ID FROM {$wpdb->posts}";
$stmt .= $wpdb->prepare(
' WHERE post_type = %s AND guid LIKE %s',
'attachment',
'%' . $wpdb->esc_like( $video_id ) . '%'
);
$attachment = $wpdb->get_col( $stmt );
if ( !empty( $attachment[0] ) ) {
$attachment_id = $attachment[0];
} else {
// Try to sideload the image.
$attachment_id = wds_ms_media_sideload_image_with_new_filename( $video_thumbnail_url, $post_id, $post_title, $video_id );
}
// Bail if unable to sideload (happens if the URL or post ID is invalid, or if the URL 404s).
if ( is_wp_error( $attachment_id ) ) {
return;
}
// Woot! We got an image, so set it as the post thumbnail.
set_post_thumbnail( $post_id, $attachment_id );
}
// https://github.com/WebDevStudios/Automatic-Featured-Images-from-Videos/blob/1.2.0/automatic-featured-images-from-videos.php
/**
* Handle the upload of a new image.
*
* @since 1.0.0
*
* @param string $url URL to sideload.
* @param int $post_id Post ID to attach to.
* @param string|null $filename Filename to use.
* @param string $video_id Video ID.
*
* @return mixed
*/
function wds_ms_media_sideload_image_with_new_filename( $url, $post_id, $filename = null, $video_id = null ) {
if ( ! $url || ! $post_id ) {
return new WP_Error( 'missing', esc_html__( 'Need a valid URL and post ID...', 'automatic-featured-images-from-videos' ) );
}
require_once( ABSPATH . 'wp-admin/includes/file.php' );
// Download file to temp location, returns full server path to temp file, ex; /home/user/public_html/mysite/wp-content/26192277_640.tmp.
$tmp = download_url( $url );
// If error storing temporarily, unlink.
if ( is_wp_error( $tmp ) ) {
// And output wp_error.
return $tmp;
}
// Fix file filename for query strings.
preg_match( '/[^\?]+\.(jpg|JPG|jpe|JPE|jpeg|JPEG|gif|GIF|png|PNG)/', $url, $matches );
// Extract filename from url for title.
$url_filename = basename( $matches[0] );
// Determine file type (ext and mime/type).
$url_type = wp_check_filetype( $url_filename );
// Override filename if given, reconstruct server path.
if ( ! empty( $filename ) ) {
$filename = sanitize_file_name( $filename );
// Extract path parts.
$tmppath = pathinfo( $tmp );
// Build new path.
$new = $tmppath['dirname'] . '/' . $filename . '.' . $tmppath['extension'];
// Renames temp file on server.
rename( $tmp, $new );
// Push new filename (in path) to be used in file array later.
$tmp = $new;
}
/* Assemble file data (should be built like $_FILES since wp_handle_sideload() will be using). */
// Full server path to temp file.
$file_array['tmp_name'] = $tmp;
if ( ! empty( $filename ) ) {
// User given filename for title, add original URL extension.
$file_array['name'] = $filename . '.' . $url_type['ext'];
} else {
// Just use original URL filename.
$file_array['name'] = $url_filename;
}
$post_data = [
// Just use the original filename (no extension).
'post_title' => get_the_title( $post_id ),
// Make sure gets tied to parent.
'post_parent' => $post_id,
];
// Required libraries for media_handle_sideload.
require_once( ABSPATH . 'wp-admin/includes/file.php' );
require_once( ABSPATH . 'wp-admin/includes/media.php' );
require_once( ABSPATH . 'wp-admin/includes/image.php' );
// Do the validation and storage stuff.
// $post_data can override the items saved to wp_posts table, like post_mime_type, guid, post_parent, post_title, post_content, post_status.
$att_id = media_handle_sideload( $file_array, $post_id, null, $post_data );
// If error storing permanently, unlink.
if ( is_wp_error( $att_id ) ) {
// Clean up.
@unlink( $file_array['tmp_name'] );
// And output wp_error.
return $att_id;
}
return $att_id;
}
// https://github.com/WebDevStudios/Automatic-Featured-Images-from-Videos/blob/1.2.0/automatic-featured-images-from-videos.php
/**
* Check if the content contains a vimeo url.
*
* Props to @rzen for lending his massive brain smarts to help with the regex.
*
* @author Gary Kovar
*
* @param $content
*
* @return string The value of the vimeo id.
*
*/
function wds_check_for_vimeo( $content ) {
if ( preg_match( '#\/\/(.+\.)?(vimeo\.com)\/(\d*)#', $content, $vimeo_matches ) ) {
return $vimeo_matches[3];
}
return false;
}
// https://github.com/WebDevStudios/Automatic-Featured-Images-from-Videos/blob/1.2.0/automatic-featured-images-from-videos.php
/**
* Get the image thumbnail and the video url from a vimeo id.
*
* @author Gary Kovar
*
* @since 1.0.5
*
* @param string $vimeo_id Vimeo video ID.
* @return array Video information.
*/
function wds_get_vimeo_details( $vimeo_id ) {
$video = [];
// @todo Get remote checking matching with wds_get_youtube_details.
$vimeo_data = wp_remote_get( 'https://www.vimeo.com/api/v2/video/' . intval( $vimeo_id ) . '.json' );
if ( 200 === wp_remote_retrieve_response_code( $vimeo_data ) ) {
$response = json_decode( $vimeo_data['body'] );
$large = isset( $response[0]->thumbnail_large ) ? $response[0]->thumbnail_large : '';
if ( $large ) {
$larger_test = explode( '_', $large );
$test_result = wp_remote_head(
$larger_test[0]
);
if ( 200 === wp_remote_retrieve_response_code( $test_result ) ) {
$large = $larger_test[0];
}
}
// For the moment, we will force jpg since WebP is still iffy.
$video['video_thumbnail_url'] = isset( $large ) ? $large . '.jpg' : false;
$video['video_url'] = $response[0]->url;
$video['video_embed_url'] = 'https://player.vimeo.com/video/' . $vimeo_id;
}
return $video;
}
function set_featured_image_from_post_meta($post_id, $post, $update) {
$post_type = 'lecture'; // the custom post type
$meta_key = 'preview_vimeo_oembed'; // the custom meta key
if ($post_type !== get_post_type($post_id) || has_post_thumbnail($post_id)) {
return;
}
$video_url = get_post_meta($post_id, $meta_key, true);
if(!$video_url) {
return;
}
$vimeo_id = wds_check_for_vimeo($video_url);
if (!$vimeo_id) {
return;
}
$vimeo_details = wds_get_vimeo_details($vimeo_id);
if (empty($vimeo_details)) {
return;
}
$video_thumbnail_url = $vimeo_details['video_thumbnail_url'];
wds_set_video_thumbnail_as_featured_image($post_id, $video_thumbnail_url, $vimeo_id);
}
add_action('wp_after_insert_post', 'set_featured_image_from_post_meta', 10, 4);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment