Hook/Action per l'Aggiornamento dei Plugin WordPress? Dalla versione 3.9

20 mag 2014, 04:15:47
Visualizzazioni: 24.3K
Voti: 17

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.

3
Commenti

la risposta di @drzaus fornita lì non è una buona pratica.

Rens Tillmann Rens Tillmann
5 ago 2016 19:32:37

@RensTillmann a parte il fatto che questo è comunque indietro di 2 anni, la domanda/risposta collegata ha sostanzialmente la stessa risposta ma precede questa domanda di altri 2 anni, da qui il 'duplicato'.

drzaus drzaus
8 ago 2016 22:45:56
Tutte le risposte alla domanda 5
6
21

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' );
20 mag 2014 04:58:08
Commenti

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

user1915665 user1915665
20 mag 2014 05:20:11

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.

drzaus drzaus
9 set 2014 12:10:17

È 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.

Brian C Brian C
21 set 2014 03:26:26

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.

giraff giraff
1 set 2015 19:37:21

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.

doublesharp doublesharp
10 set 2015 19:53:03

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

Eugen Mihailescu Eugen Mihailescu
16 set 2015 09:46:18
Mostra i restanti 1 commenti
4

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).

Vedi riferimenti 1, 2, 3

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

  1. Hai il plugin versione 1.0
  2. Esegui la pagina di aggiornamento o l'aggiornamento automatico.
  3. La versione 2.0 del tuo plugin verrà scaricata ed estratta. L'hook upgrader_process_complete verrà chiamato.
  4. La versione 1.0 del tuo plugin verrà eseguita nell'hook upgrader_process_complete.
  5. Una volta completato, ricarica la pagina e l'hook plugins_loaded verrà chiamato.
  6. 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:

  1. Aggiorni tramite la pagina di aggiornamento.
  2. Aggiorni tramite la pagina dei plugin o dei temi.
  3. 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.

23 mar 2018 09:54:55
Commenti

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 user54141
26 ott 2021 22:10:21

@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.

vee vee
14 feb 2022 09:46:58

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 user54141
15 feb 2022 16:19:23

@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.

vee vee
15 feb 2022 17:28:53
3

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.

9 set 2014 12:25:32
Commenti

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/

Flimm Flimm
15 set 2017 13:49:59

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

random_user_name random_user_name
1 mar 2019 01:17:03

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.

user54141 user54141
26 ott 2021 22:06:01
0

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:

2 nov 2023 19:21:41
0

Puoi agganciarti ai filtri upgrader_pre_install e upgrader_post_install.

7 giu 2020 06:47:34