Non ripeterti: automatizzare le attività ripetitive con WP-CLI
Pubblicato: 2022-03-11Ti sei mai trovato ad entrare nell'area di amministrazione di WordPress per aggiornare temi, plugin e core WP? Certo che hai. Ti è stato chiesto: "Puoi creare/aggiornare/eliminare tutti gli utenti su questo file CSV?" Sono sicuro che ti sei imbattuto anche in quello. Hai provato a migrare un sito e vorresti che ci fosse un plug-in o uno strumento di terze parti a cui poter accedere per svolgere il lavoro? So di averlo!
È disponibile uno strumento molto potente per aiutarti con queste attività e altro ancora. Prima di parlarvene, vorrei creare un breve aneddoto.
Il problema: in un progetto recente, c'erano diverse attività programmatiche che dovevo ripetere regolarmente. Un'attività in particolare prevedeva l'aggiornamento delle autorizzazioni a livello di utente in base all'evidenza dell'acquisto o dell'abbonamento a livello di appartenenza. Se la società non riusciva a trovare un pagamento dall'utente per un determinato livello di iscrizione, voleva che il livello di iscrizione fosse rimosso dall'utente. Perché era necessario? Forse un membro ha interrotto un abbonamento, ma un evento non è stato attivato, quindi il membro ha ancora accesso anche se non lo sta pagando (ahimè!). O forse qualcuno aveva un'offerta di prova, ma quell'offerta è scaduta e il cliente ha ancora un abbonamento (anche questo sì!).
La soluzione: invece di entrare nel pannello di amministrazione ed eliminare manualmente centinaia (forse migliaia) di abbonamenti, ho optato per uno dei miei strumenti WordPress preferiti, WP-CLI, che ha risolto il problema in pochi tasti.
In questo post, voglio presentarti WP-CLI (supponendo che tu non sia già un caro amico), guidarti attraverso un semplice comando personalizzato che ho scritto per questa particolare situazione e darti alcune idee e risorse per usare WP-CLI in il tuo stesso sviluppo.
Che cos'è WP-CLI?
Se non hai mai sentito parlare di WP-CLI prima, non sei solo. Il progetto, sebbene vecchio di diversi anni, sembrava volare sotto il radar di WordPress per un po'. Ecco una breve descrizione di cosa è e fa WP-CLI dal sito ufficiale:
WP-CLI è un insieme di strumenti da riga di comando per la gestione delle installazioni di WordPress. Puoi aggiornare plug-in, configurare installazioni multisito e molto altro senza utilizzare un browser web.
I seguenti comandi mostrano la potenza di WP-CLI pronta all'uso:
-
wp plugin update --allaggiorna tutti i plugin aggiornabili. -
wp db exportesporta un dump SQL del tuo database. -
wp media regeneraterigenera le miniature per gli allegati (ad esempio, dopo aver modificato le dimensioni nel tema). -
wp checksum coreverifica che i file core di WordPress non siano stati manomessi. -
wp search-replacecerca e sostituisce le stringhe nel database.
Se esplori più comandi qui, vedrai che ci sono molti comandi disponibili per attività ripetitive che ogni sviluppatore di WordPress o manutentore del sito esegue su base giornaliera o settimanale. Questi comandi mi hanno risparmiato innumerevoli ore di puntamento, clic e attesa per il ricaricamento della pagina nel corso dell'anno.
Sei convinto? Pronto per iniziare? Grande!
Dovrai avere WP-CLI installato con il tuo WordPress (o globalmente sul tuo computer locale). Se non hai ancora installato WP-CLI nel tuo ambiente di sviluppo locale, le istruzioni per l'installazione sono disponibili sul sito Web qui. Se stai usando Varying Vagrant Vagrants (VVV2), WP-CLI è incluso. Molti provider di hosting hanno anche WP-CLI incluso nella loro piattaforma. Presumo che tu l'abbia installato con successo andando avanti.
Utilizzo di WP-CLI per risolvere il problema
Per risolvere il problema delle attività ripetitive, dobbiamo rendere disponibile un comando WP-CLI personalizzato per la nostra installazione di WordPress. Uno dei modi più semplici per aggiungere funzionalità a qualsiasi sito è creare un plug-in. Useremo un plugin in questo caso per tre motivi principali:
- Potremo disattivare il comando personalizzato se non ne abbiamo bisogno
- Possiamo facilmente estendere i nostri comandi e sottocomandi mantenendo le cose modulari.
- Possiamo mantenere la funzionalità tra i temi e anche altre installazioni di WordPress.
Creazione del plug-in
Per creare un plugin, dobbiamo aggiungere una directory alla nostra directory /plugins nella nostra directory wp-content . Possiamo chiamare questa directory toptal-wpcli . Quindi crea due file in quella directory:
-
index.php, che dovrebbe avere solo una riga di codice:<?php // Silence is golden -
plugin.php, che è dove andrà il nostro codice (puoi nominare questo file come vuoi.)
Apri il file plugin.php e aggiungi il seguente codice:
<?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; }Ci sono due parti in queste prime righe.
Innanzitutto, abbiamo l'intestazione del plugin. Queste informazioni vengono estratte nella pagina di amministrazione dei plugin di WordPress e ci consentono di registrare il nostro plugin e attivarlo. È richiesto solo il nome del plug-in, ma dovremmo includere il resto per chiunque desideri utilizzare questo codice (così come il nostro sé futuro!).
In secondo luogo, vogliamo verificare che WP-CLI sia definito. Cioè, stiamo verificando se è presente la costante WP-CLI. In caso contrario, vogliamo salvare e non eseguire il plug-in. Se è presente, siamo liberi di eseguire il resto del nostro codice.
Tra queste due sezioni, ho aggiunto una nota che questo codice non dovrebbe essere utilizzato "così com'è" in produzione, poiché alcune delle funzioni sono segnaposto per funzioni reali. Se modifichi queste funzioni segnaposto in funzioni reali e attive, sentiti libero di eliminare questa nota.
Aggiunta del comando personalizzato
Successivamente, vogliamo includere il seguente codice:
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' );Questo blocco di codice fa due cose per noi:
- Definisce la classe
TOPTAL_WP_CLI_COMMANDS, in cui possiamo passare argomenti. - Assegna il comando
toptalalla classe, quindi possiamo eseguirlo dalla riga di comando.
Ora, se eseguiamo wp toptal remove_user , vediamo:
$ wp toptal hello hello world Ciò significa che il nostro comando toptal è registrato e il nostro sottocomando remove_user funziona.
Impostazione delle variabili
Poiché stiamo elaborando in blocco la rimozione degli utenti, vogliamo impostare le seguenti variabili:
// 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'intento di ciascuna delle variabili è il seguente:
-
total_warnings: Conteremo un avviso se l'e-mail non esiste o se l'e-mail non è associata al livello di iscrizione che stiamo rimuovendo. -
$total_users_removed: Vogliamo calcolare il numero di utenti rimossi nel processo (vedi avvertimento sotto). -
$dry_suffix: Se si tratta di un ciclo di prova, vogliamo aggiungere una formulazione all'avviso di successo finale. -
$emails_not_existing: memorizza un elenco di email che non esistono. -
$emails_without_level: memorizza un elenco di email che non hanno il livello specificato. -
$dry_run: un valore booleano che memorizza se lo script sta eseguendo un dry run (true) o meno (false). -
$level: un numero intero che rappresenta il livello da controllare ed eventualmente rimuovere. -
$email: una serie di e-mail da verificare rispetto al livello specificato. Esamineremo questo array
Con le nostre variabili impostate, siamo pronti per eseguire effettivamente la funzione. In vero stile WordPress, eseguiremo un ciclo.
Scrivere la funzione stessa
Iniziamo creando un ciclo foreach per scorrere tutte le e-mail nel nostro array $emails :
// Loop through emails foreach ( $emails as $email ) { // code coming soon } // end foreachQuindi, aggiungiamo un controllo condizionale:
// 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 Questo controllo garantisce che abbiamo un utente registrato con l'e-mail che stiamo controllando. Utilizza la funzione email_exists() per verificare se esiste un utente con quell'e-mail. Se non trova un utente con quell'e-mail, genera un avviso in modo che sappiamo sullo schermo del nostro terminale che l'e-mail non è stata trovata:
$ wp toptal remove_user [email protected] --dry-run Warning: The user [email protected] does not seem to exist. L'e-mail viene quindi archiviata $emails_not_existing per la visualizzazione in seguito. Quindi incrementiamo l'avviso totale di uno e continuiamo attraverso il ciclo fino all'e-mail successiva.
Se l'e-mail esiste, utilizzeremo le variabili $user_id e $level per verificare se l'utente ha accesso al livello. Memorizziamo il valore booleano risultante nella variabile $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 Come la maggior parte delle funzioni in questo esempio, questa function_to_check_membership_level() è fabbricata, ma la maggior parte dei plugin di appartenenza dovrebbe avere funzioni di supporto per ottenere queste informazioni.
Passiamo ora all'azione principale: rimuovere il livello dall'utente. Useremo una struttura if/else , che assomiglia a questa:
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 Se il valore di $has_level è "verità", il che significa che l'utente ha accesso al livello di appartenenza, vogliamo eseguire una funzione per rimuovere quel livello. In questo esempio, utilizzeremo la function_to_deactivate_membership_level() per eseguire questa azione.
Tuttavia, prima di rimuovere effettivamente il livello dall'utente, vogliamo racchiudere quella funzione in un controllo condizionale per vedere se si tratta effettivamente di un dry-run . Se lo è, non vogliamo rimuovere nulla, segnala solo che l'abbiamo fatto. Se non si tratta di un dry-run , andremo avanti e rimuoveremo il livello dall'utente, registreremo il nostro messaggio di successo sul terminale e continueremo a scorrere le e-mail.
Se, d'altra parte, il valore di $has_level è "false", il che significa che l'utente non ha accesso al livello di appartenenza, vogliamo registrare un avviso sul terminale, inviare l'e-mail $emails_without_level e continuare scorrendo le email.
Rifinitura e Reporting
Una volta terminato il ciclo, vogliamo registrare i nostri risultati sulla console. Se si trattava di una corsa a secco, vogliamo registrare un messaggio aggiuntivo sulla console:
if ( $dry_run ) { $dry_suffix = 'BUT, nothing really changed because this was a dry run:-).'; } Questo $dry-suffix verrà aggiunto agli avvisi e alle notifiche di successo che registriamo successivamente.
Alla fine, vogliamo registrare i nostri risultati come messaggi di successo e i nostri avvisi come messaggi di avviso. Lo faremo in questo modo:
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 ); } Si noti che stiamo usando i metodi di supporto WP_CLI::success e WP_CLI::warning . Questi sono forniti da WP-CLI per la registrazione delle informazioni sulla console. Puoi facilmente registrare le stringhe, che è ciò che facciamo qui, incluse le nostre $total_users_removed , $total_warnings e $dry_suffix .
Infine, se abbiamo accumulato avvisi durante il runtime dello script, vogliamo stampare tali informazioni sulla console. Dopo aver eseguito un controllo condizionale, convertiamo le variabili array $emails_not_existing e $emails_without_level in variabili stringa. Lo facciamo in modo da poterli stampare sulla console usando il WP_CLI::warning helper.
Aggiunta di una descrizione
Sappiamo tutti che i commenti sono utili per gli altri e per il nostro sé futuro, risalendo al nostro codice settimane, mesi o anche anni dopo. WP-CLI fornisce un'interfaccia di descrizioni brevi (shortdesc) e descrizioni lunghe (longdesc) che ci permette di annotare il nostro comando. Metteremo in cima al nostro comando, dopo che la classe TOPTAL_WP_CLI_COMMANDS è stata definita:
/** * 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 */ Nel longdesc, definiamo cosa ci aspettiamo che il nostro comando personalizzato riceva. La sintassi per shortdesc e longdesc è Markdown Extra. Nella sezione ## OPTIONS , definiamo gli argomenti che ci aspettiamo di ricevere. Se è richiesto un argomento, lo avvolgiamo in < > , e se è facoltativo, lo avvolgiamo in [ ] .
Queste opzioni vengono convalidate quando viene eseguito il comando; ad esempio, se tralasciamo il parametro email richiesto, otteniamo il seguente errore:
$ wp toptal remove_user --level=5 --dry-run Error: Parameter errors: missing --email parameter (Email of user to check against) La sezione ## EXAMPLES include un esempio di come potrebbe apparire il comando quando viene chiamato.
Il nostro comando personalizzato è ora completo. Puoi vedere il succo finale qui.
Un avvertimento e margini di miglioramento
È importante rivedere il lavoro che abbiamo svolto qui per vedere come il codice potrebbe essere migliorato, ampliato e rifattorizzato. Ci sono molte aree di miglioramento per questo script. Ecco alcune osservazioni sui miglioramenti che potrebbero essere apportati.
Occasionalmente, ho scoperto che questo script non rimuoverà tutti gli utenti che registra come "rimossi". Ciò è probabilmente dovuto al fatto che lo script viene eseguito più velocemente di quanto le query possano essere eseguite. La tua esperienza può variare, a seconda dell'ambiente e della configurazione in cui viene eseguito lo script. Il modo rapido per aggirare questo problema è eseguire ripetutamente con gli stessi input; alla fine si azzererà e segnalerà che nessun utente è stato rimosso.
Lo script potrebbe essere migliorato per attendere e convalidare che un utente sia stato rimosso prima di registrare l'utente come effettivamente rimosso. Ciò rallenterebbe l'esecuzione dello script, ma sarebbe più accurato e dovresti eseguirlo solo una volta.
Allo stesso modo, se vengono rilevati errori di questo tipo, lo script potrebbe generare errori per avvisare che un livello non è stato rimosso da un utente.
Un'altra area per migliorare lo script è consentire la rimozione di più livelli alla volta da un indirizzo e-mail. Lo script potrebbe rilevare automaticamente se sono presenti uno o più livelli e una o più e-mail da rimuovere. Mi sono stati forniti file CSV per livello, quindi ho dovuto eseguire solo un livello alla volta.
Potremmo anche rifattorizzare parte del codice per utilizzare operatori ternari invece dei controlli condizionali più dettagliati che abbiamo attualmente. Ho scelto di renderlo più facile da leggere per motivi di dimostrazione, ma sentiti libero di creare il tuo codice.
Nella fase finale, invece di stampare le email sulla console nella fase finale, potremmo anche esportarle automaticamente in un CSV o in un file di testo normale
Infine, non ci sono controlli per assicurarci di ottenere un numero intero per la variabile $level o un'e-mail o un elenco di e-mail separate da virgole nella variabile $emails . Attualmente, se qualcuno dovesse includere stringhe anziché numeri interi o nomi di accesso utente anziché e-mail, lo script non funzionerebbe (e non genererebbe errori). È possibile aggiungere controlli per numeri interi ed e-mail.
Idee per ulteriore automazione e ulteriore lettura
Come puoi vedere, anche in questo caso d'uso specifico, WP-CLI è abbastanza flessibile e potente da aiutarti a svolgere il tuo lavoro in modo rapido ed efficiente. Ti starai chiedendo: "Come posso iniziare a implementare WP-CLI nel mio flusso di sviluppo giornaliero e settimanale?"
Esistono diversi modi per utilizzare WP-CLI. Ecco alcuni dei miei preferiti:
- Aggiorna temi, plugin e core WP senza dover accedere al pannello di amministrazione.
- Esporta i database per il backup o esegui un rapido dump SQL se voglio testare una query SQL.
- Migrare i siti WordPress.
- Installa nuovi siti WordPress con dati fittizi o configurazioni di suite di plug-in personalizzate.
- Esegui checksum sui file core per assicurarti che non siano stati compromessi. (In realtà è in corso un progetto per espanderlo a temi e plug-in nel repository WP.)
- Scrivi il tuo script per controllare, aggiornare e mantenere gli host del sito (di cui ho scritto qui).
Le possibilità con WP-CLI sono praticamente illimitate. Ecco alcune risorse per farti andare avanti:
- Il sito principale di WP-CLI: http://wp-cli.org
- Comandi WP-CLI: https://developer.wordpress.org/cli/commands/
- Blog ufficiale di WP-CLI: https://make.wordpress.org/cli/
- Manuale WP-CLI: https://make.wordpress.org/cli/handbook/
- In WooCommerce? Scopri la WC-CLI: https://github.com/woocommerce/woocommerce/wiki/WC-CLI-Overview#woocommerce-commands
- Podcast Intervista a Daniel Bachhuber, manutentore del progetto: https://howibuilt.it/episode-28-daniel-bachhuber-wp-cli/
