Фильтр извлечения добавляет «</ p>» в неправильном месте

Я использую следующий код из этого вопроса , чтобы ограничить длину выдержки до 2 абзацев.

if ( ! function_exists( 'wpse0001_custom_wp_trim_excerpt' ) ) : function wpse0001_custom_wp_trim_excerpt($wpse0001_excerpt) { global $post; $raw_excerpt = $wpse0001_excerpt; if ( '' == $wpse0001_excerpt ) { $wpse0001_excerpt = get_the_content(''); $wpse0001_excerpt = strip_shortcodes( $wpse0001_excerpt ); $wpse0001_excerpt = apply_filters('the_content', $wpse0001_excerpt); // Here we choose how many paragraphs do we want to cutthe excerpt at, This part thanks to Clément Malet $wpse0001_excerpt = "<p>$wpse0001_excerpt</p>"; $wanted_number_of_paragraph = 1; $tmp = explode ('</p>', $wpse0001_excerpt); for ($i = 0; $i < $wanted_number_of_paragraph; ++$i) { if (isset($tmp[$i]) && $tmp[$i] != '') { $tmp_to_add[$i] = $tmp[$i]; } } $wpse0001_excerpt = implode('</p>', $tmp_to_add) . '</p>'; $wpse0001_excerpt = str_replace(']]>', ']]&gt;', $wpse0001_excerpt); $excerpt_end = ' <a href="'. esc_url( get_permalink() ) . '">' . '&nbsp;&raquo;&nbsp;' . sprintf(__( 'Read more about: %s &nbsp;&raquo;', 'pietergoosen' ), get_the_title()) . '</a>'; $excerpt_more = apply_filters('excerpt_more', ' ' . $excerpt_end); //$pos = strrpos($wpse0001_excerpt, '</'); //if ($pos !== false) // Inside last HTML tag //$wpse0001_excerpt = substr_replace($wpse0001_excerpt, $excerpt_end, $pos, 0); //else // After the content $wpse0001_excerpt .= $excerpt_end; return $wpse0001_excerpt; } return apply_filters('wpse0001_custom_wp_trim_excerpt', $wpse0001_excerpt, $raw_excerpt); } endif; remove_filter('get_the_excerpt', 'wp_trim_excerpt'); add_filter('get_the_excerpt', 'wpse0001_custom_wp_trim_excerpt'); 

Я установил $wanted_number_of_paragraph 2 .

Если найдено более одного абзаца в сообщении, результат будет правильным:

 <blockquote> <p>Text</p> <p>Text</p> </blockquote> 

Если найдено только один абзац в сообщении, результат неверен:

 <blockquote> <p>Text</p></p> </blockquote> 

Я попытался немного изменить приведенный выше код, но ни одна из моих модификаций не работает. Любые идеи, почему это происходит?

Это происходит потому, что использование explode() для синтаксического анализа HTML по меньшей мере одинаково злобно, как попытка сделать это с помощью регулярного выражения.

Чтобы «исправить» его, быстрый «грязный путь», вы можете добавить следующую preg_replace() после preg_replace() :

 $wpse0001_excerpt = implode( '</p>', $tmp_to_add ).'</p>'; $wpse0001_excerpt = preg_replace( '/<\/p>\s*<\/p>/', '</p>', $wpse0001_excerpt ); 

Использование чего-то вроде расширения PHP DOM было бы более чистым. Тем не менее, это уже не WordPress.