Make WordPress Core

Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#50095 closed defect (bug) (fixed)

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

Reported by: johnjamesjacoby's profile johnjamesjacoby Owned by: whyisjake's profile 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 4 years ago.
First pass attempt

Download all attachments as: .zip

Change History (8)

@johnjamesjacoby
4 years ago

First pass attempt

#1 @johnjamesjacoby
4 years 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
4 years ago

  • Description modified (diff)

#3 @SergeyBiryukov
4 years ago

  • Milestone changed from Awaiting Review to 5.5

#4 @davidbaumwald
4 years ago

  • Keywords has-patch added

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


4 years ago

#6 @whyisjake
4 years 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
4 years 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.