WordPress.org

Make WordPress Core

Opened 7 weeks ago

Last modified 13 days ago

#47824 reopened defect (bug)

get_the_content() still causes a PHP warning outside of the loop

Reported by: SergeyBiryukov Owned by: SergeyBiryukov
Milestone: 5.3 Priority: normal
Severity: normal Version: 5.2
Component: Posts, Post Types Keywords: has-patch has-unit-tests commit
Focuses: Cc:

Description

Background: #42814 / [44941]

Current state of things on PHP 7.2+:

  • Calling the_excerpt() before the loop works as expected, displaying the excerpt of a post in the $post global.
  • Calling the_content() before the loop results in a PHP warning: count(): Parameter must be an array or an object that implements Countable in wp-includes/post-template.php on line 310

get_the_excerpt(), when called without an explicit post object, falls back to the $post global, then passes the post object to wp_trim_excerpt(), which passes it to get_the_content(), and the latter calls generate_postdata().

get_the_content(), when called without an explicit post object, falls back to the $post global too, but makes an incorrect assumption that other globals (specifically $pages) are always set up in that case.

If calling the_content() outside of the loop should be disallowed, then an appropriate _doing_it_wrong() message should be added instead of the cryptic PHP warning.

If calling the_content() outside of the loop should still be supported and properly fall back to the $post global, then in_the_loop() check should be added to the condition that determines when to rely on the globals.

I'm leaning towards the latter, for consistency with get_the_excerpt().

Attachments (2)

47824.diff (461 bytes) - added by SergeyBiryukov 7 weeks ago.
47824.2.diff (1.0 KB) - added by SergeyBiryukov 7 weeks ago.

Download all attachments as: .zip

Change History (11)

@SergeyBiryukov
7 weeks ago

#1 @SergeyBiryukov
7 weeks ago

  • Keywords has-unit-tests commit added; needs-unit-tests removed

#2 follow-up: @spacedmonkey
7 weeks ago

Why not just put an is_countable check in here at line 310?

#3 in reply to: ↑ 2 @SergeyBiryukov
7 weeks ago

Replying to spacedmonkey:

Why not just put an is_countable check in here at line 310?

That would solve the warning, but would also just hide the fact that other globals are not properly set up either.

#4 follow-up: @spacedmonkey
7 weeks ago

I am not sure why the globals are not setup here. Why not add a isset check for the globals then around the 281 line and run generate_postdata to make sure they do exist?

elseif ( !isset($page) or !isset($pages)){
  $elements = generate_postdata( $_post );

#5 in reply to: ↑ 4 @SergeyBiryukov
6 weeks ago

Replying to spacedmonkey:

Why not add a isset check for the globals then around the 281 line and run generate_postdata to make sure they do exist?

That's an option too. They should always be set up in the loop, though, so just checking for in_the_loop() seems simpler.

#6 @SergeyBiryukov
6 weeks ago

#46322 was marked as a duplicate.

#7 @SergeyBiryukov
13 days ago

  • Owner set to SergeyBiryukov
  • Resolution set to fixed
  • Status changed from new to closed

In 46079:

Posts, Post Types: Avoid a PHP warning when the_content() is called outside of the loop.

Fixes #47824.

#8 @SergeyBiryukov
13 days ago

  • Resolution fixed deleted
  • Status changed from closed to reopened
There was 1 failure:

1) Tests_Query_SetupPostdata::test_setup_postdata_loop
Failed asserting that '<p>global post</p>' is not equal to '<p>global post</p>'.

/var/www/tests/phpunit/tests/query/setupPostdata.php:416

Related: #24330

#9 @SergeyBiryukov
13 days ago

In 46080:

Posts, Post Types: Revert [46079] pending test failure investigation.

See #47824.

Note: See TracTickets for help on using tickets.