| @@ -1620,9 +1620,24 @@ | ||
| 1620 | 1620 | if (!class_exists('\ThinkRank\SEO\Builder_Content')) { |
| 1621 | 1621 | require_once THINKRANK_PLUGIN_DIR . 'includes/seo/class-builder-content.php'; |
| 1622 | 1622 | } |
| 1623 | 1623 | |
| 1624 | - return \ThinkRank\SEO\Builder_Content::resolve_markup($live_content, $post); | |
| 1624 | + // Bind the live markup to the post the render makes current. Since #862 | |
| 1625 | + // the resolver runs setup_postdata() on this post, so a shortcode that | |
| 1626 | + // builds its output from the current post's content — get_the_content(), | |
| 1627 | + // get_post()->post_content, as a table of contents or a reading-time | |
| 1628 | + // shortcode does — otherwise read the last saved body while the unsaved | |
| 1629 | + // markup rendered around it, and lagged a save behind (#864). | |
| 1630 | + // | |
| 1631 | + // A clone, not the caller's object: the post is current only for the | |
| 1632 | + // duration of the render and the caller's $post must come back | |
| 1633 | + // unchanged. `thinkrank_analyzable_content` receives the clone too, | |
| 1634 | + // which is what makes $post->post_content there agree with the markup | |
| 1635 | + // being analyzed on the live path. | |
| 1636 | + $bound = clone $post; | |
| 1637 | + $bound->post_content = $live_content; | |
| 1638 | + | |
| 1639 | + return \ThinkRank\SEO\Builder_Content::resolve_markup($live_content, $bound); | |
| 1625 | 1640 | } |
| 1626 | 1641 | |
| 1627 | 1642 | public function analyze_post_content(int $post_id): array { |
| 1628 | 1643 | $post = get_post($post_id); |