providers = apply_filters( 'video_thumbnail_providers', $this->providers );
// Settings
$this->settings = new Video_Thumbnails_Settings();
// Initialize meta box
add_action( 'admin_init', array( &$this, 'meta_box_init' ) );
// Add actions to save video thumbnails when saving
add_action( 'save_post', array( &$this, 'save_video_thumbnail' ), 100, 1 );
// Add actions to save video thumbnails when posting from XML-RPC (this action passes the post ID as an argument so 'get_video_thumbnail' is used instead)
add_action( 'xmlrpc_publish_post', 'get_video_thumbnail', 10, 1 );
// Add action for Ajax reset script on edit pages
if ( in_array( basename( $_SERVER['PHP_SELF'] ), apply_filters( 'video_thumbnails_editor_pages', array( 'post-new.php', 'page-new.php', 'post.php', 'page.php' ) ) ) ) {
add_action( 'admin_head', array( &$this, 'ajax_reset_script' ) );
}
// Add action for Ajax reset callback
add_action( 'wp_ajax_reset_video_thumbnail', array( &$this, 'ajax_reset_callback' ) );
// Add admin menus
add_action( 'admin_menu', array( &$this, 'admin_menu' ) );
// Add JavaScript and CSS to admin pages
add_action( 'admin_enqueue_scripts', array( &$this, 'admin_scripts' ), 20 );
// Get the posts to be scanned in bulk
add_action('wp_ajax_video_thumbnails_bulk_posts_query', array( &$this, 'bulk_posts_query_callback' ) );
// Get the thumbnail for an individual post
add_action('wp_ajax_video_thumbnails_get_thumbnail_for_post', array( &$this, 'get_thumbnail_for_post_callback' ) );
}
/**
* Load language files
*/
function plugin_textdomain() {
load_plugin_textdomain( 'video-thumbnails', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
}
/**
* Adds the admin menu items
*/
function admin_menu() {
add_management_page( __( 'Bulk Video Thumbnails', 'video-thumbnails' ), __( 'Bulk Video Thumbs', 'video-thumbnails' ), 'manage_options', 'video-thumbnails-bulk', array( &$this, 'bulk_scanning_page' ) );
}
/**
* Enqueues necessary admin scripts
* @param string $hook A hook for the current admin page
*/
function admin_scripts( $hook ) {
// Bulk tool page
if ( 'tools_page_video-thumbnails-bulk' == $hook ) {
wp_enqueue_script( 'video-thumbnails-bulk-js', plugins_url( '/js/bulk.js' , __FILE__ ), array( 'jquery' ), VIDEO_THUMBNAILS_VERSION );
wp_localize_script( 'video-thumbnails-bulk-js', 'video_thumbnails_bulk_language', array(
'working' => __( 'Working...', 'video-thumbnails' ),
'started' => __( 'Started Scanning', 'video-thumbnails' ),
'resumed' => __( 'Resumed Scanning', 'video-thumbnails' ),
'paused' => __( 'Paused Scanning', 'video-thumbnails' ),
'done' => __( 'Done!', 'video-thumbnails' ),
'final_count_singular' => __( 'Scanned 1 post', 'video-thumbnails' ),
'final_count_plural' => __( 'Scanned %d posts', 'video-thumbnails' ),
'queue_singular' => __( '1 post in queue', 'video-thumbnails' ),
'queue_plural' => __( '%d posts in queue', 'video-thumbnails' ),
'scanning_of' => __( 'Scanning %1$s of %2$s', 'video-thumbnails' ),
'no_thumbnail' => __( 'No thumbnail', 'video-thumbnails' ),
'new_thumbnail' => __( 'New thumbnail:', 'video-thumbnails' ),
'existing_thumbnail' => __( 'Existing thumbnail:', 'video-thumbnails' ),
'error' => __( 'Error:', 'video-thumbnails' ),
) );
wp_enqueue_style( 'video-thumbnails-bulk-css', plugins_url('/css/bulk.css', __FILE__), false, VIDEO_THUMBNAILS_VERSION );
}
}
/**
* Initialize meta box on edit page
*/
function meta_box_init() {
if ( is_array( $this->settings->options['post_types'] ) ) {
foreach ( $this->settings->options['post_types'] as $type ) {
add_meta_box( 'video_thumbnail', 'Video Thumbnail', array( &$this, 'meta_box' ), $type, 'side', 'low' );
}
}
}
/**
* Renders the video thumbnail meta box
*/
function meta_box() {
global $post;
// Add hidden troubleshooting info
add_thickbox();
?>
no_video_thumbnail_troubleshooting_instructions(); ?>
ID );
if ( isset( $custom[VIDEO_THUMBNAILS_FIELD][0] ) ) $video_thumbnail = $custom[VIDEO_THUMBNAILS_FIELD][0];
if ( isset( $video_thumbnail ) && $video_thumbnail != '' ) {
echo ''; }
if ( get_post_status() == 'publish' || get_post_status() == 'private' ) {
if ( isset( $video_thumbnail ) && $video_thumbnail != '' ) {
echo '' . __( 'Reset Video Thumbnail', 'video-thumbnails' ) . '
';
} else {
echo '' . __( 'No video thumbnail for this post.', 'video-thumbnails' ) . '
';
echo '' . __( 'Search Again', 'video-thumbnails' ) . ' ' . __( 'Troubleshoot', 'video-thumbnails' ) . '
';
}
} else {
if ( isset( $video_thumbnail ) && $video_thumbnail != '' ) {
echo '' . __( 'Reset Video Thumbnail', 'video-thumbnails' ) . '
';
} else {
echo '' . __( 'A video thumbnail will be found for this post when it is published.', 'video-thumbnails' ) . '
';
}
}
}
/**
* Prints a guide for troubleshooting no video thumbnails
*/
public static function no_video_thumbnail_troubleshooting_instructions() {
?>
- settings page. If you don\'t know the name of the field your video is being saved in, please contact the developer of that theme or plugin.', 'video-thumbnails' ), admin_url( 'options-general.php?page=video_thumbnails' ) ); ?>
- Debugging page. If this doesn\'t find the thumbnail, you\'ll want to be sure to include the embed code you scanned when you request support. If it does find a thumbnail, please double check that you have the Custom Field set correctly in the settings page if you are using a a plugin or theme that stores videos in a special location.', 'video-thumbnails' ), admin_url( 'options-general.php?page=video_thumbnails&tab=debugging' ), admin_url( 'options-general.php?page=video_thumbnails' ) ); ?>
- Debugging page and click "Test Image Downloading" to test your server\'s ability to save an image from a video source.', 'video-thumbnails' ), admin_url( 'options-general.php?page=video_thumbnails&tab=debugging' ) ); ?>
- support threads to see if anyone has had the same issue.', 'video-thumbnails' ); ?>
- start a thread with a good descriptive title ("Error" or "No thumbnails" is a bad title) and be sure to include the results of your testing as well. Also be sure to include the name of your theme, any video plugins you\'re using, and any other details you can think of.', 'video-thumbnails' ); ?>
providers );
foreach ( $providers as $key => $provider ) {
$provider_videos = $provider->scan_for_videos( $markup );
if ( empty( $provider_videos ) ) continue;
foreach ( $provider_videos as $video ) {
$videos[] = array(
'id' => $video[0],
'provider' => $key,
'offset' => $video[1]
);
}
}
usort( $videos, array( &$this, 'compare_by_offset' ) );
return $videos;
}
/**
* Finds the first video in markup and retrieves a thumbnail
* @param string $markup Post markup to scan
* @return mixed Null if no thumbnail or a string with a remote URL
*/
function get_first_thumbnail_url( $markup ) {
$thumbnail = null;
$videos = $this->find_videos( $markup );
foreach ( $videos as $video ) {
$thumbnail = $this->providers[$video['provider']]->get_thumbnail_url( $video['id'] );
if ( $thumbnail != null ) break;
}
return $thumbnail;
}
/**
* Finds the video thumbnail for a post, saves/sets as featured image if enabled, saves image URL to custom field and then returns the URL
* @param int $post_id An optional post ID (can be left blank in a loop)
* @return mixed A string with an image URL if successful or null if there is no video thumbnail
*/
function get_video_thumbnail( $post_id = null ) {
// Get the post ID if none is provided
if ( $post_id == null OR $post_id == '' ) $post_id = get_the_ID();
// Check to see if thumbnail has already been found
if( ( $thumbnail_meta = get_post_meta( $post_id, VIDEO_THUMBNAILS_FIELD, true ) ) != '' ) {
return $thumbnail_meta;
}
// If the thumbnail isn't stored in custom meta, fetch a thumbnail
else {
$new_thumbnail = null;
// Filter for extensions to set thumbnail
$new_thumbnail = apply_filters( 'new_video_thumbnail_url', $new_thumbnail, $post_id );
if ( $new_thumbnail == null ) {
// Get the post or custom field to search
if ( $this->settings->options['custom_field'] ) {
$markup = get_post_meta( $post_id, $this->settings->options['custom_field'], true );
} else {
$post_array = get_post( $post_id );
$markup = $post_array->post_content;
$markup = apply_filters( 'the_content', $markup );
}
// Filter for extensions to modify what markup is scanned
$markup = apply_filters( 'video_thumbnail_markup', $markup, $post_id );
$new_thumbnail = $this->get_first_thumbnail_url( $markup );
}
// Return the new thumbnail variable and update meta if one is found
if ( $new_thumbnail != null && !is_wp_error( $new_thumbnail ) ) {
// Save as Attachment if enabled
if ( $this->settings->options['save_media'] == 1 ) {
$attachment_id = $this->save_to_media_library( $new_thumbnail, $post_id );
if ( is_wp_error( $attachment_id ) ) {
return $attachment_id;
}
$new_thumbnail = wp_get_attachment_image_src( $attachment_id, 'full' );
$new_thumbnail = $new_thumbnail[0];
}
// Add hidden custom field with thumbnail URL
if ( !update_post_meta( $post_id, VIDEO_THUMBNAILS_FIELD, $new_thumbnail ) ) add_post_meta( $post_id, VIDEO_THUMBNAILS_FIELD, $new_thumbnail, true );
// Set attachment as featured image if enabled
if ( $this->settings->options['set_featured'] == 1 && $this->settings->options['save_media'] == 1 ) {
// Make sure there isn't already a post thumbnail
if ( !ctype_digit( get_post_thumbnail_id( $post_id ) ) ) {
set_post_thumbnail( $post_id, $attachment_id );
}
}
}
return $new_thumbnail;
}
}
/**
* Gets a video thumbnail when a published post is saved
* @param int $post_id The post ID
*/
function save_video_thumbnail( $post_id ) {
// Don't save video thumbnails during autosave or for unpublished posts
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) return null;
if ( get_post_status( $post_id ) != 'publish' ) return null;
// Check that Video Thumbnails are enabled for current post type
$post_type = get_post_type( $post_id );
if ( in_array( $post_type, (array) $this->settings->options['post_types'] ) || $post_type == $this->settings->options['post_types'] ) {
$this->get_video_thumbnail( $post_id );
} else {
return null;
}
}
/**
* Creates a file name for use when saving an image to the media library.
* It will either use a sanitized version of the title or the post ID.
* @param int $post_id The ID of the post to create the filename for
* @return string A filename (without the extension)
*/
static function construct_filename( $post_id ) {
$filename = get_the_title( $post_id );
$filename = sanitize_title( $filename, $post_id );
$filename = urldecode( $filename );
$filename = preg_replace( '/[^a-zA-Z0-9\-]/', '', $filename );
$filename = substr( $filename, 0, 32 );
$filename = trim( $filename, '-' );
if ( $filename == '' ) $filename = (string) $post_id;
return $filename;
}
/**
* Saves a remote image to the media library
* @param string $image_url URL of the image to save
* @param int $post_id ID of the post to attach image to
* @return int ID of the attachment
*/
public static function save_to_media_library( $image_url, $post_id ) {
$error = '';
$response = wp_remote_get( $image_url );
if( is_wp_error( $response ) ) {
$error = new WP_Error( 'thumbnail_retrieval', sprintf( __( 'Error retrieving a thumbnail from the URL %1$s using wp_remote_get()
If opening that URL in your web browser returns anything else than an error page, the problem may be related to your web server and might be something your host administrator can solve.', 'video-thumbnails' ), $image_url ) . '
' . __( 'Error Details:', 'video-thumbnails' ) . ' ' . $response->get_error_message() );
} else {
$image_contents = $response['body'];
$image_type = wp_remote_retrieve_header( $response, 'content-type' );
}
if ( $error != '' ) {
return $error;
} else {
// Translate MIME type into an extension
if ( $image_type == 'image/jpeg' ) {
$image_extension = '.jpg';
} elseif ( $image_type == 'image/png' ) {
$image_extension = '.png';
} elseif ( $image_type == 'image/gif' ) {
$image_extension = '.gif';
} else {
return new WP_Error( 'thumbnail_upload', __( 'Unsupported MIME type:', 'video-thumbnails' ) . ' ' . $image_type );
}
// Construct a file name with extension
$new_filename = self::construct_filename( $post_id ) . $image_extension;
// Save the image bits using the new filename
do_action( 'video_thumbnails/pre_upload_bits', $image_contents );
$upload = wp_upload_bits( $new_filename, null, $image_contents );
do_action( 'video_thumbnails/after_upload_bits', $upload );
// Stop for any errors while saving the data or else continue adding the image to the media library
if ( $upload['error'] ) {
$error = new WP_Error( 'thumbnail_upload', __( 'Error uploading image data:', 'video-thumbnails' ) . ' ' . $upload['error'] );
return $error;
} else {
do_action( 'video_thumbnails/image_downloaded', $upload['file'] );
$wp_filetype = wp_check_filetype( basename( $upload['file'] ), null );
$upload = apply_filters( 'wp_handle_upload', array(
'file' => $upload['file'],
'url' => $upload['url'],
'type' => $wp_filetype['type']
), 'sideload' );
// Contstruct the attachment array
$attachment = array(
'post_mime_type' => $upload['type'],
'post_title' => get_the_title( $post_id ),
'post_content' => '',
'post_status' => 'inherit'
);
// Insert the attachment
$attach_id = wp_insert_attachment( $attachment, $upload['file'], $post_id );
// you must first include the image.php file
// for the function wp_generate_attachment_metadata() to work
require_once( ABSPATH . 'wp-admin/includes/image.php' );
do_action( 'video_thumbnails/pre_generate_attachment_metadata', $attach_id, $upload['file'] );
$attach_data = wp_generate_attachment_metadata( $attach_id, $upload['file'] );
do_action( 'video_thumbnails/after_generate_attachment_metadata', $attach_id, $upload['file'] );
wp_update_attachment_metadata( $attach_id, $attach_data );
// Add field to mark image as a video thumbnail
update_post_meta( $attach_id, 'video_thumbnail', '1' );
}
}
return $attach_id;
}
/**
* Ajax reset script for post editor
*/
function ajax_reset_script() {
echo '' . PHP_EOL;
echo '' . PHP_EOL;
}
/**
* Ajax callback for resetting a video thumbnail in the post editor
*/
function ajax_reset_callback() {
global $wpdb; // this is how you get access to the database
$post_id = $_POST['post_id'];
delete_post_meta( $post_id, VIDEO_THUMBNAILS_FIELD );
$video_thumbnail = get_video_thumbnail( $post_id );
if ( is_wp_error( $video_thumbnail ) ) {
echo $video_thumbnail->get_error_message();
} else if ( $video_thumbnail != null ) {
echo '';
} else {
echo __( 'No video thumbnail for this post.', 'video-thumbnails' );
}
die();
}
/**
* Ajax callback used to get all the post IDs to be scanned in bulk
*/
function bulk_posts_query_callback() {
// Some default args
$args = array(
'posts_per_page' => -1,
'post_type' => $this->settings->options['post_types'],
'fields' => 'ids'
);
// Setup an array for any form data and parse the jQuery serialized data
$form_data = array();
parse_str( $_POST['params'], $form_data );
$args = apply_filters( 'video_thumbnails/bulk_posts_query', $args, $form_data );
$query = new WP_Query( $args );
echo json_encode( $query->posts );
die();
}
/**
* Ajax callback used to get the video thumbnail for an individual post in the process of running the bulk tool
*/
function get_thumbnail_for_post_callback() {
$post_id = $_POST['post_id'];
$thumb = get_post_meta( $post_id, VIDEO_THUMBNAILS_FIELD, true );
if ( $thumb == '' ) {
global $video_thumbnails;
$thumb = $video_thumbnails->get_video_thumbnail( $post_id );
if ( $thumb ) {
$type = 'new';
}
} else {
$type = 'existing';
}
if ( $thumb != '' ) {
$result = array(
'type' => $type,
'url' => $thumb
);
} else {
$result = array();
}
echo json_encode( $result );
die();
}
/**
* A function that renders the bulk scanning page
*/
function bulk_scanning_page() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die( __( 'You do not have sufficient permissions to access this page.', 'video-thumbnails' ) );
}
?>
get_video_thumbnail( $post_id );
}
// Echo thumbnail
function video_thumbnail( $post_id = null ) {
if ( ( $video_thumbnail = get_video_thumbnail( $post_id ) ) == null ) { echo plugins_url() . '/video-thumbnails/default.jpg'; }
else { echo $video_thumbnail; }
}
?>