web-dev-qa-db-fra.com

Générer des références aux crochets dormants

Il semble que beaucoup de développeurs de plugins prennent le temps d’ajouter des points d’accès au filtre/action pour permettre aux utilisateurs d’ajuster les fonctionnalités de leurs produits. Ce qui est excellent, mais ce qu’ils ne font souvent pas, c’est de fournir une liste de points d’accroché et le nombre d’arguments qu’ils prennent.

Quelqu'un a-t-il trouvé le meilleur moyen automatisé de pointer sur un répertoire de plugins (ou de thèmes) et d'afficher une liste de tous les hooks disponibles?

Il semblerait que certains plug-ins analysent les points d’accès, mais pour autant que je sache, ils vous indiquent ceux qui sont en train d’être appelés pour afficher une page donnée. Ce que je reçois peut être pratique. Mais parfois, si je sais que je suis en interaction avec un plugin en particulier, je veux savoir chaque endroit où cela peut me laisser accrocher une action ou un filtre.

Donc, ce que je recherche vraiment, c’est quelque chose qui, étant donné le répertoire racine du plugin, créera une liste où chaque élément comprend:

  • étiquette
  • type (action ou filtre)
  • nombre d'arguments
  • où il est appelé (via do_action() ou apply_filter()) dans le code source

Un script serait génial, car cela pourrait vraisemblablement bien HTMLifier le tout et me le montrer directement dans l'interface utilisateur de l'administrateur pour chaque plugin. Mais même un script de ligne de commande qui génère un fichier statique utile serait bien.

10
yonatron

Je ne connais aucun script ou plug-in pour faire ce que vous voulez. Comme vous l'avez dit, il existe des scripts (voire des variables globales) que vous pouvez utiliser pour imprimer les filtres et les actions en cours d'utilisation.

En ce qui concerne les filtres et les actions en veille, j’ai écrit deux fonctions très basiques (avec un peu d’aide ici et là), qui trouve toutes les instances apply_filters et do_action dans un fichier, puis l’affiche

Bases

  • Nous allons utiliser les classes RecursiveDirectoryIterator, RecursiveIteratorIterator et RegexIterator PHP pour obtenir tous les fichiers PHP d'un répertoire. Par exemple, sur mon hôte local, j'ai utilisé E:\xammp\htdocs\wordpress\wp-includes

  • Nous allons ensuite parcourir les fichiers, puis rechercher et renvoyer (preg_match_all) toutes les instances de apply_filters et do_action. Je l'ai configuré pour correspondre aux instances imbriquées de parenthèses et aux espaces possibles entre apply_filters/do_action et la première parenthèse

Nous allons ensuite simplement créer un tableau avec tous les filtres et actions, puis parcourir le tableau et générer le nom du fichier, les filtres et les actions. Nous allons ignorer les fichiers sans filtres/actions

NOTES IMPORTANTES

  • Ces fonctions sont très chères. Exécutez-les uniquement sur une installation de test locale.

  • Modifiez les fonctions selon vos besoins. Vous pouvez décider d'écrire la sortie dans un fichier, créer une page de backend spéciale pour cela, les options sont illimitées.

OPTION 1

La première fonction d’options est très simple, nous allons renvoyer le contenu d’un fichier sous forme de chaîne en utilisant file_get_contents, rechercher les instances apply_filters/do_action et sortir simplement le nom du fichier et les noms du filtre/action.

J'ai commenté le code pour faciliter le suivi

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

Vous pouvez utiliser à suivre sur un modèle, frontend ou backend

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

Cela va imprimer

 enter image description here 

OPTION 2

Cette option est un peu plus chère à exécuter. Cette fonction renvoie le numéro de la ligne où se trouve le filtre/l'action.

Ici, nous utilisons file pour décomposer le fichier dans un tableau, puis nous recherchons et retournons le filtre/action et le numéro de ligne

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

Vous pouvez utiliser à suivre sur un modèle, frontend ou backend

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

Cela va imprimer

 enter image description here 

MODIFIER

C’est essentiellement ce que je peux faire sans que les scripts arrivent à expiration ou manquent de mémoire. Avec le code de l’option 2, il est aussi simple d’aller dans le fichier source et dans ladite code puis d’obtenir toutes les valeurs de paramètre valides du filtre/de l’action, mais aussi et surtout de récupérer la fonction et le contexte dans lequel le filtre/action est utilisé

6
Pieter Goosen

Cela ressemble à WP Parser fait ce que vous cherchez. Il est utilisé pour générer la référence officielle developer . Il répertorie les paramètres, les balises @since et les références à la source. Il fonctionne avec tous les plugins WordPress et est accessible via la ligne de commande:

wp parser create /path/to/source/code --user=<id|login>
6
Jan Beck

Le rapide et le furieux

La bonne vieille ligne de commande *nix est toujours pratique:

# 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

Beaucoup plus d'options via #man grep.

Ensuite, nous pouvons même créer un script bash simple wp-search.sh:

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

et le lancer avec.

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

Jolie sortie

Nous pouvons utiliser l'attribut --color pour coloriser la sortie de grep, mais notez que cela ne fonctionnera pas avec less.

Une autre option serait de générer un tableau HTML pour les résultats de la recherche.

Voici un exemple awk que j'ai construit et qui génère les résultats de la recherche sous forme de tableau HTML dans le fichier results.html:

  | 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

où j’ai utilisé cette astuce pour supprimer tous les blancs et celui-ci pour imprimer tous les champs sauf le premier.

J'utilise sed ici juste pour ajouter de l'espace après le deuxième point (:), juste au cas où il n'y aurait plus d'espace.

Scénario

Nous pourrions ajouter ceci à notre script wp-search.sh:

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

où vous devez ajuster le /path/to/some/directory et le /path/to/results.html à vos besoins.

Exemple - Recherche d'un plugin

Si nous essayons ceci sur le plugin wordpress-importer avec:

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

alors le fichier results.html s'affichera comme suit:

 results 

Exemple - Recherche dans le noyau

Je l'ai testé pour le coeur:

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

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

et c'est rapide!

Remarques

Pour obtenir un contexte supplémentaire, nous pourrions utiliser le -C NUMBER de grep.

Nous pouvons modifier la sortie HTML de différentes manières, mais nous espérons pouvoir l’ajuster davantage à vos besoins.

3
birgire