<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[23450] trunk/wp-includes: Output fallbacks / theme compat for post format metadata.</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg > ul, #logmsg > ol { margin-left: 0; margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://core.trac.wordpress.org/changeset/23450">23450</a></dd>
<dt>Author</dt> <dd>helen</dd>
<dt>Date</dt> <dd>2013-02-18 19:22:58 +0000 (Mon, 18 Feb 2013)</dd>
</dl>

<h3>Log Message</h3>
<pre>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 <a href="http://core.trac.wordpress.org/ticket/23347">#23347</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkwpincludesdefaultfiltersphp">trunk/wp-includes/default-filters.php</a></li>
<li><a href="#trunkwpincludesformattingphp">trunk/wp-includes/formatting.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkwpincludesdefaultfiltersphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/default-filters.php (23449 => 23450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/default-filters.php        2013-02-18 19:11:24 UTC (rev 23449)
+++ trunk/wp-includes/default-filters.php        2013-02-18 19:22:58 UTC (rev 23450)
</span><span class="lines">@@ -132,12 +132,13 @@
</span><span class="cx"> add_filter( 'the_title', 'convert_chars' );
</span><span class="cx"> add_filter( 'the_title', 'trim'          );
</span><span class="cx"> 
</span><del>-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' );
</del><ins>+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'     );
</ins><span class="cx"> 
</span><span class="cx"> add_filter( 'the_excerpt',     'wptexturize'      );
</span><span class="cx"> add_filter( 'the_excerpt',     'convert_smilies'  );
</span></span></pre></div>
<a id="trunkwpincludesformattingphp"></a>
<div class="modfile"><h4>Modified: trunk/wp-includes/formatting.php (23449 => 23450)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/wp-includes/formatting.php        2013-02-18 19:11:24 UTC (rev 23449)
+++ trunk/wp-includes/formatting.php        2013-02-18 19:22:58 UTC (rev 23450)
</span><span class="lines">@@ -1799,6 +1799,181 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> /**
</span><ins>+ * 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' =&gt; 'after',
+                'tag' =&gt; 'div',
+                'class' =&gt; get_post_format_content_class( $format ),
+                'link_class' =&gt; '',
+                'image_class' =&gt; '',
+                'gallery' =&gt; '[gallery]',
+                'audio' =&gt; '',
+                'video' =&gt; ''
+        );
+
+        $args = apply_filters( 'post_format_compat', array() );
+        $compat = wp_parse_args( $args, $defaults );
+
+        $show_content = true;
+        $format_output = '';
+        $meta = get_post_format_meta( $post-&gt;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 . '[^/&amp;\?]#', $content ) ) {
+                                        $format_output .= sprintf(
+                                                '&lt;a %shref=&quot;%s&quot;&gt;%s&lt;/a&gt;',
+                                                empty( $compat['link_class'] ) ? '' : sprintf( 'class=&quot;%s&quot; ', esc_attr( $compat['link_class'] ) ),
+                                                esc_url( $meta['url'] ),
+                                                empty( $post-&gt;post_title ) ? esc_url( $meta['url'] ) : apply_filters( 'the_title', $post-&gt;post_title )
+                                        );
+                                }
+                        }
+                        break;
+
+                case 'quote':
+                        if ( ! empty( $meta['quote'] ) &amp;&amp; ! stristr( $content, $meta['quote'] ) ) {
+                                $format_output .= sprintf( '&lt;blockquote&gt;%s&lt;/blockquote&gt;', $meta['quote'] );
+                                if ( ! empty( $meta['quote_source'] ) ) {
+                                        $format_output .= sprintf(
+                                                '&lt;cite&gt;%s&lt;/cite&gt;',
+                                                ! empty( $meta['url'] ) ?
+                                                        sprintf( '&lt;a href=&quot;%s&quot;&gt;%s&lt;/a&gt;', 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 ) &amp;&amp; ! stristr( $content, $image ) ) {
+                                        $image_html = sprintf(
+                                                '&lt;img %ssrc=&quot;%s&quot; alt=&quot;&quot; /&gt;',
+                                                empty( $compat['image_class'] ) ? '' : sprintf( 'class=&quot;%s&quot; ', esc_attr( $compat['image_class'] ) ),
+                                                $image
+                                        );
+                                        if ( empty( $meta['url'] ) ) {
+                                                $format_output .= $image_html;
+                                        } else {
+                                                $format_output .= sprintf(
+                                                        '&lt;a href=&quot;%s&quot;&gt;%s&lt;/a&gt;',
+                                                        esc_url( $meta['url'] ),
+                                                        $image_html
+                                                );
+                                        }
+                                }
+                        }
+                        break;
+
+                case 'gallery':
+                        preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches );
+                        if ( ! empty( $matches ) &amp;&amp; isset( $matches[2] ) ) {
+                                foreach ( (array) $matches[2] as $match ) {
+                                        if ( 'gallery' === $match )
+                                                break 2; // foreach + case
+                                }
+                        }
+
+                        if ( empty( $meta['gallery'] ) &amp;&amp; ! 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'] ) &amp;&amp; ! 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( '#&lt;[^&gt;]+&gt;#', $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 ) &amp;&amp; $show_content &amp;&amp; 'before' !== $compat['position'] )
+                $output .= $content . PHP_EOL . PHP_EOL;
+
+        if ( ! empty( $compat['tag'] ) )
+                $output .= sprintf( '&lt;%s class=&quot;%s&quot;&gt;', tag_escape( $compat['tag'] ), esc_attr( $compat['class'] ) );
+
+        $output .= $format_output;
+
+        if ( ! empty( $compat['tag'] ) )
+                $output .= sprintf( '&lt;/%s&gt;', tag_escape( $compat['tag'] ) );
+
+        if ( ! empty( $content ) &amp;&amp; $show_content &amp;&amp; 'before' === $compat['position'] )
+                $output .= PHP_EOL . PHP_EOL . $content;
+
+        return $output;
+}
+
+/**
</ins><span class="cx">  * Verifies that an email is valid.
</span><span class="cx">  *
</span><span class="cx">  * Does not grok i18n domains. Not RFC compliant.
</span></span></pre>
</div>
</div>

</body>
</html>