Generar referencias de gancho inactivas

10

Parece que muchos desarrolladores de complementos se toman el tiempo para agregar ganchos de filtro / acción para permitir a los usuarios ajustar la funcionalidad de sus productos. Lo cual es genial, pero lo que a menudo no hacen es proporcionar una lista de ganchos y cuántos argumentos toman.

¿Alguien ha encontrado la mejor manera automatizada de apuntar a un directorio de plugins (o temas) y ver una lista de todos los ganchos disponibles?

Me parecen algunos complementos que escanean en busca de ganchos, pero por lo que puedo decir, te muestran cuáles están siendo llamados para representar una página determinada. Lo que consigo puede ser útil. Pero a veces, si sé que estoy interactuando con un complemento en particular, quiero saber cada lugar en el que me permita conectar una acción o filtro.

Entonces, lo que realmente estoy buscando es algo que, dado un directorio raíz del complemento, creará una lista donde cada elemento incluye:

  • etiqueta
  • tipo (acción o filtro)
  • número de argumentos
  • donde se llama (vía do_action()o apply_filter()) en la fuente

Una secuencia de comandos sería genial, ya que esto presumiblemente podría HTMLify todo y mostrarlo directamente en la interfaz de usuario de administración para cada complemento. Pero incluso un script de línea de comandos que genera un archivo estático útil sería genial.

yonatron
fuente
¿entonces cuál es la pregunta? si busca una recomendación de complemento, entonces está fuera de tema aquí
Mark Kaplun
Lo sentimos, no quiero llegar demasiado lejos en el desarrollo de WordPress Meta Weeds, pero a) Soy nuevo aquí, así que no me di cuenta de que pedir recomendaciones de complementos era OT. Podría tener ... algunas opiniones ... sobre eso, pero aún así, debería haberme dado cuenta de eso primero. b) OTOH, solo estoy tratando de encontrar alguna solución a mi pregunta, ya sea un complemento existente o un script de shell, o algo desde cero. ¡Entonces la pregunta es estrictamente una solicitud de recomendación de complemento!
yonatron
bueno, parece que todos los demás se están divirtiendo, así que no hay daño. Mi "objeción" a la pregunta fue en realidad más acerca de que se trata de una pregunta de análisis de texto que es interesante para las personas que les gusta escribir software de estilo compilador pero que tiene muy poco que ver con la codificación real de WordPress. Para el registro, incluso las preguntas que se refieren a wordpress.org, como cómo enviar un complemento, generalmente se votarán como fuera de tema.
Mark Kaplun

Respuestas:

6

No hay ningún script o complemento que yo sepa que haga lo que quiera. Como ha dicho, hay secuencias de comandos ( incluso variables globales ) que puede usar para imprimir filtros y acciones que se utilizan actualmente.

En cuanto a los filtros y acciones latentes, he escrito dos funciones muy básicas ( con algo de ayuda aquí y allá ), que busca todos los apply_filtersy do_actionlas instancias en un archivo y luego lo imprime

LO ESENCIAL

  • Vamos a utilizar el RecursiveDirectoryIterator, RecursiveIteratorIteratory RegexIteratorlas clases PHP para obtener todos los archivos del PHP dentro de un directorio. Como ejemplo, en mi host local, he usadoE:\xammp\htdocs\wordpress\wp-includes

  • Luego recorreremos los archivos y buscaremos y devolveremos ( preg_match_all) todas las instancias de apply_filtersy do_action. Lo configuré para que coincida con las instancias anidadas de paréntesis y también para que coincida con los espacios en blanco posibles entre apply_filters/ do_actiony el primer paréntesis

Simplemente crearemos una matriz con todos los filtros y acciones y luego recorreremos la matriz y mostraremos el nombre del archivo, los filtros y las acciones. Omitiremos archivos sin filtros / acciones

NOTAS IMPORTANTES

  • Estas funciones son muy caras. Ejecútelos solo en una instalación de prueba local.

  • Modifique las funciones según sea necesario. Puede decidir escribir la salida en un archivo, crear una página especial para eso, las opciones son ilimitadas

OPCIÓN 1

La primera función de opciones es muy simple, devolveremos el contenido de un archivo como una cadena, buscaremos file_get_contentslas instancias apply_filters/ do_actiony simplemente enviaremos el nombre de archivo y los nombres de filtro / acción

He comentado el código para seguirlo fácilmente

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

Puede usar a continuación en una plantilla, interfaz o backend

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

Esto imprimirá

ingrese la descripción de la imagen aquí

OPCION 2

Esta opción es un poco más costosa de ejecutar. Esta función devuelve el número de línea donde se puede encontrar el filtro / acción.

Aquí usamos filepara explotar el archivo en una matriz, luego buscamos y devolvemos el filtro / acción y el número de línea

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

Puede usar a continuación en una plantilla, interfaz o backend

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

Esto imprimirá

ingrese la descripción de la imagen aquí

EDITAR

Esto es básicamente todo lo que puedo hacer sin que los scripts excedan el tiempo de espera o se queden sin memoria. Con el código en la opción 2, es tan fácil como ir a dicho archivo y dicha línea en el código fuente y luego obtener todos los valores de parámetros válidos del filtro / acción, también, lo que es más importante, obtener la función y el contexto adicional en el que se usa el filtro / acción

Pieter Goosen
fuente
1
tiene demasiado tiempo libre;) pero al final nunca es suficiente saber cuáles son los filtros, sino también cuáles son los valores y resultados de los parámetros esperados y esto no se puede lograr desde la fuente sin un seguimiento de datos para obtener el bloque doc en caso de que de archivos principales y probablemente no esté disponible en absoluto en complementos y temas no principales.
Mark Kaplun
1
@ MarkKaplun esto es algo en lo que trabajé rápidamente :-). Las funciones anteriores al menos le indican dónde están los filtros y las acciones en directorios específicos de plugins / theme / core. Sigue siendo muy importante volver a la fuente y asegurarse de comprender qué hace un filtro específico específicamente. Algunos complementos y temas están pobremente documentados, por lo que aún necesitaría algún tipo de conocimiento y antecedentes para saber o averiguar qué hace un filtro específico en una función específica ;-)
Pieter Goosen el
@PieterGoosen Sí, por lo general estoy de acuerdo con volver a mirar la fuente. Si estoy haciendo esto en primer lugar, significa que el complemento tiene ganchos pero no necesariamente bloques de documentos para ellos. Pero si miro dónde se usan realmente, me ayuda a entender si son valiosos. De todos modos, parece que podrían ser geniales. Incluso podría modificarlos en segundo lugar para simplemente escribir en un archivo HTML porque luego podría pegar la declaración de función en un complemento de MU en el servidor local y ejecutarlo desde WP CLI.
yonatron
@yonatron Me alegra que mis dos centavos me ayuden de alguna manera. Si alguna vez va a escribir su propia modificación de mi código, siempre puede agregar su código y explicación como respuesta (lo cual será genial ) ;-). Disfruta
Pieter Goosen
1
@PieterGoosen cuánto tiempo te tomó escribir este guión y documentarlo, Dios mío, es increíble ***** :)
Webloper
6

Parece que WP Parser hace lo que estás buscando. Se utiliza para generar la referencia oficial del desarrollador . Enumera parámetros, etiquetas @since y referencias a la fuente. Funciona con todos los complementos de WordPress y se puede acceder a través de la línea de comandos:

wp parser create /path/to/source/code --user=<id|login>
Jan Beck
fuente
1
No estoy muy familiarizado con ese script, pero parece que necesita un filtro o acción para estar bien documentado. Agradecería comentarios sobre esto de @Rarst ;-)
Pieter Goosen
Todavía no lo he probado, pero según la descripción, creo que la preocupación de Pieter está en el objetivo. Quiero encontrar todos los ganchos, no solo los precedidos por bloques de documentos bien formateados. Creo que las personas que se toman el tiempo para comentar sus ganchos / funciones utilizando las convenciones de WordPress ya están ejecutando este tipo de script y publicando referencias de API en sus sitios de soporte. Me doy cuenta de que hay un riesgo inherente en esto, ya que si un desarrollador no documenta públicamente un filtro, podría cambiarlo / dejarlo en desuso sin previo aviso, pero para algunos complementos que uso, no puedo esperar a que los documentos aparezcan en línea.
yonatron
También analiza ganchos indocumentados. Ejemplo: developer.wordpress.org/reference/hooks/graceful_fail
Jan Beck
4

El rápido y el furioso

La buena *nixlínea de comandos siempre es ú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

Muchas más opciones a través de #man grep.

Entonces incluso podemos crear un script bash simple wp-search.sh:

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

y ejecutarlo con

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

Salida bonita

Podemos usar el --coloratributo para colorear la salida de grep, pero tenga en cuenta que no funcionará con less.

Otra opción sería generar una tabla HTML para los resultados de búsqueda.

Aquí hay un awkejemplo que construí que genera los resultados de búsqueda como una tabla HTML en el results.htmlarchivo:

  | 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

donde utilicé este truco para eliminar todos los espacios en blanco iniciales y este para imprimir todos los campos excepto el primero.

Lo uso sedaquí solo para agregar espacio adicional después del segundo colon ( :), en caso de que no haya espacio allí.

Guión

Podríamos agregar esto a nuestro 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

donde tiene que ajustar el /path/to/some/directoryy /path/to/results.htmla sus necesidades.

Ejemplo: buscar un complemento

Si intentamos esto en el wordpress-importercomplemento con:

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

entonces el results.htmlarchivo se mostrará como:

resultados

Ejemplo: búsqueda del núcleo

El tiempo lo probé para el 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

y es rapido!

Notas

Para obtener un contexto adicional, podríamos usar el -C NUMBERde grep.

Podríamos modificar la salida HTML de varias maneras, pero esperamos que pueda ajustar esto aún más a sus necesidades.

Birgire
fuente
¡Gracias! Utilizo grep en caso de necesidad, pero soy tan novato en el mundo de las conchas que ni siquiera tuve la oportunidad de usar las tuberías para quirófano. Sin embargo, la otra cosa que quisiera agregar son las opciones para imprimirlo un poco. La salida de la línea grep anterior seguirá siendo bastante difícil de leer.
yonatron
2
Actualicé la respuesta con un ejemplo de impresión bonita @yonatron
birgire