Make WordPress Core

Opened 4 months ago

Closed 8 weeks ago

Last modified 6 weeks ago

#59043 closed defect (bug) (reported-upstream)

the_excerpt() function return excerpt with different length in page load and ajax request on WordPress 6.3

Reported by: sarathlal's profile sarathlal Owned by:
Milestone: Priority: high
Severity: major Version: 6.3
Component: Editor Keywords: needs-testing has-patch
Focuses: Cc:

Description

I'm using the_excerpt() function in a post loop that display posts from a custom WP query for "Post" post type. Using the same query with pagination parameter and same post loop to display more posts using AJAX.

Recently I noticed that the excerpt length was different on page load & AJAX load. I think, it's started after updating to WordPress 6.3. Another user also raised a related support thread in support forum.

https://wordpress.org/support/topic/unexpected-behavior-in-post-loop-after-sending-ajax-request/

Attachments (2)

59043.diff (533 bytes) - added by khokansardar 4 months ago.
59043.2.diff (1.1 KB) - added by rajinsharwar 4 months ago.
Checking for AJAX calls

Download all attachments as: .zip

Change History (29)

#1 @sarathlal
4 months ago

#59044 was marked as a duplicate.

This ticket was mentioned in PR #4988 on WordPress/wordpress-develop by @khokansardar.


4 months ago
#2

  • Keywords has-patch added

This PR fix the excerpt length related issues in frontend

Trac ticket: #59043

@khokansardar
4 months ago

#3 @khokansardar
4 months ago

  • Keywords needs-testing added

@sarathlal Please check with above patch, it should resolve the issues related excerpt.

#4 @sarathlal
4 months ago

@khokansardar Yes. The update resolved excerpt related issue. I have verified that.

#5 @poena
4 months ago

  • Keywords needs-testing-info added

Hi
Thank you for the report.

Kindly include exact step-by-step instructions for:

  • How to reproduce the problem.
  • How to test the patch, including how to confirm that both the excerpt block, all the excerpt block's settings, and the use of the_excerpt in classic themes are working correctly.

It is difficult for testers to test an issue without more information about your custom code, as the tester would need to make a lot of assumptions about both the query and how you implemented the Ajax call, that may or may not affect the test result.

#6 @sarathlal
4 months ago

@poena Sure.

Here are the custom code I'm using in my theme.

* Code in home page template.

<?php
$current_page = get_query_var('paged');
$per_page = get_option('posts_per_page');
$offset = $current_page > 0 ? $per_page * ($current_page-1) : 0;

$blog_args = array(
    'post_type' => 'post',
    'post_status' => 'publish',     
    'posts_per_page' => $per_page,
    'offset' => $offset,
    'order'=>'DESC',
    'orderby'=>'date',
);
$blogs_query = new WP_Query($blog_args);

if ( $blogs_query->have_posts() ) { ?>
        <section class="py-3">
                <div class="container">
                        <p class="section-title">Other Blogs</p>

                        <div id="th-blog-list" class="row posts-grid gx-5 gy-4">
                                <?php 
                while ($blogs_query->have_posts()) : $blogs_query->the_post();
                    $post_id   = get_the_ID();
                    ?>
                    <?php get_template_part('template-parts/post-card'); ?>
                                <?php endwhile; ?>
                        </div>

                        <?php
                        $data = array(
                                'paged' => 2,
                                '_wpnonce' => wp_create_nonce('load-posts'),
                        );
                        global $wp_query;
                        if(isset( $blogs_query->max_num_pages ) && ($blogs_query->max_num_pages > 1)){ ?>
                                <div class="row mb-4 mt-4">
                                        <div class="col-12 text-center">
                                                <span class="spinner-border spinner-border-sm" style="display:none" id="btn-loader" role="status" aria-hidden="true"></span>
                                                <?php
                                                echo '<button type="button" class="btn btn-dark ps-4 pt-2 pe-4 pb-2" id="load-more" '. implode(' ', array_map(
                                                    function ($k, $v) { return "data-" . $k .'="'. htmlspecialchars($v) .'"'; },
                                                    array_keys($data), $data
                                                )) .' />Show more</button>';
                                                ?>
                                        </div>                                          
                                </div>                  
                        <?php } ?>

                </div>
        </section>
<?php } ?>
<?php wp_reset_postdata(); ?>

* Code in template-parts/post-card.php

<?php
/**
 * Template part for displaying blog post card
 *
 * @link https://developer.wordpress.org/themes/basics/template-hierarchy/
 *
 */
?>

<div class="col-sm-12 col-md-6">
    <div class="post-item">
            <a href="<?php echo get_permalink(get_the_ID()); ?>">
                    <?php echo get_the_post_thumbnail( get_the_ID(), 'full', array( 'class' => 'f-img' ) ); ?>
            </a>
            <p class="title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></p>
            <p class="short-desc"><?php the_excerpt(); ?></p>
            <p class="author"><?php echo get_the_author(); ?> | <?php echo get_the_date('F j, Y', get_the_ID()); ?></p>
    </div>
</div>

* Code in functions.php for AJAX load more

function th37t_load_more_posts() {
        $req = $_REQUEST;

        if(!isset($_REQUEST['_wpnonce'])){
                 die('stop');
        }

        if(!(wp_verify_nonce( $_REQUEST['_wpnonce'], 'load-posts'))){
                die('stop');
        }

        unset($req["action"]);
        unset($req["_wpnonce"]);

        $per_page = get_option('posts_per_page');
        $default_data = array(
                'post_type' => 'post',
                'posts_per_page' => $per_page,
                'post_status' => 'publish',
                'order'=>'DESC',
                'orderby'=>'date',
        );
        $args = array_merge($default_data, $req);

        $ajaxposts = new WP_Query($args);

        $html = '';
        if($ajaxposts->have_posts()) {
                while($ajaxposts->have_posts()) : $ajaxposts->the_post();
                    ob_start();
                    get_template_part('template-parts/post-card');
                    $html .= ob_get_contents();
                    ob_end_clean();

                endwhile;
        }

        $next_page = false;
        $max_pages = isset($ajaxposts->max_num_pages) ? $ajaxposts->max_num_pages : false;

        $current_page = isset($_REQUEST['paged']) ? $_REQUEST['paged'] : false;

        if( $current_page && $max_pages && $current_page < $max_pages ){
                $next_page = $current_page + 1;
        }
        
        $data = array(
                'html' => $html,
                'next_page' => $next_page,
        );

        wp_send_json($data);
        exit;
}
add_action('wp_ajax_th_load_more_posts', 'th37t_load_more_posts');
add_action('wp_ajax_nopriv_th_load_more_posts', 'th37t_load_more_posts');

* Jquery code for "Load more" button

(function($){
	$('#load-more').on('click', function() {
		$('#btn-loader').show();
		$('#load-more').attr("disabled", true);
		var data = $(this).data();

		data['action'] = 'th_load_more_posts';

		$.ajax({
			type: 'POST',
			url: "<?php echo admin_url('admin-ajax.php'); ?>",
			dataType: 'JSON',
			data: data,
			success: function (res) {
				$('#btn-loader').hide();
				if(res.html){
					$('#th-blog-list').append(res.html);
				}

				if(res.next_page){
					$('#load-more').data('paged', res.next_page);
					$('#load-more').attr("disabled", false);
				}else{
					$('#load-more').attr("disabled", true);
				}
			}
		});
	});
})(jQuery);

Now on initial page load, the excerpt length will be 50 words if there are no any filter. But when I click on "Load More" button, the length will be 100 words.

I'm little confused about why the code in WordPress block affect core functionality?

#7 @Otto42
4 months ago

  • Keywords needs-patch added; has-patch removed
  • Priority changed from normal to high
  • Severity changed from normal to major

Confirmed, this is a problem in core.

Added here: https://core.trac.wordpress.org/changeset/56065#file90

It seems that the intention was to add a setting somewhere to allow the length to be modified in the editor. But there is no setting that I can find, and in any case, such a setting should not exist if the theme or a plugin is overriding the excerpt length manually.

The given patch is not the correct way to fix it. It works technically, but only through accidental means.

#8 @SergeyBiryukov
4 months ago

  • Milestone changed from Awaiting Review to 6.3.1

#9 @audrasjb
4 months ago

#59064 was marked as a duplicate.

#10 @swissspidy
4 months ago

  • Component changed from Posts, Post Types to Editor

The given patch is not the correct way to fix it. It works technically, but only through accidental means.

Agreed. It only works because is_admin() and REST_REQUEST are never both true at the same time, so the filter will never ever be applied.

In any case, this needs to be fixed in Gutenberg as the source of truth is there:
Also, any changes to this file need to be done in Gutenberg: https://github.com/WordPress/gutenberg/blob/d5d8533cf2cc04bb005bda147114cf00782d6c38/packages/block-library/src/post-excerpt/index.php#L80-L95

#12 @rajinsharwar
4 months ago

Added a fix PR as well there, can anyone take a look?
https://github.com/WordPress/gutenberg/pull/53571

@rajinsharwar
4 months ago

Checking for AJAX calls

#13 @rajinsharwar
4 months ago

  • Keywords has-patch added; needs-testing-info needs-patch removed

This ticket was mentioned in Slack in #core by audrasjb. View the logs.


3 months ago

#15 follow-up: @audrasjb
3 months ago

  • Milestone changed from 6.3.1 to 6.3.2

WP 6.3.1 is going to be released in the next few days, so let's move this ticket to 6.3.2 to give it more time to be committed and backported.

#16 @SergeyBiryukov
3 months ago

If anyone is looking for a workaround, this should restore the excerpt length to whatever it was set before it is altered in blocks/post-excerpt.php:

function wp59043_restore_excerpt_length() {
	global $wp_filter;

	unset( $wp_filter['excerpt_length']->callbacks[ PHP_INT_MAX ] );
}
add_action( 'init', 'wp59043_restore_excerpt_length' );

#17 in reply to: ↑ 15 @dcooney
3 months ago

Replying to audrasjb:

WP 6.3.1 is going to be released in the next few days, so let's move this ticket to 6.3.2 to give it more time to be committed and backported.

Without realizing this was a duplicate, I went with a different approach to solve this same issue by also checking for ! wp_doing_ajax().
https://github.com/WordPress/wordpress-develop/pull/5217

#18 @SergeyBiryukov
3 months ago

#59350 was marked as a duplicate.

This ticket was mentioned in Slack in #core-editor by fabiankaegy. View the logs.


3 months ago

This ticket was mentioned in Slack in #core by joemcgill. View the logs.


2 months ago

#21 @joemcgill
2 months ago

  • Milestone changed from 6.3.2 to 6.4

This likely needs to be tested in the Gutenberg plugin. Given the lack of movement on this, I'm going to move it to the 6.4 milestone.

#22 @swissspidy
2 months ago

#59504 was marked as a duplicate.

#24 @hellofromTonya
8 weeks ago

  • Milestone 6.4 deleted
  • Resolution set to reported-upstream
  • Status changed from new to closed

Hello @sarathlal,

Welcome to Core's Trace. Thank you for reporting this issue :)

The issue was introduced in [56065], as @Otto42 found here.

Fixing it needs to happen in the Gutenberg repo. Why? The bug is within the packages that Gutenberg maintains and Core consumes (meaning Core cannot directly change the package source code to fix the bug).

What's the process to get it resolved?

  1. It needs to be reported upstream in the Gutenberg repository. ✅

https://github.com/WordPress/gutenberg/issues/53570 was opened (thank you @rajinsharwar) to report it.

  1. Discussion should shift to that issue rather than here in Trac.
  1. Possible fixes and testing should be proposed as a Pull Request (PR) in Gutenberg and linked to its issue (not this Trac ticket).
  1. Once the fix is merged into Gutenberg, then it gets cherry picked for a release branch.
  1. Then the packages are published in Gutenberg, which would include the fix.
  1. Then a patch is submitted and committed that updates Core's package.json package versions.

To help, I'll update the Gutenberg issue with the keywords, add the issue to the project board, and leave comment on the issue.

As there's no further actions that can happen here, I'm closing this ticket as reported-upstream. Let's shift the discussions, iteration, and testing to the issue in Gutenberg.

Thank you everyone for your contributions :)

#25 @hellofromTonya
8 weeks ago

Following up:
I've taken the following actions in the upstream issue:

  1. Marked it as high priority.
  2. Moved it into the 6.4 Editor Tasks project board, where the 6.4 Editor leads track issues.
  3. Left a comment that shares context and reasoning.
  4. Talked to a colleague who has volunteered to help test and move a fix forward.
  5. Pinged the 6.4 Editor Triage Leads for their awareness and asked to include the fix in package updates if it lands before 6.4 RC1.

#26 @antonvlasenko
7 weeks ago

This ticket can be moved forward by code reviewing and testing https://github.com/WordPress/gutenberg/pull/55400, which I believe is the correct solution.

#27 @swissspidy
6 weeks ago

#59714 was marked as a duplicate.

Note: See TracTickets for help on using tickets.