Les sept décisions à ne jamais prendre quand on développe un plugin
Deuxième volet de la traduction de l‘article d’Ozh Richard, après les erreurs de code, les mauvaises décisions !
Un plugin / une librairie est nécessaire, mais est-ce qu’il est disponible ?
De nombreux plugins utilisent PHP Curl, l’un d’entre eux avait même besoin des fonctions mbstring, et ne vérifient pas s’ils sont présents. Vous devez prévenir l’utilisateur, ou faire en sorte que votre code vérifie que tout est disponible avant de lancer quoique ce soit.
NB : Curl est une extension PHP qui se généralise de plus en plus, mais qui n’est effectivement pas présente sur tous les mutualisés. Sur Wamp, elle fonctionne mal par défaut. De la même façon mbstring est un module php qui n’est pas activé par défaut, et qui peut donc poser problèmes sur certains mutualisés.
Mon commentaire : la problématique se pose aussi avec les plugins WordPress dépendant d’autres plugins.
Cas n°1 : le plugin est une extension spécifique pour un autre plugin. Par exemple, Gravity Forms Tool Bar rajoute un menu dans la barre admin pour avoir accès à l’essentiel de Gravity Forms. On peut espérer que l’utilisateur n’est pas assez débile distrait pour l’installer sans avoir Gravity Forms. Mais on n’en sait rien… et puis on peut être dans le cas, ultérieurement, où il faut désactiver Gravity Forms. Si le plugin “pour le plugin” n’a pas intégré cela, alors on risque la page blanche dans l’admin.
Cas n°2 : le plugin utilise les fonctionnalité d’un autre plugin pour “faire des trucs”. Dans mon plugin CC, j’ai pensé à un moment à utiliser Taxonomy Metadata. Le risque d’indisponibilité est encore plus grand que pour une librairie php. Le plugin peut ne pas être installé, avoir disparu du repertory ou encore ne plus être maintenu et causer des erreurs à l’activation.
Dans ce cas, il faut :
- informer dans le “about” sur les plugins nécessaires
- faire lors de l’activation du plugin une routine qui va checker si les autres plugins sont déjà activés (un débat de fond entre is_active() et function_exists() sera développé dans un autre article), proposer de les installer si ce n’est pas le cas (avec le lien qu’il faut)
- prévoir, pour toutes les fonctions qui font appel à ce premier plugin, une version dégradée, voir de ne rien faire. Si cela inactive 95% de votre plugin, il vaut peut-être mieux en empêcher l’activation ?
Réinventer la roue
En parlant de cURL, pourquoi l’utilisez vous toujours ? C’est génial et super tout ça, mais la bibliothèque peut être totalement non disponible. Quel est l’intérêt d’écrire dix lignes de code pour récupérer un contenu distant, quand une simple utilisation de wp_remote_get() va suffire, et fonctionnera toujours, même lorsque vous n’avez pas cURL ?
WordPress dispose d’un nombre de fonctions internes disponibles pour vous permettre de coder plus rapidement, et de façon compatible avec le plus grand nombre de configurations possibles. J’ai (Ozh, hein, allez sur son blog) écrit les façons simples de faire des requêtes HTTP pour gérer des options sans aller mettre les mains dans $_POST, mais il y a aussi des fonctions Ajax intégrées, des hooks et bien plus.
Avant d’écrire un morceau de code qui vous semble assez générique ou commun, vérifiez d’abord qu’il n’y a pas déjà une fonction WP qui peut le faire.
NB : pas volontaire, mais dédicace spéciale Julien avec qui nous avons longuement échangé sur les API Flickr et Wikimédia
A se graver dans le cadre de l’écran
Les avantages sont multiples, et c’est vraiment “la” chose à faire :
- ça évite de recoder pour rien ce qui a déjà été fait
- c’est généralement déjà totalement sécurisé
- ça garantit une meilleure compatibilité avec les nouvelles versions de WordPress
Exemple : vous voulez faire une requête pour récupérer tous les posts d’un terme spécifique.
Option n°1 : Vous pouvez coder la requête SQL vous même (si possible, sans oublier $wpdb->prepare), mais le jour où la structure des tables change, votre requête ne marche plus.
Option n°2 : Vous utilisez wp_query et particulièrement tax_query
Le jour où la structure des tables change, la fonction WordPress prend en charge ce changement, fait les tests et les correspondances nécessaires. Votre plugin continue à fonctionner tout seul comme un grand.
Maintenir la compatibilité pour de très vieilles versions de WordPress
Certains plugins ont des commentaires qui disent “// on fait ça pour les gens qui utilisent WP 2.5” [à l’époque de l’article, la version courante de WordPress était la 2.8]. Il s’agit d’un choix personnel, mais je pense que maintenir la compatibilité avec les anciennes versions de WordPress est une idée affreuse.
Affreuse pour vous : corriger des bugs et mettre en place de nouvelles fonctionnalités est déjà un gros travail, n’ajoutez pas le fardeau de la maintenance d’un code déprécié.
Affreuse pour l’utilisateur : c’est chouette que votre plugin continue à bien fonctionner sur leur blog obsolète, non sécurisé et déjà hacké, mais cela ne les motive pas à faire une mise à jour, alors qu’elle est vitale.
Ozh a laissé tombé la rétro-compatibilité pour ses plugins longtemps avant d’écrire son article, et il code toujours pour la dernière version disponible. Cela rend la vie tellement plus facile :)
Mes deux centimes
C’est la contrepartie du point précédent. En utilisant les fonctions du core de WordPress, vous laissez WordPress prendre soin de ce problème. Effectivement, “pas la peine d’en faire plus”.
Il y a de rares cas où il est impossible, à cause des changements de WordPress, de maintenir une compatibilité avec la version précédente. La 3.9 avec l’intégration de la V4 de TinyMce fait partie des rares contre-exemples. La méthode appliquée par TinyMce Advanced était de proposer une mise à jour uniquement à partir du moment où le blog était en 3.9. Désormais, le plugin affiche qu’il ne fonctionne qu’à partir de la 4.0
Des chemins de fichiers codés en dur
Hard Coded is Evil.
Point barre.
Surtout quand on a tout l’outillage nécessaire : WP_PLUGIN_DIR, WP_PLUGIN_URL ou mieux plugins_url(), plugin_basename( __FILE__ )
Appeler tous les fichiers, même si ce n’est pas nécessaire
Facilitez-vous la vie : scindez votre plugin en plus petits morceaux de codes, rangez les fichiers dans différents répertoires au lieu de tout mettre dans le même dossier (includes/, css/, translations/, etc…) et ne faites d’include que de ce dont vous avez besoin. Si vous êtes sur le front_end, ne chargez pas tout ce qui touche à l’admin…
Ne pas guider l’utilisateur si quelque chose se passe mal
Ne laissez pas l’utilisateur ne pas comprendre ce qui ne va pas.
Une fois que vous avez fini votre jolie fonction qui envoie un message sur Twitter, demandez-vous : que se pass-t-il si Twitter est down ?
Rien n’est plus frustrant qu’un utilisateur qui vient sur votre site demander du support, et qui ne peut pas vous expliquer ce qui ne s’est pas bien passé. A chaque fois que c’est possible, ajoutez des fonctions pour expliciter les problèmes, vérifier les résultats des opérations et envoyer un message à l’utilisateur quand il semble qu’il y a un problème.
Pas de lien de download sur la page du plugin
Sauf bien sûr si vous faites un plugin secret que personne ne doit utiliser !
Salut, Oui en effet l’API HTTP très important pour faire vos transports de données. On voit encore de remote call PHP dans les plugins mais les fonctions de l’API WP dédiée sont nettement supérieures :)
Pour les chemins je recommande plugin_dir_path() pour les fichiers php style classes et autres includes et plugin_dir_url() pour les js, css, img.