¿Filtrar la salida de un shortcode específico?
¿Existe algún hook en WordPress que pueda usar para filtrar la salida de un shortcode específico? Algo como esto:
add_filter('shortcode_output', 'my_filter_function', 2);
function my_filter_function ( $output, $shortcode ) {
....
}
Donde $shortcode
sería algo como [my_schortcode]
o incluso mejor, el shortcode y sus atributos separados en un array.
WordPress 4.7 introdujo un nuevo filtro, do_shortcode_tag
, para hacer exactamente esto.

+1 por esta solución ya que ahora reemplaza a la respuesta aceptada. Sería genial si pudieras editar tu respuesta y dar un pequeño ejemplo de cómo usarla. Los parámetros del filtro no son obvios.

Para ser exhaustivos: https://developer.wordpress.org/reference/hooks/do_shortcode_tag/

¡Más exhaustividad! https://developer.wordpress.org/reference/hooks/pre_do_shortcode_tag/

Por fin, esperé años por este tipo de implementación. WP siempre debería aplicar este tipo de filtros antes del render. Un ejemplo para eliminar indentaciones de tabulador del código fuente: function example_shortcode_output($output, $tag, $attr, $m){
if($tag == 'gallery') $output = str_replace("\t", '', $output);
return $output;
}
add_filter('do_shortcode_tag', 'example_shortcode_output', 10, 4);

No existe ningún filtro que yo conozca que esté destinado a apuntar a shortcodes individuales como tú deseas.
Sin embargo, puedes filtrar atributos con shortcode_atts_{$shortcode}
.
Puedes "secuestrar" otro shortcode creando tu propia función de callback y registrándola con el slug del shortcode original. Creo que eso es lo que probablemente necesitarás hacer.
Prueba de concepto:
function my_gallery_shortcode($atts) {
return 'hola';
}
add_shortcode('gallery','my_gallery_shortcode');
Ahora intenta usar una galería :)

Tienes razón. No existe un filtro para lo que necesitaba. Así que en lugar de eso estoy filtrando the_content
. Funciona para mi caso de uso.

A partir de la versión 4.7, hay un filtro. Consulta la respuesta de Shawn H más abajo.

Si bien no hay un hook directo, existe una solución alternativa que hace posible tu objetivo. Puedes crear un nuevo shortcode que, en cada instancia, envuelva cualquier otro shortcode cuyo output deseas filtrar.
Uso en una entrada, etc:
Aquí hay algo de texto en la entrada. Bla bla...
[filter][target_annoying_shortcode size="small" limit="20"][/filter]
Aquí hay más texto en mi entrada. Más bla bla...
En functions.php:
function my_shortcode_output_filter( $attr, $content ) {
// Convertir el shortcode en su output
$content_translated = do_shortcode(trim($content));
if($shortcode_to_modify == $content || !$content_translated) {
// Manejo de errores
return 'Hubo un error al filtrar el shortcode: '.$content;
}
// Ahora modifica el output como prefieras, aquí...
$content_translated_and_filtered = $content_translated;
return $content_translated_and_filtered;
}
add_shortcode('filter', 'my_shortcode_output_filter');

Lo único que puedes filtrar son los atributos del shortcode:
apply_filters( "shortcode_atts_{$shortcode}", $out, $pairs, $atts );
El punto es que $shortcode
es el tercer argumento al registrar un shortcode. Este argumento es bastante nuevo y casi ningún shortcode lo usa, por lo que volverá al valor predeterminado, que es una string
vacía ''
.
Esto lleva a un resultado curioso:
add_filter( 'shortcode_atts_', 'wpse112294_shortcode_atts_cb' );
function wpse112294_shortcode_atts_cb( $out, $pairs, $atts )
{
// Aquí necesitamos encontrar una forma de identificar de forma única un shortcode
// para el cual no tenemos un nombre
// Algo que haga único al shortcode:
$found = isset( $pairs['foo_attribute_key'] );
if ( $found )
{
// Eliminar instantáneamente este filtro para ahorrar tiempo de procesamiento:
remove_filter( current_filter(), __FUNCTION__ );
// ¡Hacer algo increíble aquí!
}
return $out;
}
Entonces, sí, con un 90% de probabilidad necesitamos filtrar la salida de ¡todos(!) los shortcodes e intentar de alguna manera identificar el shortcode por algunos argumentos predeterminados ($pairs
) o por argumentos de entrada (imposible). Luego, finalmente, podremos procesar la salida. ¿Podemos procesar la cadena en sí? No. Esto tiene que hacerse de la manera que @s_ha_dum mostró arriba.

Si bien @s_ha_dum proporcionó una respuesta decente, es posible crear un nuevo shortcode con el propósito de filtrar un shortcode existente. Por ejemplo,
function filter_function($atts, $content) {
extract(shortcode_atts(array(
'att1' => 'val1',
'att2' => 'val2'
), $atts));
//guardar la salida del shortcode en $return
$return = do_shortcode("[existing_shortcode att1='$att1' att2='$att2'".$content."/existing_shortcode]");
//insertar código para modificar $return
echo $return;
}
add_shortcode('new_shortcode','filter_function');
ten en cuenta que para el shortcode [embed]
, debes usar
global $wp_embed;
$return = $wp_embed->run_shortcode("[embed ...
en lugar de do_shortcode
