Hook/Acțiune pentru Actualizare Plugin WordPress? De la versiunea 3.9
Am căutat de mai multe ori acest subiect, dar căutările mele nu au dezvăluit multe lucruri în afară de cod personalizat care poate sau nu poate fi o practică bună în WordPress.
Începând cu cele mai recente versiuni (WordPress 3.9 "Smith"), a fost adăugat un hook pentru procesul de actualizare a plugin-urilor? Întreb acest lucru pentru că este o necesitate foarte de bază, dar nu o văd adăugată în codex (încă). Dacă nu, care este practica comună și cea mai bună pe care o folosesc dezvoltatorii?
EDITARE: Pentru clarificare, nu vorbesc despre activare, ci despre actualizare, astfel încât, dacă există modificări în baza de date sau în alte aspecte, acestea să poată fi abordate.

Cred că nu a fost adăugată nicio acțiune. Poți verifica detaliile versiunii pentru orice versiune și vedea dacă au fost adăugate acțiuni noi.
Modul WordPress de a rula cod la actualizarea pluginului este descris aici:
Modul corect de a gestiona o actualizare este să rulezi procedura de actualizare doar atunci când este necesar. În mod ideal, ai stoca o „versiune” în opțiunea de bază de date a pluginului tău și apoi o versiune în cod. Dacă acestea nu se potrivesc, ai putea să declanșezi procedura de actualizare, iar apoi să setezi opțiunea din baza de date să fie egală cu versiunea din cod. Așa gestionează multe pluginuri actualizările și așa funcționează și nucleul WordPress.
și cu un exemplu de cod aici:
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' );

Mulțumesc - atunci voi folosi pur și simplu această metodă. WP chiar ar trebui să adauge un action pentru asta :D

tehnic vorbind, ar trebui să folosești register_activation_hook
, deoarece în majoritatea cazurilor un plugin este dezactivat/activat ori de câte ori îl actualizezi din admin. Folosirea lui plugins_loaded
va face verificarea ta la fiecare încărcare de pagină (inclusiv pe frontend). A fost discuție despre introducerea unui register_update_hook
, dar a fost marcat ca WONTFIX acum ceva timp. Discuția de acolo este utilă.

Este important să înțelegem că o actualizare în masă a plugin-urilor NU rulează hook-urile de activare - AR TREBUI să o facă, dar nu o face în versiunea 3.9.2. Prin "actualizare în masă" mă refer la o actualizare făcută din pagina de actualizări din Dashboard. Actualizările individuale făcute din pagina plugin-ului rulează hook-urile fără probleme.

Problema este că plugin-urile pot fi actualizate și prin FTP, ceea ce înseamnă că hook-ul nu va fi declanșat în niciun caz. De aceea trebuie să apelezi la opțiunea stocată în baza de date.

Pentru a completa comentariul lui @giraff, același lucru este valabil și pentru cei care își gestionează codul cu sisteme de control al versiunilor precum SVN sau Git. Din acest motiv, acest răspuns este cea mai bună metodă de a gestiona actualizările.

Nu sunt sigur dacă la asta te-ai referit, dar dacă cauți niște hook-uri declanșate înainte și după actualizare, atunci aruncă o privire la upgrader_pre_install, respectiv upgrader_post_install

Începând cu WordPress 3.9, poți utiliza hook-ul upgrader_process_complete
.
Acest hook va fi declanșat atunci când procesul de actualizare este finalizat (plugin-urile și temele sunt actualizate).
Iată un exemplu de cod:
<?php
/**
* Plugin Name: Test plugin 1
* Plugin URI: https://rundiz.com
* Description: Un plugin foarte simplu pentru testare. Acest plugin nu face nimic.
* 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);
/**
* Procesul de actualizare completat.
*
* @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)
{
// obține versiunea curentă a plugin-ului. ( 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'
) {
// dacă plugin-urile au fost actualizate.
$this_plugin = plugin_basename(__FILE__);
$this_plugin_updated = false;
if (array_key_exists('plugins', $hook_extra)) {
// dacă actualizarea în masă a plugin-urilor (în pagina de actualizare)
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)) {
// dacă actualizarea normală a plugin-ului sau prin actualizare automată.
if ($this_plugin === $hook_extra['plugin']) {
$this_plugin_updated = true;
}
}
if ($this_plugin_updated === true) {
// dacă acest plugin tocmai a fost actualizat.
// efectuează-ți sarcinile aici.
// NU procesa nimic din noua versiune de cod aici, deoarece va funcționa pe versiunea veche a plugin-ului.
// citește din nou!! codul rulat aici nu este noua versiune (tocmai actualizată) ci versiunea anterioară.
file_put_contents(WP_CONTENT_DIR . '/test.txt', 'v'.$plugin_version."\r\n", FILE_APPEND);
// setează transient pentru a-l rula mai târziu.
set_transient('testplugin_just_updated', 1);
}
} elseif (
array_key_exists('type', $hook_extra) &&
$hook_extra['type'] == 'theme'
) {
// dacă temele au fost actualizate.
// la fel ca la plugin, actualizarea în masă a temelor va fi setată în $hook_extra['themes'] ca 'theme1', 'theme2'.
// actualizarea normală sau prin actualizare automată va fi setată în $hook_extra['theme'] ca 'theme1'.
}
}// endif; $hook_extra
}// testplugin_upgrade_completed
add_action('plugins_loaded', 'testplugin_pluginloaded');
/**
* Rulează odată ce plugin-ul este încărcat (la fiecare încărcare de pagină).
*/
function testplugin_pluginloaded()
{
// obține versiunea curentă a plugin-ului. ( 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')) {
// dacă a fost marcat în transient că acest plugin tocmai a fost actualizat și utilizatorul curent este administrator.
// poți folosi noua versiune de cod aici.
file_put_contents(WP_CONTENT_DIR . '/test-update-by-transient.txt', 'v'.$plugin_version."\r\n", FILE_APPEND);
// codul tău de actualizare aici.
// șterge transient-ul când este gata pentru a nu permite rularea acestui cod din nou.
delete_transient('testplugin_just_updated');
}
}// testplugin_pluginloaded
Hook-ul upgrader_process_complete
va rula cu versiunea curentă de cod în timp ce plugin-ul/tema este actualizată. Nu folosește noua versiune.
Scenariu
- Ai plugin-ul versiunea 1.0
- Rulezi pagina de actualizare sau actualizarea automată.
- Plugin-ul tău versiunea 2.0 va fi descărcat și extras. Hook-ul
upgrader_process_complete
va fi apelat. - Plugin-ul tău versiunea 1.0 va rula în hook-ul
upgrader_process_complete
. - Odată finalizat, reîncarcă pagina și hook-ul
plugins_loaded
va fi apelat. - Plugin-ul tău versiunea 2.0 rulează în hook-ul
plugins_loaded
. (Plugin-ul trebuie să fie activat.)
Acestea au fost deja explicate în codul postat anterior (înainte de editare), dar poate nu suficient de clar sau greu de observat.
Hook-ul upgrader_process_complete
este creat pentru aceasta (te rog citește în link-ul de referință 3). Pentru a rula după ce actualizarea este finalizată.
Poți folosi hook-ul plugins_loaded
cu codul din răspunsul acceptat. A funcționat și este mai scurt sau poți avea o idee mai bună de utilizat cu hook-ul upgrader_process_complete
.
Hook-ul upgrader_process_complete
va funcționa când:
- Actualizezi prin pagina de actualizare.
- Actualizezi prin pagina de plugin-uri sau teme.
- Actualizezi prin actualizare automată sau WP Cron.
Codul de mai sus nu funcționează când actualizezi plugin-ul sau tema prin FTP deoarece nu poate detecta opțiunea transient. În acest caz, răspunsul acceptat este singura opțiune bună pentru tine.

Acest hook pare bun la prima vedere, dar dacă verifici codex-ul, există un avertisment care spune că rulează codul din versiunea anterioară a pluginului. Acest lucru se întâmplă deoarece acest hook nu rulează după întregul proces de actualizare. De fapt, rulează după ce descărcarea este finalizată și înainte ca vechea versiune să fie ștearsă.

@user54141 Da, folosește codul din versiunea anterioară.
De aceea folosesc set_transient()
pentru a marca că acest plugin tocmai a fost actualizat și get_transient()
după hook-ul plugins_loaded
(care funcționează la reîncărcarea paginii) pentru a verifica dacă într-adevăr a fost actualizat, apoi rulez noul cod.
Hook-ul plugins_loaded
va funcționa după reîncărcarea paginii, iar transient-ul va fi verificat pentru a confirma că plugin-ul a fost actualizat.
Odată ce noul cod actualizat a fost rulat, acel transient va fi șters, astfel încât să poată rula o singură dată după actualizarea pluginului.

Deoarece această soluție verifică în final dacă plugin-ul a fost actualizat pe plugins_loaded
, este mult mai simplu să folosești răspunsul selectat, care face același lucru cu mult mai puțin cod.

@user54141 Da, codul din răspunsul acceptat este foarte bun. Sunt de acord. Cu toate acestea, acest hook este încă util pentru cineva care ar putea avea o idee mai bună decât mine pentru a-l folosi atunci când actualizarea pluginului este finalizată. Aceasta este scopul hook-ului upgrader_process_complete
.

Din discuția în care s-a decis să nu se adauge un hook/funcție personalizat specific pentru actualizare, reiese că "majoritatea oamenilor" (acum 4 ani) folosesc register_activation_hook
, deoarece este apelat atunci când un plugin este actualizat prin pagina de administrare; majoritatea exemplelor pe care le-am văzut de atunci urmează această tendință.
Pentru majoritatea cazurilor de utilizare, aș sugera să nu folosiți hook-ul prin plugins_loaded
, deoarece ar fi apelat la fiecare încărcare de pagină. Excepția de la această regulă este menționată în discuție: căile de actualizare prin FTP/SVN sunt 'cazuri marginale', deoarece WordPress nu ar avea un mecanism pentru a ști că plugin-ul a fost modificat, caz în care răspunsul anterior ar putea fi mai relevant.
Consultați https://gist.github.com/zaus/c08288c68b7f487193d1 pentru un exemplu de 'cadru simplu' folosind register_activation_hook
.

register_activation_hook
nu este garantat să ruleze la actualizări, vezi https://make.wordpress.org/core/2010/10/27/plugin-activation-hooks-no-longer-fire-for-updates/

Foarte important - NU utilizați plugins_loaded
- rulează la fiecare încărcare și poate fi solicitant/încet.

register_activation_hook
nu mai rulează la actualizări. Aceasta a fost o inconsistență pe care au reparat-o. Acum este declanșat doar la activarea plugin-urilor.
Folosirea plugins_loaded
este recomandată în codex. Nu este lent pentru că WP face o singură interogare pentru toate opțiunile site-ului și le stochează în cache, deci chiar dacă utilizați get_option()
pentru a verifica versiunea salvată în baza de date, nu se face efectiv o cerere către baza de date. Doar verifică cererea din cache.

În timp ce căutam ceva similar în noiembrie 2023, am decis să împărtășesc această sugestie: filtrul update_plugins_{$hostname}
a fost introdus în WordPress începând cu versiunea 5.8.0.
Această funcționalitate funcționează doar dacă plugin-ul utilizează antetul Update URI
. Deci, dacă dezvolți un plugin, poți include antetul Update URI
în partea de sus a fișierului principal, cu valoarea fiind endpoint-ul tău JSON. Apoi, vei folosi filtrul înlocuind {hostname}
cu numele de gazdă al acelui URL. De exemplu, să presupunem că acesta este fișierul meu de plugin personalizat, situat în /wp-content/plugins/my-custom-plugin/my-custom-plugin.php
, iar în partea de sus am:
/**
* Plugin Name: My Custom Plugin
* Version: 1.0.0
* Author: AuRise Creative
* Update URI: https://aurisecreative.com/update-my-custom-plugin/
*/
Acum aș putea folosi acest filtru pentru a verifica actualizările plugin-ului și a prelua datele de actualizare (dacă există) pentru acel plugin.
/**
* Verifică actualizările pentru plugin
*
* @param array|false $update Datele de actualizare ale plugin-ului cu cele mai recente detalii. Valoare implicită false.
* @param array $plugin_data Antetele plugin-ului.
* @param string $plugin_file Numele fișierului plugin-ului.
* @param string $locales Locale instalate pentru căutarea traducerilor.
*
* @return array|false Un array asociativ cu datele de actualizare în caz de succes. False în caz contrar.
*/
function prefix_check_for_plugin_updates($update, $plugin_data, $plugin_file, $locales = '')
{
// Efectuează operații
return $update;
}
add_filter('update_plugins_aurisecreative.com', 'prefix_check_for_plugin_updates', 10, 4);
Din păcate, această funcționalitate funcționează doar pentru plugin-urile care utilizează acest antet, deci cel mai probabil pentru plugin-urile premium.
Surse:

Puteți interveni în filtrele upgrader_pre_install și upgrader_post_install.
