Gere referências de gancho inativas

10

Parece que muitos desenvolvedores de plugins gastam tempo adicionando ganchos de filtro / ação para permitir que os usuários ajustem a funcionalidade de seus produtos. O que é ótimo, mas o que eles geralmente não fazem é fornecer uma lista de ganchos e quantos argumentos eles levam.

Alguém encontrou a melhor maneira automatizada de apontar para um diretório de plugins (ou temas) e ver uma lista de todos os ganchos disponíveis?

Eu pareço alguns plugins que procuram por ganchos, mas até onde eu sei, eles mostram quais estão realmente sendo chamados para renderizar uma determinada página. O que eu recebo pode ser útil. Mas, às vezes, se eu sei que estou interagindo com um plug-in específico, quero saber todos os lugares em que ele pode me permitir vincular uma ação ou filtro.

Então, o que realmente estou procurando é algo que, dado um diretório raiz do plug-in, crie uma lista na qual cada item inclua:

  • tag
  • tipo (ação ou filtro)
  • número de argumentos
  • onde é chamado (via do_action()ou apply_filter()) na fonte

Um script seria ótimo, pois isso provavelmente poderia HTMLify muito bem a coisa toda e mostrá-lo diretamente na interface do administrador para cada plug-in. Mas mesmo um script de linha de comando que gera um arquivo estático útil seria ótimo.

yonatron
fonte
Então, qual é a pergunta? se você olhar para uma recomendação de encaixe, então é off-topic aqui
Mark Kaplun
Desculpe, não quero ir muito longe nas ervas daninhas do WordPress Development Meta , mas a) eu sou novo aqui, então não percebi que pedir recomendações de plugins era OT. Eu posso ter ... algumas opiniões ... sobre isso, mas ainda assim, eu deveria ter percebido isso primeiro. b) OTOH, estou apenas tentando encontrar uma solução para minha pergunta, seja um plug-in ou script de shell existente ou algo do zero. Portanto, a pergunta é estritamente uma solicitação de recomendação de plug-in!
Yonatron # 7/15
bem, parece que todo mundo está se divertindo, então nenhum dano é causado. Minha "objeção" à questão era, na verdade, mais sobre ser uma questão de análise de texto que é interessante para pessoas que gostam de escrever software no estilo de compilador, mas tem muito pouco a ver com a codificação wordpress real. Para o registro, mesmo as perguntas sobre o wordpress.org, como enviar um plug-in, geralmente serão votadas como off-topic.
precisa

Respostas:

6

Não há nenhum script ou plugin que eu conheça para fazer o que você deseja. Como você afirmou, existem scripts ( mesmo variáveis ​​globais ) que você pode usar para imprimir filtros e ações atualmente em uso.

Quanto aos filtros e ações dormentes, eu escrevi duas funções muito básicas ( com alguma ajuda aqui e ali ), que encontra todos apply_filterse do_actioninstâncias em um arquivo e, em seguida, imprime-lo para fora

FUNDAMENTOS

  • Usaremos a RecursiveDirectoryIterator, RecursiveIteratorIteratore RegexIteratorclasses PHP para obter todos os arquivos do PHP dentro de um diretório. Como exemplo, no meu host local, eu useiE:\xammp\htdocs\wordpress\wp-includes

  • Em seguida, percorreremos os arquivos e procuraremos e retornaremos ( preg_match_all) todas as instâncias de apply_filterse do_action. Eu o configurei para coincidir com instâncias aninhadas de parênteses e também para coincidir com possíveis espaços em branco entre apply_filters/ do_actione o primeiro parêntese

Simplesmente criaremos uma matriz com todos os filtros e ações e, em seguida, percorreremos a matriz e produziremos o nome do arquivo, filtros e ações. Iremos pular arquivos sem filtros / ações

ANOTAÇÕES IMPORTANTES

  • Essas funções são muito caras. Execute-os apenas em uma instalação de teste local.

  • Modifique as funções conforme necessário. Você pode decidir gravar a saída em um arquivo, criar uma página de back-end especial para isso, as opções são ilimitadas

OPÇÃO 1

A primeira função de opções é muito simples; retornaremos o conteúdo de um arquivo como uma string usando file_get_contents, pesquisemos as instâncias apply_filters/ do_actione simplesmente produzimos o nome do arquivo e os nomes de filtro / ação

Eu comentei o código para facilitar o acompanhamento

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

Você pode usar a seguir em um modelo, front-end ou back-end

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

Isso imprimirá

insira a descrição da imagem aqui

OPÇÃO 2

Essa opção é um pouco mais cara de executar. Esta função retorna o número da linha onde o filtro / ação pode ser encontrado.

Aqui usamos filepara explodir o arquivo em uma matriz, depois pesquisamos e retornamos o filtro / ação e o número da linha

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

Você pode usar a seguir em um modelo, front-end ou back-end

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

Isso imprimirá

insira a descrição da imagem aqui

EDITAR

Isso é basicamente o máximo que posso fazer sem que os scripts atinjam o tempo limite ou fiquem sem memória. Com o código na opção 2, é tão fácil quanto ir para o referido arquivo e a referida linha no código-fonte e, em seguida, obter todos os valores de parâmetro válidos do filtro / ação, também, o mais importante, obter a função e o contexto em que o filtro / ação é usado

Pieter Goosen
fonte
11
você tem muito tempo livre;) mas, no final, nunca é suficiente saber quais são os filtros, mas também quais são os valores e resultados de parâmetros esperados, e isso não pode ser alcançado a partir da fonte sem o rastreamento para obter o bloco de documentos. dos arquivos principais e provavelmente não está disponível em plugins e temas não essenciais.
precisa
11
@ MarkKaplun isso é apenas algo em que eu trabalhei rapidamente :-). As funções acima indicam pelo menos onde estão os filtros e as ações em diretórios específicos de plugins / temas / principais. Ainda é muito importante voltar à fonte e entender o que um filtro específico faz especificamente. Alguns plugins e temas são pouco conhecidos, então você ainda precisa de algum tipo de conhecimento e experiência para saber ou descobrir o que um filtro específico fazer em uma função específica ;-)
Pieter Goosen
@PieterGoosen Sim, eu geralmente estou bem em voltar para olhar a fonte. Se estou fazendo isso em primeiro lugar, significa que o plug-in possui ganchos, mas não necessariamente blocos de documentos para eles. Mas se eu der uma olhada em onde eles são realmente usados, isso me ajudará a entender se são valiosos. De qualquer forma, estes parecem ser ótimos. Eu posso até modificá-los 2º para gravar em um arquivo HTML, porque então eu poderia colar a declaração de função em um MU Plugin no servidor local e executá-la no WP CLI.
Yonatron # 7/15
@yonatron Fico feliz que meus dois centavos ajuda de alguma forma. Se você quiser escrever sua própria modificação no meu código, sempre poderá adicionar seu código e explicação como resposta (o que será ótimo ) ;-). Aproveite
Pieter Goosen
11
@PieterGoosen quanto tempo você levou para escrever este roteiro, bem como para documentar, caramba seu impressionante ***** :)
Webloper
6

Parece que o WP Parser faz o que você está procurando. É usado para gerar a referência oficial do desenvolvedor . Ele lista parâmetros, tags @since e referências à fonte. Ele funciona com todos os plugins do WordPress e pode ser acessado via linha de comando:

wp parser create /path/to/source/code --user=<id|login>
Jan Beck
fonte
11
Não estou muito familiarizado com esse script, mas parece que ele precisa de um filtro ou ação para ser bem documentado. Gostaria de receber feedback sobre isso a partir @Rarst ;-)
Pieter Goosen
Ainda não tentei, mas com base na descrição, acho que a preocupação de Pieter está no alvo. Quero encontrar todos os ganchos, não apenas os precedidos por blocos de documentos bem formatados. Acho que as pessoas que tomam tempo para comentar seus ganchos / funções usando as convenções do WordPress já estão executando esse tipo de script e publicando referências de API em seus sites de suporte. Percebo que há algum risco inerente a isso, pois se um desenvolvedor não documentar publicamente um filtro, ele poderá ser alterado / preterido sem aviso prévio, mas para alguns plug-ins que uso, não posso esperar que os documentos sejam exibidos on-line.
Yonatron # 7/15
Ele também analisa ganchos não documentados. Exemplo: developer.wordpress.org/reference/hooks/graceful_fail
Jan Beck
4

Velozes e Furiosos

A boa e velha *nixlinha de comando é sempre útil:

# 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

Muito mais opções via #man grep.

Podemos até criar um script bash simples wp-search.sh:

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

e execute-o com.

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

Pretty output

Podemos usar o --coloratributo para colorir a saída de grep, mas observe que ele não funcionará less.

Outra opção seria gerar uma tabela HTML para os resultados da pesquisa.

Aqui está um awkexemplo que eu construí que exibe os resultados da pesquisa como uma tabela HTML no results.htmlarquivo:

  | 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

onde usei esse truque para remover todos os espaços em branco à esquerda e este para imprimir todos os campos, exceto o primeiro.

Eu uso sedaqui apenas para adicionar espaço extra após o segundo dois pontos ( :), caso não haja espaço lá.

Roteiro

Poderíamos adicionar isso ao nosso wp-search.shscript:

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

onde você tem que ajustar /path/to/some/directorye /path/to/results.htmlàs suas necessidades.

Exemplo - Pesquisando um Plug-in

Se tentarmos isso no wordpress-importerplugin com:

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

o results.htmlarquivo será exibido como:

resultados

Exemplo - Pesquisando o Núcleo

Eu testei o tempo para o núcleo:

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

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

e é rápido!

Notas

Para obter um contexto extra, podemos usar o -C NUMBERgrep.

Poderíamos modificar a saída HTML de várias maneiras, mas espero que você possa ajustá-lo ainda mais às suas necessidades.

Birgire
fonte
Obrigado! Eu uso grep em uma pitada, mas sou tão novato em coisas de casca que nem sequer comecei a usar os canos para OR. A outra coisa que eu gostaria de adicionar são opções para imprimir um pouco. A saída da linha grep acima ainda será muito difícil de analisar.
yonatron
2
Eu atualizei a resposta com um exemplo de @yonatron cópia bonita
birgire