web-dev-qa-db-fra.com

Filtre Wordpress pour modifier la sortie HTML finale

Wordpress prend en charge les filtres de manière à obtenir toutes sortes de contenus spécifiques et à les modifier avant la sortie. Comme le filtre "the_content", qui vous permet d'accéder au balisage d'une publication avant qu'elle ne soit affichée à l'écran. 

J'essaie de trouver un filtre fourre-tout qui me donne une dernière chance de modifier le balisage final dans son intégralité avant la sortie. Quelqu'un en sait un?

J'ai parcouru la liste des filtres plusieurs fois, mais rien ne me saute aux yeux: http://adambrown.info/p/wp_hooks/hook/filters

(J'ai fait appel à certaines communautés spécifiques à Wordpress pour cette question, mais n'ayant reçu aucune réponse, je pensais me tourner vers le vénérable SO.)

48
chipotle_warrior

Autant que je sache, il n’ya pas d’accroche pour cela car les thèmes utilisent du HTML qui ne sera pas traité par WordPress.

Cependant, vous pouvez utiliser utiliser le tampon de sortie pour intercepter le code HTML final:

<?php
// example from php.net
function callback($buffer) {
  // replace all the apples with oranges
  return (str_replace("apples", "oranges", $buffer));
}
ob_start("callback");
?>
<html><body>
<p>It's like comparing apples to oranges.</p>
</body></html>
<?php ob_end_flush(); ?>
/* output:
   <html><body>
   <p>It's like comparing oranges to oranges.</p>
   </body></html>
*/
16
moff

WordPress n'a pas de filtre "sortie finale", mais vous pouvez en pirater un ensemble. L'exemple ci-dessous réside dans un "Must Use" plugin que j'ai créé pour un projet. 

Note: Je n'ai pas testé avec des plugins qui pourraient utiliser l'action "shutdown".

Le plugin fonctionne en parcourant tous les niveaux de mémoire tampon ouverts, en les fermant et en capturant leur sortie. Il déclenche ensuite le filtre "final_output", faisant écho au contenu filtré.

Malheureusement, WordPress effectue presque exactement le même processus (fermeture des tampons ouverts), mais ne capture pas réellement le tampon pour le filtrer (le vide uniquement), ainsi les actions supplémentaires "d'arrêt" n'auront pas accès à celui-ci. Pour cette raison, l'action ci-dessous est prioritaire par rapport à WordPress.

wp-content/mu-plugins/buffer.php

<?php

/**
 * Output Buffering
 *
 * Buffers the entire WP process, capturing the final output for manipulation.
 */

ob_start();

add_action('shutdown', function() {
    $final = '';

    // We'll need to get the number of ob levels we're in, so that we can iterate over each, collecting
    // that buffer's output into the final output.
    $levels = ob_get_level();

    for ($i = 0; $i < $levels; $i++) {
        $final .= ob_get_clean();
    }

    // Apply any filters to the final output
    echo apply_filters('final_output', $final);
}, 0);

Un exemple de raccordement au filtre final_output:

<?php

add_filter('final_output', function($output) {
    return str_replace('foo', 'bar', $output);
});

Modifier:

Ce code utilise des fonctions anonymes, qui ne sont prises en charge que dans PHP 5.3 ou plus récent. Si vous utilisez un site Web utilisant PHP 5.2 ou une version plus ancienne, vous ne vous rendez pas service. PHP 5.2 a été publié en 2006, et même si Wordpress STILL le prend en charge, vous ne devez pas l’utiliser.

46
kfriend

la question est peut-être ancienne, mais j'ai trouvé un meilleur moyen de le faire.

function callback($buffer) {
  // modify buffer here, and then return the updated code
  return $buffer;
}

function buffer_start() { ob_start("callback"); }

function buffer_end() { ob_end_flush(); }

add_action('wp_head', 'buffer_start');
add_action('wp_footer', 'buffer_end');

Explication Ce code de plug-in enregistre deux actions - buffer_start et buffer_end.

buffer_start est exécuté à la fin de la section d'en-tête du code HTML. Le paramètre, la fonction callback, est appelé à la fin de la mise en mémoire tampon de la sortie. Cela se produit au bas de la page lorsque la deuxième action enregistrée, buffer_end, est exécutée.

La fonction callback est l'endroit où vous ajoutez votre code pour modifier la valeur de la sortie (la variable $buffer). Ensuite, vous retournez simplement le code modifié et la page sera affichée.

Notes Assurez-vous d’utiliser des noms de fonction uniques pour buffer_start, buffer_end et callback, afin qu’ils ne soient pas en conflit avec d’autres fonctions que vous pourriez avoir dans les plugins.

18
Jacer Omri

@jacer, si vous utilisez les points suivants, le header.php est également inclus.

function callback($buffer) {      
    $buffer = str_replace('replacing','width',$buffer);
    return $buffer; 
}

function buffer_start() { ob_start("callback"); } 
function buffer_end() { ob_end_flush(); }

add_action('after_setup_theme', 'buffer_start');
add_action('shutdown', 'buffer_end');
10
Nick Kuijpers

En effet, il y a eu récemment une discussion sur la liste de diffusion WP-Hackers sur le sujet de la modification de la page complète et il semble que le consensus était que la mise en mémoire tampon de la sortie avec ob_start (), etc., était la seule vraie solution. Des discussions ont également eu lieu sur ses avantages et inconvénients: http://groups.google.com/group/wp-hackers/browse_thread/thread/e1a6f4b29169209a#

Pour résumer: cela fonctionne et constitue la meilleure solution lorsque cela est nécessaire (comme dans le plug-in WP-Supercache), mais ralentit la vitesse globale, car votre contenu n'est pas autorisé à être envoyé au navigateur car il est prêt, mais doit attendre la document complet à rendre (pour ob_end ()) avant de pouvoir être traité par vous et envoyé au navigateur.

3

Vous pouvez essayer de regarder dans le fichier wp-includes/formatting.php. Par exemple, la fonction wpautop . Si vous souhaitez faire quelque chose avec la page entière, regardez le plugin Super Cache. Cela écrit la page Web finale dans un fichier pour la mise en cache. Voir comment fonctionne ce plug-in peut vous donner des idées.

3
Brent Baisley

J'utilisais la meilleure solution de ce post (par kfriend) pendant un certain temps. Il utilise un mu-plugin pour mettre en tampon la sortie entière. 

Mais cette solution interrompt la mise en cache de wp-super-cache et aucun fichier supercache n'est généré lorsque je télécharge le mu-plugin.

Donc: Si vous utilisez wp-super-cache, vous pouvez utiliser le filtre de ce plugin comme ceci:

add_filter('wp_cache_ob_callback_filter', function($buffer) {
    $buffer = str_replace('foo', 'bar', $buffer);
    return $buffer;
});
2
Arne L

J'ai rencontré des problèmes avec ce code, car je me retrouve avec ce qui semble être la source d'origine de la page, de sorte que certains plugins n'ont aucun effet sur la page. J'essaie de résoudre ceci maintenant - je n'ai pas trouvé beaucoup d'informations sur les meilleures pratiques pour collecter les résultats de wordpress.

Mise à jour et sollicitation:

Le code de KFRIEND n'a pas fonctionné pour moi, car il capture les sources non traitées de wordpress, pas le même résultat que celui qui finit dans le navigateur. Ma solution n'est probablement pas élégante en utilisant une variable globals pour tamponner le contenu - mais au moins, je sais obtenir le même code HTML collecté que celui fourni au navigateur. Peut-être que différentes configurations de plugins créent des problèmes, mais grâce à l'exemple de code de Jacer Omri ci-dessus, j'ai fini avec cela.

Ce code est dans mon cas situé généralement dans functions.php dans le dossier theme.

$GLOBALS['oldschool_buffer_variable'] = '';
function sc_callback($data){
    $GLOBALS['final_html'] .= $data;
    return $data;
}
function sc_buffer_start(){
    ob_start('sc_callback');
}
function sc_buffer_end(){
    // Nothing makes a difference in my setup here, ob_get_flush() ob_end_clean() or whatever
    // function I try - nothing happends they all result in empty string. Strange since the
    // different functions supposedly have very different behaviours. Im guessing there are 
    // buffering all over the place from different plugins and such - which makes it so 
    // unpredictable. But that's why we can do it oldschool :D
    ob_end_flush();

    // Your final HTML is here, Yeeha!
    $output = $GLOBALS['oldschool_buffer_variable'];
}
add_action('wp_loaded', 'sc_buffer_start');
add_action('shutdown', 'sc_buffer_end');
1
Kim Steinhaug

Modifié https://stackoverflow.com/users/419673/kfriend answer.

Tout le code sera sur functions.php. Vous pouvez faire ce que vous voulez avec le code HTML sur le filtre "final_output".

Sur le thème 'functions.php'

//we use 'init' action to use ob_start()
add_action( 'init', 'process_post' );

function process_post() {
     ob_start();
}


add_action('shutdown', function() {
    $final = '';

    // We'll need to get the number of ob levels we're in, so that we can iterate over each, collecting
    // that buffer's output into the final output.
    $levels = ob_get_level();

    for ($i = 0; $i < $levels; $i++) {
        $final .= ob_get_clean();
    }

    // Apply any filters to the final output
    echo apply_filters('final_output', $final);
}, 0);

add_filter('final_output', function($output) {
    //this is where changes should be made
    return str_replace('foo', 'bar', $output); 
});
1
okto

Essayez de le résoudre avec JavaScript avant d'utiliser les tampons de sortie.

Supposons que vous souhaitiez ajouter une visionneuse lors du chargement des iframes, par exemple:

(function ($) {

    $(document).ready(function () {
        showSpinnerWhileIFrameLoads();
    });

    function showSpinnerWhileIFrameLoads() {
        var iframe = $('iframe');
        if (iframe.length) {
            $(iframe).before('<div id=\'spinner\'><i class=\'fa fa-spinner fa-spin fa-3x fa-fw\'></i></div>');
            $(iframe).on('load', function() {
                document.getElementById('spinner').style.display='none';
            });
        }
    }

})(jQuery);

Si vous adaptez cette idée à vos besoins, vous devriez généralement pouvoir manipuler la sortie HTML avec JavaScript sans avoir à manipuler les tampons de sortie, ce qui peut endommager le cache par exemple.

0
Lucas Bustamante