Hook/Action per l'Aggiornamento dei Plugin WordPress? Dalla versione 3.9
Ho fatto diverse ricerche su questo argomento, ma le mie ricerche non rivelano molto, se non codice personalizzato che potrebbe essere o meno una buona pratica WordPress.
A partire dalle ultime versioni (WordPress 3.9 "Smith"), è stato aggiunto un hook al processo di aggiornamento dei plugin? Lo chiedo perché è un'esigenza molto basilare, eppure non lo vedo aggiunto al codex (per ora). In caso contrario, quali sono le pratiche comuni e migliori che gli sviluppatori utilizzano?
MODIFICA: Solo per chiarire, non mi riferisco all'attivazione, ma all'aggiornamento, in modo che se ci sono modifiche nel database o altro possano essere gestite.

Non credo sia stata aggiunta un'azione. Puoi controllare i dettagli della versione per qualsiasi versione e vedere eventuali nuove azioni aggiunte.
Il modo WordPress di eseguire codice all'aggiornamento del plugin è quello descritto qui:
Il modo corretto per gestire un percorso di aggiornamento è eseguire una procedura di aggiornamento solo quando è necessario. Idealmente, dovresti memorizzare una "versione" nell'opzione del database del tuo plugin, e poi una versione nel codice. Se non corrispondono, dovresti attivare la tua procedura di aggiornamento, e poi impostare l'opzione del database in modo che corrisponda alla versione nel codice. Questo è come molti plugin gestiscono gli aggiornamenti, ed è anche come funziona il core.
e con esempio di codice qui:
function myplugin_update_db_check() {
global $jal_db_version;
if (get_site_option( 'jal_db_version' ) != $jal_db_version) {
jal_install();
}
}
add_action( 'plugins_loaded', 'myplugin_update_db_check' );

Grazie - utilizzerò semplicemente quel metodo allora. WP dovrebbe davvero aggiungere un'azione per questo :D

tecnicamente dovresti usare register_activation_hook
, poiché nella maggior parte dei casi un plugin viene disattivato/attivato ogni volta che lo aggiorni dall'amministrazione. Usare l'hook plugins_loaded
eseguirà il tuo controllo ad ogni caricamento di pagina (incluso il frontend). Si era parlato di introdurre register_update_hook
, ma è stato marchiato come WONTFIX tempo fa. La discussione lì è utile.

È importante capire che un aggiornamento massivo di plugin NON esegue gli hook di attivazione - DOVREBBE, ma non lo fa nella 3.9.2. Con "aggiornamento massivo" intendo un aggiornamento effettuato dalla pagina degli aggiornamenti nella Dashboard. Gli aggiornamenti individuali effettuati dalla pagina del plugin eseguono gli hook senza problemi.

Il fatto è che i plugin possono anche essere aggiornati via FTP, il che significa che l'hook non verrà attivato in ogni caso. Ecco perché è necessario ricorrere all'opzione memorizzata nel database.

Per ampliare il commento di @giraff, lo stesso vale per chi gestisce il codice con sistemi di controllo versione come SVN o Git. Per questo motivo, questa risposta è il modo migliore per gestire gli aggiornamenti.

Non sono sicuro se è questo che intendevi, ma se stai cercando degli hook attivati prima e dopo l'aggiornamento, dai un'occhiata a upgrader_pre_install rispettivamente upgrader_post_install

Da WordPress 3.9 puoi usare l'hook upgrader_process_complete
.
Questo hook viene attivato quando il processo di aggiornamento è completato (plugin e temi sono aggiornati).
Ecco un esempio di codice:
<?php
/**
* Plugin Name: Test plugin 1
* Plugin URI: https://rundiz.com
* Description: Un plugin molto semplice per testing. Questo plugin non fa nulla.
* Version: 0.1.8
* Author: Vee Winch
* Author URI: http://rundiz.com
* License: MIT
* License URI: https://opensource.org/licenses/MIT
* Text Domain: test-plugin1
* Domain Path:
*/
add_action('upgrader_process_complete', 'testplugin_upgrade_completed', 10, 2);
/**
* Processo di aggiornamento completato.
*
* @see \WP_Upgrader::run() (wp-admin/includes/class-wp-upgrader.php)
* @param \WP_Upgrader $upgrader_object
* @param array $hook_extra
*/
function testplugin_upgrade_completed(\WP_Upgrader $upgrader_object, $hook_extra)
{
// ottieni la versione corrente del plugin ( https://wordpress.stackexchange.com/a/18270/41315 )
if(!function_exists('get_plugin_data')){
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
}
// https://developer.wordpress.org/reference/functions/get_plugin_data/
$plugin_data = get_plugin_data(__FILE__);
$plugin_version = ($plugin_data['Version'] ?? 'unknown.version');
unset($plugin_data);
if (
is_array($hook_extra) &&
array_key_exists('action', $hook_extra) &&
$hook_extra['action'] == 'update'
) {
if (
array_key_exists('type', $hook_extra) &&
$hook_extra['type'] == 'plugin'
) {
// se sono stati aggiornati i plugin.
$this_plugin = plugin_basename(__FILE__);
$this_plugin_updated = false;
if (array_key_exists('plugins', $hook_extra)) {
// se aggiornamento multiplo di plugin (nella pagina di aggiornamento)
foreach ($hook_extra['plugins'] as $each_plugin) {
if ($each_plugin === $this_plugin) {
$this_plugin_updated = true;
break;
}
}// endforeach;
unset($each_plugin);
} elseif (array_key_exists('plugin', $hook_extra)) {
// se aggiornamento normale o automatico.
if ($this_plugin === $hook_extra['plugin']) {
$this_plugin_updated = true;
}
}
if ($this_plugin_updated === true) {
// se questo plugin è stato appena aggiornato.
// esegui qui le tue operazioni.
// NON elaborare nulla dal nuovo codice qui, perché funzionerà sulla vecchia versione del plugin.
// leggi di nuovo!! il codice eseguito qui NON è la nuova versione (appena aggiornata) ma la versione precedente.
file_put_contents(WP_CONTENT_DIR . '/test.txt', 'v'.$plugin_version."\r\n", FILE_APPEND);
// imposta un transient per eseguirlo più tardi.
set_transient('testplugin_just_updated', 1);
}
} elseif (
array_key_exists('type', $hook_extra) &&
$hook_extra['type'] == 'theme'
) {
// se sono stati aggiornati i temi.
// come per i plugin, l'aggiornamento multiplo avrà i nomi in $hook_extra['themes'] come 'theme1', 'theme2'.
// l'aggiornamento normale o automatico avrà il nome in $hook_extra['theme'] come 'theme1'.
}
}// endif; $hook_extra
}// testplugin_upgrade_completed
add_action('plugins_loaded', 'testplugin_pluginloaded');
/**
* Eseguito al caricamento del plugin (ad ogni caricamento di pagina).
*/
function testplugin_pluginloaded()
{
// ottieni la versione corrente del plugin ( https://wordpress.stackexchange.com/a/18270/41315 )
if(!function_exists('get_plugin_data')){
require_once(ABSPATH . 'wp-admin/includes/plugin.php');
}
// https://developer.wordpress.org/reference/functions/get_plugin_data/
$plugin_data = get_plugin_data(__FILE__);
$plugin_version = ($plugin_data['Version'] ?? 'unknown.version');
unset($plugin_data);
if (get_transient('testplugin_just_updated') && current_user_can('manage_options')) {
// se è stato marcato nel transient che questo plugin è appena stato aggiornato e l'utente corrente è un admin.
// qui puoi usare il nuovo codice della versione.
file_put_contents(WP_CONTENT_DIR . '/test-update-by-transient.txt', 'v'.$plugin_version."\r\n", FILE_APPEND);
// il tuo codice di aggiornamento qui.
// elimina il transient al termine per evitare che questo codice venga eseguito di nuovo.
delete_transient('testplugin_just_updated');
}
}// testplugin_pluginloaded
L'hook upgrader_process_complete
verrà eseguito con la versione corrente del codice mentre il plugin/tema sta aggiornando. Non utilizza la nuova versione.
Scenario
- Hai il plugin versione 1.0
- Esegui la pagina di aggiornamento o l'aggiornamento automatico.
- La versione 2.0 del tuo plugin verrà scaricata ed estratta. L'hook
upgrader_process_complete
verrà chiamato. - La versione 1.0 del tuo plugin verrà eseguita nell'hook
upgrader_process_complete
. - Una volta completato, ricarica la pagina e l'hook
plugins_loaded
verrà chiamato. - La versione 2.0 del tuo plugin viene eseguita nell'hook
plugins_loaded
. (Il plugin deve essere attivato.)
Questo è già spiegato nel codice che ho pubblicato prima (prima della modifica) ma forse non era chiaro o difficile da vedere.
L'hook upgrader_process_complete
è creato per questo (leggi nel link di riferimento 3). Per eseguire dopo il completamento dell'aggiornamento.
Puoi usare l'hook plugins_loaded
con il codice nella risposta accettata. Funziona ed è più breve oppure puoi avere altre idee migliori da usare con l'hook upgrader_process_complete
.
L'hook upgrader_process_complete
funzionerà quando:
- Aggiorni tramite la pagina di aggiornamento.
- Aggiorni tramite la pagina dei plugin o dei temi.
- Aggiorni tramite aggiornamento automatico o WP Cron.
Il codice sopra non funziona quando aggiorni plugin o temi via FTP perché non può rilevare l'opzione transient. In questo caso, la risposta accettata è l'unica opzione migliore per te.

Questo hook sembra buono a prima vista, ma se controlli il codex, c'è un avviso che dice che esegue il codice dalla versione precedente del plugin. Questo perché questo hook non viene eseguito dopo l'intero processo di aggiornamento. In realtà viene eseguito dopo il completamento del download e prima che la vecchia versione venga persino eliminata.

@user54141 Sì, utilizza il codice dalla versione precedente.
Ecco perché uso set_transient()
per marcare che questo plugin è stato appena aggiornato e uso get_transient()
dopo l'hook plugins_loaded
(funziona quando la pagina viene ricaricata) per verificare se è stato effettivamente aggiornato e quindi eseguire il nuovo codice.
L'hook plugins_loaded
funzionerà dopo il ricaricamento della pagina e il transient verificherà che il plugin sia stato appena aggiornato.
Una volta che il nuovo codice aggiornato è stato eseguito, eliminerà quel transient in modo che possa essere eseguito una sola volta dopo l'aggiornamento del plugin.

Poiché questa soluzione alla fine verifica se il plugin è stato aggiornato su plugins_loaded, è molto più semplice utilizzare la risposta selezionata che fa la stessa cosa con molto meno codice.

@user54141 Sì, il codice della risposta accettata è molto buono. Sono d'accordo. Tuttavia questo hook è ancora utile per qualcuno che potrebbe avere un'idea migliore della mia per utilizzarlo quando l'aggiornamento del plugin è completato. Questo è lo scopo dell'hook upgrader_process_complete
.

Dalla discussione dove hanno deciso di non aggiungere un hook/funzione specifica per gli aggiornamenti, sembra che "la maggior parte delle persone" (a partire da 4 anni fa) utilizzi register_activation_hook
, poiché viene chiamato quando un plugin viene aggiornato tramite la pagina di amministrazione; la maggior parte degli esempi che ho visto da allora segue questa tendenza.
Per la maggior parte degli utilizzi, suggerirei di non agganciarsi tramite plugins_loaded
, poiché verrebbe chiamato ad ogni caricamento di pagina. L'eccezione a questa regola è menzionata nella discussione: i percorsi di aggiornamento tramite FTP/SVN sono "casi limite", poiché WordPress non avrebbe un meccanismo per sapere che il plugin è stato modificato, nel qual caso la risposta precedente potrebbe essere più rilevante.
Vedi https://gist.github.com/zaus/c08288c68b7f487193d1 per un esempio di "semplice framework" che utilizza register_activation_hook
.

register_activation_hook
non è garantito che venga eseguito durante gli aggiornamenti, vedi https://make.wordpress.org/core/2010/10/27/plugin-activation-hooks-no-longer-fire-for-updates/

Assolutamente - NON usare plugins_loaded
- viene eseguito ad ogni caricamento e può essere oneroso/lento.

register_activation_hook
non viene più eseguito durante gli aggiornamenti. Era un'incoerenza che hanno corretto. Ora viene attivato solo durante l'attivazione dei plugin.
L'uso di plugins_loaded
è raccomandato nel codex. Non è lento perché WordPress esegue una singola query per tutte le opzioni del sito e le memorizza nella cache, quindi anche se usi get_option()
per verificare la versione salvata nel database, non viene effettivamente fatta una richiesta al DB. Viene solo controllata la richiesta memorizzata nella cache.

Mentre cercavo qualcosa di correlato a novembre 2023, ho pensato di condividere questo suggerimento: il filtro update_plugins_{$hostname}
è stato introdotto nella versione 5.8.0 di WordPress.
Questa funzionalità funziona solo se il plugin utilizza l'intestazione Update URI
. Quindi, se stai creando un plugin, puoi includere l'intestazione Update URI
all'inizio del file principale con il valore che punta al tuo endpoint JSON. Poi dovrai agganciarti al filtro sostituendo {hostname}
con il nome host di quell'URL. Ad esempio, supponiamo che questo sia il mio file plugin personalizzato situato in /wp-content/plugins/my-custom-plugin/my-custom-plugin.php
e ho l'intestazione qui:
/**
* Plugin Name: My Custom Plugin
* Version: 1.0.0
* Author: AuRise Creative
* Update URI: https://aurisecreative.com/update-my-custom-plugin/
*/
Ora posso agganciarmi agli aggiornamenti del plugin per recuperare i dati di aggiornamento (se presenti) per quel plugin.
/**
* Controlla gli aggiornamenti del Plugin
*
* @param array|false $update I dati di aggiornamento del plugin con gli ultimi dettagli. Default false.
* @param array $plugin_data Intestazioni del plugin.
* @param string $plugin_file Nome file del plugin.
* @param string $locales Lingue installate per cercare traduzioni.
*
* @return array|false Un array associativo con i dati di aggiornamento in caso di successo. False altrimenti.
*/
function prefix_check_for_plugin_updates($update, $plugin_data, $plugin_file, $locales = '')
{
// Fai qualcosa
return $update;
}
add_filter('update_plugins_aurisecreative.com', 'prefix_check_for_plugin_updates', 10, 4);
Sfortunatamente, questo funziona solo per i plugin che utilizzano l'intestazione, quindi molto probabilmente nei plugin premium.
Fonti:

Puoi agganciarti ai filtri upgrader_pre_install e upgrader_post_install.
