Фильтрация вывода конкретного шорткода?
Существует ли в WordPress хук, который можно использовать для фильтрации вывода определенного шорткода? Что-то вроде этого:
add_filter('shortcode_output', 'my_filter_function', 2);
function my_filter_function ( $output, $shortcode ) {
....
}
Где $shortcode
был бы чем-то вроде [my_schortcode]
или, что еще лучше, шорткодом и его атрибутами, разделенными в массив.
В WordPress 4.7 был представлен новый фильтр do_shortcode_tag
, который как раз и предназначен для этого.

+1 за это решение, так как теперь оно заменяет принятый ответ. Было бы хорошо, если бы вы могли отредактировать свой ответ и привести небольшой пример использования. Параметры фильтра не очевидны.

Для полноты картины: https://developer.wordpress.org/reference/hooks/do_shortcode_tag/

Ещё больше полноты! https://developer.wordpress.org/reference/hooks/pre_do_shortcode_tag/

Наконец-то, ждал годами такую реализацию. WP всегда должен применять такие фильтры перед рендерингом. Пример удаления табуляции из исходного кода: 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);

Нет известного мне фильтра, который предназначен для работы с отдельными шорткодами, как вам нужно.
Однако вы можете фильтровать атрибуты с помощью shortcode_atts_{$shortcode}
.
Вы можете "перехватить" другой шорткод, создав собственный обработчик и зарегистрировав его с оригинальным слагом шорткода. Думаю, это именно то, что вам, скорее всего, понадобится сделать.
Доказательство концепции:
function my_gallery_shortcode($atts) {
return 'howdy';
}
add_shortcode('gallery','my_gallery_shortcode');
Теперь попробуйте использовать галерею :)

Вы правы. Нет фильтра для того, что я хотел. Поэтому вместо этого я фильтрую the_content
. Это работает для моего случая использования.

Начиная с версии 4.7, есть фильтр. Смотрите ответ Shawn H ниже.

Хотя специального хука для этого не существует, есть небольшой обходной путь, который позволяет достичь желаемого. Вы можете создать новый шорткод, который в каждом конкретном случае будет оборачивать любой другой шорткод, вывод которого вы хотите отфильтровать.
Использование в записи и т.д.:
Здесь какой-то текст записи. Бла-бла...
[filter][target_annoying_shortcode size="small" limit="20"][/filter]
Здесь продолжение текста в моей записи. Еще бла-бла...
В файле functions.php:
function my_shortcode_output_filter( $attr, $content ) {
// Преобразуем шорткод в его вывод
$content_translated = do_shortcode(trim($content));
if($shortcode_to_modify == $content || !$content_translated) {
// Обработка ошибок
return 'Произошла ошибка при фильтрации шорткода: '.$content;
}
// Теперь модифицируем вывод как нужно, здесь...
$content_translated_and_filtered = $content_translated;
return $content_translated_and_filtered;
}
add_shortcode('filter', 'my_shortcode_output_filter');

Единственное, что можно отфильтровать — это атрибуты шорткода:
apply_filters( "shortcode_atts_{$shortcode}", $out, $pairs, $atts );
Дело в том, что $shortcode
— это третий аргумент при регистрации шорткода. Этот аргумент появился сравнительно недавно, и почти ни один шорткод его не использует, поэтому по умолчанию он будет равен пустой строке ''
.
Это приводит к забавному результату:
add_filter( 'shortcode_atts_', 'wpse112294_shortcode_atts_cb' );
function wpse112294_shortcode_atts_cb( $out, $pairs, $atts )
{
// здесь нам нужно найти способ однозначно идентифицировать шорткод,
// для которого у нас нет имени
// что-то, что делает шорткод уникальным:
$found = isset( $pairs['foo_attribute_key'] );
if ( $found )
{
// Немедленно удаляем этот фильтр, чтобы сэкономить время обработки:
remove_filter( current_filter(), __FUNCTION__ );
// делаем что-то потрясающее здесь!
}
return $out;
}
Итак, да, с вероятностью 90% нам придется фильтровать вывод каждого(!) шорткода и пытаться каким-то образом идентифицировать его либо по стандартным аргументам ($pairs
), либо по входным аргументам (что невозможно). Затем, наконец, мы сможем обработать вывод. Можем ли мы обработать саму строку? Нет. Это нужно делать так, как показал @s_ha_dum выше.

Хотя @s_ha_dum дал достойный ответ, вы можете создать новый шорткод для фильтрации существующего шорткода. Например,
function filter_function($atts, $content) {
extract(shortcode_atts(array(
'att1' => 'val1',
'att2' => 'val2'
), $atts));
// сохраняем вывод шорткода в $return
$return = do_shortcode("[existing_shortcode att1='$att1' att2='$att2'".$content."/existing_shortcode]");
// вставляем код для модификации $return
echo $return;
}
add_shortcode('new_shortcode','filter_function');
обратите внимание, что для шорткода [embed]
необходимо использовать
global $wp_embed;
$return = $wp_embed->run_shortcode("[embed ...
вместо do_shortcode
