Make WordPress Core

Opened 9 years ago

Closed 9 years ago

Last modified 7 years ago

#30013 closed defect (bug) (fixed)

Array to string conversion notice when multiple post types are queried in edit.php

Reported by: jeremyfelt's profile jeremyfelt Owned by: wonderboymusic's profile wonderboymusic
Milestone: 4.4 Priority: normal
Severity: normal Version:
Component: Posts, Post Types Keywords: good-first-bug has-patch
Focuses: administration Cc:

Description

In edit.php, the requested list table post type is captured as the global $typenow and then assigned to the global $post_type. This $post_type string is then used to display help tabs, to fire a filter for screen options, and as a value for a hidden input.

If a plugin modifies a query - either accidentally or intentionally - to include multiple post types by using $query->set( 'post_type', array( 'page', 'my_post_type' ); on parse_query, the global $post_type is then turned into an array through wp->register_globals() and an "array to string conversion" notice is shown.

We should probably treat the global $post_type separately from the string required to make the page display properly.

Attachments (4)

30013.diff (425 bytes) - added by Kloon 9 years ago.
Ensure typenow is a string on edit.php
30013.2.diff (448 bytes) - added by Kloon 9 years ago.
Do check in get_post_type_object() instead of $typenow as per Nacin's feedback
30013-unit-test.diff (575 bytes) - added by Kloon 9 years ago.
Unit test get_post_type_object function with non scalar values
30013.3.diff (1.4 KB) - added by wonderboymusic 9 years ago.

Download all attachments as: .zip

Change History (13)

#1 @jeremyfelt
9 years ago

  • Keywords needs-patch good-first-bug added
  • Milestone changed from Awaiting Review to Future Release

@Kloon
9 years ago

Ensure typenow is a string on edit.php

#2 @Kloon
9 years ago

  • Keywords has-patch added; needs-patch removed

Since edit.php does not support multiple post types the patch does a check to ensure that the $typenow var is a string.

#3 @nacin
9 years ago

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

As noted in a code review during a video call with the Cape Town contributor day, I don't think this patch fixes the notice that was reported. $typenow is set in admin.php only if the post type exists, which means it's going to be a string once we get to edit.php.

jeremyfelt was reporting that wp_edit_posts_query() ends up running $wp->register_globals() which sets up the $post_type global (why do we even do this in the admin? ugh) which if the post_type query variable was modified on parse_query or whatever, the $post_type global would then be an array. I don't think it actually has anything to do with $typenow; that's just the starting value for $post_type.

That said, edit.php?post_type[]=post&post_type[]=page *does* result in this notice involving $typenow:

  • PHP Warning: Illegal offset type in isset or empty in /Users/nacin/Sites/develop/src/wp-includes/post.php on line 1151

To fix that, we'd need to put an is_string() check in get_post_type_object(). I think it's hypothetically possible for a post type name to be an integer due to the way PHP handles numeric strings as an array key (it doesn't), so it's possible that is_scalar() is a better check. That would simply avoid the warning and let isset() do its work.

A simple unit test for the latter issue might look like this:

# in tests/phpunit/tests/post/types.php, these new methods in Test_Post_Types:
function test_get_post_type_object_with_non_scalar_values() {
    $this->assertFalse( get_post_type_object( array() );
    $this->assertFalse( get_post_type_object( new stdClass );
}

This test would never "fail" in the sense that false would be returned, but the test would error out due to the warning, producing an E result.

@Kloon
9 years ago

Do check in get_post_type_object() instead of $typenow as per Nacin's feedback

@Kloon
9 years ago

Unit test get_post_type_object function with non scalar values

#4 @Kloon
9 years ago

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

Hopefully I did this right, added unit test and patch in separate diffs.

#5 @DrewAPicture
9 years ago

  • Owner set to Kloon
  • Status changed from new to assigned

#6 @norcross
9 years ago

saw there's also an array to string conversion error in the same file on lines 237 and 319

line 237: add_screen_option( 'per_page', array( 'default' => 20, 'option' => 'edit_' . $post_type . '_per_page' ) );

line 319: <input type="hidden" name="post_type" class="post_type_page" value="<?php echo $post_type; ?>" />

not sure if this should be in the same patch or not

#7 @wonderboymusic
9 years ago

  • Milestone changed from Future Release to 4.4
  • Owner changed from Kloon to wonderboymusic

30013.3.diff combines/refreshes

#8 @wonderboymusic
9 years ago

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

In 34100:

Check if the $post_type passed to get_post_type_object() is a scalar value. Non-scalars were producing PHP warnings.

Adds unit tests.

Props Kloon.
Fixes #30013.

#9 @dingo_bastard
7 years ago

Is this still an issue or is this completely fixed? I added a filter to my custom post type, and got the warning pointing to

/wp-admin/edit.php on line 257
/wp-admin/edit.php on line 342

I removed the custom made filter, and when trying to filter out my custom post type by date, I still got the same notice (plus nothing actually gets filtered). The code is located here if anyone's interested: https://gist.github.com/dingo-d/a770ed318de55dd380ef80b73733abf3

I checked every part of my code, just to insure it's not something I did, but it seems fine.

Is there a workaround for this?

My wp version is 4.6.1

Last edited 7 years ago by dingo_bastard (previous) (diff)
Note: See TracTickets for help on using tickets.