Filtro de Wordpress para modificar la salida html final


Wordpress tiene un gran soporte de filtro para obtener todo tipo de bits específicos de contenido y modificarlo antes de la salida. Como el filtro "the_content", que te permite acceder al marcado de una publicación antes de que salga a la pantalla.

Estoy tratando de encontrar un filtro general que me dé una última oportunidad de modificar el marcado final en su totalidad antes de la salida. Alguien sabe de uno?

He navegado por la lista de filtros varias veces, pero nada salta a la vista me: http://adambrown.info/p/wp_hooks/hook/filters

(He aprovechado algunas comunidades específicas de Wordpress para esta pregunta, pero al no haber recibido una sola respuesta, pensé en recurrir a la venerable SO.)

 46
Author: chipotle_warrior, 2009-04-21

9 answers

AFAIK, no hay ningún gancho para esto, ya que los temas utilizan HTML que no será procesado por WordPress.

Podría, sin embargo, usar el búfer de salida para capturar el 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>
*/
 15
Author: moff,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-21 14:06:18

WordPress no tiene un filtro de "salida final", pero puedes hackear uno. El siguiente ejemplo reside dentro de un plugin "Must Use" que he creado para un proyecto.

Nota: No he probado con ningún plugin que pueda hacer uso de la acción "shutdown".

El plugin funciona iterando a través de todos los niveles de búfer abiertos, cerrándolos y capturando su salida. Luego dispara el filtro "final_output", haciéndose eco del contenido filtrado.

Lamentablemente, WordPress realiza casi exactamente el mismo proceso (cerrando los búferes abiertos), pero en realidad no captura el búfer para filtrarlo (simplemente lo vacía), por lo que las acciones adicionales de "apagado" no tendrán acceso a él. Debido a esto, la siguiente acción se prioriza por encima de 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 ejemplo de conexión al filtro final_output:

<?php

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

Editar:

Este código utiliza funciones anónimas, que solo son soportadas en PHP 5.3 o más reciente. Si está ejecutando un sitio web utilizando PHP 5.2 o anterior, se está haciendo un flaco favor. PHP 5.2 fue lanzado en 2006, y aunque Wordpress TODAVÍA lo soporta, no debe usarlo.

 43
Author: kfriend,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-07 18:58:02

La pregunta es quizás vieja, pero he encontrado una mejor manera de hacerlo.

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

Explicación Este código de plugin registra dos acciones - buffer_start y buffer_end.

buffer_start se ejecuta al final de la sección de encabezado del html. El parámetro, la función callback, se llama al final del búfer de salida. Esto ocurre al pie de página, cuando se ejecuta la segunda acción registrada, buffer_end.

La función callback es donde agrega su código para cambiar la valor de la salida (la variable $buffer). A continuación, simplemente devuelve el código modificado y se mostrará la página.

Notas Asegúrese de usar nombres de función únicos para buffer_start, buffer_end, y callback, por lo que no entran en conflicto con otras funciones que pueda tener en los complementos.

 18
Author: Jacer Omri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-22 23:21:10

@jacer, si usa los siguientes hooks, el encabezado.php también se incluye.

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
Author: Nick Kuijpers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-20 15:45:40

Puede intentar buscar en el formato wp-includes/.archivo php. Por ejemplo, la función wpautop. Si estás buscando hacer algo con toda la página, mira el plugin Super Cache. Que escribe la página web final en un archivo para el almacenamiento en caché. Ver cómo funciona ese plug-in puede darte algunas ideas.

 3
Author: Brent Baisley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-21 13:23:25

De hecho, hubo una discusión recientemente en la lista de correo WP-Hackers sobre el tema de la modificación de la página completa y parece que el consenso fue que el búfer de salida con ob_start (), etc., era la única solución real. También hubo alguna discusión sobre los aspectos positivos y negativos de la misma: http://groups.google.com/group/wp-hackers/browse_thread/thread/e1a6f4b29169209a #

Para resumir: Funciona y es la mejor solución cuando es necesario (como en el plugin WP-Supercache) pero ralentiza las velocidades generales porque su contenido no se le permite ser enviado al navegador ya que está listo, sino que tiene que esperar a que el documento completo sea renderizado (para ob_end() ) antes de que pueda ser procesado por usted y enviado al navegador.

 3
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-04-29 21:31:53

Estuve usando la solución principal de este post (por kfriend) por un tiempo. Utiliza un mu-plugin para almacenar toda la salida.

Pero esta solución rompe el almacenamiento en caché de wp-super-cache y no se generan archivos supercache cuando subo el mu-plugin.

Así que: Si estás usando wp-super-cache, puedes usar el filtro de este plugin de la siguiente manera:

add_filter('wp_cache_ob_callback_filter', function($buffer) {
    $buffer = str_replace('foo', 'bar', $buffer);
    return $buffer;
});
 2
Author: Arne L,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-04 10:51:28

Me he encontrado con problemas con este código, ya que termino con lo que parece ser la fuente original de la página, por lo que algunos plugins no tienen ningún efecto en la página. Estoy tratando de resolver esto ahora-no he encontrado mucha información sobre las mejores prácticas para recopilar la salida de wordpress.

Actualización y sollución:

El código de KFRIEND no funcionó para mí, ya que captura la fuente no procesada de wordpress, no la misma salida que termina en el navegador de hecho. Mi sollution es probablemente no es elegante usar una variable globals para almacenar en búfer el contenido, pero al menos sé que obtengo el mismo HTML recopilado que se entrega al navegador. Podría ser que diferentes configuraciones de plugins crea problemas, pero gracias al ejemplo de código de Jacer Omri anterior terminé con esto.

Este código se encuentra en mi caso típicamente en funciones.php en la carpeta del tema.

$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
Author: Kim Steinhaug,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-10-12 09:38:35

Modificado https://stackoverflow.com/users/419673/kfriend respuesta.

Todo el código estará en funciones.php. Puedes hacer lo que quieras con el html en el filtro "final_output".

En las funciones de su tema.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); 
});
 0
Author: okto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-18 16:18:02