Make WordPress Core

#57011 closed defect (bug) (fixed)

wp_list_authors is broken in WordPress 6.1

Reported by: lifeboat's profile lifeboat Owned by: sergeybiryukov's profile SergeyBiryukov
Milestone: 6.2 Priority: normal
Severity: normal Version: 6.1
Component: Users Keywords: has-patch has-unit-tests fixed-major
Focuses: Cc:

Description

The command $result = wp_list_authors('exclude_admin=0&optioncount=1&echo=0'); doesn't work in WordPress 6.1. The problem happens as soon as an author with 0 posts is reached. The exact error is: PHP Fatal error: Uncaught Error: Object of class stdClass could not be converted to string in /var/www/html/blog/wp-includes/author-template.php:568

I fixed this by adding a new line after $posts = isset( $post_counts[ $author_id ] ) ? $post_counts[ $author_id ] : 0; (Which is at line 497.)

New line: if (!is_scalar($posts)) {$posts = 0;}

Attachments (1)

57011.diff (844 bytes) - added by peterwilsoncc 22 months ago.

Download all attachments as: .zip

Change History (20)

#1 @brookedot
23 months ago

Do you get the same error with the following without your modification?

<?php
$result = wp_list_authors( array(
             'exclude_admin' => 0,
             'optioncount'   => 1,
             'echo'          => 0,

) );

#2 @lifeboat
23 months ago

Yes, same error.

#3 @thedaysse
23 months ago

I'm seeing this error on a site i administer - had to make optioncount false to get it working again.

#4 @lifeboat
22 months ago

It is still broken in 6.1.1.

#5 @peterwilsoncc
22 months ago

This looks to be related to [54262] for #17025.

The variable name $post_counts is used for both the database query result and for storing the an array of counts keyed by the author's ID.

<?php
if ( ! is_array( $post_counts ) ) {
        $post_counts = $wpdb->get_results(
                "SELECT DISTINCT post_author, COUNT(ID) AS count
                FROM $wpdb->posts
                WHERE " . get_private_posts_cap_sql( 'post' ) . '
                GROUP BY post_author'
        );

        foreach ( (array) $post_counts as $row ) {
                $post_counts[ $row->post_author ] = $row->count;
        }
}

(extract from wp-includes/author-template.php)

This results in an array mixing both the row objects and integers:

array(2) {
  [0] =>
  class stdClass#2234 (2) {
    public $post_author =>
    string(1) "1"
    public $count =>
    string(1) "4"
  }
  [1] =>
  string(1) "4"
}

57011.diff renames the variable used for the database query to $post_counts_query.

#6 @SergeyBiryukov
22 months ago

  • Component changed from General to Users
  • Milestone changed from Awaiting Review to 6.1.2

#7 @lifeboat
22 months ago

That would definitely fix the problem. Thanks!

#8 @SergeyBiryukov
21 months ago

  • Owner set to SergeyBiryukov
  • Status changed from new to accepted

#9 @Toru
21 months ago

I just run into exactly same problem, for a site updated to 6.1.x.

$args for wp_list_authors() was this. and optioncount parameter was causing Fatal error: Uncaught Error: Object of class stdClass could not be converted to string in ... author-template.php on line 568

`
<?php $args = array(

'orderby' => 'post_count',
'order' => 'DESC',
'number' => null,
'optioncount' => true,
'exclude' => array( 1 ),

); ?>
`

Tried out the patch 57011.diff, I can confirm that this fixed the issue. Looking forward to be merged into 6.1.2.

#10 @johnbillion
21 months ago

  • Keywords needs-unit-tests added

This would benefit from some test coverage

#11 @peterwilsoncc
21 months ago

@johnbillion Do you have any thoughts of how I can consistently cause a collision in the two uses of $post_count for the purpose of testing. (source)

tests/phpunit/tests/user/wpListAuthors.php has a decent amount of coverage but missed the collision

#12 @johnbillion
21 months ago

I think this happens when the numerically indexed result of $post_counts = $wpdb->get_results( ... ) contains a key that matches the ID of a user who doesn't have any posts, therefore the iteration after it doesn't replace the stdClass object with the count property. For example, if element with key 1 in that array happens to match the ID of a user who doesn't have any posts.

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


21 months ago
#13

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

#14 @peterwilsoncc
21 months ago

I've got a test going in the linked pull request:

  • test pushed first to show failure on trunk
  • fixes show test passing

I'm worried the test is potentially flakey though, changes to the fixtures could result in the error not being hit if $wpdb->get_results( ... ) isn't keyed as expected.

#15 @SergeyBiryukov
19 months ago

  • Resolution set to fixed
  • Status changed from accepted to closed

In 55444:

Users: Use a separate variable for the post counts query in wp_list_authors().

This avoids a collision if wp_list_authors() is called with the optioncount parameter enabled, and the resulting array for the post counts query contains a key that matches the ID of a user who does not have any posts.

Follow-up to [54262].

Props peterwilsoncc, johnbillion, lifeboat, brookedot, thedaysse, Toru.
Fixes #57011.

#16 @SergeyBiryukov
19 months ago

  • Keywords fixed-major added
  • Resolution fixed deleted
  • Status changed from closed to reopened

Reopening for 6.1.2 consideration.

@SergeyBiryukov commented on PR #3816:


19 months ago
#17

Thanks for the PR! Merged in r55444.

#18 @SergeyBiryukov
18 months ago

  • Milestone changed from 6.1.2 to 6.2.1

Moving to 6.2.1, as there are no plans for 6.1.2 at this time.

#19 @SergeyBiryukov
18 months ago

  • Milestone changed from 6.2.1 to 6.2
  • Resolution set to fixed
  • Status changed from reopened to closed

This is already included in the 6.2 branch as of [55504], no backport needed.

Note: See TracTickets for help on using tickets.