From c94c28ac02b393b41b7df2c75fe986b7ab8a42c5 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 20 Aug 2026 21:05:22 -0300 Subject: [PATCH 1/2] Optimize entry meta logic --- classes/models/FrmEntryMeta.php | 47 +++++++++++++++++++++------------ 1 file changed, 30 insertions(+), 17 deletions(-) diff --git a/classes/models/FrmEntryMeta.php b/classes/models/FrmEntryMeta.php index d8f1d36058..58dcf6a675 100644 --- a/classes/models/FrmEntryMeta.php +++ b/classes/models/FrmEntryMeta.php @@ -6,14 +6,18 @@ class FrmEntryMeta { /** - * @param int $entry_id - * @param int $field_id - * @param string $meta_key usually set to '' as this parameter is no longer used. - * @param mixed $meta_value + * @since x.x Added the $field parameter. + * + * @param int $entry_id + * @param int $field_id + * @param string $meta_key usually set to '' as this parameter is no longer used. + * @param mixed $meta_value + * @param stdClass|null $field The field $field_id belongs to, when the caller already has + * it loaded. Looked up here when it is not passed. * * @return int */ - public static function add_entry_meta( $entry_id, $field_id, $meta_key, $meta_value ) { + public static function add_entry_meta( $entry_id, $field_id, $meta_key, $meta_value, $field = null ) { global $wpdb; if ( FrmAppHelper::is_empty_value( $meta_value ) ) { @@ -28,7 +32,7 @@ public static function add_entry_meta( $entry_id, $field_id, $meta_key, $meta_va 'created_at' => current_time( 'mysql', 1 ), ); - self::set_value_before_save( $new_values ); + self::set_value_before_save( $new_values, $field ); $new_values = apply_filters( 'frm_add_entry_meta', $new_values ); $query_results = $wpdb->insert( $wpdb->prefix . 'frm_item_metas', $new_values ); @@ -42,14 +46,18 @@ public static function add_entry_meta( $entry_id, $field_id, $meta_key, $meta_va } /** - * @param int $entry_id - * @param int $field_id - * @param string $meta_key Deprecated. - * @param array|string $meta_value + * @since x.x Added the $field parameter. + * + * @param int $entry_id + * @param int $field_id + * @param string $meta_key Deprecated. + * @param array|string $meta_value + * @param stdClass|null $field The field $field_id belongs to, when the caller already has + * it loaded. Looked up here when it is not passed. * * @return bool|int */ - public static function update_entry_meta( $entry_id, $field_id, $meta_key, $meta_value ) { + public static function update_entry_meta( $entry_id, $field_id, $meta_key, $meta_value, $field = null ) { if ( ! $field_id ) { return false; } @@ -62,7 +70,7 @@ public static function update_entry_meta( $entry_id, $field_id, $meta_key, $meta ); $where_values = $values; $values['meta_value'] = $meta_value; - self::set_value_before_save( $values ); + self::set_value_before_save( $values, $field ); $values = apply_filters( 'frm_update_entry_meta', $values ); if ( is_array( $values['meta_value'] ) ) { @@ -79,13 +87,18 @@ public static function update_entry_meta( $entry_id, $field_id, $meta_key, $meta /** * @since 3.0 + * @since x.x Added the $field parameter. * - * @param array $values + * @param array $values + * @param stdClass|null $field The field for $values['field_id'], when the caller already has + * it loaded. Looked up here when it is not passed. * * @return void */ - private static function set_value_before_save( &$values ) { - $field = FrmField::getOne( $values['field_id'] ); + private static function set_value_before_save( &$values, $field = null ) { + if ( ! is_object( $field ) ) { + $field = FrmField::getOne( $values['field_id'] ); + } if ( ! $field ) { return; @@ -156,7 +169,7 @@ public static function update_entry_metas( $entry_id, $values ) { if ( ! $previous_field_ids || ! in_array( $field_id, $previous_field_ids, true ) ) { // If value does not exist, then create it - self::add_entry_meta( $entry_id, $field_id, '', $meta_value ); + self::add_entry_meta( $entry_id, $field_id, '', $meta_value, $field ); continue; } @@ -165,7 +178,7 @@ public static function update_entry_metas( $entry_id, $values ) { unset( $values_indexed_by_field_id[ $field_id ] ); } else { // If value exists, then update it - self::update_entry_meta( $entry_id, $field_id, '', $meta_value ); + self::update_entry_meta( $entry_id, $field_id, '', $meta_value, $field ); } }//end foreach From 5d6903ecf84d51dbdac3d721195dd1cc7a2c0330 Mon Sep 17 00:00:00 2001 From: Mike Letellier Date: Thu, 20 Aug 2026 21:32:38 -0300 Subject: [PATCH 2/2] Add another test --- tests/phpunit/entries/test_FrmEntryMeta.php | 31 +++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/tests/phpunit/entries/test_FrmEntryMeta.php b/tests/phpunit/entries/test_FrmEntryMeta.php index a83e1db564..762356bf02 100644 --- a/tests/phpunit/entries/test_FrmEntryMeta.php +++ b/tests/phpunit/entries/test_FrmEntryMeta.php @@ -81,6 +81,37 @@ private function create_text_and_number_fields() { return array( $form, $text_field_id, $number_field_id ); } + /** + * Callers may hand set_value_before_save() a field they have already loaded, so that + * update_entry_metas() does not look the same field up a second time for every value. + * The packing has to follow the field that was passed, otherwise the argument is being + * ignored and the second lookup is back. + * + * @covers FrmEntryMeta::set_value_before_save + */ + public function test_set_value_before_save_packs_with_the_field_that_was_passed() { + list( , $text_field_id ) = $this->create_text_and_number_fields(); + + $as_number = clone FrmField::getOne( $text_field_id ); + $as_number->type = 'number'; + + $values = array( + 'item_id' => 1, + 'field_id' => $text_field_id, + 'meta_value' => 'abc', + ); + $this->run_private_method( array( 'FrmEntryMeta', 'set_value_before_save' ), array( &$values, $as_number ) ); + $this->assertEqualsWithDelta( 0.0, $values['meta_value'], PHP_FLOAT_EPSILON, 'The passed number field should coerce a non-numeric value to a float.' ); + + $values = array( + 'item_id' => 1, + 'field_id' => $text_field_id, + 'meta_value' => 'abc', + ); + $this->run_private_method( array( 'FrmEntryMeta', 'set_value_before_save' ), array( &$values, null ) ); + $this->assertSame( 'abc', $values['meta_value'], 'With no field passed the stored text field should be looked up and leave the value alone.' ); + } + /** * The field argument has to stay optional. add_entry_meta() and update_entry_meta() are * called with four arguments from dozens of places across the add-ons, and those callers