WordPress 3.5 nous a été livré il y a à peu près deux semaines avec, entre autres, une toute nouvelle fenêtre des médias qui avait bien besoin d’un coup de jeune. Bien entendu, de tels gros changements impliquent également des changements pour nous, développeurs, sans parler… des obligatoires bugs de jeunesse.
Autant cette nouvelle fenêtre modale est une bonne chose pour l’utilisateur selon moi, autant pour les développeurs elle représente un peu le 21-12-2012, mais le vrai, celui qui te pète à la gueule, qui tache et qui engendre des veuves (j’en fait pas trop, c’est bon ?). Bon, je ne vais pas m’étendre sur tous les problèmes engendrés, parmi lesquels on peut compter quelques petites incohérences ergonomiques, bugs CSS, impossibilité de modifier les champs d’origine, JS et ajax à profusion (avec les bugs qui vont avec), manque cruel de hooks, etc (mention spéciale pour l’introduction d’un smarty-like).
Bon, je vais arrêter de faire du mauvais esprit et plutôt aborder le sujet du jour : les champs personnalisés que l’on voudrait ajouter avec nos plugins.
Le premier point important est que tout est fait en ajax, donc si par exemple vous avez fait ceci pour des raisons d’optimisation, vous êtes foutu ^^ :
1234
if ( is_admin() && (!defined('DOING_AJAX') || !DOING_AJAX) ) {
add_filter('attachment_fields_to_edit', 'my_plugin_attachment_fields_to_edit', 11, 2);
// ...
}
Maintenant il y a deux méthodes pour séparer les champs que l’on va ajouter dans la fenêtre modale et ceux de la page normale d’édition d’un média.
La première consiste à utiliser DOING_AJAX
:
12345
if ( is_admin() && defined('DOING_AJAX') && DOING_AJAX ) {
// Fenêtre modale
} elseif ( is_admin() ) {
// Page d'édition d'un média
}
La deuxième consiste à utiliser de nouveaux paramètres lors de l’ajout des champs
010203040506070809101112
add_filter('attachment_fields_to_edit', 'my_plugin_attachment_fields_to_edit', 11, 2);
function my_plugin_attachment_fields_to_edit($form_fields, $post) {
$form_fields['my-plugin'] = array(
'label' => __('Salut'),
'input' => 'html',
'html' => __("Un champs perso"),
'show_in_edit' => false,
'show_in_modal' => true,
);
return $form_fields;
}
Ces deux nouveaux paramètres sont show_in_edit
et show_in_modal
, et sont à true par défaut.
Bon, ça c’était le tour de chauffe, juste une nouvelle habitude à prendre :)
Là on va s’attaquer à un peu plus lourd puisqu’il s’agit d’un bug, qui sera probablement réparé dans la 3.5.1, mais en attendant il faut faire avec.
Situation :
Vous ajoutez par exemple une case à cocher pour modifier le code html envoyé à l’éditeur (comme ajouter un shortcode).
Changement de comportement :
Cette case à cocher doit entrainer une action, comme l’enregistrement d’une meta, que vous ajoutez en utilisant le filtre attachment_fields_to_save
.
Le changement s’effectue dans la manière dont est lancé ce hook : il n’est plus déclenché au moment où on clique sur « Insérer dans l’article » mais à chaque fois que l’on coche/décoche la case (via ajax).
Le problème :
Lorsque l’on coche la case, les infos sont bien envoyées.
action save-attachment-compat
id 325
attachments[325][my-plugin] 1
nonce g5h684d87
post_id 342
Mais lorsque l’on la décoche, l’info se perd, la valeur « décochée » n’est pas envoyée.
action save-attachment-compat
id 325
nonce g5h684d87
post_id 342
Dès lors, l’ajax répond par un échec.
Après moultes tentatives avec diverses façons de faire, je n’en ai trouvé qu’une qui fonctionne au final, celle qui est mentionnée sur le trac WP (que j’ai découvert après avoir trouvé la solution u_u) : utiliser un input hidden additionnel.
Concrètement ça donne ça :
01020304050607080910111213141516171819202122232425262728
add_filter('attachment_fields_to_edit', 'my_plugin_attachment_fields_to_edit', 11, 2);
function my_plugin_attachment_fields_to_edit($form_fields, $post) {
$html = '<label>'
.'<input type="checkbox" name="attachments['.$post->ID.'][my-plugin]" value="1" /> '
.__("Allez, fais pas l'radin")
.'</label>'
.'<input type="hidden" name="attachments['.$post->ID.'][my-plugin-hidden]" value="1"/>';
$form_fields['my-plugin'] = array(
'label' => __('Salut'),
'input' => 'html',
'html' => $html
);
return $form_fields;
}
add_filter('attachment_fields_to_save', 'my_plugin_attachment_fields_to_save', 10, 2);
function my_plugin_attachment_fields_to_save($post, $attachment) {
if ( isset($attachment['my-plugin']) && $attachment['my-plugin'] )
update_post_meta($post['ID'], '_my-plugin', 1);
else
delete_post_meta($post['ID'], '_my-plugin');
return $post;
}
Pour résumer, la valeur du champs caché est toujours envoyée, et empêche l’ajax de renvoyer un échec. Au niveau de l’enregistrement de la meta, rien ne change. Au final, un petit bug tout bête qui fait perdre énormément de temps si on ne connait pas le patch provisoire.
Voilà, j’espère que ceci vous fera économiser du temps, bien que l’article arrive un peu tard par manque de temps pour me pencher sur ce problème.
Pour terminer sur une bonne note, et toujours en relation avec les médias, il est quand même à noter une meilleure prise en compte des taxonomies. Plus besoin de « vil-hacker » dans tous les sens pour avoir une vrai metabox. Enfin… jusqu’au moment où il faudra toucher à la fenêtre modale, là j’ai comme l’impression que ça va être une autre histoire :p
See ya!
[update] 27-01-2013
Bonne nouvelle. L’astuce de l’input hidden n’est plus nécessaire avec WordPress 3.5.1, l’appel ajax ne retourne plus un echec car un « menu_order » est envoyé :)
Commentaires
Commentaire de Julio Potier @ BoiteAWeb.
Encore une fois j’adore le soucis du détail, on sent que tu as cherché loin et longtemps, tu n’as pas abandonné et tu as réussi à trouver des solutions.
Penses-tu que les hooks JS pourraient améliorer tout ça ?
See you
Commentaire de Greg.
Je pense qu’en premier, la résolution du bug aidera beaucoup pour un retour à « la normale », ainsi que le petit nombre d’autres problèmes que j’ai noté.
Ensuite, j’ai compris grâce à Raherian que les fichiers « smarty-like » dont j’ai parlé sont en fait du underscorejs. Comme je ne connais pas (seulement de nom), forcément, ça pique. MAIS, ça n’enlève pas le fait qu’en utilisant cette méthode les templates sont bloqués hélas, on ne peut pas les modifier à moins d’ajouter une bonne couche de JS :/ Ça, je pense que ce sera possible peut-être plus tard avec des hooks, peut-être php, peut-être JS.
Mais pour répondre à ta question, oui, les hooks JS vont beaucoup aider (hélas, car je préfère le php au JS), et j’irais même plus loin en disant qu’ils vont offrir un tout nouveau panel de possibilités, et je suis sûr que tu es du même avis, tu les attend comme une puc***** devant sa première b***. (< = je t'explique sur Skype si t'as pas compris x)) Bref, pour résumer, la 3.5.1 sera d'un grand secours malgré une petite perte de fonctionnalités par rapport à 3.4.2. Mais pour les hooks JS il faut espérer pour la 3.6 (et prier très fort). PS : merci ;)
Commentaire de Julio Potier @ BoiteAWeb.
« comme une puce devant sa première byte. » ok
Commentaire de Julien Maury.
Salut,
Pour ceux qui en douteraient, ce mec est un développeur caché dans le corps d’un designer. :D
Merci pour cette exploration accompagnée de solutions concrètes. Est-ce que cette « migration » vers le js n’est pas à mettre en relation avec le tweet d’un certain Andrew concernant php 5.3, je dis cela comme cela :‹
Commentaire de Greg.
Salut Julien.
Je dirais oui dans le fond et non dans la forme.
Nacin disait dans son tweet que php, qui évolue de version en version (on en est à 5.4 stable et 5.5 alpha), stoppe le support de php 5.3. Or, la plupart des sites utilisant WordPress sont encore en php 5.2.
Par là, on comprend que WordPress est retenu en arrière par un soucis de rétro-compatibilité, mais que le désir d’évoluer vers des versions plus récentes est bien présent. Un peu comme un intégrateur qui veut bénéficier du CSS3 mais qui doit prévoir le support de IE6-8.
Du coup, le passage à underscorejs pour la fenêtre médias traduit aussi ce désir d’évoluer.
Après, le choix de underscorejs parce que php 5.2, non, je ne crois pas, je ne vois pas de rapport.
Merci pour ton message :)
Commentaire de Julio Potier @ BoiteAWeb.
Et voilà, je m’en suis servi, merci à toi ! #over9000