<!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>[27094] trunk: Consolidate handling of <object>, <audio> and <video> in wpautop() and add unit tests for them.</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 { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { 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/27094">27094</a></dd>
<dt>Author</dt> <dd>azaozz</dd>
<dt>Date</dt> <dd>2014-02-05 00:45:53 +0000 (Wed, 05 Feb 2014)</dd>
</dl>

<h3>Log Message</h3>
<pre>Consolidate handling of <object>, <audio> and <video> in wpautop() and add unit tests for them. Part props wonderboymusic, see <a href="http://core.trac.wordpress.org/ticket/26864">#26864</a></pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesformattingphp">trunk/src/wp-includes/formatting.php</a></li>
<li><a href="#trunktestsphpunittestsformattingAutopphp">trunk/tests/phpunit/tests/formatting/Autop.php</a></li>
<li><a href="#trunktestsphpunittestsmediaphp">trunk/tests/phpunit/tests/media.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesformattingphp"></a>
<div class="modfile"><h4>Modified: trunk/src/wp-includes/formatting.php (27093 => 27094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/src/wp-includes/formatting.php     2014-02-05 00:33:49 UTC (rev 27093)
+++ trunk/src/wp-includes/formatting.php        2014-02-05 00:45:53 UTC (rev 27094)
</span><span class="lines">@@ -238,16 +238,30 @@
</span><span class="cx">  $pee = preg_replace('!(<' . $allblocks . '[^>]*>)!', "\n$1", $pee);
</span><span class="cx">  $pee = preg_replace('!(</' . $allblocks . '>)!', "$1\n\n", $pee);
</span><span class="cx">  $pee = str_replace(array("\r\n", "\r"), "\n", $pee); // cross-platform newlines
</span><del>-       if ( strpos($pee, '<object') !== false ) {
-               $pee = preg_replace('|\s*<param([^>]*)>\s*|', "<param$1>", $pee); // no pee inside object/embed
-               $pee = preg_replace('|\s*</embed>\s*|', '</embed>', $pee);
</del><ins>+
+       if ( strpos( $pee, '</object>' ) !== false ) {
+               // no P/BR around param and embed
+               $pee = preg_replace( '|(<object[^>]*>)\s*|', '$1', $pee );
+               $pee = preg_replace( '|\s*</object>|', '</object>', $pee );
+               $pee = preg_replace( '%\s*(</?(?:param|embed)[^>]*>)\s*%', '$1', $pee );
</ins><span class="cx">   }
</span><ins>+
+       if ( strpos( $pee, '<source' ) !== false || strpos( $pee, '<track' ) !== false ) {
+               // no P/BR around source and track
+               $pee = preg_replace( '%([<\[](?:audio|video)[^>\]]*[>\]])\s*%', '$1', $pee );
+               $pee = preg_replace( '%\s*([<\[]/(?:audio|video)[>\]])%', '$1', $pee );
+               $pee = preg_replace( '%\s*(<(?:source|track)[^>]*>)\s*%', '$1', $pee );
+       }
+
</ins><span class="cx">   $pee = preg_replace("/\n\n+/", "\n\n", $pee); // take care of duplicates
</span><span class="cx">  // make paragraphs, including one at the end
</span><span class="cx">  $pees = preg_split('/\n\s*\n/', $pee, -1, PREG_SPLIT_NO_EMPTY);
</span><span class="cx">  $pee = '';
</span><del>-       foreach ( $pees as $tinkle )
</del><ins>+
+       foreach ( $pees as $tinkle ) {
</ins><span class="cx">           $pee .= '<p>' . trim($tinkle, "\n") . "</p>\n";
</span><ins>+       }
+
</ins><span class="cx">   $pee = preg_replace('|<p>\s*</p>|', '', $pee); // under certain strange conditions it could create a P of entirely whitespace
</span><span class="cx">  $pee = preg_replace('!<p>([^<]+)</(div|address|form)>!', "<p>$1</p></$2>", $pee);
</span><span class="cx">  $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee); // don't pee all over a tag
</span><span class="lines">@@ -256,11 +270,13 @@
</span><span class="cx">  $pee = str_replace('</blockquote></p>', '</p></blockquote>', $pee);
</span><span class="cx">  $pee = preg_replace('!<p>\s*(</?' . $allblocks . '[^>]*>)!', "$1", $pee);
</span><span class="cx">  $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*</p>!', "$1", $pee);
</span><ins>+
</ins><span class="cx">   if ( $br ) {
</span><span class="cx">          $pee = preg_replace_callback('/<(script|style).*?<\/\\1>/s', '_autop_newline_preservation_helper', $pee);
</span><span class="cx">          $pee = preg_replace('|(?<!<br />)\s*\n|', "<br />\n", $pee); // optionally make line breaks
</span><span class="cx">          $pee = str_replace('<WPPreserveNewline />', "\n", $pee);
</span><span class="cx">  }
</span><ins>+
</ins><span class="cx">   $pee = preg_replace('!(</?' . $allblocks . '[^>]*>)\s*<br />!', "$1", $pee);
</span><span class="cx">  $pee = preg_replace('!<br />(\s*</?(?:p|li|div|dl|dd|dt|th|pre|td|ul|ol)[^>]*>)!', '$1', $pee);
</span><span class="cx">  $pee = preg_replace( "|\n</p>$|", '</p>', $pee );
</span></span></pre></div>
<a id="trunktestsphpunittestsformattingAutopphp"></a>
<div class="modfile"><h4>Modified: trunk/tests/phpunit/tests/formatting/Autop.php (27093 => 27094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/phpunit/tests/formatting/Autop.php   2014-02-05 00:33:49 UTC (rev 27093)
+++ trunk/tests/phpunit/tests/formatting/Autop.php      2014-02-05 00:45:53 UTC (rev 27094)
</span><span class="lines">@@ -98,4 +98,169 @@
</span><span class="cx">          $str = 'Username: <input type="text" id="username" name="username" /><br />Password: <input type="password" id="password1" name="password1" />';
</span><span class="cx">          $this->assertEquals( "<p>$str</p>", trim( wpautop( $str ) ) );
</span><span class="cx">  }
</span><ins>+
+       /**
+        * wpautop() Should not add <p> and <br/> around <source> and <track>
+        *
+        * @ticket 26864
+        */
+       public function test_source_track_elements() {
+               $content = "Paragraph one.\n\n" .
+                       '<video class="wp-video-shortcode" id="video-0-1" width="640" height="360" preload="metadata" controls="controls">
+                               <source type="video/mp4" src="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4" />
+                               <!-- WebM/VP8 for Firefox4, Opera, and Chrome -->
+                               <source type="video/webm" src="myvideo.webm" />
+                               <!-- Ogg/Vorbis for older Firefox and Opera versions -->
+                               <source type="video/ogg" src="myvideo.ogv" />
+                               <!-- Optional: Add subtitles for each language -->
+                               <track kind="subtitles" src="subtitles.srt" srclang="en" />
+                               <!-- Optional: Add chapters -->
+                               <track kind="chapters" src="chapters.srt" srclang="en" />
+                               <a href="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4">http://domain.tld/wp-content/uploads/2013/12/xyz.mp4</a>
+                       </video>' .
+                       "\n\nParagraph two.";
+
+               $content2 = "Paragraph one.\n\n" .
+                       '<video class="wp-video-shortcode" id="video-0-1" width="640" height="360" preload="metadata" controls="controls">
+
+                       <source type="video/mp4" src="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4" />
+
+                       <!-- WebM/VP8 for Firefox4, Opera, and Chrome -->
+                       <source type="video/webm" src="myvideo.webm" />
+
+                       <!-- Ogg/Vorbis for older Firefox and Opera versions -->
+                       <source type="video/ogg" src="myvideo.ogv" />
+
+                       <!-- Optional: Add subtitles for each language -->
+                       <track kind="subtitles" src="subtitles.srt" srclang="en" />
+
+                       <!-- Optional: Add chapters -->
+                       <track kind="chapters" src="chapters.srt" srclang="en" />
+
+                       <a href="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4">http://domain.tld/wp-content/uploads/2013/12/xyz.mp4</a>
+
+                       </video>' .
+                       "\n\nParagraph two.";
+
+               $expected = "<p>Paragraph one.</p>\n" . // line breaks only after <p>
+                       '<p><video class="wp-video-shortcode" id="video-0-1" width="640" height="360" preload="metadata" controls="controls">' .
+                       '<source type="video/mp4" src="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4" />' .
+                       '<!-- WebM/VP8 for Firefox4, Opera, and Chrome -->' .
+                       '<source type="video/webm" src="myvideo.webm" />' .
+                       '<!-- Ogg/Vorbis for older Firefox and Opera versions -->' .
+                       '<source type="video/ogg" src="myvideo.ogv" />' .
+                       '<!-- Optional: Add subtitles for each language -->' .
+                       '<track kind="subtitles" src="subtitles.srt" srclang="en" />' .
+                       '<!-- Optional: Add chapters -->' .
+                       '<track kind="chapters" src="chapters.srt" srclang="en" />' .
+                       '<a href="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4">' .
+                       "http://domain.tld/wp-content/uploads/2013/12/xyz.mp4</a></video></p>\n" .
+                       '<p>Paragraph two.</p>';
+
+               // When running the content through wpautop() from wp_richedit_pre()
+               $shortcode_content = "Paragraph one.\n\n" .
+                       '[video width="720" height="480" mp4="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4"]
+                       <!-- WebM/VP8 for Firefox4, Opera, and Chrome -->
+                       <source type="video/webm" src="myvideo.webm" />
+                       <!-- Ogg/Vorbis for older Firefox and Opera versions -->
+                       <source type="video/ogg" src="myvideo.ogv" />
+                       <!-- Optional: Add subtitles for each language -->
+                       <track kind="subtitles" src="subtitles.srt" srclang="en" />
+                       <!-- Optional: Add chapters -->
+                       <track kind="chapters" src="chapters.srt" srclang="en" />
+                       [/video]' .
+                       "\n\nParagraph two.";
+
+               $shortcode_expected = "<p>Paragraph one.</p>\n" . // line breaks only after <p>
+                       '<p>[video width="720" height="480" mp4="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4"]' .
+                       '<!-- WebM/VP8 for Firefox4, Opera, and Chrome --><source type="video/webm" src="myvideo.webm" />' .
+                       '<!-- Ogg/Vorbis for older Firefox and Opera versions --><source type="video/ogg" src="myvideo.ogv" />' .
+                       '<!-- Optional: Add subtitles for each language --><track kind="subtitles" src="subtitles.srt" srclang="en" />' .
+                       '<!-- Optional: Add chapters --><track kind="chapters" src="chapters.srt" srclang="en" />' .
+                       "[/video]</p>\n" .
+                       '<p>Paragraph two.</p>';
+
+               $this->assertEquals( $expected, trim( wpautop( $content ) ) );
+               $this->assertEquals( $expected, trim( wpautop( $content2 ) ) );
+               $this->assertEquals( $shortcode_expected, trim( wpautop( $shortcode_content ) ) );
+       }
+
+       /**
+        * wpautop() Should not add <p> and <br/> around <param> and <embed>
+        *
+        * @ticket 26864
+        */
+       public function test_param_embed_elements() {
+               $content1 = '
+Paragraph one.
+
+<object width="400" height="224" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">
+       <param name="src" value="http://domain.tld/wp-content/uploads/2013/12/xyz.swf" />
+       <param name="allowfullscreen" value="true" />
+       <param name="allowscriptaccess" value="always" />
+       <param name="overstretch" value="true" />
+       <param name="flashvars" value="isDynamicSeeking=true" />
+
+       <embed width="400" height="224" type="application/x-shockwave-flash" src="http://domain.tld/wp-content/uploads/2013/12/xyz.swf" wmode="direct" seamlesstabbing="true" allowfullscreen="true" overstretch="true" flashvars="isDynamicSeeking=true" />
+</object>
+
+Paragraph two.';
+
+               $expected1 = "<p>Paragraph one.</p>\n" . // line breaks only after <p>
+                       '<p><object width="400" height="224" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0">' .
+                       '<param name="src" value="http://domain.tld/wp-content/uploads/2013/12/xyz.swf" />' .
+                       '<param name="allowfullscreen" value="true" />' .
+                       '<param name="allowscriptaccess" value="always" />' .
+                       '<param name="overstretch" value="true" />' .
+                       '<param name="flashvars" value="isDynamicSeeking=true" />' .
+                       '<embed width="400" height="224" type="application/x-shockwave-flash" src="http://domain.tld/wp-content/uploads/2013/12/xyz.swf" wmode="direct" seamlesstabbing="true" allowfullscreen="true" overstretch="true" flashvars="isDynamicSeeking=true" />' .
+                       "</object></p>\n" .
+                       '<p>Paragraph two.</p>';
+
+               $content2 = '
+Paragraph one.
+
+<div class="video-player" id="x-video-0">
+<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="640" height="360" id="video-0" standby="Standby text">
+  <param name="movie" value="http://domain.tld/wp-content/uploads/2013/12/xyz.swf" />
+  <param name="quality" value="best" />
+
+  <param name="seamlesstabbing" value="true" />
+  <param name="allowfullscreen" value="true" />
+  <param name="allowscriptaccess" value="always" />
+  <param name="overstretch" value="true" />
+
+  <!--[if !IE]--><object type="application/x-shockwave-flash" data="http://domain.tld/wp-content/uploads/2013/12/xyz.swf" width="640" height="360" standby="Standby text">
+    <param name="quality" value="best" />
+
+    <param name="seamlesstabbing" value="true" />
+    <param name="allowfullscreen" value="true" />
+    <param name="allowscriptaccess" value="always" />
+    <param name="overstretch" value="true" />
+  </object><!--<![endif]-->
+</object></div>
+
+Paragraph two.';
+
+               $expected2 = "<p>Paragraph one.</p>\n" . // line breaks only after block tags
+                       '<div class="video-player" id="x-video-0">' . "\n" .
+                       '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="640" height="360" id="video-0" standby="Standby text">' .
+                       '<param name="movie" value="http://domain.tld/wp-content/uploads/2013/12/xyz.swf" />' .
+                       '<param name="quality" value="best" />' .
+                       '<param name="seamlesstabbing" value="true" />' .
+                       '<param name="allowfullscreen" value="true" />' .
+                       '<param name="allowscriptaccess" value="always" />' .
+                       '<param name="overstretch" value="true" />' .
+                       '<!--[if !IE]--><object type="application/x-shockwave-flash" data="http://domain.tld/wp-content/uploads/2013/12/xyz.swf" width="640" height="360" standby="Standby text">' .
+                       '<param name="quality" value="best" />' .
+                       '<param name="seamlesstabbing" value="true" />' .
+                       '<param name="allowfullscreen" value="true" />' .
+                       '<param name="allowscriptaccess" value="always" />' .
+                       '<param name="overstretch" value="true" /></object><!--<![endif]-->' .
+                       "</object></div>\n" .
+                       '<p>Paragraph two.</p>';
+
+               $this->assertEquals( $expected1, trim( wpautop( $content1 ) ) );
+               $this->assertEquals( $expected2, trim( wpautop( $content2 ) ) );
+       }
</ins><span class="cx"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsmediaphp"></a>
<div class="modfile"><h4>Modified: trunk/tests/phpunit/tests/media.php (27093 => 27094)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/tests/phpunit/tests/media.php      2014-02-05 00:33:49 UTC (rev 27093)
+++ trunk/tests/phpunit/tests/media.php 2014-02-05 00:45:53 UTC (rev 27094)
</span><span class="lines">@@ -364,4 +364,45 @@
</span><span class="cx">          $matches = get_media_embedded_in_content( $content, $types );
</span><span class="cx">          $this->assertEquals( $contents, $matches );
</span><span class="cx">  }
</span><ins>+
+       /**
+        * Test [video] shortcode processing
+        *
+        * @ticket 26864
+        */
+       function test_video_shortcode_body() {
+               $width = 720;
+               $height = 480;
+
+               $video =<<<VIDEO
+[video width="720" height="480" mp4="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4"]
+<!-- WebM/VP8 for Firefox4, Opera, and Chrome -->
+<source type="video/webm" src="myvideo.webm" />
+<!-- Ogg/Vorbis for older Firefox and Opera versions -->
+<source type="video/ogg" src="myvideo.ogv" />
+<!-- Optional: Add subtitles for each language -->
+<track kind="subtitles" src="subtitles.srt" srclang="en" />
+<!-- Optional: Add chapters -->
+<track kind="chapters" src="chapters.srt" srclang="en" />
+[/video]
+VIDEO;
+
+               $w = $GLOBALS['content_width'];
+               $h = ceil( ( $height * $w ) / $width );
+
+               $content = apply_filters( 'the_content', $video );
+
+               $expected = '<div style="width: ' . $w . 'px; max-width: 100%;" class="wp-video">' .
+                       "<!--[if lt IE 9]><script>document.createElement(\'video\');</script><![endif]-->\n" .
+                       '<video class="wp-video-shortcode" id="video-0-1" width="' . $w . '" height="' . $h . '" preload="metadata" controls="controls">' .
+                       '<source type="video/mp4" src="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4" />' .
+                       '<!-- WebM/VP8 for Firefox4, Opera, and Chrome --><source type="video/webm" src="myvideo.webm" />' .
+                       '<!-- Ogg/Vorbis for older Firefox and Opera versions --><source type="video/ogg" src="myvideo.ogv" />' .
+                       '<!-- Optional: Add subtitles for each language --><track kind="subtitles" src="subtitles.srt" srclang="en" />' .
+                       '<!-- Optional: Add chapters --><track kind="chapters" src="chapters.srt" srclang="en" />' .
+                       '<a href="http://domain.tld/wp-content/uploads/2013/12/xyz.mp4">' .
+                       "http://domain.tld/wp-content/uploads/2013/12/xyz.mp4</a></video></div>\n";
+
+               $this->assertEquals( $expected, $content );
+       }
</ins><span class="cx"> }
</span></span></pre>
</div>
</div>

</body>
</html>