Skip to content

Commit

Permalink
Introduce fetch_prepared_meta_from_db
Browse files Browse the repository at this point in the history
  • Loading branch information
fgiannar committed Jan 30, 2025
1 parent fb69c92 commit 92e223e
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 37 deletions.
85 changes: 48 additions & 37 deletions projects/packages/sync/src/modules/class-meta.php
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public function get_objects_by_id( $object_type, $config ) {
}
}

$conditionals = array();
$meta_objects = array();
$where_sql = '';
$current_query_length = 0;

Expand All @@ -78,38 +78,14 @@ public function get_objects_by_id( $object_type, $config ) {
$current_query_length += strlen( $where_sql );

if ( $current_query_length > self::MAX_DB_QUERY_LENGTH ) {
$conditionals[] = $where_sql;
$meta_objects = $this->fetch_prepared_meta_from_db( $object_type, $where_sql, $meta_objects );
$where_sql = '';
$current_query_length = 0;
}
}

if ( ! empty( $where_sql ) ) {
$conditionals[] = $where_sql;
}

$meta_objects = array();

foreach ( $conditionals as $where ) {
$meta = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT * FROM {$table} WHERE {$where}",
ARRAY_A
);

if ( ! is_wp_error( $meta ) && ! empty( $meta ) ) {
foreach ( $meta as $meta_entry ) {
$object_id = $meta_entry[ $object_id_column ];
$meta_key = $meta_entry['meta_key'];
$key = $object_id . '-' . $meta_key;

if ( ! isset( $meta_objects[ $key ] ) ) {
$meta_objects[ $key ] = array();
}

$meta_objects[ $key ][] = $this->get_prepared_meta_object( $object_type, $meta_entry );
}
}
$meta_objects = $this->fetch_prepared_meta_from_db( $object_type, $where_sql, $meta_objects );
}

return $meta_objects;
Expand All @@ -131,25 +107,60 @@ public function get_object_by_id( $object_type, $id = null, $meta_key = null ) {
return null;
}

$table = _get_meta_table( $object_type );
$table = _get_meta_table( $object_type );

if ( ! $table ) {
return null;
}

$object_id_column = $object_type . '_id';

// Sanitize so that the array only has integer values.
$meta = $wpdb->get_results(
$wpdb->prepare(
$where_condition = $wpdb->prepare(
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT * FROM {$table} WHERE {$object_id_column} = %d AND meta_key = %s",
$id,
$meta_key
),
ARRAY_A
"{$object_id_column} = %d AND meta_key = %s",
$id,
$meta_key
);

$meta_objects = null;
$meta_objects = $this->fetch_prepared_meta_from_db( $object_type, $where_condition );

$key = $id . '-' . $meta_key;

return $meta_objects[ $key ] ?? null;
}

/**
* Fetch meta from DB and return them in a standard format.
*
* @param string $object_type The meta object type, eg 'post', 'user' etc.
* @param string $where Prepared SQL 'where' statement.
* @param array $meta_objects An existing array of meta to populate. Defaults to an empty array.
* @return array
*/
private function fetch_prepared_meta_from_db( $object_type, $where, $meta_objects = array() ) {
global $wpdb;

$table = _get_meta_table( $object_type );
$object_id_column = $object_type . '_id';

$meta = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.DirectDatabaseQuery.DirectQuery
// phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
"SELECT * FROM {$table} WHERE {$where}",
ARRAY_A
);

if ( ! is_wp_error( $meta ) && ! empty( $meta ) ) {
foreach ( $meta as $meta_entry ) {
$meta_objects[] = $this->get_prepared_meta_object( $object_type, $meta_entry );
$object_id = $meta_entry[ $object_id_column ];
$meta_key = $meta_entry['meta_key'];
$key = $object_id . '-' . $meta_key;

if ( ! isset( $meta_objects[ $key ] ) ) {
$meta_objects[ $key ] = array();
}

$meta_objects[ $key ][] = $this->get_prepared_meta_object( $object_type, $meta_entry );
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,42 @@ public function assertOptionIsSynced( $meta_key, $value, $type, $object_id ) {
$this->assertEqualsObject( $value, $this->server_replica_storage->get_metadata( $type, $object_id, $meta_key, true ), 'Synced option doesn\'t match local option.' );
}

/**
* Verify that get_object_by_id will return null for non existing meta.
*/
public function test_get_object_by_id_will_return_null_for_non_existing_meta() {
$module = Modules::get_module( 'meta' );
$this->assertNull( $module->get_object_by_id( 'post', $this->post_id, 'does_not_exist' ) );
}

/**
* Test get_object_by_id with multiple meta for the same object_id and key.
*/
public function test_get_object_by_id_multiple_meta_same_object_id_and_key() {
$meta_id = add_post_meta( $this->post_id, $this->whitelisted_post_meta, 'bar' );
$module = Modules::get_module( 'meta' );

$metas = $module->get_object_by_id( 'post', $this->post_id, $this->whitelisted_post_meta );
$expected = array(
array(
'meta_type' => 'post',
'meta_id' => (string) $this->meta_id,
'meta_key' => $this->whitelisted_post_meta,
'meta_value' => 'foo',
'object_id' => (string) $this->post_id,
),
array(
'meta_type' => 'post',
'meta_id' => (string) $meta_id,
'meta_key' => $this->whitelisted_post_meta,
'meta_value' => 'bar',
'object_id' => (string) $this->post_id,
),
);

$this->assertSame( $expected, $metas );
}

/**
* Verify that meta_values above size limit are truncated in get_object_by_id
*/
Expand Down

0 comments on commit 92e223e

Please sign in to comment.