diff --git a/includes/fields/class-acf-field-checkbox.php b/includes/fields/class-acf-field-checkbox.php index 5935a041..abd434c8 100644 --- a/includes/fields/class-acf-field-checkbox.php +++ b/includes/fields/class-acf-field-checkbox.php @@ -499,22 +499,34 @@ function update_value( $value, $post_id, $field ) { // select -> update_value() $value = acf_get_field_type( 'select' )->update_value( $value, $post_id, $field ); - // save_other_choice - if ( $field['save_custom'] ) { + // save_custom + if ( ! empty( $field['save_custom'] ) && is_array( $value ) ) { // get raw $field (may have been changed via repeater field) // if field is local, it won't have an ID - $selector = $field['ID'] ? $field['ID'] : $field['key']; - $field = acf_get_field( $selector ); - if ( ! $field ) { - return false; + $selector = ''; + if ( ! empty( $field['ID'] ) ) { + $selector = $field['ID']; + } elseif ( ! empty( $field['key'] ) ) { + $selector = $field['key']; } - // bail early if no ID (JSON only) - if ( ! $field['ID'] ) { + // bail early if we have no selector for lookup + if ( ! $selector ) { return $value; } + $field = acf_get_field( $selector ); + + // bail early if lookup failed or field is JSON only + if ( ! is_array( $field ) || empty( $field['ID'] ) ) { + return $value; + } + + if ( ! isset( $field['choices'] ) || ! is_array( $field['choices'] ) ) { + $field['choices'] = array(); + } + // loop foreach ( $value as $v ) { diff --git a/includes/fields/class-acf-field-select.php b/includes/fields/class-acf-field-select.php index bd9f810b..5fb07f2e 100644 --- a/includes/fields/class-acf-field-select.php +++ b/includes/fields/class-acf-field-select.php @@ -576,14 +576,29 @@ public function update_value( $value, $post_id, $field ) { // Save custom options back to the field definition if configured. if ( ! empty( $field['save_options'] ) && is_array( $value ) ) { // Get the raw field, using the ID if present or the key otherwise (i.e. when using JSON). - $selector = $field['ID'] ? $field['ID'] : $field['key']; - $field = acf_get_field( $selector ); + $selector = ''; + if ( ! empty( $field['ID'] ) ) { + $selector = $field['ID']; + } elseif ( ! empty( $field['key'] ) ) { + $selector = $field['key']; + } + + // Bail when field lookup can't be attempted. + if ( ! $selector ) { + return $value; + } + + $field = acf_get_field( $selector ); // Bail if we don't have a valid field or field ID (JSON only). - if ( empty( $field['ID'] ) ) { + if ( ! is_array( $field ) || empty( $field['ID'] ) ) { return $value; } + if ( ! isset( $field['choices'] ) || ! is_array( $field['choices'] ) ) { + $field['choices'] = array(); + } + foreach ( $value as $v ) { // Ignore if the option already exists. if ( isset( $field['choices'][ $v ] ) ) { diff --git a/tests/php/includes/fields/test-class-acf-field-checkbox.php b/tests/php/includes/fields/test-class-acf-field-checkbox.php index e46c28e1..63456bf7 100644 --- a/tests/php/includes/fields/test-class-acf-field-checkbox.php +++ b/tests/php/includes/fields/test-class-acf-field-checkbox.php @@ -176,6 +176,35 @@ public function test_update_value_empty() { $this->assertEmpty( $result ); } + /** + * Test save_custom does not trigger warnings for JSON-only fields. + */ + public function test_update_value_save_custom_handles_json_field_without_id() { + $field = $this->get_field( + array( + 'save_custom' => 1, + ) + ); + + $result = $this->field_instance->update_value( array( 'custom_value' ), $this->post_id, $field ); + $this->assertSame( array( 'custom_value' ), $result ); + } + + /** + * Test save_custom bails early when field key and ID are both missing. + */ + public function test_update_value_save_custom_handles_missing_field_identifier() { + $field = $this->get_field( + array( + 'save_custom' => 1, + ) + ); + unset( $field['key'] ); + + $result = $this->field_instance->update_value( array( 'custom_value' ), $this->post_id, $field ); + $this->assertSame( array( 'custom_value' ), $result ); + } + /** * Test validate_value with valid selection. */ diff --git a/tests/php/includes/fields/test-class-acf-field-select.php b/tests/php/includes/fields/test-class-acf-field-select.php index 106b7969..4e0c9b28 100644 --- a/tests/php/includes/fields/test-class-acf-field-select.php +++ b/tests/php/includes/fields/test-class-acf-field-select.php @@ -202,6 +202,37 @@ public function test_update_value_converts_to_strings() { $this->assertContains( 'blue', $result ); } + /** + * Test save_options does not trigger warnings for JSON-only fields. + */ + public function test_update_value_save_options_handles_json_field_without_id() { + $field = $this->get_field( + array( + 'save_options' => 1, + 'multiple' => 1, + ) + ); + + $result = $this->field_instance->update_value( array( 'custom_value' ), $this->post_id, $field ); + $this->assertSame( array( 'custom_value' ), $result ); + } + + /** + * Test save_options bails early when field key and ID are both missing. + */ + public function test_update_value_save_options_handles_missing_field_identifier() { + $field = $this->get_field( + array( + 'save_options' => 1, + 'multiple' => 1, + ) + ); + unset( $field['key'] ); + + $result = $this->field_instance->update_value( array( 'custom_value' ), $this->post_id, $field ); + $this->assertSame( array( 'custom_value' ), $result ); + } + /** * Test get_rest_schema returns valid schema. */