Automattic\WooCommerce\Internal\DataStores\Orders
OrdersTableDataStore::filter_raw_meta_data
For post based data stores, this was used to filter internal meta data. For custom tables, technically there is no internal meta data, (i.e. we store all core data as properties for the order, and not in meta data). So this method is a no-op.
Except that some meta such as billing_address_index and shipping_address_index are infact stored in meta data, so we need to filter those out.
However, declaring $internal_meta_keys is still required so that our backfill and other comparison checks works as expected.
Method of the class: OrdersTableDataStore{}
No Hooks.
Returns
Array. Filtered meta data.
Usage
$OrdersTableDataStore = new OrdersTableDataStore(); $OrdersTableDataStore->filter_raw_meta_data( $object, $raw_meta_data );
- $object(WC_Data) (required) (passed by reference — &)
- Object to filter meta data for.
- $raw_meta_data(array) (required)
- Raw meta data.
OrdersTableDataStore::filter_raw_meta_data() OrdersTableDataStore::filter raw meta data code WC 11.0.1
public function filter_raw_meta_data( &$object, $raw_meta_data ) { // phpcs:ignore Universal.NamingConventions.NoReservedKeywordParameterNames.objectFound
/*
* Defensive last-resort guard. The meta data should always arrive as an array of meta-row
* objects, but a corrupt persistent object cache entry can surface as a scalar, an object, a
* well-formed array whose elements are not meta rows, or an array of objects that are missing
* required columns. Any of these would otherwise fatal or silently load wrong values
* downstream (array_filter()/array_diff() on a non-array, $meta->meta_key on a non-object
* element, or a real key hydrated with a null value from a partial row).
*
* A row is usable when it carries meta_key and meta_value - the fields init_meta_data() reads
* as data. meta_id is intentionally NOT required here: unlike OrdersTableDataStoreMeta::
* is_valid_cached_meta(), which validates raw database rows at the HPOS 'orders_meta'
* boundary (those always have a meta_id), this guard also runs against the post-filter output
* that WC_Data::read_meta_data() caches and re-validates on a cache hit. That output can
* legitimately include virtual rows injected by extensions via the
* woocommerce_data_store_wp_post_read_meta filter (orders use the 'post' meta type), which
* carry meta_key and meta_value but no meta_id (init_meta_data() reads such a row's id as 0).
* Requiring meta_id would reclassify those legitimate rows as corrupt and churn the cache -
* purging it and re-logging on every read - so we only treat a missing meta_key or meta_value
* as corruption. Drop
* anything that is not a usable meta row so the order still loads, and when corruption is
* detected invalidate the cached entries so the next read self-heals from the database.
*/
$is_corrupt = false;
if ( is_array( $raw_meta_data ) ) {
$valid_meta_data = array_filter(
$raw_meta_data,
static fn( $meta ) => is_object( $meta )
&& property_exists( $meta, 'meta_key' )
&& property_exists( $meta, 'meta_value' )
);
$is_corrupt = count( $valid_meta_data ) !== count( $raw_meta_data );
$raw_meta_data = $valid_meta_data;
} else {
$is_corrupt = true;
$raw_meta_data = array();
}
if ( $is_corrupt ) {
$this->error_logger->warning(
sprintf(
'Discarded malformed meta data for order %1$d while reading; invalidating the cached entry so it is re-read from the database.',
(int) $object->get_id()
),
array( 'source' => 'hpos-data-cache' )
);
/*
* Invalidate every cache the corrupt value could have come from so the next read
* self-heals from the database. The HPOS meta cache (orders_meta group) is primed by
* init_order_record(), while WC_Data::read_meta_data() reads the object's own legacy
* meta cache (the 'orders' group for orders) and, on a cache hit, skips re-caching -
* so without clearing that group the corrupt entry would persist across reads.
*/
$this->data_store_meta->clear_cached_data( array( $object->get_id() ) );
/*
* delete_meta_cache() is defined on WC_Data, so $object always has it in a consistent
* deploy. The guard only covers the brief window during a plugin upgrade where this
* (newer) class can be loaded before an opcode-cached, older abstract-wc-data.php gains
* the method, which would otherwise fatal on an undefined method.
*/
if ( is_callable( array( $object, 'delete_meta_cache' ) ) ) {
$object->delete_meta_cache();
}
}
$filtered_meta_data = parent::filter_raw_meta_data( $object, $raw_meta_data );
$allowed_keys = array(
'_billing_address_index',
'_shipping_address_index',
);
$allowed_meta = array_filter(
$raw_meta_data,
function ( $meta ) use ( $allowed_keys ) {
return in_array( $meta->meta_key, $allowed_keys, true );
}
);
return array_merge( $allowed_meta, $filtered_meta_data );
}