Generuj uśpione referencje haka

10

Wygląda na to, że wielu programistów wtyczek poświęca trochę czasu na dodanie haków filtru / akcji, aby umożliwić użytkownikom dostosowanie funkcjonalności swoich produktów. Co jest świetne, ale to, czego często nie robią, to lista haków i ile argumentów biorą.

Czy ktoś znalazł najlepszy zautomatyzowany sposób, aby wskazać katalog wtyczki (lub motywu) i zobaczyć listę wszystkich dostępnych haków?

Wydaje mi się, że niektóre wtyczki skanują w poszukiwaniu haków, ale o ile wiem, pokazują, które z nich są faktycznie wywoływane w celu renderowania danej strony. Które dostaję może być przydatne. Ale czasami, jeśli wiem, że wchodzę w interakcję z konkretną wtyczką, chcę poznać każde miejsce, w którym może mi pozwolić na działanie lub filtr.

Więc tak naprawdę szukam czegoś, co, biorąc pod uwagę katalog główny wtyczki, utworzy listę, w której każdy element zawiera:

  • etykietka
  • typ (akcja lub filtr)
  • liczba argumentów
  • gdzie nazywa się (przez do_action()lub apply_filter()) w źródle

Skrypt byłby świetny, ponieważ prawdopodobnie mógłby ładnie zhifikować całość i pokazać mi ją w interfejsie administratora dla każdej wtyczki. Ale nawet skrypt wiersza polecenia, który wyświetla użyteczny plik statyczny, byłby świetny.

yonatron
źródło
więc jakie jest pytanie? jeśli szukasz rekomendacji wtyczki, to jest nie na temat
Mark Kaplun,
Przepraszam, nie chcę wchodzić zbyt daleko w chwasty Meta WordPress Development , ale a) Jestem tu nowy, więc nie zdawałem sobie sprawy, że prośby o rekomendacje wtyczek były OT. Mógłbym mieć… jakieś opinie… na ten temat, ale i tak powinienem był to zrozumieć. b) OTOH, po prostu próbuję znaleźć rozwiązanie mojego pytania, czy to istniejąca wtyczka lub skrypt powłoki, czy coś od zera. Tak więc pytanie jest wyłącznie poleceniem wtyczki!
yonatron,
wydaje się, że wszyscy dobrze się bawią, więc nie szkodzi. Moje „zastrzeżenie” do tego pytania polegało na tym, że jest to pytanie analizujące tekst, które jest interesujące dla osób, które lubią pisać oprogramowanie w stylu kompilatora, ale mają niewiele wspólnego z faktycznym kodowaniem wordpress. Dla przypomnienia, nawet pytania dotyczące wordpress.org, takie jak przesłanie wtyczki, będą zwykle głosowane jako nie na temat.
Mark Kaplun,

Odpowiedzi:

6

Nie ma skryptu ani wtyczki, o których wiem, aby robić to, co chcesz. Jak już wspomniałeś, istnieją skrypty ( nawet zmienne globalne ), których możesz użyć do drukowania filtrów i aktualnie używanych akcji.

Jeśli chodzi o uśpione filtry i akcje, napisałem dwie bardzo podstawowe funkcje ( z pewną pomocą tu i tam ), które znajdują wszystkie apply_filtersi do_actioninstancje w pliku, a następnie drukują go

PODSTAWY

  • Będziemy używać RecursiveDirectoryIterator, RecursiveIteratorIteratora RegexIteratorklasy PHP, aby uzyskać wszystkie pliki PHP w katalogu. Jako przykład użyłem na moim localhostE:\xammp\htdocs\wordpress\wp-includes

  • Następnie przejdziemy przez pliki i przeszukamy i zwrócimy ( preg_match_all) wszystkie wystąpienia apply_filtersi do_action. Skonfigurowałem go, aby pasował do zagnieżdżonych instancji nawiasów, a także aby dopasować możliwe białe spacje między apply_filters/ do_actiona pierwszym nawiasiem

Po prostu utworzymy tablicę ze wszystkimi filtrami i akcjami, a następnie przejdziemy przez tablicę i wyprowadzimy nazwę pliku oraz filtry i akcje. Pomiń pliki bez filtrów / akcji

WAŻNE NOTATKI

  • Te funkcje są bardzo drogie. Uruchom je tylko na lokalnej instalacji testowej.

  • Zmodyfikuj funkcje zgodnie z potrzebami. Możesz zdecydować się zapisać wynik do pliku, utworzyć specjalną stronę zaplecza, opcje są nieograniczone

OPCJA 1

Pierwszy opcje funkcja jest bardzo prosta, wrócimy zawartość pliku jako ciąg znaków z wykorzystaniem file_get_contents, wyszukać apply_filters/ do_actionprzypadkach i po prostu wyjście nazwy pliku i filtrowanie nazw / action

Skomentowałem kod dla łatwego śledzenia

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;
}

Możesz użyć w follow na szablonie, frontendzie lub backendu

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

To zostanie wydrukowane

wprowadź opis zdjęcia tutaj

OPCJA 2

Ta opcja jest nieco droższa w uruchomieniu. Ta funkcja zwraca numer wiersza, w którym można znaleźć filtr / akcję.

Tutaj używamy filedo rozbicia pliku na tablicę, a następnie szukamy i zwracamy filtr / akcję oraz numer linii

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;
}

Możesz użyć w follow na szablonie, frontendzie lub backendu

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

To zostanie wydrukowane

wprowadź opis zdjęcia tutaj

EDYTOWAĆ

Jest to w zasadzie tyle, ile mogę, bez przekroczenia limitu czasu skryptów lub braku pamięci. Z kodem w opcji 2 jest tak proste, jak przejście do wspomnianego pliku i linii w kodzie źródłowym, a następnie uzyskanie wszystkich prawidłowych wartości parametrów filtru / akcji, a także, co ważne, uzyskanie funkcji i dalszego kontekstu, w którym używany jest filtr / akcja

Pieter Goosen
źródło
1
masz za dużo wolnego czasu;) ale w końcu nigdy nie wystarczy wiedzieć, jakie są filtry, ale także jakie są oczekiwane wartości parametrów i wyniki, i nie można tego osiągnąć ze źródła bez baktrackingu, aby uzyskać blok dokumentu w przypadku podstawowych plików i prawdopodobnie nie są dostępne we wszystkich nie-podstawowych wtyczkach i motywach.
Mark Kaplun,
1
@MarkKaplun to tylko coś, nad czym szybko pracowałem :-). Powyższe funkcje przynajmniej mówią ci, gdzie filtry i akcje znajdują się w określonych katalogach wtyczek / motywów / rdzeni. Nadal bardzo ważne jest, aby wrócić do źródła i upewnić się, że rozumiesz, co konkretnie robi konkretny filtr. Niektóre wtyczki i motywy są słabo udokumentowane, więc nadal potrzebujesz wiedzy i tła, aby wiedzieć lub dowiedzieć się, co robi konkretny filtr w określonej funkcji ;-)
Pieter Goosen
@PieterGoosen Tak. Zwykle mam ochotę wskoczyć z powrotem i spojrzeć na źródło. Jeśli robię to przede wszystkim, oznacza to, że wtyczka ma haki, ale niekoniecznie dla nich bloki dokumentów. Ale jeśli spojrzę na to, gdzie są faktycznie używane, pomaga mi to ustalić, czy są cenne. W każdym razie wyglądają, jakby mogły być świetne. Mogę nawet zmodyfikować je jako drugie, aby po prostu zapisać do pliku HTML, ponieważ wtedy mógłbym po prostu umieścić deklarację funkcji we wtyczce MU na lokalnym serwerze i uruchomić ją z WP CLI.
yonatron,
@yonatron Cieszę się, że moje dwa centy w jakiś sposób pomagają. Jeśli kiedykolwiek przyjdziesz napisać własną modyfikację z mojego kodu, zawsze możesz dodać kod i wyjaśnienie jako odpowiedź ( co będzie świetne ) ;-). Ciesz się
Pieter Goosen,
1
@PieterGoosen, ile czasu zajęło Ci napisanie tego skryptu, a także udokumentowanie, niech to będzie niesamowite ***** :)
Webloper
6

Wygląda na to, że WP Parser robi to, czego szukasz. Służy do generowania oficjalnej referencji programisty . Zawiera parametry, tagi @since i odniesienia do źródła. Działa ze wszystkimi wtyczkami WordPress i można uzyskać do niego dostęp za pośrednictwem wiersza poleceń:

wp parser create /path/to/source/code --user=<id|login>
Jan Beck
źródło
1
Nie znam się dobrze na tym skrypcie, ale wydaje się, że wymaga on filtru lub działania, aby być dobrze udokumentowanym. Będziemy wdzięczni za opinie od @Rarst ;-)
Pieter Goosen
Jeszcze tego nie próbowałem, ale na podstawie opisu myślę, że troska Pietera jest ukierunkowana. Chcę znaleźć wszystkie haki, nie tylko te poprzedzone dobrze sformatowanymi blokami dokumentów. Myślę, że ludzie, którzy poświęcają czas na komentowanie swoich haków / funkcji za pomocą konwencji WordPress, już uruchamiają tego rodzaju skrypty i publikują odwołania API w swoich witrynach wsparcia. Zdaję sobie sprawę, że wiąże się to z pewnym ryzykiem, ponieważ jeśli programista nie udokumentuje publicznie filtra, może zostać zmieniony / wycofany bez ostrzeżenia, ale w przypadku niektórych wtyczek, których używam, nie mogę się doczekać, aż dokumenty pojawią się w Internecie.
yonatron,
Analizuje również nieudokumentowane haki. Przykład: developer.wordpress.org/reference/hooks/graceful_fail
Jan Beck
4

Szybcy i wściekli

*nixWiersz polecenia good ol ' jest zawsze przydatny:

# 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

Wiele innych opcji za pośrednictwem #man grep.

Następnie możemy nawet stworzyć prosty skrypt bash wp-search.sh:

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

i uruchomić z.

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

Niezła wydajność

Możemy użyć --coloratrybutu do pokolorowania wyniku grep, ale należy pamiętać, że nie będzie on działał less.

Inną opcją byłoby wygenerowanie tabeli HTML dla wyników wyszukiwania.

Oto awkskonstruowany przeze mnie przykład, który wyświetla wyniki wyszukiwania w postaci tabeli HTML do results.htmlpliku:

  | 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

gdzie użyłem tej sztuczki, aby usunąć wszystkie wiodące białe pola, a tej do wydrukowania wszystkich pól oprócz pierwszego.

Używam sedtutaj tylko po to, by dodać dodatkową spację po drugim dwukropku ( :), na wypadek, gdyby nie było tam spacji.

Scenariusz

Możemy dodać to do naszego wp-search.shskryptu:

#!/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

gdzie musisz dostosować /path/to/some/directoryi /path/to/results.htmldo swoich potrzeb.

Przykład - wyszukiwanie wtyczki

Jeśli wypróbujemy to na wordpress-importerwtyczce z:

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

wtedy results.htmlplik będzie wyświetlany jako:

wyniki

Przykład - Przeszukiwanie rdzenia

Czas przetestowałem to pod kątem rdzenia:

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

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

i jest szybki!

Notatki

Aby uzyskać dodatkowy kontekst, możemy użyć -C NUMBERgrep.

Możemy zmodyfikować dane wyjściowe HTML na różne sposoby, ale mam nadzieję, że dostosujesz je do swoich potrzeb.

birgire
źródło
Dzięki! Używam grepa w szczypcie, ale jestem tak nowicjuszem w sprawach powłoki, że nigdy nie przywykłem do używania rur do OR. Inną rzeczą, którą chciałbym dodać, są opcje, aby trochę wydrukować. Wyjście powyższej linii grep nadal będzie dość trudne do przejrzenia.
yonatron,
2
Zaktualizowałem odpowiedź przykładem ładnego druku @yonatron
birgire,