Veraltete Funktionen in einer Plugin-Klasse

8

Ich aktualisiere eines meiner Plugins und bin ein wenig mit veralteten Funktionen beschäftigt.

Ursprünglich hatte mein Plugin eine globale Variable und die Hauptklasse des Plugins wurde instanziiert und in der globalen Variablen gespeichert. Auf diese Weise können Benutzer die globale Funktion verwenden, um auf Funktionen in der Plugin-Klasse zuzugreifen.

$GLOBALS['my_custom_plugin'] = new my_custom_plugin();

Dann hatte ich zum Beispiel in meinen FAQ Code, der zeigte, wie man eine der Funktionen meiner Klasse aus einem bestimmten Hook entfernt und zu einem anderen Hook hinzufügt:

function move_input(){ 
    global $my_custom_plugin;
    remove_action( 'before_main_content', array( $my_custom_plugin, 'display_input') );
    add_action( 'after_main_content', array( $my_custom_plugin, 'display_input' ) );
}
add_action( 'wp_head' , 'move_input' );

In meinem Update wurde die display_input()Funktion in eine andere Klasse verschoben und ich möchte die Leute wissen lassen, wie sie darauf zugreifen können. Ich habe versucht, die ursprüngliche Funktion (in der Haupt-Plugin-Klasse) durch den folgenden Verfallshinweis zu ersetzen:

public function display_input() { 
    _deprecated_function( 'display_price', '2.0', 'my_custom_plugin()->display->display_input' );
    return $this->display->display_input();
}

Die Funktionen add_actionund remove_actionscheinen jedoch nicht den Verfallshinweis auszulösen. Seltsamerweise verursacht das vollständige Entfernen der Funktion auch keinen Fehler, obwohl er array( $my_custom_plugin, 'display_input')nicht vorhanden ist.

Wenn jemand versucht, direkt auf die Funktion zuzugreifen:

$my_custom_plugin->display_input();

Dann sehe ich die Debug-Hinweise. Ist das das erwartete Ergebnis für _deprecated_function()? oder fehlt mir etwas Ist es möglich, einen Debug-Hinweis anzuzeigen, wenn jemand versucht, eine Aktion mithilfe einer veralteten Funktion zu entfernen oder hinzuzufügen?

Aktualisieren

Mir wurde klar, dass ich die Debug-Meldung für das einfach nicht sah, add_actionda ich sie ziemlich tief auf der Seite hinzufügte. #facepalm! Ich sehe jedoch immer noch keinen Debug-Hinweis für die remove_action.

Helgatheviking
quelle
Interessant call_user_func(function(){trigger_error('hello?');});funktioniert, aber es schlägt in einem Rückruf fehl, der pro add_action registriert wurde.
Fuxia
Vorbereitung auf Facepalm, aber ist das eine Frage oder eine Aussage?
Helgatheviking
Nur ein Testergebnis. Ich bin auch überrascht.
Fuxia
Ok, also habe ich nicht wirklich übersehen etwas, das einfach ist , wie es ist ?
Helgatheviking
2
Oh, Query Monitor hat die Nachricht in meinem Setup ausgeblendet. Die Nachricht für add_action()war tatsächlich da. remove_action()kann nicht so gehandhabt werden.
Fuxia

Antworten:

2

Nicht vorhandene Rückrufe

Eines der schönen Dinge ist, dass weder do_action()noch apply_filters()ein Fehler ausgelöst wird, wenn kein Rückruf vorhanden ist. Dies bedeutet, dass dies der sicherste Weg ist, Plugin-Daten in Vorlagen einzufügen: Wenn ein Plugin deaktiviert ist und do_action()/ apply_filters()oder der Rückruf nicht im globalen $wp_filtersArray gefunden wird, geschieht nichts.

Fehlerausgabe

Wenn Sie jetzt remove_filter()die Funktion / Methode aufrufen , die den Rückruf ursprünglich verknüpft hat, wird der Rückruf einfach aus dem globalen Array entfernt, was bedeutet, dass der Rückruf nie ausgeführt wird, da er nicht mehr registriert ist.

Die Lösung ist einfach: Entfernen Sie den Rückruf, nachdem er ausgelöst wurde, indem Sie ihn aus dem Rückruf selbst entfernen.

Rückrufe entfernen

Wir alle wissen, dass das WPs-Plugin "API" beim Entfernen ein Problem darstellt. Das Problem ist hauptsächlich das seltsame Konstrukt, Schlüssel im global $wp_filter;Array mit "eindeutigen" Namen zu versehen . Eine sehr einfache Lösung besteht darin, nur __METHOD__Filter zu verwenden und aufzurufen, die Sie im statischen Kontext entfernen möchten:

class FOoooo
{
    public function __construct()
    {
        add_filter( 'hook', array( __CLASS__, 'bar' ) );
    }
    public static function bar( $baz )
    {
        remove_filter( current_filter(), __METHOD__ );

        return $baz;
    }
}

Das ist zwar nicht schön, aber für einige Anwendungsfälle eine Art Lösung . Aber denken Sie nicht einmal daran, einen Verschluss zu entfernen.

Oben entfernt nur den Rückruf, führt ihn trotzdem aus. Trotzdem können Sie weiter gehen und remove_all_actions()(oder remove_all_filters()) verwenden.

// Check if a callback is attached and tell about the deprecated stuff
if ( has_action( 'before_main_content' ) )
    _deprecated_function( 'display_price', '2.0', 'my_custom_plugin()->display->display_input' );
// Remove the callback
remove_all_actions( 'before_main_content' );

Sie können vielleicht sogar noch weiter gehen, den Rückruf aus dem globalen Filterarray extrahieren und ihn erneut an den neuen Hook / Filter anhängen (sofern diese kompatibel sind).

Kaiser
quelle
Danke Kaiser! Dies ist eine großartige und detaillierte Antwort. Ich werde versuchen, es morgen zu testen.
Helgatheviking