WordPress et les pièces jointes

La gestion des pièces jointes (attachments), n’est pas ce que l’on peut appeler un point fort de WordPress. Avec le Media Manager, la version 2.5.x améliore sensiblement l’ergonomie d’un point de vue utilisateur. L’API s’étoffe également, mais la documentation reste assez pauvre. Voici donc un résumé des fonctions que WordPress met à notre disposition pour la gestion des attachements.

La base de données

Les pièces jointes sont stockées dans la base de données dans la table wp_posts sous forme d’articles (posts). Ils sont considérés comme des « sous-articles », et sont rattachés à des articles principaux. Les champs de la table wp_posts concernés sont:

Champ Type Valeur Description
ID bigint(20)   Identifiant unique de l’article
post_content longtext   Description
post_title text   Nom du fichier
post_excerpt text   Intitulé
post_status varchar(20) inherit  
post_parent bigint(20)   ID de l’article auquel est attachée la pièce jointe
guid varchar(255)   url du fichier (de la pièce jointe)
post_type varchar(20) attachment  
post_mime_type varchar(100)   Type mime du document (image/jpeg par exemple)

Les autres champs ne sont pas utilisés.

L’API

Les fonctions

Les fonctions sont toutes regroupées dans trois fichiers

  • wp-include/posts.php,
  • wp-include/post_template.php,
  • wp-include/media.php.

Il faut distinguer deux catégories de fonctions: la première permet de manipuler les pièces jointes, et la seconde permet d’en récupérer la liste et les paramètres pour les afficher.

Dans la première catégorie, nous trouvons wp_delete_attachment, wp_insert_attachment ou wp_update_attachment_metadata, qui permettent respectivement d’ajouter, d’effacer ou de modifier
une pièce jointe.

Les fonctions de la seconde catégorie sont plus nombreuses, mais souvent redondantes. Les plus importantes sont:

Fonction Arguments /
Valeur par défaut
Description
wp_attachment_is_image $id True ou False selon que la pièce jointe est une image ou pas
wp_get_attachment_image_src $id,
$size=’thumbnail’,
$icon = false
Renvoi un tableau contenant l’URL de l’image, ainsi que ses dimensions (hauteur, largeur). L’image peut être la pièce jointe elle-même ou une vignette
wp_get_attachment_image $attachment_id,
$size=’thumbnail’,
$icon = false
Renvoi la balise html pointant sur l’image ou la vignette (thumbnail).
La réponse prend donc la forme: <img src= » » …>
wp_count_attachments $mime_type Renvoi un tableau avec la liste des types mime, et le nombre de documents par type (Array ($mime, $count))
wp_get_attachment_link $id = 0,
$size = ‘thumbnail’,
$permalink = false,
$icon = false
Renvoi le [perma]lien complet permettant l’affichage de la pièce jointe spécifiée.
get_children $args, $output Renvoi la liste des pièces jointes, en fonction des critères spécifiés dans args. La syntaxe est identique à la fonction get_posts
$ouput peut prendre les valeurs OBJECT, ARRAY_N, ou ARRAY_A.
La fonction appelle get_posts en ajoutant les arguments numberposts=-1, post_type=attachment et post_status => inherit
wp_get_attachment_metadata $post_id,
$unfiltered = false
 
wp_mime_type_icon $id Renvoi une url vers l’icône correspondant au type mime de la pièce jointe.

size peut prendre les valeurs thumb, thumbnail, medium ou full.

Exemple d’application des fonctions précédentes: Affichage d’une liste de documents attachés (sans les images) à un article spécifié par $id.

$attachments = get_children(
    array(
        'post_parent' => $post_id,
        'post_status' => 'inherit',
        'post_type' => 'attachment')
);
if ( empty($attachments) )
    return '';
 
$output = "\n";
foreach ( $attachments as $id =>; $attachment ) {
    if (substr($attachment->post_mime_type, 0, 5) != 'image') {
        $output .= wp_get_attachment_link($id, 'thumbnail', true, true) .' ';
        $output .= wp_get_attachment_link($id, 'thumbnail', true, false) . "\n";
    }
}
echo $output;

Ce code va générer le HTML suivant:

<a title="album_martinique_2007" href="url 1">
    <img class="attachment-thumbnail" src="url thumbnail" alt="" width="46" height="60" />
</a>
<a title="album_martinique_2007" href="url 1">album_martinique_2007</a>
 
<a title="Calendrier" href="url 2">
    <img class="attachment-thumbnail" src="url thumbnail" alt="" width="46" height="60" />
</a>
<a title="Calendrier" href="url 2">Calendrier</a>
 
<a title="IPTC XMP Core" href="url 3">
    <img class="attachment-thumbnail" src="url thumbnail" alt="" width="46" height="60" />
</a>
<a title="IPTC XMP Core" href="url thumbnail">IPTC XMP Core</a>

ce qui donne:

Liste obtenue
Liste obtenue

Les fonctions get_posts et get_children ont quelques limitations. Par exemple, nous ne pouvons pas récupérer les pièces jointes d’un ensemble de catégories, ou exclure une ou plusieurs catégories. Dans ce cas, il reste à « taper » directement dans la base de données, ce qui n’est pas conseillé, et rend le développement plus vulnérable aux changements de version.

Les filtres et les hooks

Les filtres et les hooks ne sont pas très nombreux:

Fonctions Filtres Actions (Hooks)
wp_insert_attachment   edit_attachment,
add_attachment
wp_delete_attachment wp_delete_file delete_attachment
wp_get_attachment_url wp_get_attachment_url  
wp_get_attachment_metadata wp_get_attachment_metadata  
wp_get_attachment_image_src icon_dir  
wp_mime_type_icon icon_dir
icon_dirs
wp_mime_type_icon
 
wp_ext2type ext2type  

Autres ressources

WordPress inclut également une série de vignettes pour décrire les types mime des documents. Ces images se trouvent dans le répertoire /wp-includes/images/crystal.

Les filtres icon_dir, icon_dirs et wp_mime_type_icon permettent d’influer sur l’affichage des vignettes (thumbnail). ext2type permet d’ajouter des types de documents.

Ces filtres ne sont pas complètement efficaces, car mal gérés dans certaines fonctions (wp_get_attachment_link par exemple). Je n’ai réellement réussi à m’en servir qu’avec la fonction wp_mime_type_icon.

Les templates

Les pièces jointes sont stockées comme de simples articles dans la base de WordPress. Au niveau des templates, il faut pourtant différencier un article principal et une pièce jointe, pour adapter l’affichage. WordPress propose quelques fonctions complémentaires pour gérer les attachments dans les thèmes.

Il existe d’abord un tag conditionnel (conditional tag), is_attachment() qui permet de savoir si nous sommes dans le cas d’un article ou d’une pièce jointe. WordPress propose également des templates dédiées. Lorsque l’on clique sur un lien correspondant à une pièce jointe, WordPress cherchera à utiliser les templates suivantes (dans cet ordre):

  • image.php
  • attachment.php
  • index.php

Les templates image.php et attachment.php peuvent être créees pour afficher proprement une pièce jointe. Vous pouvez regarder, à titre d’exemple, la template image.php du thème classic, disponible par défaut dans WordPress.

Le permalien d’une pièce jointe prend la forme suivante:
http://<url du blog>/<url de l'article>/<url de la pièce jointe>

Conclusion

Depuis les versions 2.5.x, WordPress améliore sensiblement la gestion des pièces jointes, à la fois côté utilisateur, avec le Media Manager, et du côté développeur, avec une série de fonctions et de filtres permettant de proposer de nouvelles fonctionnalités, sans avoir besoin de requêter directement la base de données. Il subsiste encore quelques points à améliorer, notamment dans la gestion des vignettes.

23 thoughts on “WordPress et les pièces jointes”

  1. Emmanuel, je viens de trouver ton plugin EG-Attachments qui répond à toutes mes attentes. Excellent plugin. Je n’ai donc plus de problèmes. Merci !

  2. Emmanuel, j’ai utilisé la fonction que tu donnes dans cet article pour afficher une liste de documents attachés (sans les images) à un article spécifié par $id. Je me sers de cette fonction dans la sidebar de mon article. Mais j’ai deux problèmes :
    1-le lien pointe vers l’attachment et non vers le fichier joint lui même.
    2-J’utilise le plugin « simple tags » et l’attachment apparait dans la liste des articles relatifs, or j’aimerais qu’il n’apparaisse pas.
    Je ne sais pas comment faire pour resoudre ces deux problèmes, aurais-tu une idée ? Merci.

  3. Bonjour Emmanuel,

    Merci pour cet article. Il est vrai que le fonctionnement de la médiathèque est un peu obscur.

    J’ai un sous-dossier au sein de wp-content/uploads que j’aimerai connecter à la médiathèque de WordPress afin de rendre les fichiers accessibles en administration via le back-office. Ce dossier est alimenté par un script maison, bientôt intégré à un plugin.
    Peut-être cela peut t’intéresser et tu auras une idée de sa réalisation? Je cherche une solution et tu m’as l’air bien documenté ;-))

    Plus de détails ici : http://www.wordpress-fr.net/support/viewtopic.php?pid=191755

  4. Bonjour,

    Question bête mais à quoi sert la variable global $post dans l’exemple d’utilisation de preg_replace ? Ca m’intéresse car je suis en train d’essayer de manipuler the_content pour rajouter une div avec une class à une partie d’un post.

    Merci d’avance,

  5. Si les videos sont associees a l’article, il est tout a fait possible de recuperer les URL
    Il faut pour cela faire une boucle comme indiqué dans l’article, et récupérer l’URL avec la fonction get_attachment_link($id)

  6. j’ai des videos dans des articles, je me demandais si il était possible de récuperer l’url de la video via ce systeme d’attachment…

  7. Merci pour cette réponse rapide, claire et technique.
    Pour les lightbox j’ai déjà un plugin-in qui tourne, mais pour ce que je veux faire c’est exactement ça ; je teste tout à l’heure ^^.

  8. Bonjour,
    La seule solution que je vois est de faire un preg_replace dans le filtre the_content.
    J’utilise cette technique pour ajouter la balise « rel=lightbox » sur mon blog. La fonction ressemble a cela:

    add_filter('the_content', 'add_lightbox' );
    function add_lightbox($content) {
    	global $post;
    
    	if (!is_feed() && strpos($content, 'rel="lightbox"') === FALSE) {
    		$search_pattern = "/<a(.*?)href=('|\")([^>]*).(bmp|gif|jpeg|jpg|png)('|\")(.*?)>(.*?)<\/a>/i";
    		$replace_pattern = '<a$1href=$2$3.$4$5 rel="lightbox['.$post->ID.']"$6>$7</a>';
    		$content = preg_replace ( $search_pattern , $replace_pattern , $content );
    	}
    	return ($content);
    }
    

    Il faudra que tu transformes les expressions régulières pour obtenir ce que tu veux, et utiliser la fonction wp_mime_type_icon pour recuperer l’icone correspondant au document.

    Sinon tu as toujours mon plugin 😉

  9. Hey !

    Un petit mot, tout d’abord pour dire merci d’avoir posté quelque chose d’intéressant et d’utile sur les pièces jointes, cela m’a bien aidé ^^.

    Par contre j’aurai un question : sous WordPress quand j’affiche une pièce jointe de type image, il me l’a met dans une balise « caption », et affiche un aperçu de l’image, alors que quand je fais exactement la même manip pour n’importe quel autre type de fichier il me met juste un vieux lien tout pourri. Tu saurais ou il faut tripatouiller pour rajouter des icônes d’aperçu aux autres types de fichiers ?

    D’après ton code j’ai réussi à afficher des icônes aux types de fichier, mais je bloque sur la fonction « the_content » appelée dans la boucle WordPress. J’arrive seulement à afficher les pièces jointes comme je veux en dessous du contenu.
    (J’ai posté un article test sur mon blog, article du 18/07/09)

    Enfin, pour résumer : comment remplacer le vieux lien a href des pièces jointes par une jolie icône dans un article ?

    Merci d’avance ^^

  10. c’est vrai que l’idéal serait de pouvoir attacher un doc a plusieurs articles/pages…
    il faudrait revoir le fonctionnement de WP, qui malheureusement bloque les liaisons en laissant le champs directement dans la table des posts, et il faudrait donc créer une table de liaison à part.
    cela pourrait permettre sans passer par des custom fields de lier des articles avec d’autres articles ou bien des docs ou encore meme des commentaires, à la base n’ayant pas de rapport.
    Le coté négatif d’un tel systeme est la complexité de la gestion que cela induit. il faut un backoffice propre, intelligent sinon les liaison prennent le dessus et on ne comprend vite plus rien.
    a méditer 🙂

  11. Oui, le problème est l’attachement des pièces jointes qui ne peut concerner qu’un article… On ne peut donc les réutiliser dans d’autres articles en les affichant avec un appel comme wp_get_attachment_image, si j’ai compris.

    Idéalement, il faudrait pouvoir :
    – attacher une image à un fichier sans passer par l’édition d’un message ;
    – pouvoir attacher l’image à plusieurs articles.

    Du coup, je crois que la seule solution pour personnaliser la gestion des images reste les Custom Fields, et je vais m’en servir pour concevoir un thème… même si cette solution ne me satisfait pas sur le plan intellectuel.

  12. Merci pour les compliments.
    Effectivement, il est toujours plus pratique d’utiliser le « media manager » que d’uploader les images via FTP et d’en saisir le nom a la main. J’avoue pratiquer ce genre de chose pour les icones situes a gauche des articles. Il est dommage que WP n’aille pas plus loin, en proposant de quoi reellement exploiter les pieces jointes.

  13. alors la, bravo, code clair, et simple
    j’avais refait ca a ma sauce en moins propre.

    et ta doc est plus concise et plus facile d’accès que celle de WP 🙂

    la je code un petit bout pour récup les images automatiquement et les afficher en thumb, sans avoir à passer par des champs complémentaires comme c’est souvent expliqué dans les autres site …. domage d’avoir a passer par des champs complémentaires et donc des uploads via ftp, des remaniement d images alors que WP fait tout ca tres bien 😀

    je vais revoir ca avec ton code …

    merci !

  14. Merci pour ces éclaircissements…

    En revanche, le « substr » n’empêche pas, selon mes tests, en copiant-collant fidèlement ton code (première version…) l’affichage des images… Voilà pourquoi, je ne comprenais pas.

    Je teste ta nouvelle version, et te tiens informé.

    Je suis avec intérêt ton extension.

    Merci.

  15. Bonjour,

    J’ai legerement modifie le code pour qu’il soit plus lisible.
    En fait, la condition if (substr ...) permet de ne pas afficher les images.
    Ensuite, le premier appel a wp_get_attachment_link permet l’affichage de l’icone (dernier parametre a TRUE), tandis que le second affiche le nom de l’attachement.
    Ces deux lignes sont dans la boucle foreach qui parcourt la liste des attachments.

    Je prepare actuellement un plugin qui permettra d’afficher la liste des fichiers attaches via un shortcode, ce qui evitera tout developpement. Le plugin devrait etre publie d’ici une semaine maximum.

  16. Bonjour Emmnanuel,

    Je me replonge dans ton article (dont j’ai déjà dit le plus grand bien), riche en enseignements !

    Néanmoins, car je suis légèrement bouché, je ne comprends pas deux éléments dans ton exemple… Quels sont les utilités de :

    1/if (substr($attachment->post_mime_type, 0, 5) != ‘image’)

    2/$output .= wp_get_attachment_link($id, ‘thumbnail’, true, false) . « \n »;

    Cette deuxième ligne se rapporte-t-elle à la fonction get_children ?

    Merci pour les éclaircissements.

    J’espère que le code ajouté à mon commentaire ne perturbera la page ! 🙂

    V.

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.