Ne vous répétez pas : automatiser les tâches répétitives avec WP-CLI

Publié: 2022-03-11

Vous êtes-vous déjà retrouvé dans la zone d'administration de WordPress pour mettre à jour les thèmes, les plugins et le noyau WP ? Bien sûr que vous avez. Vous a-t-on demandé : "Pouvez-vous créer/mettre à jour/supprimer tous les utilisateurs de ce fichier CSV ?" Je suis sûr que vous avez rencontré cela aussi. Avez-vous essayé de migrer un site et souhaité qu'il y ait un plug-in ou un outil tiers que vous puissiez utiliser pour faire le travail ? je sais que j'ai!

Automatisation des tâches répétitives avec WP-CLI

Il existe un outil très puissant disponible pour vous aider dans ces tâches et plus encore. Avant de vous en parler, je voudrais mettre en place une petite anecdote.

Le problème : Dans un projet récent, il y avait plusieurs tâches programmatiques que je devais répéter régulièrement. Une tâche en particulier consistait à mettre à jour les autorisations au niveau de l'utilisateur en fonction de la preuve d'un achat ou d'un abonnement au niveau de l'adhésion. Si l'entreprise ne trouvait pas de paiement de la part de l'utilisateur pour un niveau d'adhésion particulier, elle souhaitait supprimer le niveau d'adhésion de l'utilisateur. Pourquoi était-ce nécessaire ? Peut-être qu'un membre a arrêté un abonnement, mais qu'un événement ne s'est pas déclenché, et donc le membre a toujours accès même s'il ne paie pas pour cela (yikes !). Ou peut-être que quelqu'un était sur une offre d'essai, mais cette offre a expiré et le client a toujours un abonnement (yikes aussi !).

La solution : Au lieu d'aller dans le panneau d'administration et de supprimer manuellement des centaines (peut-être des milliers) d'abonnements, j'ai opté pour l'un de mes outils WordPress préférés, WP-CLI, qui a résolu le problème en quelques frappes.

Dans cet article, je souhaite vous présenter WP-CLI (en supposant que vous n'êtes pas déjà des amis proches), vous guider à travers une simple commande personnalisée que j'ai écrite pour cette situation particulière et vous donner quelques idées et ressources pour utiliser WP-CLI dans votre propre développement.

Qu'est-ce que WP-CLI ?

Si vous n'avez jamais entendu parler de WP-CLI auparavant, vous n'êtes pas seul. Le projet, bien que vieux de plusieurs années, a semblé voler sous le radar de WordPress pendant un moment. Voici une brève description de ce qu'est et fait WP-CLI sur le site officiel :

WP-CLI est un ensemble d'outils en ligne de commande pour gérer les installations de WordPress. Vous pouvez mettre à jour les plugins, configurer des installations multisites et bien plus encore, sans utiliser de navigateur Web.

Les commandes suivantes vous montrent la puissance de WP-CLI prête à l'emploi :

  • wp plugin update --all met à jour tous les plugins pouvant être mis à jour.
  • wp db export exporte un vidage SQL de votre base de données.
  • wp media regenerate régénère les vignettes des pièces jointes (par exemple, après avoir modifié la taille de votre thème).
  • wp checksum core vérifie que les fichiers principaux de WordPress n'ont pas été falsifiés.
  • wp search-replace recherche et remplace les chaînes dans la base de données.

Si vous explorez plus de commandes ici, vous verrez qu'il existe de nombreuses commandes disponibles pour les tâches répétitives que chaque développeur ou responsable de site WordPress effectue quotidiennement ou hebdomadairement. Ces commandes m'ont fait économiser d'innombrables heures de pointage, de clic et d'attente de rechargement de page au cours de l'année.

Êtes-vous convaincu? Prêt à commencer? Génial!

Vous devrez avoir WP-CLI installé avec votre WordPress (ou globalement sur votre machine locale). Si vous n'avez pas encore installé WP-CLI sur votre environnement de développement local, les instructions d'installation sont disponibles sur le site Web ici. Si vous utilisez Varying Vagrant Vagrants (VVV2), WP-CLI est inclus. De nombreux hébergeurs ont également WP-CLI inclus sur leur plate-forme. Je suppose que vous l'avez installé avec succès à l'avenir.

Utiliser WP-CLI pour résoudre le problème

Pour résoudre le problème des tâches répétitives, nous devons mettre une commande WP-CLI personnalisée à la disposition de notre installation WordPress. L'un des moyens les plus simples d'ajouter des fonctionnalités à n'importe quel site consiste à créer un plugin. Nous utiliserons un plugin dans ce cas pour trois raisons principales :

  1. Nous pourrons désactiver la commande personnalisée si nous n'en avons pas besoin
  2. Nous pouvons facilement étendre nos commandes et sous-commandes tout en gardant les choses modulaires.
  3. Nous pouvons maintenir les fonctionnalités sur tous les thèmes et même sur d'autres installations WordPress.

Création du plugin

Pour créer un plugin, nous devons ajouter un répertoire à notre répertoire /plugins dans notre répertoire wp-content . Nous pouvons appeler ce répertoire toptal-wpcli . Créez ensuite deux fichiers dans ce répertoire :

  • index.php , qui ne devrait avoir qu'une seule ligne de code : <?php // Silence is golden
  • plugin.php , où ira notre code (vous pouvez nommer ce fichier comme vous voulez.)

Ouvrez le fichier plugin.php et ajoutez le code suivant :

 <?php /** * Plugin Name: TOPTAL WP-CLI Commands * Version: 0.1 * Plugin URI: https://n8finch.com/ * Description: Some rando wp-cli commands to make life easier... * Author: Nate Finch * Author URI: https://n8finch.com/ * Text Domain: toptal-wpcli * Domain Path: /languages/ * License: GPL v3 */ /** * NOTE: THIS PLUGIN FILE WILL NOT WORK IN PRODUCTION AS IS AND IS ONLY FOR DEMONSTRATION PURPOSES! * You can of course take the code and repurpose it:-). */ if ( !defined( 'WP_CLI' ) && WP_CLI ) { //Then we don't want to load the plugin return; }

Il y a deux parties dans ces premières lignes.

Tout d'abord, nous avons l'en-tête du plugin. Ces informations sont extraites de la page d'administration des plugins WordPress et nous permettent d'enregistrer notre plugin et de l'activer. Seul le nom du plug-in est requis, mais nous devrions inclure le reste pour quiconque souhaiterait utiliser ce code (ainsi que nous-mêmes !).

Deuxièmement, nous voulons vérifier que WP-CLI est défini. Autrement dit, nous vérifions si la constante WP-CLI est présente. Si ce n'est pas le cas, nous voulons renflouer et ne pas exécuter le plugin. S'il est présent, nous sommes clairs pour exécuter le reste de notre code.

Entre ces deux sections, j'ai ajouté une note indiquant que ce code ne doit pas être utilisé "tel quel" en production, car certaines des fonctions sont des espaces réservés pour les fonctions réelles. Si vous modifiez ces fonctions d'espace réservé en fonctions réelles et actives, n'hésitez pas à supprimer cette note.

Ajout de la commande personnalisée

Ensuite, nous voulons inclure le code suivant :

 class TOPTAL_WP_CLI_COMMANDS extends WP_CLI_Command { function remove_user() { echo "\n\n hello world \n\n"; } } WP_CLI::add_command( 'toptal', 'TOPTAL_WP_CLI_COMMANDS' );

Ce bloc de code fait deux choses pour nous :

  1. Il définit la classe TOPTAL_WP_CLI_COMMANDS , à laquelle nous pouvons passer des arguments.
  2. Il attribue la commande toptal à la classe, afin que nous puissions l'exécuter à partir de la ligne de commande.

Maintenant, si nous wp toptal remove_user , nous voyons :

 $ wp toptal hello hello world

Cela signifie que notre commande toptal est enregistrée et que notre sous-commande remove_user fonctionne.

Configuration des variables

Étant donné que nous traitons en bloc la suppression d'utilisateurs, nous souhaitons configurer les variables suivantes :

 // Keep a tally of warnings and loops $total_warnings = 0; $total_users_removed = 0; // If it's a dry run, add this to the end of the success message $dry_suffix = ''; // Keep a list of emails for users we may want to double check $emails_not_existing = array(); $emails_without_level = array(); // Get the args $dry_run = $assoc_args['dry-run']; $level = $assoc_args['level']; $emails = explode( ',', $assoc_args['email'] );

L'intention de chacune des variables est la suivante :

  • total_warnings : nous afficherons un avertissement si l'e-mail n'existe pas ou si l'e-mail n'est pas associé au niveau d'adhésion que nous supprimons.
  • $total_users_removed : nous voulons comptabiliser le nombre d'utilisateurs supprimés au cours du processus (voir la mise en garde ci-dessous).
  • $dry_suffix : s'il s'agit d'un essai à blanc, nous souhaitons ajouter un libellé à l'avis de réussite final.
  • $emails_not_existing : stocke une liste d'e-mails qui n'existent pas.
  • $emails_without_level : stocke une liste d'e-mails qui n'ont pas le niveau spécifié.
  • $dry_run : Un booléen qui stocke si le script effectue une simulation (true) ou non (false).
  • $level : Un entier représentant le niveau à vérifier et éventuellement supprimer.
  • $email : Un tableau d'e-mails à vérifier par rapport au niveau donné. Nous allons parcourir ce tableau

Avec nos variables définies, nous sommes prêts à exécuter réellement la fonction. À la manière de WordPress, nous exécuterons une boucle.

Écrire la fonction elle-même

Nous commençons par créer une boucle foreach pour parcourir tous les e-mails de notre tableau $emails :

 // Loop through emails foreach ( $emails as $email ) { // code coming soon } // end foreach

Ensuite, nous ajoutons une vérification conditionnelle :

 // Loop through emails foreach ( $emails as $email ) { //Get User ID $user_id = email_exists($email); if( !$user_id ) { WP_CLI::warning( "The user {$email} does not seem to exist." ); array_push( $emails_not_existing, $email ); $total_warnings++; continue; } } // end foreach

Cette vérification garantit que nous avons un utilisateur enregistré avec l'e-mail que nous vérifions. Il utilise la fonction email_exists() pour vérifier s'il y a un utilisateur avec cet email. S'il ne trouve pas d'utilisateur avec cet e-mail, il lance un avertissement afin que nous sachions sur l'écran de notre terminal que l'e-mail n'a pas été trouvé :

 $ wp toptal remove_user [email protected] --dry-run Warning: The user [email protected] does not seem to exist.

L'e-mail est ensuite stocké dans le tableau $emails_not_existing pour un affichage ultérieur. Ensuite, nous incrémentons l'avertissement total de un et poursuivons la boucle jusqu'au prochain e-mail.

Si l'e-mail existe, nous utiliserons les variables $user_id et $level pour vérifier si l'utilisateur a accès au niveau. Nous stockons la valeur booléenne résultante dans la variable $has_level :

 // Loop through emails foreach ( $emails as $email ) { //Get User ID $user_id = email_exists($email); if( !$user_id ) { WP_CLI::warning( "The user {$email} does not seem to exist." ); array_push( $emails_not_existing, $email ); $total_warnings++; continue; } // Check membership level. This is a made up function, but you could write one or your membership plugin probably has one. $has_level = function_to_check_membership_level( $level, $user_id ); } // end foreach

Comme la plupart des fonctions de cet exemple, cette function_to_check_membership_level() est fabriquée, mais la plupart des plugins d'adhésion devraient avoir des fonctions d'assistance pour vous fournir ces informations.

Passons maintenant à l'action principale : supprimer le niveau de l'utilisateur. Nous allons utiliser une structure if/else , qui ressemble à ceci :

 foreach ( $emails as $email ) { // Previous code here... // Check membership level. This is a made up function, but you could write one or your membership plugin probably has one. $has_level = function_to_check_membership_level( $level, $user_id ); if ( $has_level ) { if ( !$dry_run ) { // Deactivate membership level. This is a made up function, but you could write one or your membership plugin probably has one. function_to_deactivate_membership_level( $level, $user_id, 'inactive' ); } WP_CLI::success( "Membership canceled for {$email}, Level {$level} removed" . PHP_EOL ); $total_users_removed++; } else { WP_CLI::warning( "The user {$email} does not have Level = {$level} membership." ); array_push( $emails_without_level, $email ); $total_warnings++; } // We could echo something here to show that things are processing... } // end foreach

Si la valeur de $has_level est "vérité", ce qui signifie que l'utilisateur a accès au niveau d'adhésion, nous souhaitons exécuter une fonction pour supprimer ce niveau. Dans cet exemple, nous utiliserons la function_to_deactivate_membership_level() pour effectuer cette action.

Cependant, avant de supprimer réellement le niveau de l'utilisateur, nous souhaitons enfermer cette fonction dans une vérification conditionnelle pour voir s'il s'agit réellement d'un dry-run . Si c'est le cas, nous ne voulons rien supprimer, seulement signaler que nous l'avons fait. S'il ne s'agit pas d'un dry-run , nous allons supprimer le niveau de l'utilisateur, enregistrer notre message de réussite dans le terminal et continuer à parcourir les e-mails.

Si, d'autre part, la valeur de $has_level est "falsey", ce qui signifie que l'utilisateur n'a pas accès au niveau d'adhésion, nous voulons enregistrer un avertissement sur le terminal, envoyer l'e-mail au tableau $emails_without_level et continuer en boucle dans les e-mails.

Finalisation et rapport

Une fois la boucle terminée, nous souhaitons enregistrer nos résultats dans la console. S'il s'agissait d'un essai à blanc, nous souhaitons enregistrer un message supplémentaire dans la console :

 if ( $dry_run ) { $dry_suffix = 'BUT, nothing really changed because this was a dry run:-).'; }

Ce $dry-suffix sera ajouté aux avertissements et aux notifications de réussite que nous enregistrerons ensuite.

Pour finir, nous souhaitons enregistrer nos résultats sous forme de message de réussite et nos avertissements sous forme de messages d'avertissement. Nous procéderons comme ceci :

 WP_CLI::success( "{$total_users_removed} User/s been removed, with {$total_warnings} warnings. {$dry_suffix}" ); if ( $total_warnings ) { $emails_not_existing = implode(',', $emails_not_existing); $emails_without_level = implode(',', $emails_without_level); WP_CLI::warning( "These are the emails to double check and make sure things are on the up and up:" . PHP_EOL . "Non-existent emails: " . $emails_not_existing . PHP_EOL . "Emails without the associated level: " . $emails_without_level . PHP_EOL ); }

Notez que nous utilisons les méthodes d'assistance WP_CLI::success et WP_CLI::warning . Ceux-ci sont fournis par WP-CLI pour la journalisation des informations sur la console. Vous pouvez facilement enregistrer des chaînes, ce que nous faisons ici, y compris nos $total_users_removed , $total_warnings et $dry_suffix .

Enfin, si nous avons accumulé des avertissements tout au long de l'exécution du script, nous souhaitons imprimer ces informations sur la console. Après avoir exécuté une vérification conditionnelle, nous convertissons les variables de tableau $emails_not_existing et $emails_without_level en variables de chaîne. Nous faisons cela pour pouvoir les imprimer sur la console en utilisant la méthode d'assistance WP_CLI::warning .

Ajouter une description

Nous savons tous que les commentaires sont utiles aux autres et à nous-mêmes en revenant à notre code des semaines, des mois ou même des années plus tard. WP-CLI fournit une interface de descriptions courtes (shortdesc) et de descriptions longues (longdesc) qui nous permet d'annoter notre commande. Nous mettrons en tête de notre commande, après la définition de la classe TOPTAL_WP_CLI_COMMANDS :

 /** * Remove a membership level from a user * * ## OPTIONS * --level=<number> * : Membership level to check for and remove * * --email=<email> * : Email of user to check against * * [--dry-run] * : Run the entire search/replace operation and show report, but don't save changes to the database. * * ## EXAMPLES * * wp toptal remove_user --level=5 [email protected],[email protected], [email protected] --dry-run * * @when after_wp_load */

Dans le longdesc, nous définissons ce que nous attendons de notre commande personnalisée. La syntaxe pour shortdesc et longdesc est Markdown Extra. Sous la section ## OPTIONS , nous définissons les arguments que nous nous attendons à recevoir. Si un argument est requis, nous l'enveloppons dans < > , et s'il est facultatif, nous l'enveloppons dans [ ] .

Ces options sont validées lors de l'exécution de la commande ; par exemple, si nous omettons le paramètre email requis, nous obtenons l'erreur suivante :

 $ wp toptal remove_user --level=5 --dry-run Error: Parameter errors: missing --email parameter (Email of user to check against)

La section ## EXAMPLES inclut un exemple de ce à quoi la commande pourrait ressembler lorsqu'elle est appelée.

Notre commande personnalisée est maintenant terminée. Vous pouvez voir l'essentiel ici.

Une mise en garde et une marge d'amélioration

Il est important de revoir le travail que nous avons fait ici pour voir comment le code pourrait être amélioré, élargi et refactorisé. Il existe de nombreux domaines d'amélioration pour ce script. Voici quelques observations sur les améliorations qui pourraient être apportées.

Parfois, j'ai trouvé que ce script ne supprimerait pas tous les utilisateurs qu'il enregistre comme "supprimés". Cela est probablement dû au fait que le script s'exécute plus rapidement que les requêtes ne peuvent s'exécuter. Votre expérience peut varier en fonction de l'environnement et de la configuration dans lesquels le script est exécuté. Le moyen le plus rapide de contourner ce problème consiste à exécuter plusieurs fois avec les mêmes entrées ; il finira par se mettre à zéro et signalera qu'aucun utilisateur n'a été supprimé.

Le script pourrait être amélioré pour attendre et valider qu'un utilisateur a été supprimé avant de consigner l'utilisateur comme réellement supprimé. Cela ralentirait l'exécution du script, mais ce serait plus précis et vous n'auriez à l'exécuter qu'une seule fois.

De même, s'il y avait des erreurs trouvées comme celle-ci, le script pourrait générer des erreurs pour alerter qu'un niveau n'avait pas été supprimé d'un utilisateur.

Un autre domaine pour améliorer le script est de permettre à plusieurs niveaux à la fois d'être supprimés d'une adresse e-mail. Le script pourrait détecter automatiquement s'il y avait un ou plusieurs niveaux et un ou plusieurs e-mails à supprimer. On m'a donné des fichiers CSV par niveau, donc je n'avais besoin que d'exécuter un niveau à la fois.

Nous pourrions également refactoriser une partie du code pour utiliser des opérateurs ternaires au lieu des vérifications conditionnelles plus détaillées que nous avons actuellement. J'ai choisi de rendre cela plus facile à lire pour des raisons de démonstration, mais n'hésitez pas à personnaliser le code.

Dans la dernière étape, au lieu d'imprimer des e-mails sur la console à l'étape finale, nous pourrions également les exporter automatiquement vers un fichier CSV ou texte brut

Enfin, aucune vérification n'est effectuée pour s'assurer que nous obtenons un entier pour la variable $level ou un e-mail ou une liste d'e-mails séparés par des virgules dans la variable $emails . Actuellement, si quelqu'un incluait des chaînes au lieu d'entiers ou des noms de connexion d'utilisateur au lieu d'e-mails, le script ne fonctionnerait pas (et ne générerait aucune erreur). Des contrôles pour les nombres entiers et les e-mails pourraient être ajoutés.

Idées pour une automatisation plus poussée et une lecture plus approfondie

Comme vous pouvez le voir, même dans ce cas d'utilisation spécifique, WP-CLI est assez flexible et suffisamment puissant pour vous aider à faire votre travail rapidement et efficacement. Vous vous demandez peut-être : « Comment puis-je commencer à implémenter WP-CLI dans mon flux de développement quotidien et hebdomadaire ?

Il existe plusieurs façons d'utiliser WP-CLI. Voici quelques-uns de mes favoris:

  • Mettez à jour les thèmes, les plugins et le noyau WP sans avoir à accéder au panneau d'administration.
  • Exporter des bases de données pour la sauvegarde ou effectuer un vidage SQL rapide si je veux tester une requête SQL.
  • Migrer des sites WordPress.
  • Installez de nouveaux sites WordPress avec des données factices ou des configurations de suites de plugins personnalisées.
  • Exécutez des sommes de contrôle sur les fichiers principaux pour vous assurer qu'ils n'ont pas été compromis. (Il y a en fait un projet en cours pour étendre cela aux thèmes et plugins dans le repo WP.)
  • Écrivez votre propre script pour vérifier, mettre à jour et maintenir les hôtes du site (dont j'ai parlé ici).

Les possibilités avec WP-CLI sont à peu près illimitées. Voici quelques ressources pour vous aider à aller de l'avant :

  • Le site principal de WP-CLI : http://wp-cli.org
  • Commandes WP-CLI : https://developer.wordpress.org/cli/commands/
  • Blog officiel WP-CLI : https://make.wordpress.org/cli/
  • Manuel WP-CLI : https://make.wordpress.org/cli/handbook/
  • Dans WooCommerce ? Consultez le WC-CLI : https://github.com/woocommerce/woocommerce/wiki/WC-CLI-Overview#woocommerce-commands
  • Podcast Interview avec Daniel Bachhuber, mainteneur du projet : https://howibuilt.it/episode-28-daniel-bachhuber-wp-cli/