WordPress.org

Make WordPress Core

Opened 14 months ago

Closed 12 months ago

Last modified 11 months ago

#50095 closed defect (bug) (fixed)

WP_List_Util::filter() not compatible with lists of objects that use magic methods

Reported by: johnjamesjacoby Owned by: whyisjake
Milestone: 5.5 Priority: normal
Severity: normal Version: 4.7
Component: Formatting Keywords: has-patch has-dev-note
Focuses: Cc:

Description (last modified by johnjamesjacoby)

When calling wp_filter_object_list() and passing in an array of objects that use magic methods (specifically __isset() and __get()) for retrieving their properties, it will always return an empty array.

Here's a quick example:

add_action( 'init', function() {

class Thing {
    public $data = array();

    public function __isset( $key ) {
        return isset( $this->data[ $key ] );
    }
    public function __get( $key ) {
        return isset( $this->data[ $key ] ) ? $this->data[ $key ] : null;
    }
    public function __set( $key, $value ) {
        $this->data[ $key ] = $value;
    }
    public function __unset( $key ) {
        unset( $this->data[ $key ] );
    }
}

$thing1 = new Thing;
$thing1->greeting = 'hello';

$thing2 = new Thing;
$thing2->greeting = 'howdy';

$test = array( $thing1, $thing2 );

wp_die(
    var_dump(
        wp_filter_object_list( $test, array( 'greeting' => 'howdy' ) )
    )
);

} );

The above code will output:

array (size=0)
  empty

I expected for this utility to be flexible enough to handle these cases, because a few WordPress classes (like WP_User) already use magic methods similar to my above example.

The reason I expected that, is because it's already flexible enough to work with either an object or an array, even though most function names and documentation lean towards "object" an array will work just fine. In addition, there is no documentation stating that magic methods are not supported, leading me to believe they should be if they can be.

Attachments (1)

50095.patch (916 bytes) - added by johnjamesjacoby 14 months ago.
First pass attempt

Download all attachments as: .zip

Change History (8)

@johnjamesjacoby
14 months ago

First pass attempt

#1 @johnjamesjacoby
14 months ago

50095.patch suggests changing WP_List_Util::filter() to only use array_key_exists() when the item is actually an array. When the item is of type object then it will use isset() instead, allowing it to be compatible with magic __isset() and friends.

Here is a comment from php.net identifying a similar issue with array_key_exists().

With this patch attached, tests appear to pass, and the above code example correctly outputs:

array (size=1)
  1 => 
    object(Thing)[616]
      public 'data' => 
        array (size=1)
          'greeting' => string 'howdy' (length=5)

#2 @johnjamesjacoby
14 months ago

  • Description modified (diff)

#3 @SergeyBiryukov
14 months ago

  • Milestone changed from Awaiting Review to 5.5

#4 @davidbaumwald
12 months ago

  • Keywords has-patch added

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


12 months ago

#6 @whyisjake
12 months ago

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

In 48413:

Formatting: Ensure that wp_filter_object_list() will return an array when being passed an object with magic methods.

Fixes #50095.

Props johnjamesjacoby.

#7 @desrosj
11 months ago

  • Keywords has-dev-note added

This received a call out in the Miscellaneous Developer Changes in 5.5 dev note: https://make.wordpress.org/core/2020/07/29/miscellaneous-developer-focused-changes-in-wordpress-5-5/.

Note: See TracTickets for help on using tickets.