Générer des références de hook dormantes

10

Il semble que de nombreux développeurs de plug-ins 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 at-il trouvé le meilleur moyen automatisé de pointer sur un répertoire de plug-ins (ou de thèmes) et d'afficher une liste de tous les hooks disponibles?

Il semblerait que certains plug-ins analysent les points d'ancrage, mais pour autant que je sache, ils vous indiquent ceux qui sont réellement 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 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:

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

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

    
posée yonatron 04.10.2015 - 20:42

3 réponses

6

Je ne connais aucun script ou plug-in pour faire ce que vous voulez. Comme vous l'avez dit, il existe des scripts ( même 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 une aide quelconque ici et là ) qui trouve toutes les instances apply_filters et do_action dans un fichier, puis l’affiche out

BASICS

  • Nous allons utiliser les classes PHP RecursiveDirectoryIterator , RecursiveIteratorIterator et RegexIterator 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 ignorerons les fichiers sans filtres / actions

REMARQUES IMPORTANTES

  • Ces fonctions sont très coûteuses. Ne les exécutez que 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 spéciale pour le backend, 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 avec file_get_contents , rechercher les occurrences apply_filters /% co_de et simplement sortir le nom de fichier et les noms de filtre / action

J'ai commenté le code pour pouvoir le suivre facilement

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' );

Ceci imprimera

OPTION2

Cetteoptionestunpeupluschèreàexécuter.Cettefonctionrenvoielenumérodelaligneoùsetrouvelefiltre/l'action.

Ici,nousutilisonsdo_actionpourdécomposerlefichierdansuntableau,puisnousrecherchonsetretournonslefiltre/actionetlenumérodeligne

functionget_all_filters_and_actions2($path=''){//Checkifwehaveapath,ifnot,returnfalseif(!$path)returnfalse;//Validateandsanitizepath$path=filter_var($path,FILTER_SANITIZE_URL);/***Ifvaliadtionfails,returnfalse**Youcanaddanerrormessageofsomethingheretotell*theuserthattheURLvalidationfailed*/if(!$path)returnfalse;//GeteachphpfilefromthedirectoryorURL$dir=newRecursiveDirectoryIterator($path);$flat=newRecursiveIteratorIterator($dir);$files=newRegexIterator($flat,'/\.php$/i');if($files){$output='';$array=[];foreach($filesas$name=>$file){/***Matchandreturnallinstancesofapply_filters(**)ordo_action(**)*Theregexwillmatchthefollowing*-Anydepthofnestingofparentheses,soapply_filters('filter_name',parameter(1,2))willbematched*-Whitespacesthatmightexistbetweenapply_filtersordo_actionandthefirstparentheses*///Usefile_get_contentstogetcontentsofthephpfile$get_file_contents=file($file);foreach($get_file_contentsas$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($arrayas$file_name=>$values){$output.='<ul>';$output.='<strong>FilePath:'.$file_name.'</strong></br>';$output.='Thefollowingfiltersand/oractionsareavailable';foreach($valuesas$line_number=>$string){$whitespaces='&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';$output.='<li>Linereference'.$line_number.$whitespaces.$string[0].'</li>';}$output.='</ul>';}}return$output;}returnfalse;}

Vouspouvezutiliseràsuivresurunmodèle,frontendoubackend

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

Ceciimprimera

EDIT

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 toutes les valeurs de paramètre valides du filtre / de l’action, ainsi que, ce qui est important, d’obtenir la fonction et le contexte dans lequel le filtre / action est utilisé

    
réponse donnée Pieter Goosen 07.10.2015 - 10:04
6

On dirait que WP Parser fait ce que vous recherchez. Il est utilisé pour générer la référence de développeur officielle. 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>
    
réponse donnée Jan Beck 07.10.2015 - 12:20
3

Le rapide et le furieux

La bonne ligne de commande ' *nix est toujours utile:

# 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 d'autres 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 lancez-le 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 de 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 espaces blancs et Ceci pour imprimer tous les champs sauf le premier.

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

Script

Nous pourrions l'ajouter à 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 adapter /path/to/some/directory et /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:

Exemple-Recherchedanslenoyau

Jel'aitestépourlenoyau:

timebashwp-search.shphp"add_filter\|do_action" /path/to/wordpress/core/

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

et c'est rapide!

Notes

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.

    
réponse donnée birgire 07.10.2015 - 12:56

Lire d'autres questions sur les étiquettes