From 351438ebe1d410fffe6dca0b250d180a0ebf6290 Mon Sep 17 00:00:00 2001 From: Helen Hou-Sandi Date: Mon, 18 Feb 2013 19:22:58 +0000 Subject: [PATCH] Output fallbacks / theme compat for post format metadata. * Currently handles link, quote, image, gallery, audio, and video formats. * `add_theme_support()` for a given post format is now an indicator that the theme handles format-specific metadata. * If no support for a given format is defined, fallback output will be generated and hooked onto the_content if a post has metadata for that format. * Fallbacks attempt to be smart about not duplicating data already appearing in the post content itself. Gallery is particularly liberal, looking for any instance of the gallery shortcode in the content, not just an exact match to the gallery shortcode defined in the format-specific meta. * Compat output defaults to being wrapped in a `div` with a class of `post-format-content`. Theme authors: please test and evaluate, keeping in mind that the goal is to support user expectations of not losing format-specific data they've entered in the admin when viewing the front-end of their site. props wonderboymusic, beaulebens, helen. see #23347. git-svn-id: https://develop.svn.wordpress.org/trunk@23450 602fd350-edb4-49c9-b593-d223f7449a82 --- wp-includes/default-filters.php | 13 +-- wp-includes/formatting.php | 175 ++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 6 deletions(-) diff --git a/wp-includes/default-filters.php b/wp-includes/default-filters.php index 333cf28132..d6d877ded0 100644 --- a/wp-includes/default-filters.php +++ b/wp-includes/default-filters.php @@ -132,12 +132,13 @@ add_filter( 'the_title', 'wptexturize' ); add_filter( 'the_title', 'convert_chars' ); add_filter( 'the_title', 'trim' ); -add_filter( 'the_content', 'wptexturize' ); -add_filter( 'the_content', 'convert_smilies' ); -add_filter( 'the_content', 'convert_chars' ); -add_filter( 'the_content', 'wpautop' ); -add_filter( 'the_content', 'shortcode_unautop' ); -add_filter( 'the_content', 'prepend_attachment' ); +add_filter( 'the_content', 'post_formats_compat', 7 ); +add_filter( 'the_content', 'wptexturize' ); +add_filter( 'the_content', 'convert_smilies' ); +add_filter( 'the_content', 'convert_chars' ); +add_filter( 'the_content', 'wpautop' ); +add_filter( 'the_content', 'shortcode_unautop' ); +add_filter( 'the_content', 'prepend_attachment' ); add_filter( 'the_excerpt', 'wptexturize' ); add_filter( 'the_excerpt', 'convert_smilies' ); diff --git a/wp-includes/formatting.php b/wp-includes/formatting.php index bd88852e7c..c162a3596f 100644 --- a/wp-includes/formatting.php +++ b/wp-includes/formatting.php @@ -1798,6 +1798,181 @@ function convert_smilies($text) { return $output; } +/** + * Return the class for a post format content wrapper + * + * @since 3.6.0 + * + * @param string $format + */ +function get_post_format_content_class( $format ) { + return apply_filters( 'post_format_content_class', 'post-format-content', $format ); +} + +/** + * Ouput the class for a post format content wrapper + * + * @since 3.6.0 + * + * @param string $format + */ +function post_format_content_class( $format ) { + echo get_post_format_content_class( $format ); +} + +/** + * Provide fallback behavior for Posts that have associated post format + * + * @since 3.6.0 + * + * @param string $content + */ +function post_formats_compat( $content, $id = 0 ) { + $post = empty( $id ) ? get_post() : get_post( $id ); + if ( empty( $post ) ) + return $content; + + $format = get_post_format( $post ); + if ( empty( $format ) || in_array( $format, array( 'status', 'aside', 'chat' ) ) ) + return $content; + + if ( current_theme_supports( 'post-formats', $format ) ) + return $content; + + $defaults = array( + 'position' => 'after', + 'tag' => 'div', + 'class' => get_post_format_content_class( $format ), + 'link_class' => '', + 'image_class' => '', + 'gallery' => '[gallery]', + 'audio' => '', + 'video' => '' + ); + + $args = apply_filters( 'post_format_compat', array() ); + $compat = wp_parse_args( $args, $defaults ); + + $show_content = true; + $format_output = ''; + $meta = get_post_format_meta( $post->ID ); + + switch ( $format ) { + case 'link': + $compat['tag'] = ''; + + if ( ! empty( $meta['url'] ) ) { + $esc_url = preg_quote( $meta['url'], '#' ); + // Make sure the same URL isn't in the post (modified/extended versions allowed) + if ( ! preg_match( '#' . $esc_url . '[^/&\?]#', $content ) ) { + $format_output .= sprintf( + '%s', + empty( $compat['link_class'] ) ? '' : sprintf( 'class="%s" ', esc_attr( $compat['link_class'] ) ), + esc_url( $meta['url'] ), + empty( $post->post_title ) ? esc_url( $meta['url'] ) : apply_filters( 'the_title', $post->post_title ) + ); + } + } + break; + + case 'quote': + if ( ! empty( $meta['quote'] ) && ! stristr( $content, $meta['quote'] ) ) { + $format_output .= sprintf( '
%s
', $meta['quote'] ); + if ( ! empty( $meta['quote_source'] ) ) { + $format_output .= sprintf( + '%s', + ! empty( $meta['url'] ) ? + sprintf( '%s', esc_url( $meta['url'] ), $meta['quote_source'] ) : + $meta['quote_source'] + ); + } + } + break; + + case 'image': + if ( ! empty( $meta['image'] ) ) { + $image = is_numeric( $meta['image'] ) ? wp_get_attachment_url( $meta['image'] ) : $meta['image']; + + if ( ! empty( $image ) && ! stristr( $content, $image ) ) { + $image_html = sprintf( + '', + empty( $compat['image_class'] ) ? '' : sprintf( 'class="%s" ', esc_attr( $compat['image_class'] ) ), + $image + ); + if ( empty( $meta['url'] ) ) { + $format_output .= $image_html; + } else { + $format_output .= sprintf( + '%s', + esc_url( $meta['url'] ), + $image_html + ); + } + } + } + break; + + case 'gallery': + preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches ); + if ( ! empty( $matches ) && isset( $matches[2] ) ) { + foreach ( (array) $matches[2] as $match ) { + if ( 'gallery' === $match ) + break 2; // foreach + case + } + } + + if ( empty( $meta['gallery'] ) && ! empty( $compat['gallery'] ) ) { + $format_output .= $compat['gallery']; + } elseif ( ! empty( $meta['gallery'] ) ) { + $format_output .= $meta['gallery']; + } + break; + + case 'video': + case 'audio': + $shortcode_regex = '/' . get_shortcode_regex() . '/s'; + $matches = preg_match( $shortcode_regex, $content ); + if ( ! $matches || $format !== $matches[2] ) { + if ( empty( $meta['media'] ) && ! empty( $compat[$format] ) ) { + $format_output .= $compat[$format]; + } elseif ( ! empty( $meta['media'] ) ) { + // the metadata is a shortcode or an embed code + if ( preg_match( $shortcode_regex, $meta['media'] ) || preg_match( '#<[^>]+>#', $meta['media'] ) ) { + $format_output .= $meta['media']; + } elseif ( ! stristr( $content, $meta['media'] ) ) { + // attempt to embed the URL + $format_output .= sprintf( '[embed]%s[/embed]', $meta['media'] ); + } + } + } + break; + default: + return $content; + break; + } + + if ( empty( $format_output ) ) + return $content; + + $output = ''; + + if ( ! empty( $content ) && $show_content && 'before' !== $compat['position'] ) + $output .= $content . PHP_EOL . PHP_EOL; + + if ( ! empty( $compat['tag'] ) ) + $output .= sprintf( '<%s class="%s">', tag_escape( $compat['tag'] ), esc_attr( $compat['class'] ) ); + + $output .= $format_output; + + if ( ! empty( $compat['tag'] ) ) + $output .= sprintf( '', tag_escape( $compat['tag'] ) ); + + if ( ! empty( $content ) && $show_content && 'before' === $compat['position'] ) + $output .= PHP_EOL . PHP_EOL . $content; + + return $output; +} + /** * Verifies that an email is valid. *