WordPress: Personnaliser la fenêtre de téléchargement des images

Pour différentes raisons, j’ai souvent souhaité ajouter des champs dans la fenêtre de chargement des images (media upload window) de WordPress.
Cette fenêtre, tout comme le menu « media » ne nous donne, en effet, qu’un accès très limité aux informations que l’on peut associer aux pièces jointes ou aux images. Nous pourrions, par exemple, sur ces pièces jointes, autoriser ou interdire les commentaires, ou ajouter des mots-clés, ou les rattacher à une autre taxonomie.
Il y a quelques mois, mes premières recherches n’avaient rien donné. Je les ai reprises pour la version de 1.9.3 de EG-Attachments, et j’ai finalement trouvé des solutions.

Avant de commencer l’article proprement dit, parlons un peu des post types.

Rappel sur les types d’articles

Les types d’articles (post types) ont été introduits avec la version 2.9 de WordPress, puis améliorés avec la version 3.0, en donnant aux développeurs la possibilité de créer leur propre type.

Les types par défaut sont: les articles, les pages, les pièces jointes (attachments), les révisions, et les menus.

Chaque type dispose d’un certain nombre de caractéristiques, comme

  • des fonctionnalités (supports): title, editor, comments, revisions, trackbacks, author, excerpt, page-attributes, thumbnail, et custom-fields
  • des taxonomies,
  • des droits d’accès (capabilities).

Par défaut, les pièces jointes disposent:

  • uniquement de la fonctionnalités comments,
  • d’aucune taxonomie.

Pour les fonctionnalités nous disposons des fonctions suivantes:

  • add_post_type_support( $post_type, $feature ) (voir codex) permet d’ajouter une fonctionnalité à un type,
  • remove_post_type_support ( $post_type, $feature ) (voir codex) effectue l’action inverse,
  • post_type_supports ( $post_type, $feature ) (voir codex) nous renvoie un booléen pour indiquer si le type dispose ou non de la fonctionnalité spécifiée.

L’association des post types avec les taxonomies, s’effectue avec la fonction register_taxonomy_for_object_type($taxonomy, $post_type).

Exemple: register_taxonomy_for_object_type('series', 'post').

Premier niveau de personnalisation

Cette introduction va nous permettre très rapidement et simplement de personnaliser nos pièces jointes, en leur associant une ou plusieurs taxonomies.
Pour associer des mots-clés aux pièces jointes, il suffit en effet d’insérer le code suivant, dans un plugin ou le fichier function.php d’un thème:

1
2
3
4
function my_init() {
	register_taxonomy_for_object_type('post_tag', 'attachment');
} // End of init
add_action('init', 'my_init');

Automatiquement, un champ supplémentaire apparaîtra dans la fenêtre d’édition des pièces jointes:

Associer les pièces jointes aux mots-clés

L’opération est identique pour les catégories, ou toute autre taxonomie, créée par un WordPress, ou une extension.

Personnalisation avancée

Ce premier niveau de personnalisation est intéressant, mais pas complètement satisfaisant: d’abord, il ne permet de gérer que les taxonomies, ensuite le mode de saisie n’est pas très ergonomique.

Pour aller plus loin, nous allons avoir besoin de deux éléments supplémentaires:

  • Deux filtres attachment_fields_to_edit et attachment_fields_to_save,
  • Les fonctions d’affichage du formulaire.

Les filtres

Le filtre attachment_fields_to_edit est appelé à la fin de l’affichage du formulaire permettant la saisie d’informations sur une image ou une pièce jointe, juste avant le bouton de sauvegarde des modifications.

Position des personnalisations

Le filtre accepte deux arguments: function attachment_fields_to_edit($form_fields, $post)

  • $form_fields contient les champs du formulaire affiché (nous y reviendrons dans le paragraphe suivant),
  • $post contient toutes les informations disponibles sur la pièce jointe en cours d’affichage.

attachment_fields_to_save est appelé après l’appui sur le bouton « Enregistrer les modifications », lors de la vérification des informations saisies (en mode Ajax ou direct). Il faut donc y placer la vérification, et les actions associées, aux champs ajoutés dans le filtre attachment_fields_to_edit.

Le filtre accepte deux arguments: function attachment_fields_to_save ( $post, $attachment )

  • $post contient toutes les informations disponibles sur la pièce jointe,
  • $attachment contient la valeur des champs saisis dans le formulaires.

L’affichage du formulaire d’édition des pièces jointes

Le formulaire permettant d’éditer les paramètres des pièces jointes (titre, légende, …) n’est pas directement codé en HTML: WordPress utilise un tableau ($form_fields), pour décrire les différents champs du formulaire. Ce tableau est ensuite traité par une fonction chargée de l’affichage.

Chaque élément du tableau contient (liste non exhaustive):

  • label: le titre du champ,
  • input: le type de champ, avec trois possibilités: textarea, hidden et html,
  • html: si le champ précédent est égal à la valeur html, la valeur doit contenir le code html permettant l’affichage du champ.

Donc, pour personnaliser le formulaire d’édition des pièces jointes, il faut

  • Créer une fonction qui va modifier la liste des champs du formulaire,
  • Attacher cette fonction au filtre attachment_fields_to_edit,
  • Créer une fonction qui va récupérer les valeurs du formulaire et les traiter,
  • Attacher cette fonction au filtre attachment_fields_to_save.

Exemple 1

Ajouter une checkbox pour gérer les commentaires, peut se faire de la façon suivante:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
add_action('admin_init', 'my_admin_init');
 
function my_admin_init() {
	add_filter( 'attachment_fields_to_edit', array(& $this, 'my_media_upload_comments_fields_edit'), 10, 2 );
	add_filter( 'attachment_fields_to_save', array(& $this, 'my_media_upload_comments_fields_save'), 10, 2 );
}
 
function my_media_upload_comments_fields_edit( $form_fields, $post ) {
	if (post_type_supports('attachment', 'comments')) {
		$form_fields['comment_status'] = array(
			'label' => 'Allow comments',
			'input' => 'html',
			'html'	=> '
<input id="attachments['.$post->ID.'][comment_status]" type="checkbox" name="attachments['.$post->ID.'][comment_status]" value="1" checked="checked" />'.
				'<label for="attachments['.$post->ID.'][comment_status]">'.__('Allow comments on this attachments').'</label>'
		);
	}
}
 
function my_media_upload_comments_fields_save( $post, $attachment ) {
 
	// Nous complétons les informations sur la pièce jointe, en fonction des informations saisies dans le formulaire
	if (isset($attachment['comment_status'])) $post['comment_status'] = 'open';
	else $post['comment_status'] = 'closed';
}

Un commentaire au sujet du formulaire: le code HTML ne comporte rien de particulier, à l’exception du format des identifiants des champs. Les identifiants doivent avoir le format attachments[id de la pièce jointe][nom du champ].

Le formulaire devient alors:

Ajout d'un champ

Exemple 2

Si nous souhaitons maintenant améliorer la sélection des mots-clés, il nous faut:

  • Associer les mots-clés aux pièces jointes,
  • Modifier le formulaire crée par WordPress,
  • Gérer les valeurs saisies dans ce formulaire modifié.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
add_action('admin_init', 'my_admin_init');
 
function my_admin_init() {
	add_filter( 'attachment_fields_to_edit', 'my_media_upload_tags_fields_edit');
	add_filter( 'attachment_fields_to_save', 'my_media_upload_tags_fields_save');
}
 
function my_media_upload_tags_fields_edit( $form_fields, $post ) {
 
	// Get tags linked to the attachments
	$terms = get_the_terms($post->ID, 'post_tag');
	$default_tags = array();
	if (is_array($terms) && sizeof($terms)>0) {
		foreach ($terms as $term) {
			$default_tags[$term->term_id] = $term->slug;
		}
	}
	// Get all terms (tags)
	$tags_list = get_terms('post_tag');
	$string = '';
	foreach ($tags_list as $tag) {
		if (isset($default_tags[$tag->term_id])) $checked = 'checked="checked"'; else $checked = '';
		$string .= '<li style="width:32%;float:left;">'.
				'<input type="checkbox" value="'.$tag->slug.'" name="attachments['.$post->ID.'][tags][]" id="tags-'.$post->ID.'" '. $checked .' /> '.
				'<label for="tags-'.$post->ID.'">'.htmlspecialchars($tag->name).'</label>'.
				'</li>';
	} // End of foreach
	if ($string != '') $string = '<ul style="width:100%;">'.$string.'</ul>';
 
	$form_fields['post_tag'] = array_merge($form_fields['post_tag'], array(	'input' => 'html', 'html' => $string));
 
	return $form_fields;
} // End of media_upload_custom_fields_edit
 
function my_media_upload_tags_fields_save( $post, $attachment ) {
 
	if (! isset($attachment['tags'])) $selected_tags = array();
	else if (is_array($attachment['tags'])) $selected_tags = $attachment['tags'];
	else $selected_tags = array($attachment['tags']);
		if (sizeof($selected_tags)== 0) wp_delete_object_term_relationships( $post['ID'], 'post_tag' ) ;
	else wp_set_object_terms($post['ID'], $selected_tags, 'post_tag');
	return ($post);
} // End of media_upload_custom_fields_save
Amélioration de la sélection des tags

Conclusion

Manifestement, WordPress recèle quelques fonctionnalités cachées: Je ne comprends pas pourquoi, la possibilité de lier des pièces jointes aux taxonomies n’apparaît pas, au moins en options, alors que le code est là, prêt à être utilisé. Ces fonctions apparaîtront peut-être dans de futures versions.

En attendant, nous avons tous les outils nécessaires pour réaliser nos personnalisations.

Références

Deux articles m’ont permis de construire celui-ci:

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.