Generieren Sie ruhende Hook-Referenzen

10

Es scheint, dass sich viele Plugin-Entwickler die Zeit nehmen, Filter- / Aktions-Hooks hinzuzufügen, damit Benutzer die Funktionalität ihrer Produkte optimieren können. Was großartig ist, aber was sie oft nicht tun, ist eine Liste von Hooks und wie viele Argumente sie nehmen.

Hat jemand die beste automatisierte Möglichkeit gefunden, auf ein Plugin- (oder Theme-) Verzeichnis zu verweisen und eine Liste aller verfügbaren Hooks anzuzeigen?

Ich habe anscheinend einige Plugins, die nach Hooks suchen, aber soweit ich das beurteilen kann, zeigen sie Ihnen, welche tatsächlich aufgerufen werden, um eine bestimmte Seite zu rendern. Was ich bekomme, kann praktisch sein. Aber manchmal, wenn ich weiß, dass ich mit einem bestimmten Plugin interagiere, möchte ich jeden Ort kennen, an dem ich eine Aktion oder einen Filter einbinden kann.

Was ich also wirklich suche, ist etwas, das bei einem Plugin-Stammverzeichnis eine Liste erstellt, in der jedes Element Folgendes enthält:

  • Etikett
  • Typ (Aktion oder Filter)
  • Anzahl der Argumente
  • wo es in der Quelle (via do_action()oder apply_filter()) genannt wird

Ein Skript wäre großartig, da dies vermutlich das Ganze gut HTMLifizieren und mir für jedes Plugin direkt in der Admin-Benutzeroberfläche zeigen könnte. Aber auch ein Befehlszeilenskript, das eine nützliche statische Datei ausgibt, wäre großartig.

Yonatron
quelle
Also, was ist die Frage? Wenn Sie nach einer Plugin-Empfehlung suchen, dann ist sie hier nicht zum Thema
Mark Kaplun
Tut mir leid, ich möchte nicht zu weit in das Unkraut der WordPress-Entwicklungsmeta vordringen, aber a) Ich bin neu hier und habe nicht bemerkt, dass es OT ist, nach Plugin-Empfehlungen zu fragen. Ich könnte… einige Meinungen… dazu haben, aber trotzdem hätte ich das zuerst realisieren sollen. b) OTOH, ich versuche nur, eine Lösung für meine Frage zu finden, ob ein vorhandenes Plugin oder Shell-Skript oder etwas von Grund auf neu. Die Frage ist also ausschließlich eine Plugin-Empfehlungsanfrage!
Yonatron
Nun, es scheint, als hätten alle anderen Spaß, also wird kein Schaden angerichtet. Mein "Einwand" gegen die Frage war eigentlich eher, dass es sich um eine Textanalyse handelt, die für Leute interessant ist, die gerne Software im Compiler-Stil schreiben, aber sehr wenig mit der tatsächlichen WordPress-Codierung zu tun haben. Für die Aufzeichnung werden sogar Fragen, die sich auf wordpress.org beziehen, wie das Einreichen eines Plugins, normalerweise als nicht zum Thema gehörend eingestuft.
Mark Kaplun

Antworten:

6

Es gibt kein Skript oder Plugin, von dem ich weiß, dass es das tut, was Sie wollen. Wie Sie bereits angegeben haben, gibt es Skripte ( auch globale Variablen ), mit denen Sie Filter und Aktionen drucken können, die derzeit verwendet werden.

In Bezug auf ruhende Filter und Aktionen habe ich zwei sehr grundlegende Funktionen geschrieben ( mit etwas Hilfe hier und da ), die alle apply_filtersund do_actionInstanzen in einer Datei finden und dann ausdrucken

GRUNDLAGEN

  • Wir verwenden das RecursiveDirectoryIterator, RecursiveIteratorIteratorund RegexIteratorKlassen PHP alle die PHP - Dateien in einem Verzeichnis zu erhalten. Als Beispiel habe ich auf meinem localhost verwendetE:\xammp\htdocs\wordpress\wp-includes

  • Wir werden dann die Dateien durchlaufen und preg_match_allalle Instanzen von apply_filtersund suchen und zurückgeben ( ) do_action. Ich habe es so eingerichtet, dass es mit verschachtelten Instanzen von Klammern und auch mit möglichen Leerzeichen zwischen apply_filters/ do_actionund der ersten Klammer übereinstimmt

Wir werden dann einfach ein Array mit allen Filtern und Aktionen erstellen und dann das Array durchlaufen und den Dateinamen sowie die Filter und Aktionen ausgeben. Wir werden Dateien ohne Filter / Aktionen überspringen

WICHTIGE NOTIZEN

  • Diese Funktionen sind sehr teuer. Führen Sie sie nur in einer lokalen Testinstallation aus.

  • Ändern Sie die Funktionen nach Bedarf. Sie können entscheiden, die Ausgabe in eine Datei zu schreiben, eine spezielle Backend-Seite dafür zu erstellen, die Optionen sind unbegrenzt

OPTION 1

Die erste Optionsfunktion ist sehr einfach. Wir geben den Inhalt einer Datei als Zeichenfolge zurück file_get_contents, suchen nach den apply_filters/ do_actionInstanzen und geben einfach den Dateinamen und die Filter- / Aktionsnamen aus

Ich habe den Code zur leichteren Verfolgung kommentiert

function get_all_filters_and_actions( $path = '' )
{
    //Check if we have a path, if not, return false
    if ( !$path ) 
        return false;

    // Validate and sanitize path
    $path = filter_var( $path, FILTER_SANITIZE_URL );
    /**
     * If valiadtion fails, return false
     *
     * You can add an error message of something here to tell
     * the user that the URL validation failed
     */
    if ( !$path ) 
        return false;

    // Get each php file from the directory or URL  
    $dir   = new RecursiveDirectoryIterator( $path );
    $flat  = new RecursiveIteratorIterator( $dir );
    $files = new RegexIterator( $flat, '/\.php$/i' );

    if ( $files ) {

        $output = '';
        foreach($files as $name=>$file) {
            /**
             * Match and return all instances of apply_filters(**) or do_action(**)
             * The regex will match the following
             * - Any depth of nesting of parentheses, so apply_filters( 'filter_name', parameter( 1,2 ) ) will be matched
             * - Whitespaces that might exist between apply_filters or do_action and the first parentheses
             */
            // Use file_get_contents to get contents of the php file
            $get_file_content =  file_get_contents( $file );
            // Use htmlspecialchars() to avoid HTML in filters from rendering in page
            $save_content = htmlspecialchars( $get_file_content );
            preg_match_all( '/(apply_filters|do_action)\s*(\([^()]*(?:(?-1)[^()]*)*+\))/', $save_content, $matches );

            // Build an array to hold the file name as key and apply_filters/do_action values as value
            if ( $matches[0] )
                $array[$name] = $matches[0];
        }
        foreach ( $array as $file_name=>$value ) {

            $output .= '<ul>';
                $output .= '<strong>File Path: ' . $file_name .'</strong></br>';
                $output .= 'The following filters and/or actions are available';
                foreach ( $value as $k=>$v ) {
                    $output .= '<li>' . $v . '</li>';
                }
            $output .= '</ul>';
        }
        return $output;
    }

    return false;
}

Sie können at follow für eine Vorlage, ein Frontend oder ein Backend verwenden

echo get_all_filters_and_actions( 'E:\xammp\htdocs\wordpress\wp-includes' );

Dies wird gedruckt

Geben Sie hier die Bildbeschreibung ein

OPTION 2

Diese Option ist etwas teurer in der Ausführung. Diese Funktion gibt die Zeilennummer zurück, in der sich der Filter / die Aktion befindet.

Hier verwenden wir file, um die Datei in ein Array zu zerlegen, dann suchen wir den Filter / die Aktion und die Zeilennummer und geben sie zurück

function get_all_filters_and_actions2( $path = '' )
{
    //Check if we have a path, if not, return false
    if ( !$path ) 
        return false;

    // Validate and sanitize path
    $path = filter_var( $path, FILTER_SANITIZE_URL );
    /**
     * If valiadtion fails, return false
     *
     * You can add an error message of something here to tell
     * the user that the URL validation failed
     */
    if ( !$path ) 
        return false;

    // Get each php file from the directory or URL  
    $dir   = new RecursiveDirectoryIterator( $path );
    $flat  = new RecursiveIteratorIterator( $dir );
    $files = new RegexIterator( $flat, '/\.php$/i' );

    if ( $files ) {

        $output = '';
        $array  = [];
        foreach($files as $name=>$file) {
            /**
             * Match and return all instances of apply_filters(**) or do_action(**)
             * The regex will match the following
             * - Any depth of nesting of parentheses, so apply_filters( 'filter_name', parameter( 1,2 ) ) will be matched
             * - Whitespaces that might exist between apply_filters or do_action and the first parentheses
             */
            // Use file_get_contents to get contents of the php file
            $get_file_contents =  file( $file );
            foreach ( $get_file_contents as  $key=>$get_file_content ) {
                preg_match_all( '/(apply_filters|do_action)\s*(\([^()]*(?:(?-1)[^()]*)*+\))/', $get_file_content, $matches );

                if ( $matches[0] )
                    $array[$name][$key+1] = $matches[0];
            }
        }

        if ( $array ) {
            foreach ( $array as $file_name=>$values ) {
                $output .= '<ul>';
                    $output .= '<strong>File Path: ' . $file_name .'</strong></br>';
                    $output .= 'The following filters and/or actions are available';

                    foreach ( $values as $line_number=>$string ) {
                        $whitespaces = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
                        $output .= '<li>Line reference ' . $line_number . $whitespaces . $string[0] . '</li>';
                    }
                $output .= '</ul>';
            }
        }
        return $output;

    }

    return false;
}

Sie können at follow für eine Vorlage, ein Frontend oder ein Backend verwenden

echo get_all_filters_and_actions2( 'E:\xammp\htdocs\wordpress\wp-includes' );

Dies wird gedruckt

Geben Sie hier die Bildbeschreibung ein

BEARBEITEN

Dies ist im Grunde so viel, wie ich tun kann, ohne dass die Skripte abgelaufen sind oder nicht genügend Speicherplatz zur Verfügung steht. Mit dem Code in Option 2 ist es so einfach, wie die Datei und die Zeile im Quellcode aufzurufen und dann alle gültigen Parameterwerte des Filters / der Aktion abzurufen. Wichtig ist auch, die Funktion und den weiteren Kontext abzurufen, in dem Der Filter / die Aktion wird verwendet

Pieter Goosen
quelle
1
du hast zu viel Freizeit;) aber am Ende ist es nie genug zu wissen, was die Filter sind, aber auch was die erwarteten Parameterwerte und Ergebnisse sind und dies kann nicht von der Quelle ohne Bactracking erreicht werden, um den Doc-Block für den Fall zu erhalten von Kerndateien und wahrscheinlich überhaupt nicht in Nicht-Kern-Plugins und -Themen verfügbar.
Mark Kaplun
1
@ MarkKaplun das ist nur etwas woran ich schnell gearbeitet habe :-). Die obigen Funktionen zeigen Ihnen zumindest, wo sich Filter und Aktionen in bestimmten Plugin- / Theme- / Core-Verzeichnissen befinden. Es bleibt immer noch sehr wichtig, zur Quelle zurückzukehren und sicherzustellen, dass Sie verstehen, was ein bestimmter Filter speziell tut. Einige Plugins und Themes sind schlecht dokumentiert, so dass Sie immer noch etwas Wissen und Hintergrund benötigen, um zu wissen oder herauszufinden, was ein bestimmter Filter in einer bestimmten Funktion tut ;-)
Pieter Goosen
@PieterGoosen Ja, ich bin normalerweise in Ordnung, wenn ich zurückspringe, um mir die Quelle anzusehen. Wenn ich das zuerst mache, bedeutet das, dass das Plugin Hooks hat, aber nicht unbedingt Doc-Blöcke für sie. Aber wenn ich mir anschaue, wo sie tatsächlich verwendet werden, hilft es mir zu verstehen, ob sie wertvoll sind. Wie auch immer, diese sehen so aus, als könnten sie großartig sein. Ich könnte sie sogar als 2. ändern, um nur in eine HTML-Datei zu schreiben, weil ich dann einfach die Funktionsdeklaration in ein MU-Plugin auf dem lokalen Server stecken und sie über die WP-CLI ausführen könnte.
Yonatron
@yonatron Ich bin froh, dass meine zwei Cent irgendwie helfen. Wenn Sie jemals kommen, um Ihre eigene Änderung aus meinem Code zu schreiben, können Sie jederzeit Ihren Code und Ihre Erklärung als Antwort hinzufügen ( was großartig sein wird ) ;-). Viel Spaß
Pieter Goosen
1
@PieterGoosen, wie viel Zeit Sie gebraucht haben, um dieses Skript zu schreiben und zu dokumentieren,
meine Güte
6

Klingt so, als ob WP Parser das tut, wonach Sie suchen. Es wird verwendet, um die offizielle Entwicklerreferenz zu generieren . Es listet Parameter, @ seit Tags und Verweise auf die Quelle auf. Es funktioniert mit allen WordPress-Plugins und kann über die Befehlszeile aufgerufen werden:

wp parser create /path/to/source/code --user=<id|login>
Jan Beck
quelle
1
Ich bin mit diesem Skript nicht sehr vertraut, aber es scheint, dass es einen Filter oder eine Aktion benötigt, um gut dokumentiert zu sein. Würde mich über Feedback von @Rarst freuen ;-)
Pieter Goosen
Ich habe es noch nicht ausprobiert, aber aufgrund der Beschreibung denke ich, dass Pieters Besorgnis auf dem richtigen Weg ist. Ich möchte alle Hooks finden, nicht nur diejenigen, denen gut formatierte Doc-Blöcke vorausgehen. Ich denke, Leute, die sich die Zeit nehmen, ihre Hooks / Funktionen mithilfe von WordPress-Konventionen zu kommentieren, führen diese Art von Skript bereits aus und veröffentlichen API-Referenzen auf ihren Support-Sites. Mir ist klar, dass dies mit einem gewissen Risiko verbunden ist, denn wenn ein Entwickler einen Filter nicht öffentlich dokumentiert, kann er ohne Vorwarnung geändert / veraltet werden. Bei einigen von mir verwendeten Plugins kann ich jedoch nicht warten, bis Dokumente online angezeigt werden.
Yonatron
Es analysiert auch undokumentierte Hooks. Beispiel: developer.wordpress.org/reference/hooks/graceful_fail
Jan Beck
4

The Fast and the Furious

Die gute alte *nixKommandozeile ist immer praktisch:

# grep  --line-number                                         \
        --exclude-dir=/path/to/some/directory                 \
        --include=*.php                                       \ 
        --recursive                                           \
        "add_filter\|do_action\|apply_filters"                \
        /path/to/wp-content/plugins/some-plugin               \ 
 | less

Viele weitere Optionen über #man grep.

Dann können wir sogar ein einfaches Bash-Skript erstellen wp-search.sh:

#!/bash/bin
grep --line-number                            \
    --exclude-dir=/path/to/some/directory     \
    --include=*.$1                            \
    --recursive $2 $3

und führen Sie es mit.

 # bash wp-search.sh php "add_filter\|do_action\|apply_filters" /path/to/some-plugin

Hübsche Ausgabe

Wir können --colorAttribute verwenden, um die Ausgabe von zu kolorieren grep, aber beachten Sie, dass es nicht funktioniert less.

Eine andere Möglichkeit wäre, eine HTML-Tabelle für die Suchergebnisse zu generieren.

Hier ist ein awkBeispiel, das ich erstellt habe und das die Suchergebnisse als HTML-Tabelle in die results.htmlDatei ausgibt :

  | sed 's/:/: /2' \
  | awk ' \
        BEGIN { \
            print "<table><tr><th>Results</th><th>Location</th></tr>"  \
        } \
        { \
            $1=$1; location=$1; $1=""; print "<tr><td>" $0 "</td><td>" location "</td><tr>" \
        } \
        END {  \
           print "</table>" \
       }' \
 > results.html

wo ich diesen Trick verwendet habe , um alle führenden Leerzeichen zu entfernen und diesen , um alle Felder außer dem ersten zu drucken.

Ich benutze sedhier nur, um nach dem zweiten Doppelpunkt ( :) zusätzlichen Platz hinzuzufügen , nur für den Fall, dass dort kein Platz ist.

Skript

Wir könnten dies zu unserem wp-search.shSkript hinzufügen :

#!/bash/bin
grep   --with-filename \
       --line-number \
       --exclude-dir=/path/to/some/directory \
       --include=*.$1 \
       --recursive $2 $3 \
| sed 's/:/: /2' \
| awk ' BEGIN { \
        print "<table><tr><th>Results</th><th>Location</th></tr>"  \
    } \
    { \
        $1=$1; location=$1; $1=""; print "<tr><td>" $0 "</td><td>" location "</td><tr>" \
    } \
    END {  \
        print "</table>" \
    }' \
> /path/to/results.html

wo Sie das /path/to/some/directoryund /path/to/results.htmlan Ihre Bedürfnisse anpassen müssen.

Beispiel - Suche nach einem Plugin

Wenn wir dies auf dem wordpress-importerPlugin versuchen mit:

bash wp-search.sh php "add_filter\|do_action" /path/to/wp-content/plugins/wordpress-importer/

dann wird die results.htmlDatei angezeigt als:

Ergebnisse

Beispiel - Durchsuchen des Kerns

Ich habe es mal auf den Kern getestet:

time bash wp-search.sh php "add_filter\|do_action" /path/to/wordpress/core/

real    0m0.083s
user    0m0.067s
sys     0m0.017s

und es ist schnell!

Anmerkungen

Um zusätzlichen Kontext zu erhalten, verwenden wir möglicherweise das -C NUMBERvon grep.

Wir könnten die HTML-Ausgabe auf verschiedene Arten ändern, aber hoffentlich können Sie dies weiter an Ihre Bedürfnisse anpassen.

Birgire
quelle
Vielen Dank! Ich benutze zur Not grep, aber ich bin so ein Neuling in Sachen Shell, dass ich nie dazu gekommen bin, die Pfeifen für den OP zu verwenden. Die andere Sache, die ich hinzufügen möchte, sind Optionen, um es ein wenig zu drucken. Die Ausgabe der obigen Grep-Zeile wird immer noch ziemlich schwer zu überfliegen sein.
Yonatron
2
Ich habe die Antwort mit einem Beispiel für hübschen Druck @yonatron
birgire