Contenu principal
Médiaception

Mediaception

L’image à la une pour un média ? C’est possible.

12345
add_action( 'init', 'sf_post_type_supports' );

function sf_post_type_supports() {
	add_post_type_support( 'attachment', 'thumbnail' );
}

Oui, tout simplement.
Utilité ? C'est vrai que c'est pas flagrant. On pourrait s'en servir comme jaquette pour un fichier audio, ou comme preview pour un fichier vidéo.
Du coup, on pourrait limiter le support de l'image à la une aux fichiers audio et vidéo.

123456
add_action( 'init', 'sf_post_type_supports' );

function sf_post_type_supports() {
	add_post_type_support( 'attachment:audio', 'thumbnail' );
	add_post_type_support( 'attachment:video', 'thumbnail' );
}

Et… c'est presque ça. En théorie ça marche (la Théorie est un beau pays, j'aimerais y vivre un jour, car en Théorie tout se passe bien).
Le support est bien activé et la metabox dans la page d'édition d'un média audio ou vidéo (et pas les autres) est bien disponible. Seulement voilà, tout ne marche pas comme prévu, la fenêtre pour choisir son image ne s'affiche pas en « modale », on est redirigé vers la page d'upload.
Le problème est lié aux fonctions post_type_supports() et current_theme_supports() qui, dans le core de WordPress sont utilisées seulement avec 'attachment' et non avec 'attachment:audio' et 'attachment:video'.
Il faut donc ajouter quelques petites choses. D'abord je vais définir deux fonctions « outil » qui me seront utiles. La première est un raccourcis qui indiquera si le média est un fichier audio ou vidéo. La seconde est une sorte de post_type_supports() qui tient compte du mime en gros.

01020304050607080910111213141516
if ( !function_exists('post_mime_type_is_audio_or_video') ):
function post_mime_type_is_audio_or_video( $post ) {
	return $post->post_type == 'attachment' && !empty($post->post_mime_type) && ( 0 === strpos( $post->post_mime_type, 'audio/' ) || 0 === strpos( $post->post_mime_type, 'video/' ) );
}
endif;


if ( !function_exists('post_mime_type_supports_thumbnail') ):
function post_mime_type_supports_thumbnail( $post ) {
	if ( 'attachment' !== $post->post_type || empty( $post->post_mime_type ) )
		return false;

	$mime = reset((explode('/', $post->post_mime_type)));
	return (current_theme_supports( 'post-thumbnails', 'attachment' ) || current_theme_supports( 'post-thumbnails', 'attachment:'.$mime )) && post_type_supports( 'attachment:'.$mime, 'thumbnail' ) && !post_type_supports( 'attachment', 'thumbnail' );
}
endif;

Et maintenant il nous faut ajouter les scripts javascripts nécessaires pour la fenêtre modale.

12345678
add_action( 'admin_enqueue_scripts', 'sf_attachment_add_media_editor_js' );
function sf_attachment_add_media_editor_js( $hook_suffix ) {
	global $typenow, $post;
	if ( $hook_suffix == 'post.php' && $typenow == 'attachment' && post_mime_type_is_audio_or_video( $post ) && post_mime_type_supports_thumbnail( $post ) ) {
		add_thickbox();
		wp_enqueue_media( array( 'post' => $post ) );
	}
}

Attention, wp_enqueue_media() est disponible dans WordPress depuis la version 3.5 seulement.

Fini ? Non, pas tout à fait, il y a encore un bug.
À ce stade on arrive bien à ouvrir la fenêtre modale pour sélectionner l'image, mais au début de la liste il y a une image « vide », et si auparavant on a déjà choisi une image à la une, elle ne sera pas sélectionnée (c'était sensée être l'image vide justement).
Pour comprendre ce qui se passe il faut comprendre un peu le fonctionnement de la fenêtre, comment elle se rempli.
Lorsque l'on ouvre cette fenêtre modale pour la première fois, ce n'est pas un appel ajax qui est fait pour la remplir d'images, mais plusieurs.
Le premier appel va aller chercher l'image actuellement à la une. Les suivants iront chercher toutes les autres images par paquets de 50. Notre problème actuel est le premier appel qui ne se fait pas, car une variable javascript n'est pas imprimée dans la page.
La solution est donc toute simple (car il y a bien sûr le filtre kivabien) : ajouter un filtre depuis ma précédente fonction sf_attachment_add_media_editor_js() et ajouter cette variable dans la page.

010203040506070809101112131415161718
add_action( 'admin_enqueue_scripts', 'sf_attachment_add_media_editor_js' );
function sf_attachment_add_media_editor_js( $hook_suffix ) {
	global $typenow, $post;
	if ( $hook_suffix == 'post.php' && $typenow == 'attachment' && post_mime_type_is_audio_or_video( $post ) && post_mime_type_supports_thumbnail( $post ) ) {
		add_filter( 'media_view_settings', 'sf_attachment_view_settings', 10, 2 );
		add_thickbox();
		wp_enqueue_media( array( 'post' => $post ) );
	}
}


function sf_attachment_view_settings( $settings, $post ) {
	if ( post_mime_type_is_audio_or_video( $post ) && post_mime_type_supports_thumbnail( $post ) ) {
		$featured_image_id = get_post_meta( $post->ID, '_thumbnail_id', true );
		$settings['post']['featuredImageId'] = $featured_image_id ? $featured_image_id : -1;
	}
	return $settings;
}

Le code complet pour cette seconde partie :

0102030405060708091011121314151617181920212223242526272829303132333435363738394041424344
add_action( 'init', 'sf_post_type_supports' );

function sf_post_type_supports() {
	add_post_type_support( 'attachment:audio', 'thumbnail' );
	add_post_type_support( 'attachment:video', 'thumbnail' );
}


add_action( 'admin_enqueue_scripts', 'sf_attachment_add_media_editor_js' );
function sf_attachment_add_media_editor_js( $hook_suffix ) {
	global $typenow, $post;
	if ( $hook_suffix == 'post.php' && $typenow == 'attachment' && post_mime_type_is_audio_or_video( $post ) && post_mime_type_supports_thumbnail( $post ) ) {
		add_filter( 'media_view_settings', 'sf_attachment_view_settings', 10, 2 );
		add_thickbox();
		wp_enqueue_media( array( 'post' => $post ) );
	}
}


function sf_attachment_view_settings( $settings, $post ) {
	if ( post_mime_type_is_audio_or_video( $post ) && post_mime_type_supports_thumbnail( $post ) ) {
		$featured_image_id = get_post_meta( $post->ID, '_thumbnail_id', true );
		$settings['post']['featuredImageId'] = $featured_image_id ? $featured_image_id : -1;
	}
	return $settings;
}


if ( !function_exists('post_mime_type_is_audio_or_video') ):
function post_mime_type_is_audio_or_video( $post ) {
	return $post->post_type == 'attachment' && !empty($post->post_mime_type) && ( 0 === strpos( $post->post_mime_type, 'audio/' ) || 0 === strpos( $post->post_mime_type, 'video/' ) );
}
endif;


if ( !function_exists('post_mime_type_supports_thumbnail') ):
function post_mime_type_supports_thumbnail( $post ) {
	if ( 'attachment' !== $post->post_type || empty( $post->post_mime_type ) )
		return false;

	$mime = reset((explode('/', $post->post_mime_type)));
	return (current_theme_supports( 'post-thumbnails', 'attachment' ) || current_theme_supports( 'post-thumbnails', 'attachment:'.$mime )) && post_type_supports( 'attachment:'.$mime, 'thumbnail' ) && !post_type_supports( 'attachment', 'thumbnail' );
}
endif;

See ya!