WordPress.org

Make WordPress Core

Opened 3 weeks ago

Last modified 3 weeks ago

#50095 new defect (bug)

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

Reported by: johnjamesjacoby Owned by:
Milestone: 5.5 Priority: normal
Severity: normal Version: 4.7
Component: Formatting Keywords:
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 3 weeks ago.
First pass attempt

Download all attachments as: .zip

Change History (4)

@johnjamesjacoby
3 weeks ago

First pass attempt

#1 @johnjamesjacoby
3 weeks 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
3 weeks ago

  • Description modified (diff)

#3 @SergeyBiryukov
3 weeks ago

  • Milestone changed from Awaiting Review to 5.5
Note: See TracTickets for help on using tickets.