10up / distributor

Share content between your websites.
https://distributorplugin.com
GNU General Public License v2.0
628 stars 155 forks source link

Fatal error due to using `array_key_exists` on a non-array value #1158

Closed dkotter closed 9 months ago

dkotter commented 9 months ago

Describe the bug

In a recent demo of Distributor, a PHP fatal error occurred when trying to Pull content from one site into another (within a multisite). The error we got was Fatal error: array_key_exists() expects parameter 2 to be array, null given, pointing to this line of code: https://github.com/10up/distributor/blob/8e46f93f35130624819044d1a825a9c905fc4858/includes/classes/InternalConnections/NetworkSiteConnection.php#L285

I originally was not able to reproduce this, either in the demo environment or locally. But in testing something else I ran across the same issue and I think I can reliably reproduce now.

If you're using Internal Connections and you Pull a piece of content from one site to another (say from Site A into Site B), if you then try and Pull that same piece of content into another site (say from Site A into Site C), this error occurs.

In looking at the structure of the dt_connection_map meta, this is what I see:

array(
    'internal' => array(
        1 => array(
            'post_id' => 123,
            'time'    => 123456789,
        ),
    ),
    'external' => array(),
)

In looking at/around the mentioned code, we iterate over the meta values and look for a key of internal. But that key doesn't exist within the inner array and thus the error occurs.

I don't know if this is due to a structure change within this meta as part of the v2 release or if this is a long standing bug that just hasn't been noticed. EDIT: seems to be a PHP 8 thing, whereas previously this would throw a PHP warning but now throws a fatal.

I think we can fix this by doing something like this:

foreach ( $post_props['meta']['dt_connection_map'] as $connection_type => $distributed ) {
    $distributed = maybe_unserialize( $distributed );

    if ( 'internal' === $connection_type && array_key_exists( $current_blog_id, $distributed ) ) {
        $dt_pull_messages['duplicated'] = 1;
        continue 2;
    }
}

Steps to Reproduce

Not sure. The issue happened when Pulling content from one site into another, within a multisite environment. But have not been able to reproduce locally

Screenshots, screen recording, code snippet

No response

Environment information

No response

WordPress information

No response

Code of Conduct