Process custom field arrays

The snippet below shows how to process arrays in custom fields using the same black / white / protect lists from the Broadcast settings.

Usually, Broadcast will process each custom field using the lists (black, white, protect) and will not delve deeper into custom field arrays.

/**
  @brief    Save the child post's original custom field data.
  @details  We have to use modify_post since after_switch_to_blog does not have the child posts's ID set yet.
  @since    2018-06-24 11:12:23
**/
function bc_threewp_broadcast_broadcasting_modify_post( $action )
{
  $bcd = $action->broadcasting_data;  // Convenience.
  $bcd->process_custom_field_arrays = get_post_meta( $bcd->new_post( 'ID' ) );
}
add_action( 'threewp_broadcast_broadcasting_modify_post', 'bc_threewp_broadcast_broadcasting_modify_post' );

/**
  @brief    Process any arrays in the child's custom fields using the custom field lists.
  @details  Usually, Broadcast will process each custom field using the lists (black, white, protect) and will not delve deeper into custom field arrays.
  @since    2018-06-24 11:48:05
**/
function bc_threewp_broadcast_broadcasting_before_restore_current_blog( $action )
{
  $bcd = $action->broadcasting_data;  // Convenience.

  $cf = $bcd->custom_fields(); // Convenience.

  // Load the current fields.
  $child_fields = $bcd->custom_fields()->child_fields();
  $child_fields->load();

  // And now go through them, processing only arrays.
  foreach( $child_fields as $custom_field => $values )
  {
    $value = reset( $values );

    $array = maybe_unserialize( $value );
    // We are only interested in arrays.
    if ( ! is_array( $array ) )
      continue;

    // Use $new_array in order to keep track of what has been changed.
    $new_array = $array;
    foreach( $new_array as $key => $value )
    {
      if ( $cf->blacklist_has( $key ) )
        if ( ! $cf->whitelist_has( $key ) )
        {
          ThreeWP_Broadcast()->debug( 'Custom field arrays: Deleting custom field array key %s', $key );
          unset( $new_array[ $key ] );
        }

      if ( $cf->protectlist_has( $key ) )
      {
        // Retrieve the original current value.
        if ( isset( $bcd->process_custom_field_arrays[ $custom_field ] ) )
        {
          $original_array = reset( $bcd->process_custom_field_arrays[ $custom_field ] );
          $original_array = maybe_unserialize( $original_array );
          if ( is_array( $original_array ) )
          {
            // Does the original array have this key?
            if ( isset( $original_array[ $key ] ) )
            {
              ThreeWP_Broadcast()->debug( 'Custom field arrays: Restoring custom field array key %s to %s', $key, $original_array[ $key ] );
              $new_array[ $key ] = $original_array[ $key ];
            }
          }
        }
      }
    }

    // Compare the original array with the new one.
    if ( md5( json_encode( $array ) ) != md5( json_encode( $new_array ) ) )
      $bcd->custom_fields()->child_fields()->update_meta( $custom_field, $new_array );
  }
}
add_action( 'threewp_broadcast_broadcasting_before_restore_current_blog', 'bc_threewp_broadcast_broadcasting_before_restore_current_blog' );