<!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>[44941] trunk: Posts: Avoid the use of globals in `get_the_content()` and related functions.</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 { white-space: pre-line; 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" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/44941">44941</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/44941","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>boonebgorges</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2019-03-20 15:48:46 +0000 (Wed, 20 Mar 2019)</dd>
</dl>

<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Posts: Avoid the use of globals in `get_the_content()` and related functions.

This changeset introduces `$post` parameters to `get_the_content()` and
`wp_trim_excerpt()`. When a `$post` object is passed to one of these functions,
the functions will operate on the data from that object, rather than from the
post globals (`$authordata`, `$page`, etc). This ensures that the functions work
in a predictable manner when used outside of the regular post loop.

The global-mismatch problem is surfaced in cases where `get_the_excerpt()` is
called outside of the post loop, on posts that don't have a defined excerpt. In
these cases, the post globals - used to generate a fallback excerpt - may refer
to the incorrect object, resulting in PHP notices or other unpredictable
behavior. See <a href="https://core.trac.wordpress.org/ticket/36934">#36934</a> for a related issue.

Props spacedmonkey, kraftbj, Shital Patel.
Fixes <a href="https://core.trac.wordpress.org/ticket/42814">#42814</a>.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunksrcwpincludesclasswpqueryphp">trunk/src/wp-includes/class-wp-query.php</a></li>
<li><a href="#trunksrcwpincludesdefaultfiltersphp">trunk/src/wp-includes/default-filters.php</a></li>
<li><a href="#trunksrcwpincludesformattingphp">trunk/src/wp-includes/formatting.php</a></li>
<li><a href="#trunksrcwpincludesposttemplatephp">trunk/src/wp-includes/post-template.php</a></li>
<li><a href="#trunksrcwpincludesqueryphp">trunk/src/wp-includes/query.php</a></li>
<li><a href="#trunktestsphpunittestspostgetTheExcerptphp">trunk/tests/phpunit/tests/post/getTheExcerpt.php</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunktestsphpunittestspostgetTheContentphp">trunk/tests/phpunit/tests/post/getTheContent.php</a></li>
<li><a href="#trunktestsphpunittestsquerygeneratePostdataphp">trunk/tests/phpunit/tests/query/generatePostdata.php</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunksrcwpincludesclasswpqueryphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-query.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-query.php  2019-03-20 15:42:09 UTC (rev 44940)
+++ trunk/src/wp-includes/class-wp-query.php    2019-03-20 15:48:46 UTC (rev 44941)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4155,6 +4155,42 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        return;
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                $elements = $this->generate_postdata( $post );
+               if ( false === $elements ) {
+                       return;
+               }
+
+               $id           = $elements['id'];
+               $authordata   = $elements['authordata'];
+               $currentday   = $elements['currentday'];
+               $currentmonth = $elements['currentmonth'];
+               $page         = $elements['page'];
+               $pages        = $elements['pages'];
+               $multipage    = $elements['multipage'];
+               $more         = $elements['more'];
+               $numpages     = $elements['numpages'];
+
+               return true;
+       }
+
+       /**
+        * Generate post data.
+        *
+        * @since 5.2.0
+        *
+        * @param WP_Post|object|int $post WP_Post instance or Post ID/object.
+        * @return array|bool $elements Elements of post or false on failure.
+        */
+       public function generate_postdata( $post ) {
+
+               if ( ! ( $post instanceof WP_Post ) ) {
+                       $post = get_post( $post );
+               }
+
+               if ( ! $post ) {
+                       return false;
+               }
+
</ins><span class="cx" style="display: block; padding: 0 10px">                 $id = (int) $post->ID;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $authordata = get_userdata( $post->post_author );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -4235,7 +4271,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">                 */
</span><span class="cx" style="display: block; padding: 0 10px">                do_action_ref_array( 'the_post', array( &$post, &$this ) );
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                return true;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $elements = compact( 'id', 'authordata', 'currentday', 'currentmonth', 'page', 'pages', 'multipage', 'more', 'numpages' );
+
+               return $elements;
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px">        /**
</span><span class="cx" style="display: block; padding: 0 10px">         * After looping through a nested query, this function
</span></span></pre></div>
<a id="trunksrcwpincludesdefaultfiltersphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/default-filters.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/default-filters.php 2019-03-20 15:42:09 UTC (rev 44940)
+++ trunk/src/wp-includes/default-filters.php   2019-03-20 15:48:46 UTC (rev 44941)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -182,7 +182,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'the_excerpt', 'convert_chars' );
</span><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'the_excerpt', 'wpautop' );
</span><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'the_excerpt', 'shortcode_unautop' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-add_filter( 'get_the_excerpt', 'wp_trim_excerpt' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+add_filter( 'get_the_excerpt', 'wp_trim_excerpt', 10, 2 );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'the_post_thumbnail_caption', 'wptexturize' );
</span><span class="cx" style="display: block; padding: 0 10px"> add_filter( 'the_post_thumbnail_caption', 'convert_smilies' );
</span></span></pre></div>
<a id="trunksrcwpincludesformattingphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/formatting.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/formatting.php      2019-03-20 15:42:09 UTC (rev 44940)
+++ trunk/src/wp-includes/formatting.php        2019-03-20 15:48:46 UTC (rev 44941)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -3678,14 +3678,17 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * The ' [&hellip;]' string can be modified by plugins/themes using the {@see 'excerpt_more'} filter
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @since 1.5.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.2.0 Added the `$post` parameter.
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param string $text Optional. The excerpt. If set to empty, an excerpt is generated.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string             $text Optional. The excerpt. If set to empty, an excerpt is generated.
+ * @param WP_Post|object|int $post Optional. WP_Post instance or Post ID/object. Default is null.
</ins><span class="cx" style="display: block; padding: 0 10px">  * @return string The excerpt.
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function wp_trim_excerpt( $text = '' ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function wp_trim_excerpt( $text = '', $post = null ) {
</ins><span class="cx" style="display: block; padding: 0 10px">         $raw_excerpt = $text;
</span><span class="cx" style="display: block; padding: 0 10px">        if ( '' == $text ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                $text = get_the_content( '' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         $post = get_post( $post );
+               $text = get_the_content( '', false, $post );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">                $text = strip_shortcodes( $text );
</span><span class="cx" style="display: block; padding: 0 10px">                $text = excerpt_remove_blocks( $text );
</span></span></pre></div>
<a id="trunksrcwpincludesposttemplatephp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/post-template.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/post-template.php   2019-03-20 15:42:09 UTC (rev 44940)
+++ trunk/src/wp-includes/post-template.php     2019-03-20 15:48:46 UTC (rev 44941)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -253,6 +253,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">  * Retrieve the post content.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @since 0.71
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 5.2.0 Added the `$post` parameter.
</ins><span class="cx" style="display: block; padding: 0 10px">  *
</span><span class="cx" style="display: block; padding: 0 10px">  * @global int   $page      Page number of a single post/page.
</span><span class="cx" style="display: block; padding: 0 10px">  * @global int   $more      Boolean indicator for whether single post/page is being viewed.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -261,15 +262,26 @@
</span><span class="cx" style="display: block; padding: 0 10px">  *                          part of the content separated by the `<!--nextpage-->` tag.
</span><span class="cx" style="display: block; padding: 0 10px">  * @global int   $multipage Boolean indicator for whether multiple pages are in play.
</span><span class="cx" style="display: block; padding: 0 10px">  *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param string $more_link_text Optional. Content for when there is more text.
- * @param bool   $strip_teaser   Optional. Strip teaser content before the more text. Default is false.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string             $more_link_text Optional. Content for when there is more text.
+ * @param bool               $strip_teaser   Optional. Strip teaser content before the more text. Default is false.
+ * @param WP_Post|object|int $post           Optional. WP_Post instance or Post ID/object. Default is null.
</ins><span class="cx" style="display: block; padding: 0 10px">  * @return string
</span><span class="cx" style="display: block; padding: 0 10px">  */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function get_the_content( $more_link_text = null, $strip_teaser = false ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function get_the_content( $more_link_text = null, $strip_teaser = false, $post = null ) {
</ins><span class="cx" style="display: block; padding: 0 10px">         global $page, $more, $preview, $pages, $multipage;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $post = get_post();
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $_post = get_post( $post );
</ins><span class="cx" style="display: block; padding: 0 10px"> 
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+        if ( ! ( $_post instanceof WP_Post ) ) {
+               return '';
+       }
+
+       if ( null === $post ) {
+               $elements = compact( 'page', 'more', 'preview', 'pages', 'multipage' );
+       } else {
+               $elements = generate_postdata( $_post );
+       }
+
</ins><span class="cx" style="display: block; padding: 0 10px">         if ( null === $more_link_text ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $more_link_text = sprintf(
</span><span class="cx" style="display: block; padding: 0 10px">                        '<span aria-label="%1$s">%2$s</span>',
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -276,7 +288,12 @@
</span><span class="cx" style="display: block; padding: 0 10px">                        sprintf(
</span><span class="cx" style="display: block; padding: 0 10px">                                /* translators: %s: Name of current post */
</span><span class="cx" style="display: block; padding: 0 10px">                                __( 'Continue reading %s' ),
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                the_title_attribute( array( 'echo' => false ) )
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         the_title_attribute(
+                                       array(
+                                               'echo' => false,
+                                               'post' => $_post,
+                                       )
+                               )
</ins><span class="cx" style="display: block; padding: 0 10px">                         ),
</span><span class="cx" style="display: block; padding: 0 10px">                        __( '(more&hellip;)' )
</span><span class="cx" style="display: block; padding: 0 10px">                );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -286,15 +303,16 @@
</span><span class="cx" style="display: block; padding: 0 10px">        $has_teaser = false;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        // If post password required and it doesn't match the cookie.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( post_password_required( $post ) ) {
-               return get_the_password_form( $post );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( post_password_required( $_post ) ) {
+               return get_the_password_form( $_post );
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( $page > count( $pages ) ) { // if the requested page doesn't exist
-               $page = count( $pages ); // give them the highest numbered page that DOES exist
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $elements['page'] > count( $elements['pages'] ) ) { // if the requested page doesn't exist
+               $elements['page'] = count( $elements['pages'] ); // give them the highest numbered page that DOES exist
</ins><span class="cx" style="display: block; padding: 0 10px">         }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        $content = $pages[ $page - 1 ];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $page_no = $elements['page'];
+       $content = $elements['pages'][ $page_no - 1 ];
</ins><span class="cx" style="display: block; padding: 0 10px">         if ( preg_match( '/<!--more(.*?)?-->/', $content, $matches ) ) {
</span><span class="cx" style="display: block; padding: 0 10px">                $content = explode( $matches[0], $content, 2 );
</span><span class="cx" style="display: block; padding: 0 10px">                if ( ! empty( $matches[1] ) && ! empty( $more_link_text ) ) {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -306,13 +324,13 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $content = array( $content );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( false !== strpos( $post->post_content, '<!--noteaser-->' ) && ( ! $multipage || $page == 1 ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( false !== strpos( $_post->post_content, '<!--noteaser-->' ) && ( ! $elements['multipage'] || $elements['page'] == 1 ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 $strip_teaser = true;
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        $teaser = $content[0];
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-        if ( $more && $strip_teaser && $has_teaser ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $elements['more'] && $strip_teaser && $has_teaser ) {
</ins><span class="cx" style="display: block; padding: 0 10px">                 $teaser = '';
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -319,8 +337,8 @@
</span><span class="cx" style="display: block; padding: 0 10px">        $output .= $teaser;
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        if ( count( $content ) > 1 ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                if ( $more ) {
-                       $output .= '<span id="more-' . $post->ID . '"></span>' . $content[1];
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+         if ( $elements['more'] ) {
+                       $output .= '<span id="more-' . $_post->ID . '"></span>' . $content[1];
</ins><span class="cx" style="display: block; padding: 0 10px">                 } else {
</span><span class="cx" style="display: block; padding: 0 10px">                        if ( ! empty( $more_link_text ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -332,7 +350,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">                                 * @param string $more_link_element Read More link element.
</span><span class="cx" style="display: block; padding: 0 10px">                                 * @param string $more_link_text    Read More text.
</span><span class="cx" style="display: block; padding: 0 10px">                                 */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-                                $output .= apply_filters( 'the_content_more_link', ' <a href="' . get_permalink() . "#more-{$post->ID}\" class=\"more-link\">$more_link_text</a>", $more_link_text );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+                         $output .= apply_filters( 'the_content_more_link', ' <a href="' . get_permalink( $_post ) . "#more-{$_post->ID}\" class=\"more-link\">$more_link_text</a>", $more_link_text );
</ins><span class="cx" style="display: block; padding: 0 10px">                         }
</span><span class="cx" style="display: block; padding: 0 10px">                        $output = force_balance_tags( $output );
</span><span class="cx" style="display: block; padding: 0 10px">                }
</span></span></pre></div>
<a id="trunksrcwpincludesqueryphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/query.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/query.php   2019-03-20 15:42:09 UTC (rev 44940)
+++ trunk/src/wp-includes/query.php     2019-03-20 15:48:46 UTC (rev 44941)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1111,3 +1111,23 @@
</span><span class="cx" style="display: block; padding: 0 10px"> 
</span><span class="cx" style="display: block; padding: 0 10px">        return false;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+/**
+ * Generates post data.
+ *
+ * @since 5.2.0
+ *
+ * @global WP_Query $wp_query Global WP_Query instance.
+ *
+ * @param WP_Post|object|int $post WP_Post instance or Post ID/object.
+ * @return array|bool Elements of post, or false on failure.
+ */
+function generate_postdata( $post ) {
+       global $wp_query;
+
+       if ( ! empty( $wp_query ) && $wp_query instanceof WP_Query ) {
+               return $wp_query->generate_postdata( $post );
+       }
+
+       return false;
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestspostgetTheContentphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/post/getTheContent.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/post/getTheContent.php                          (rev 0)
+++ trunk/tests/phpunit/tests/post/getTheContent.php    2019-03-20 15:48:46 UTC (rev 44941)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,78 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * @group post
+ * @group formatting
+ */
+class Tests_Post_GetTheContent extends WP_UnitTestCase {
+       /**
+        * @ticket 42814
+        */
+       public function test_argument_back_compat_more_link_text() {
+               $text = 'Foo<!--more-->Bar';
+               $p    = self::factory()->post->create( array( 'post_content' => $text ) );
+
+               $q = new WP_Query( array( 'p' => $p ) );
+               while ( $q->have_posts() ) {
+                       $q->the_post();
+
+                       $found = get_the_content( 'Ping' );
+               }
+
+               $this->assertContains( '>Ping<', $found );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_argument_back_compat_strip_teaser() {
+               $text = 'Foo<!--more-->Bar';
+               $p    = self::factory()->post->create( array( 'post_content' => $text ) );
+
+               $this->go_to( get_permalink( $p ) );
+
+               $q = new WP_Query( array( 'p' => $p ) );
+               while ( $q->have_posts() ) {
+                       $q->the_post();
+
+                       $found = get_the_content( null, true );
+               }
+
+               $this->assertNotContains( 'Foo', $found );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_content_other_post() {
+               $text_1 = 'Foo<!--nextpage-->Bar<!--nextpage-->Baz';
+               $post_1 = self::factory()->post->create_and_get( array( 'post_content' => $text_1 ) );
+
+               $text_2 = 'Bing<!--nextpage-->Bang<!--nextpage-->Boom';
+               $post_2 = self::factory()->post->create_and_get( array( 'post_content' => $text_2 ) );
+               setup_postdata( $post_1 );
+               $found = get_the_content( null, true, $post_2 );
+
+               $this->assertSame( 'Bing', $found );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_should_respect_pagination_of_inner_post() {
+               $text_1 = 'Foo<!--nextpage-->Bar<!--nextpage-->Baz';
+               $post_1 = self::factory()->post->create_and_get( array( 'post_content' => $text_1 ) );
+
+               $text_2 = 'Bing<!--nextpage-->Bang<!--nextpage-->Boom';
+               $post_2 = self::factory()->post->create_and_get( array( 'post_content' => $text_2 ) );
+               $go_to  = add_query_arg( 'page', '2', get_permalink( $post_1->ID ) );
+               $this->go_to( $go_to );
+
+               while ( have_posts() ) {
+                       the_post();
+                       $found = get_the_content( '', false, $post_2 );
+               }
+
+               $this->assertSame( 'Bang', $found );
+       }
+}
</ins></span></pre></div>
<a id="trunktestsphpunittestspostgetTheExcerptphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/post/getTheExcerpt.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/post/getTheExcerpt.php  2019-03-20 15:42:09 UTC (rev 44940)
+++ trunk/tests/phpunit/tests/post/getTheExcerpt.php    2019-03-20 15:48:46 UTC (rev 44941)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -57,4 +57,92 @@
</span><span class="cx" style="display: block; padding: 0 10px">                $post_id         = self::factory()->post->create( array( 'post_excerpt' => 'Bar' ) );
</span><span class="cx" style="display: block; padding: 0 10px">                $this->assertSame( 'Bar', get_the_excerpt( $post_id ) );
</span><span class="cx" style="display: block; padding: 0 10px">        }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+       /**
+        * @ticket 42814
+        */
+       public function test_should_fall_back_on_post_content_if_excerpt_is_empty_and_post_is_inferred_from_context() {
+               $post_id = self::factory()->post->create(
+                       array(
+                               'post_content' => 'Foo',
+                               'post_excerpt' => '',
+                       )
+               );
+
+               $q = new WP_Query(
+                       array(
+                               'p' => $post_id,
+                       )
+               );
+
+               while ( $q->have_posts() ) {
+                       $q->the_post();
+                       $found = get_the_excerpt();
+               }
+
+               $this->assertSame( 'Foo', $found );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_should_fall_back_on_post_content_if_excerpt_is_empty_and_post_is_provided() {
+               $GLOBALS['post'] = self::factory()->post->create_and_get(
+                       array(
+                               'post_content' => 'Foo',
+                               'post_excerpt' => '',
+                       )
+               );
+               $this->assertSame( 'Foo', get_the_excerpt( $GLOBALS['post'] ) );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_should_respect_post_parameter_in_the_loop() {
+               $p1 = self::factory()->post->create_and_get( array( 'post_excerpt' => 'Foo' ) );
+               $p2 = self::factory()->post->create_and_get( array( 'post_excerpt' => 'Bar' ) );
+               $q  = new WP_Query(
+                       array(
+                               'p' => $p1->ID,
+                       )
+               );
+
+               while ( $q->have_posts() ) {
+                       $q->the_post();
+                       $found = get_the_excerpt( $p2 );
+               }
+
+               $this->assertSame( 'Bar', $found );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_should_respect_post_parameter_in_the_loop_when_falling_back_on_post_content() {
+               $p1 = self::factory()->post->create_and_get(
+                       array(
+                               'post_content' => 'Foo',
+                               'post_excerpt' => '',
+                       )
+               );
+               $p2 = self::factory()->post->create_and_get(
+                       array(
+                               'post_content' => 'Bar',
+                               'post_excerpt' => '',
+                       )
+               );
+               $q  = new WP_Query(
+                       array(
+                               'p' => $p1->ID,
+                       )
+               );
+
+               while ( $q->have_posts() ) {
+                       $q->the_post();
+                       $found = get_the_excerpt( $p2 );
+               }
+
+               $this->assertSame( 'Bar', $found );
+       }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunktestsphpunittestsquerygeneratePostdataphp"></a>
<div class="addfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Added: trunk/tests/phpunit/tests/query/generatePostdata.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/query/generatePostdata.php                              (rev 0)
+++ trunk/tests/phpunit/tests/query/generatePostdata.php        2019-03-20 15:48:46 UTC (rev 44941)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -0,0 +1,145 @@
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+<?php
+
+/**
+ * @group query
+ * @covers ::generate_postdata
+ */
+class Tests_Query_GeneratePostdata extends WP_UnitTestCase {
+
+       /**
+        * @ticket 42814
+        */
+       public function test_setup_by_id() {
+               $p    = self::factory()->post->create_and_get();
+               $data = generate_postdata( $p->ID );
+               $this->assertSame( $p->ID, $data['id'] );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_setup_by_fake_post() {
+               $fake     = new stdClass;
+               $fake->ID = 98765;
+               $data     = generate_postdata( $fake->ID );
+
+               // Fails because there's no post with this ID.
+               $this->assertNotSame( $fake->ID, $data['id'] );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_setup_by_postish_object() {
+               $p = self::factory()->post->create();
+
+               $post     = new stdClass();
+               $post->ID = $p;
+               $data     = generate_postdata( $p );
+
+               $this->assertSame( $p, $data['id'] );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_authordata() {
+               $u    = self::factory()->user->create_and_get();
+               $p    = self::factory()->post->create_and_get(
+                       array(
+                               'post_author' => $u->ID,
+                       )
+               );
+               $data = generate_postdata( $p );
+
+               $this->assertNotEmpty( $data['authordata'] );
+               $this->assertEquals( $u, $data['authordata'] );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_currentday() {
+               $p    = self::factory()->post->create_and_get(
+                       array(
+                               'post_date' => '1980-09-09 06:30:00',
+                       )
+               );
+               $data = generate_postdata( $p );
+
+               $this->assertSame( '09.09.80', $data['currentday'] );
+       }
+
+       public function test_currentmonth() {
+               $p    = self::factory()->post->create_and_get(
+                       array(
+                               'post_date' => '1980-09-09 06:30:00',
+                       )
+               );
+               $data = generate_postdata( $p );
+
+               $this->assertSame( '09', $data['currentmonth'] );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_single_page() {
+               $post = self::factory()->post->create_and_get(
+                       array(
+                               'post_content' => 'Page 0',
+                       )
+               );
+               $data = generate_postdata( $post );
+
+               $this->assertSame( 0, $data['multipage'] );
+               $this->assertSame( 1, $data['numpages'] );
+               $this->assertEquals( array( 'Page 0' ), $data['pages'] );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_multi_page() {
+               $post = self::factory()->post->create_and_get(
+                       array(
+                               'post_content' => 'Page 0<!--nextpage-->Page 1<!--nextpage-->Page 2<!--nextpage-->Page 3',
+                       )
+               );
+               $data = generate_postdata( $post );
+
+               $this->assertSame( 1, $data['multipage'] );
+               $this->assertSame( 4, $data['numpages'] );
+               $this->assertEquals( array( 'Page 0', 'Page 1', 'Page 2', 'Page 3' ), $data['pages'] );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_nextpage_at_start_of_content() {
+               $post = self::factory()->post->create_and_get(
+                       array(
+                               'post_content' => '<!--nextpage-->Page 1<!--nextpage-->Page 2<!--nextpage-->Page 3',
+                       )
+               );
+               $data = generate_postdata( $post );
+
+               $this->assertSame( 1, $data['multipage'] );
+               $this->assertSame( 3, $data['numpages'] );
+               $this->assertEquals( array( 'Page 1', 'Page 2', 'Page 3' ), $data['pages'] );
+       }
+
+       /**
+        * @ticket 42814
+        */
+       public function test_trim_nextpage_linebreaks() {
+               $post = self::factory()->post->create_and_get(
+                       array(
+                               'post_content' => "Page 0\n<!--nextpage-->\nPage 1\nhas a line break\n<!--nextpage-->Page 2<!--nextpage-->\n\nPage 3",
+                       )
+               );
+               $data = generate_postdata( $post );
+
+               $this->assertEquals( array( 'Page 0', "Page 1\nhas a line break", 'Page 2', "\nPage 3" ), $data['pages'] );
+       }
+}
</ins></span></pre>
</div>
</div>

</body>
</html>