Skip to content

Move address fields to Lite - #3171

Open
Crabcyborg wants to merge 31 commits into
masterfrom
move_address_fields_to_lite
Open

Move address fields to Lite#3171
Crabcyborg wants to merge 31 commits into
masterfrom
move_address_fields_to_lite

Conversation

@Crabcyborg

@Crabcyborg Crabcyborg commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

This update moves Address fields into Lite. It also includes several changes for submitting address field data to our Lite payment gateways (Stripe, Square and PayPal). This includes a new update that passes billing address for PayPal Commerce credit card transactions, which should help with preventing issues with false positives appearing when PayPal runs its fraud protection.

Main things to test

  • That Address fields work without Pro active.
  • That Pro Address fields still work as expected.
  • That our payment gateways are properly using the new address data.
  • If address data is not sent to a payment gateway, that nothing goes wrong.

Summary by CodeRabbit

  • New Features
    • Added a structured Address field with street, city, state, ZIP, and country inputs.
    • Address layouts adapt to US, European, international, and generic formats.
    • Added an address type selector in the form builder.
    • Improved combo-field labels, placeholders, defaults, and error handling.
  • Bug Fixes
    • Payment integrations now resolve address country codes consistently.
    • Added US ZIP code validation.
  • Styling
    • Refined address-field spacing in the form builder.
  • Tests
    • Added coverage for address behavior, formatting, validation, and exports.

@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a native address field type with shared combo-field helpers, type-specific rendering and formatting, import and validation handling, payment integration updates, styling, and PHPUnit coverage.

Changes

Address Field Type

Layer / File(s) Summary
Combo helpers
classes/controllers/FrmComboFieldsController.php, classes/models/fields/FrmFieldCombo.php, classes/models/fields/FrmFieldName.php
Adds shared combo-field handling for defaults, placeholders, labels, attributes, errors, and export headings.
Address field model
classes/models/fields/FrmFieldAddress.php
Adds address sub-fields, address-type layouts, formatting, import parsing, ZIP validation, sanitization, and export headings.
Address controller and registration
classes/controllers/FrmAddressesController.php, classes/factories/FrmFieldFactory.php, classes/models/FrmField.php, classes/controllers/FrmFieldsController.php
Registers the address field, defines its sub-fields and country-code lookup, adds field selection, removes Pro duplication, and removes the unique-values upsell.
Rendering and builder controls
classes/views/combo-fields/..., classes/views/frm-fields/front-end/address-field/..., classes/views/frm-fields/back-end/combo-field/sub-field-options.php, resources/scss/admin/components/form/_form-field.scss, css/frm_testing_mode.css, css/frm_admin.css
Adds address and combo-field templates, select defaults, accessibility markup, error rendering, builder spacing, and button-state stylesheet updates.
Payment integrations
paypal/controllers/FrmPayPalLiteAppController.php, square/controllers/FrmSquareLiteAppController.php
Uses FrmAddressesController::get_country_code() for PayPal and Square address data.
PHPUnit coverage
tests/phpunit/fields/test_FrmFieldAddress.php, tests/phpunit/fields/test_FrmFieldCombo.php
Adds address-field tests and updates combo-field fixture names and expectations.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

Suggested reviewers: truongwp

Sequence Diagram(s)

sequenceDiagram
  participant FormBuilder
  participant FrmFieldAddress
  participant FrmAddressesController
  participant PaymentController
  FormBuilder->>FrmFieldAddress: configure address type and sub-fields
  FrmFieldAddress->>FrmAddressesController: render address controls and country codes
  FrmAddressesController-->>FormBuilder: return address field markup
  PaymentController->>FrmAddressesController: convert country name to code
  FrmAddressesController-->>PaymentController: return country code
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 88.52% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the primary change: moving address field functionality into the Lite product.
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch move_address_fields_to_lite

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@deepsource-io

deepsource-io Bot commented Jun 23, 2026

Copy link
Copy Markdown

DeepSource Code Review

We reviewed changes in 8e08e53...1e5135f on this pull request. Below is the summary for the review, and you can see the individual issues we found as inline review comments.

See full review on DeepSource ↗

Important

Some issues found as part of this review are outside of the diff in this pull request and aren't shown in the inline review comments due to GitHub's API limitations. You can see those issues on the DeepSource dashboard.

PR Report Card

Overall Grade   Security  

Reliability  

Complexity  

Hygiene  

Code Review Summary

Analyzer Status Updated (UTC) Details
PHP Aug 4, 2026 7:25p.m. Review ↗
JavaScript Aug 4, 2026 7:25p.m. Review ↗

Important

AI Review is run only on demand for your team. We're only showing results of static analysis review right now. To trigger AI Review, comment @deepsourcebot review on this thread.

* @param array $fields
* @param array $field
*/
return apply_filters( 'frm_address_sub_fields', $fields, $field );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

$label = $field_name;
}

return $field->name . ' - ' . $label;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot access property $name on array|object


The property you are trying to access is not defined and will cause unexpected behavior when used.

*/
public static function get_dropdown_label( $atts ) {
$default = $atts['sub_field']['placeholder'] ?? ' ';
return apply_filters( 'frm_combo_dropdown_label', $default, $atts );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

$field_obj = FrmFieldFactory::get_field_type( $atts['field']['type'], $atts['field'] );

if ( $atts['field']['type'] === 'address' ) {
$placeholder = $field_obj->address_string_to_array( $placeholder );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method FrmFieldType::address_string_to_array()


The method you are trying to call is not defined, which can result in a fatal error.


if ( $atts['field']['type'] === 'address' ) {
$placeholder = $field_obj->address_string_to_array( $placeholder );
$default_value = $field_obj->address_string_to_array( $default_value );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method FrmFieldType::address_string_to_array()


The method you are trying to call is not defined, which can result in a fatal error.

if ( $sub_field['label'] ) {
FrmComboFieldsController::include_sub_label(
array(
'field' => $field,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

);
}

$temp_id = ! empty( $atts['field_id'] ) ? $atts['field_id'] : $field['id'];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

$temp_id = ! empty( $atts['field_id'] ) ? $atts['field_id'] : $field['id'];

// Don't show individual field errors when there is a combo field error
if ( ! empty( $errors ) && isset( $errors[ 'field' . $temp_id . '-' . $key ] ) && ! isset( $errors[ 'field' . $field['id'] ] ) ) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

$html_id = $args['html_id'];
$field_name = $args['field_name'];
$errors = $args['errors'];
$inputs_attrs = $this->get_inputs_container_attrs();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to protected method get_inputs_container_attrs() of class FrmFieldCombo


The method you are trying to call is not defined, which can result in a fatal error.

id="frm_field_<?php echo esc_attr( $field_id . '-' . $name ); ?>_container"
class="frm_form_field form-field frm_form_subfield-<?php echo esc_attr( $name ); ?> <?php echo esc_attr( $sub_field['wrapper_classes'] ); ?><?php
if ( isset( $errors ) ) {
FrmComboFieldsController::maybe_add_error_class( compact( 'field', 'name', 'errors', 'atts' ) );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to function compact() contains possibly undefined variable $atts


One or more variables used inside the compact() function is undefined, resulting in run-time warnings to be raised when the code executes.

* @param array $fields
* @param array $field
*/
return apply_filters( 'frm_address_sub_fields', $fields, $field );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

$label = $field_name;
}

return $field->name . ' - ' . $label;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot access property $name on array|object


The property you are trying to access is not defined and will cause unexpected behavior when used.

*/
public static function get_dropdown_label( $atts ) {
$default = $atts['sub_field']['placeholder'] ?? ' ';
return apply_filters( 'frm_combo_dropdown_label', $default, $atts );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

$field_obj = FrmFieldFactory::get_field_type( $atts['field']['type'], $atts['field'] );

if ( $atts['field']['type'] === 'address' ) {
$placeholder = $field_obj->address_string_to_array( $placeholder );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method FrmFieldType::address_string_to_array()


The method you are trying to call is not defined, which can result in a fatal error.


if ( $atts['field']['type'] === 'address' ) {
$placeholder = $field_obj->address_string_to_array( $placeholder );
$default_value = $field_obj->address_string_to_array( $default_value );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method FrmFieldType::address_string_to_array()


The method you are trying to call is not defined, which can result in a fatal error.

if ( $sub_field['label'] ) {
FrmComboFieldsController::include_sub_label(
array(
'field' => $field,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

);
}

$temp_id = ! empty( $atts['field_id'] ) ? $atts['field_id'] : $field['id'];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

$temp_id = ! empty( $atts['field_id'] ) ? $atts['field_id'] : $field['id'];

// Don't show individual field errors when there is a combo field error
if ( ! empty( $errors ) && isset( $errors[ 'field' . $temp_id . '-' . $key ] ) && ! isset( $errors[ 'field' . $field['id'] ] ) ) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

$html_id = $args['html_id'];
$field_name = $args['field_name'];
$errors = $args['errors'];
$inputs_attrs = $this->get_inputs_container_attrs();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to protected method get_inputs_container_attrs() of class FrmFieldCombo


The method you are trying to call is not defined, which can result in a fatal error.

id="frm_field_<?php echo esc_attr( $field_id . '-' . $name ); ?>_container"
class="frm_form_field form-field frm_form_subfield-<?php echo esc_attr( $name ); ?> <?php echo esc_attr( $sub_field['wrapper_classes'] ); ?><?php
if ( isset( $errors ) ) {
FrmComboFieldsController::maybe_add_error_class( compact( 'field', 'name', 'errors', 'atts' ) );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to function compact() contains possibly undefined variable $atts


One or more variables used inside the compact() function is undefined, resulting in run-time warnings to be raised when the code executes.

* @param array $fields
* @param array $field
*/
return apply_filters( 'frm_address_sub_fields', $fields, $field );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

$label = $field_name;
}

return $field->name . ' - ' . $label;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot access property $name on array|object


The property you are trying to access is not defined and will cause unexpected behavior when used.

*/
public static function get_dropdown_label( $atts ) {
$default = $atts['sub_field']['placeholder'] ?? ' ';
return apply_filters( 'frm_combo_dropdown_label', $default, $atts );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

$field_obj = FrmFieldFactory::get_field_type( $atts['field']['type'], $atts['field'] );

if ( $atts['field']['type'] === 'address' ) {
$placeholder = $field_obj->address_string_to_array( $placeholder );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method FrmFieldType::address_string_to_array()


The method you are trying to call is not defined, which can result in a fatal error.


if ( $atts['field']['type'] === 'address' ) {
$placeholder = $field_obj->address_string_to_array( $placeholder );
$default_value = $field_obj->address_string_to_array( $default_value );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method FrmFieldType::address_string_to_array()


The method you are trying to call is not defined, which can result in a fatal error.

if ( $sub_field['label'] ) {
FrmComboFieldsController::include_sub_label(
array(
'field' => $field,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

);
}

$temp_id = ! empty( $atts['field_id'] ) ? $atts['field_id'] : $field['id'];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

$temp_id = ! empty( $atts['field_id'] ) ? $atts['field_id'] : $field['id'];

// Don't show individual field errors when there is a combo field error
if ( ! empty( $errors ) && isset( $errors[ 'field' . $temp_id . '-' . $key ] ) && ! isset( $errors[ 'field' . $field['id'] ] ) ) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

$html_id = $args['html_id'];
$field_name = $args['field_name'];
$errors = $args['errors'];
$inputs_attrs = $this->get_inputs_container_attrs();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to protected method get_inputs_container_attrs() of class FrmFieldCombo


The method you are trying to call is not defined, which can result in a fatal error.

id="frm_field_<?php echo esc_attr( $field_id . '-' . $name ); ?>_container"
class="frm_form_field form-field frm_form_subfield-<?php echo esc_attr( $name ); ?> <?php echo esc_attr( $sub_field['wrapper_classes'] ); ?><?php
if ( isset( $errors ) ) {
FrmComboFieldsController::maybe_add_error_class( compact( 'field', 'name', 'errors', 'atts' ) );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to function compact() contains possibly undefined variable $atts


One or more variables used inside the compact() function is undefined, resulting in run-time warnings to be raised when the code executes.

* @param array $fields
* @param array $field
*/
return apply_filters( 'frm_address_sub_fields', $fields, $field );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

$label = $field_name;
}

return $field->name . ' - ' . $label;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cannot access property $name on array|object


The property you are trying to access is not defined and will cause unexpected behavior when used.

*/
public static function get_dropdown_label( $atts ) {
$default = $atts['sub_field']['placeholder'] ?? ' ';
return apply_filters( 'frm_combo_dropdown_label', $default, $atts );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

$field_obj = FrmFieldFactory::get_field_type( $atts['field']['type'], $atts['field'] );

if ( $atts['field']['type'] === 'address' ) {
$placeholder = $field_obj->address_string_to_array( $placeholder );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method FrmFieldType::address_string_to_array()


The method you are trying to call is not defined, which can result in a fatal error.


if ( $atts['field']['type'] === 'address' ) {
$placeholder = $field_obj->address_string_to_array( $placeholder );
$default_value = $field_obj->address_string_to_array( $default_value );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method FrmFieldType::address_string_to_array()


The method you are trying to call is not defined, which can result in a fatal error.

if ( $sub_field['label'] ) {
FrmComboFieldsController::include_sub_label(
array(
'field' => $field,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

);
}

$temp_id = ! empty( $atts['field_id'] ) ? $atts['field_id'] : $field['id'];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

$temp_id = ! empty( $atts['field_id'] ) ? $atts['field_id'] : $field['id'];

// Don't show individual field errors when there is a combo field error
if ( ! empty( $errors ) && isset( $errors[ 'field' . $temp_id . '-' . $key ] ) && ! isset( $errors[ 'field' . $field['id'] ] ) ) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

$html_id = $args['html_id'];
$field_name = $args['field_name'];
$errors = $args['errors'];
$inputs_attrs = $this->get_inputs_container_attrs();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to protected method get_inputs_container_attrs() of class FrmFieldCombo


The method you are trying to call is not defined, which can result in a fatal error.

id="frm_field_<?php echo esc_attr( $field_id . '-' . $name ); ?>_container"
class="frm_form_field form-field frm_form_subfield-<?php echo esc_attr( $name ); ?> <?php echo esc_attr( $sub_field['wrapper_classes'] ); ?><?php
if ( isset( $errors ) ) {
FrmComboFieldsController::maybe_add_error_class( compact( 'field', 'name', 'errors', 'atts' ) );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to function compact() contains possibly undefined variable $atts


One or more variables used inside the compact() function is undefined, resulting in run-time warnings to be raised when the code executes.

array()
);

$this->assertIsArray( $result, 'Result should be an array.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertIsArray()


The method you are trying to call is not defined, which can result in a fatal error.

);

$this->assertIsArray( $result, 'Result should be an array.' );
$this->assertArrayHasKey( 'line1', $result, 'Result should have line1 key.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.


$this->assertIsArray( $result, 'Result should be an array.' );
$this->assertArrayHasKey( 'line1', $result, 'Result should have line1 key.' );
$this->assertArrayHasKey( 'line2', $result, 'Result should have line2 key.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

$this->assertIsArray( $result, 'Result should be an array.' );
$this->assertArrayHasKey( 'line1', $result, 'Result should have line1 key.' );
$this->assertArrayHasKey( 'line2', $result, 'Result should have line2 key.' );
$this->assertArrayHasKey( 'city', $result, 'Result should have city key.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

$this->assertArrayHasKey( 'line1', $result, 'Result should have line1 key.' );
$this->assertArrayHasKey( 'line2', $result, 'Result should have line2 key.' );
$this->assertArrayHasKey( 'city', $result, 'Result should have city key.' );
$this->assertArrayHasKey( 'state', $result, 'Result should have state key.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

$result = FrmAddressesController::add_optional_class( $class, $field );

$this->assertStringContainsString( 'frm_optional', $result, 'Result should contain frm_optional class.' );
$this->assertStringContainsString( 'frm_form_field', $result, 'Result should contain original class.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

public function test_address_field_model_can_be_instantiated() {
$field = new FrmFieldAddress();

$this->assertInstanceOf( 'FrmFieldAddress', $field, 'Should be instance of FrmFieldAddress.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertInstanceOf()


The method you are trying to call is not defined, which can result in a fatal error.

$field = new FrmFieldAddress();

$this->assertInstanceOf( 'FrmFieldAddress', $field, 'Should be instance of FrmFieldAddress.' );
$this->assertInstanceOf( 'FrmFieldCombo', $field, 'Should extend FrmFieldCombo.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertInstanceOf()


The method you are trying to call is not defined, which can result in a fatal error.

$result = FrmAddressesController::get_sub_fields( $field );

foreach ( $expected_keys as $key ) {
$this->assertArrayHasKey( $key, $result, "Result should have {$key} for {$address_type} address type." );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

$this->assertArrayHasKey( 'city', $result, 'Result should have city.' );
$this->assertArrayHasKey( 'state', $result, 'Result should have state.' );
$this->assertArrayHasKey( 'zip', $result, 'Result should have zip.' );
$this->assertArrayHasKey( 'country', $result, 'Result should have country.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

array()
);

$this->assertIsArray( $result, 'Result should be an array.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertIsArray()


The method you are trying to call is not defined, which can result in a fatal error.

);

$this->assertIsArray( $result, 'Result should be an array.' );
$this->assertArrayHasKey( 'line1', $result, 'Result should have line1 key.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.


$this->assertIsArray( $result, 'Result should be an array.' );
$this->assertArrayHasKey( 'line1', $result, 'Result should have line1 key.' );
$this->assertArrayHasKey( 'line2', $result, 'Result should have line2 key.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

$this->assertIsArray( $result, 'Result should be an array.' );
$this->assertArrayHasKey( 'line1', $result, 'Result should have line1 key.' );
$this->assertArrayHasKey( 'line2', $result, 'Result should have line2 key.' );
$this->assertArrayHasKey( 'city', $result, 'Result should have city key.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

$this->assertArrayHasKey( 'line1', $result, 'Result should have line1 key.' );
$this->assertArrayHasKey( 'line2', $result, 'Result should have line2 key.' );
$this->assertArrayHasKey( 'city', $result, 'Result should have city key.' );
$this->assertArrayHasKey( 'state', $result, 'Result should have state key.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

$result = FrmAddressesController::add_optional_class( $class, $field );

$this->assertStringContainsString( 'frm_optional', $result, 'Result should contain frm_optional class.' );
$this->assertStringContainsString( 'frm_form_field', $result, 'Result should contain original class.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertStringContainsString()


The method you are trying to call is not defined, which can result in a fatal error.

public function test_address_field_model_can_be_instantiated() {
$field = new FrmFieldAddress();

$this->assertInstanceOf( 'FrmFieldAddress', $field, 'Should be instance of FrmFieldAddress.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertInstanceOf()


The method you are trying to call is not defined, which can result in a fatal error.

$field = new FrmFieldAddress();

$this->assertInstanceOf( 'FrmFieldAddress', $field, 'Should be instance of FrmFieldAddress.' );
$this->assertInstanceOf( 'FrmFieldCombo', $field, 'Should extend FrmFieldCombo.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertInstanceOf()


The method you are trying to call is not defined, which can result in a fatal error.

$result = FrmAddressesController::get_sub_fields( $field );

foreach ( $expected_keys as $key ) {
$this->assertArrayHasKey( $key, $result, "Result should have {$key} for {$address_type} address type." );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

$this->assertArrayHasKey( 'city', $result, 'Result should have city.' );
$this->assertArrayHasKey( 'state', $result, 'Result should have state.' );
$this->assertArrayHasKey( 'zip', $result, 'Result should have zip.' );
$this->assertArrayHasKey( 'country', $result, 'Result should have country.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
square/controllers/FrmSquareLiteAppController.php (1)

182-206: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Normalize optional address keys before using them.

After Line 182 relaxes validation to line1, Line 195 and Lines 198-206 still read optional keys directly. Missing keys now trigger undefined-index notices on payment AJAX paths.

Suggested fix
 	private static function maybe_add_address_data( &$details, $address, $address_field_id ) {
 		if ( ! is_array( $address ) || ! isset( $address['line1'] ) ) {
 			return;
 		}
+
+		$line1   = $address['line1'] ?? '';
+		$line2   = $address['line2'] ?? '';
+		$city    = $address['city'] ?? '';
+		$state   = $address['state'] ?? '';
+		$zip     = $address['zip'] ?? '';
+		$country = $address['country'] ?? '';
@@
 		if ( 'us' === $address_field->field_options['address_type'] ) {
 			$country_code = 'US';
 		} else {
-			$country_code = FrmAddressesController::get_country_code( $address['country'] );
+			$country_code = FrmAddressesController::get_country_code( $country );
 		}
 
-		if ( ! $address['line1'] && ! $address['line2'] && ! $address['city'] && ! $address['state'] && ! $address['zip'] && ! $country_code ) {
+		if ( ! $line1 && ! $line2 && ! $city && ! $state && ! $zip && ! $country_code ) {
 			return;
 		}
 
-		$details['addressLines'] = array( $address['line1'], $address['line2'] );
-		$details['city']         = $address['city'];
-		$details['state']        = $address['state'];
-		$details['postalCode']   = $address['zip'];
+		$details['addressLines'] = array( $line1, $line2 );
+		$details['city']         = $city;
+		$details['state']        = $state;
+		$details['postalCode']   = $zip;
 		$details['countryCode']  = $country_code;
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@square/controllers/FrmSquareLiteAppController.php` around lines 182 - 206,
The code validates that the address array contains the required line1 key but
then directly accesses optional address keys (line2, city, state, zip) without
verifying they exist first, causing undefined-index notices. After the initial
address validation and before accessing individual address fields in the section
where you populate the details array (around lines 198-206), ensure each
optional address key is safely accessed using either isset() checks or the null
coalescing operator (??). This should be done for address['line2'],
address['city'], address['state'], address['zip'], and address['country'] to
provide default values when these keys are missing from the address array.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@classes/controllers/FrmAddressesController.php`:
- Around line 140-152: The code accesses $field['address_type'] multiple times
in conditional checks without ensuring it exists, which will cause
undefined-index notices for legacy or incomplete field configurations. Add a
defensive default assignment for $field['address_type'] at the beginning of the
get_sub_fields() method or at the start of this code block, before the first
conditional that checks for 'europe', 'us', or 'generic' address types. Use a
sensible default like 'generic' to keep rendering deterministic when the
address_type key is absent from the field configuration.
- Line 276: The `get_country_code()` method accesses `self::$country_codes`
directly as an array without validating that the filtered result from the
`frm_country_codes` filter is actually an array. If a callback returns a
non-array value, this causes type errors when the method is invoked in payment
processing paths. Add validation where the filter result is assigned to
`self::$country_codes` to ensure it returns an array, and provide a default
empty array as a fallback if the filter returns a non-array value or null. This
will prevent type errors when `get_country_code()` is called during PayPal and
Square payment processing.

In `@classes/controllers/FrmComboFieldsController.php`:
- Around line 112-116: The FrmComboFieldsController is using $atts['key'] to
look up sub-field identifiers in methods like include_placeholder and when
accessing the default_value array, but downstream callers are passing the
sub-field identifier under the 'name' key instead, causing silent lookup
failures and undefined index notices. Replace all references to $atts['key']
with $atts['name'] in the combo field helper methods to align the sub-field key
contract, specifically in the include_placeholder function call and the
default_value array access around lines 112-116, and apply the same fix to the
corresponding code at lines 179-180.
- Around line 105-109: The $field_obj variable returned from
FrmFieldFactory::get_field_type() has a broader type, but the
address_string_to_array() method is specific to address field types. After
checking that $atts['field']['type'] === 'address', narrow the type of
$field_obj to the specific address field type (using an instanceof check, type
assertion, or type cast) before calling address_string_to_array() on it to
satisfy static analysis checks and prevent a fatal runtime error.
- Around line 164-165: The code directly accesses `$field[ $option_name ]`
without first verifying that the key exists in the array, which causes PHP
notices when the key is absent. Guard the array access by using isset() to check
if the key exists before attempting to access it. Modify the condition to first
verify that the key is present in the $field array, and only then check if its
value is not empty. This will prevent undefined array key notices from being
rendered.

In `@classes/models/fields/FrmFieldAddress.php`:
- Around line 333-339: The current CSV import parsing for addresses uses
is_numeric() to distinguish zip codes from country names, which fails for
alphanumeric postal codes like Canadian (M5V 3A8) or UK (SW1A 1AA) formats.
Replace the is_numeric() check with a more robust validation method that can
handle alphanumeric postal code formats. This may involve using regex patterns
to match common postal code formats or implementing a smarter detection
mechanism that doesn't rely purely on numeric validation. Make sure to apply
this fix consistently across all affected locations where address field parsing
occurs, including the code sections around lines 333-339 and the additional
locations mentioned in the review (354-370).
- Around line 146-147: In the FrmFieldAddress class, the translatable_strings
method currently assigns the result of parent::translatable_strings() to the
$strings variable and then returns it on the next line. This violates the
PHP-CS-Fixer return_assignment rule. Remove the intermediate variable assignment
and directly return the result of the parent::translatable_strings() call in a
single statement.

In `@classes/views/frm-fields/front-end/address-field/address-field.php`:
- Around line 47-58: The helper functions
FrmComboFieldsController::maybe_add_error_class,
FrmComboFieldsController::add_atts_to_input, and
FrmComboFieldsController::get_dropdown_label expect a key parameter in the $atts
array, but the code is passing name instead. Update the compact() calls on lines
47, 56, and 58 (and line 82 mentioned in "Also applies to") to pass key instead
of name to these helper methods, ensuring the parameter name matches what the
combo-field helper contracts expect and preventing undefined index notices.

---

Outside diff comments:
In `@square/controllers/FrmSquareLiteAppController.php`:
- Around line 182-206: The code validates that the address array contains the
required line1 key but then directly accesses optional address keys (line2,
city, state, zip) without verifying they exist first, causing undefined-index
notices. After the initial address validation and before accessing individual
address fields in the section where you populate the details array (around lines
198-206), ensure each optional address key is safely accessed using either
isset() checks or the null coalescing operator (??). This should be done for
address['line2'], address['city'], address['state'], address['zip'], and
address['country'] to provide default values when these keys are missing from
the address array.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cff847f2-64dc-4ad9-9060-9e7518bbded9

📥 Commits

Reviewing files that changed from the base of the PR and between b096bc4 and 3937b09.

📒 Files selected for processing (15)
  • classes/controllers/FrmAddressesController.php
  • classes/controllers/FrmComboFieldsController.php
  • classes/controllers/FrmFieldsController.php
  • classes/controllers/FrmHooksController.php
  • classes/factories/FrmFieldFactory.php
  • classes/models/FrmField.php
  • classes/models/fields/FrmFieldAddress.php
  • classes/views/combo-fields/addresses/back-end-field-opts.php
  • classes/views/combo-fields/input-form-builder.php
  • classes/views/combo-fields/input.php
  • classes/views/frm-fields/front-end/address-field/address-field.php
  • css/frm_admin.css
  • paypal/controllers/FrmPayPalLiteAppController.php
  • resources/scss/admin/components/form/_form-field.scss
  • square/controllers/FrmSquareLiteAppController.php

Comment thread classes/controllers/FrmAddressesController.php Outdated
*/
public static function get_country_code( $country ) {
self::maybe_define_country_codes();
return self::$country_codes[ $country ] ?? '';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Audit local callbacks for frm_country_codes and inspect return values manually.
rg -n --type=php "add_filter\s*\(\s*'frm_country_codes'" .

Repository: Strategy11/formidable-forms

Length of output: 165


🏁 Script executed:

#!/bin/bash
# Find and inspect the FrmAddressesController.php file
find . -name "FrmAddressesController.php" -type f

Repository: Strategy11/formidable-forms

Length of output: 214


🏁 Script executed:

#!/bin/bash
# Look for the apply_filters call with frm_country_codes
rg -n "frm_country_codes" --type=php . | head -30

Repository: Strategy11/formidable-forms

Length of output: 303


🏁 Script executed:

#!/bin/bash
# Search for maybe_define_country_codes method
rg -n "maybe_define_country_codes" --type=php .

Repository: Strategy11/formidable-forms

Length of output: 549


🏁 Script executed:

#!/bin/bash
# Read the FrmAddressesController.php file around lines 270-280 to see get_country_code
sed -n '270,290p' ./classes/controllers/FrmAddressesController.php | cat -n

Repository: Strategy11/formidable-forms

Length of output: 752


🏁 Script executed:

#!/bin/bash
# Read around line 551 to see the filter application
sed -n '545,560p' ./classes/controllers/FrmAddressesController.php | cat -n

Repository: Strategy11/formidable-forms

Length of output: 486


🏁 Script executed:

#!/bin/bash
# Get the full file outline to understand structure
ast-grep outline ./classes/controllers/FrmAddressesController.php

Repository: Strategy11/formidable-forms

Length of output: 228


🏁 Script executed:

#!/bin/bash
# Read the complete maybe_define_country_codes method
sed -n '286,560p' ./classes/controllers/FrmAddressesController.php | cat -n

Repository: Strategy11/formidable-forms

Length of output: 17206


🏁 Script executed:

#!/bin/bash
# Search for PayPal and Square payment integration usage with country codes
rg -n -A 5 "get_country_code" ./classes/controllers/FrmAddressesController.php

Repository: Strategy11/formidable-forms

Length of output: 340


🏁 Script executed:

#!/bin/bash
# Look for PayPal and Square payment path code
find . -name "*[Pp]ay[Pp]al*" -o -name "*[Ss]quare*" | grep -E "\.(php|js)$" | head -10

Repository: Strategy11/formidable-forms

Length of output: 672


🏁 Script executed:

#!/bin/bash
# Search for get_country_code usage in PayPal files
rg -n "get_country_code" ./paypal/ --type=php

Repository: Strategy11/formidable-forms

Length of output: 578


🏁 Script executed:

#!/bin/bash
# Look for Square integration
find . -path "./paypal" -prune -o -name "*[Ss]quare*" -type f -print | head -20

Repository: Strategy11/formidable-forms

Length of output: 1245


🏁 Script executed:

#!/bin/bash
# Search for square payment processing
rg -n "square" --type=php . -i | grep -i "payment\|country\|code" | head -20

Repository: Strategy11/formidable-forms

Length of output: 3174


🏁 Script executed:

#!/bin/bash
# Search for get_country_code usage in Square files
rg -n "get_country_code" ./square/ --type=php

Repository: Strategy11/formidable-forms

Length of output: 305


🏁 Script executed:

#!/bin/bash
# Look at PayPal usage context around line 415 and 478
sed -n '410,420p' ./paypal/controllers/FrmPayPalLiteAppController.php | cat -n

Repository: Strategy11/formidable-forms

Length of output: 575


🏁 Script executed:

#!/bin/bash
# Look at context around line 478 in PayPal
sed -n '473,483p' ./paypal/controllers/FrmPayPalLiteAppController.php | cat -n

Repository: Strategy11/formidable-forms

Length of output: 569


Validate filtered country-code map before indexing in payment paths.

The frm_country_codes filter output is used directly as an array map without validation. If a callback returns a non-array value, get_country_code() will throw a type error when accessed in PayPal and Square payment processing (lines 415, 478, and 195 respectively).

Suggested fix
 public static function get_country_code( $country ) {
 	self::maybe_define_country_codes();
-	return self::$country_codes[ $country ] ?? '';
+	if ( ! is_array( self::$country_codes ) ) {
+		return '';
+	}
+	return self::$country_codes[ (string) $country ] ?? '';
 }
@@
-	self::$country_codes = apply_filters( 'frm_country_codes', self::$country_codes );
+	$filtered_codes      = apply_filters( 'frm_country_codes', self::$country_codes );
+	self::$country_codes = is_array( $filtered_codes ) ? $filtered_codes : array();
🧰 Tools
🪛 GitHub Check: PHPStan

[failure] 276-276:
Method FrmAddressesController::get_country_code() should return string but returns mixed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@classes/controllers/FrmAddressesController.php` at line 276, The
`get_country_code()` method accesses `self::$country_codes` directly as an array
without validating that the filtered result from the `frm_country_codes` filter
is actually an array. If a callback returns a non-array value, this causes type
errors when the method is invoked in payment processing paths. Add validation
where the filter result is assigned to `self::$country_codes` to ensure it
returns an array, and provide a default empty array as a fallback if the filter
returns a non-array value or null. This will prevent type errors when
`get_country_code()` is called during PayPal and Square payment processing.

Comment thread classes/controllers/FrmComboFieldsController.php
Comment on lines +112 to +116
self::include_placeholder( $placeholder, $atts['key'], $atts['field'] );
$atts['field']['placeholder'] = '';

$atts['field']['default_value'] = $default_value[ $atts['key'] ] ?? '';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Align sub-field key contract (name vs key) across combo helpers.

These helpers read $atts['key'], but downstream callers pass name, so placeholder/default/error lookup can silently fail and produce undefined-index notices.

Suggested fix
 public static function add_atts_to_input( $atts ) {
+	$sub_field_key = $atts['key'] ?? $atts['name'] ?? '';
+	if ( '' === $sub_field_key ) {
+		return;
+	}
+
 	$placeholder   = $atts['field']['placeholder'] ?? '';
 	$default_value = $atts['field']['default_value'];
 	$field_obj     = FrmFieldFactory::get_field_type( $atts['field']['type'], $atts['field'] );
@@
-	self::include_placeholder( $placeholder, $atts['key'], $atts['field'] );
+	self::include_placeholder( $placeholder, $sub_field_key, $atts['field'] );
 	$atts['field']['placeholder'] = '';
 
-	$atts['field']['default_value'] = $default_value[ $atts['key'] ] ?? '';
+	$atts['field']['default_value'] = $default_value[ $sub_field_key ] ?? '';
@@
 public static function maybe_add_error_class( $atts ) {
+	$sub_field_key = $atts['key'] ?? $atts['name'] ?? '';
+	if ( '' === $sub_field_key ) {
+		return;
+	}
+
 	$temp_id   = ! empty( $atts['atts']['field_id'] ) ? $atts['atts']['field_id'] : $atts['field']['id'];
-	$has_error = isset( $atts['errors'][ 'field' . $temp_id . '-' . $atts['key'] ] );
+	$has_error = isset( $atts['errors'][ 'field' . $temp_id . '-' . $sub_field_key ] );

Also applies to: 179-180

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@classes/controllers/FrmComboFieldsController.php` around lines 112 - 116, The
FrmComboFieldsController is using $atts['key'] to look up sub-field identifiers
in methods like include_placeholder and when accessing the default_value array,
but downstream callers are passing the sub-field identifier under the 'name' key
instead, causing silent lookup failures and undefined index notices. Replace all
references to $atts['key'] with $atts['name'] in the combo field helper methods
to align the sub-field key contract, specifically in the include_placeholder
function call and the default_value array access around lines 112-116, and apply
the same fix to the corresponding code at lines 179-180.

Comment on lines +164 to +165
if ( $field[ $option_name ] !== '' ) {
echo '<div class="frm_description">' . wp_kses_post( $field[ $option_name ] ) . '</div>';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Guard sub-label array access before dereferencing.

$field[ $option_name ] is accessed directly; when that key is absent, PHP notices leak into rendering.

Suggested fix
-	if ( $field[ $option_name ] !== '' ) {
+	if ( isset( $field[ $option_name ] ) && '' !== $field[ $option_name ] ) {
 		echo '<div class="frm_description">' . wp_kses_post( $field[ $option_name ] ) . '</div>';
 	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if ( $field[ $option_name ] !== '' ) {
echo '<div class="frm_description">' . wp_kses_post( $field[ $option_name ] ) . '</div>';
if ( isset( $field[ $option_name ] ) && '' !== $field[ $option_name ] ) {
echo '<div class="frm_description">' . wp_kses_post( $field[ $option_name ] ) . '</div>';
}
🧰 Tools
🪛 ast-grep (0.44.0)

[warning] 164-164: Avoid side effects in a file that defines symbols
Context: echo '

' . wp_kses_post( $field[ $option_name ] ) . '
';
Note: [CWE-710] Improper Adherence to Coding Standards.

(no-side-effect)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@classes/controllers/FrmComboFieldsController.php` around lines 164 - 165, The
code directly accesses `$field[ $option_name ]` without first verifying that the
key exists in the array, which causes PHP notices when the key is absent. Guard
the array access by using isset() to check if the key exists before attempting
to access it. Modify the condition to first verify that the key is present in
the $field array, and only then check if its value is not empty. This will
prevent undefined array key notices from being rendered.

Comment thread classes/models/fields/FrmFieldAddress.php Outdated
Comment on lines +333 to +339
$sep = apply_filters( 'frm_csv_sep', ', ' );
$value = explode( $sep, $value );
$count = count( $value );

if ( $count < 4 || $count > 6 ) {
return $value;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Harden CSV import parsing for 5-part addresses.

Using is_numeric( $last_item ) to distinguish zip vs country misparses valid alphanumeric postal codes (e.g., CA/UK), shifting line2/city/state/zip into wrong keys.

Suggested fix
 protected function prepare_import_value( $value, $atts ) {
 	if ( is_array( $value ) ) {
 		return $value;
 	}
 
+	$raw_value = $value;
 	$sep   = apply_filters( 'frm_csv_sep', ', ' );
 	$value = explode( $sep, $value );
 	$count = count( $value );
 
 	if ( $count < 4 || $count > 6 ) {
-		return $value;
+		return $this->address_string_to_array( $raw_value );
 	}
@@
-	$last_item = end( $value );
+	$last_item   = trim( (string) end( $value ) );
+	$has_country = 5 === $count && '' !== FrmAddressesController::get_country_code( $last_item );
 
-	if ( $count === 6 || ( $count === 5 && is_numeric( $last_item ) ) ) {
+	if ( 6 === $count || ( 5 === $count && ! $has_country ) ) {
 		$new_value['line2'] = $value[1];
 		$new_value['city']  = $value[2];
 		$new_value['state'] = $value[3];
 		$new_value['zip']   = $value[4];

Also applies to: 354-370

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@classes/models/fields/FrmFieldAddress.php` around lines 333 - 339, The
current CSV import parsing for addresses uses is_numeric() to distinguish zip
codes from country names, which fails for alphanumeric postal codes like
Canadian (M5V 3A8) or UK (SW1A 1AA) formats. Replace the is_numeric() check with
a more robust validation method that can handle alphanumeric postal code
formats. This may involve using regex patterns to match common postal code
formats or implementing a smarter detection mechanism that doesn't rely purely
on numeric validation. Make sure to apply this fix consistently across all
affected locations where address field parsing occurs, including the code
sections around lines 333-339 and the additional locations mentioned in the
review (354-370).

Comment thread classes/views/frm-fields/front-end/address-field/address-field.php Outdated
* @param array $field
*/
/** @var array */
$result = apply_filters( 'frm_address_sub_fields', $fields, $field );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

public static function get_dropdown_label( $atts ) {
$default = $atts['sub_field']['placeholder'] ?? ' ';
/** @var string */
$result = apply_filters( 'frm_combo_dropdown_label', $default, $atts );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

* @param array $args
*/
/** @var string */
$result = apply_filters( 'frm_address_format', $address_format, array( 'field' => $this->field ) );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function apply_filters invoked with 3 parameters, 2 required


The function call is not valid, which will result in a fatal runtime error.

$this->assertArrayHasKey( 'state', $result, 'Result should have state.' );
$this->assertArrayHasKey( 'zip', $result, 'Result should have zip.' );
// Generic address type does not include country field
$this->assertArrayNotHasKey( 'country', $result, 'Result should not have country for generic address type.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayNotHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

*/
public function test_get_country_code_returns_empty_string_for_invalid_country() {
$result = FrmAddressesController::get_country_code( 'Invalid Country Name' );
$this->assertSame( '', $result, 'Country code for invalid country should be empty string.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

*/
public function test_get_country_code_returns_empty_string_for_empty_string() {
$result = FrmAddressesController::get_country_code( '' );
$this->assertSame( '', $result, 'Country code for empty string should be empty string.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
classes/views/frm-fields/back-end/combo-field/sub-field-options.php (1)

58-58: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider using FrmAppHelper::selected() for consistent selected-state handling.

The current strict comparison (===) may fail when $default_value and $opt_value have mismatched types (e.g., integer vs. string). The codebase provides FrmAppHelper::selected() (see FrmAppHelper.php:2185-2191) which handles selected state consistently across Lite and Pro by delegating to FrmProAppHelper::selected() when available, or falling back to WordPress's selected() otherwise.

♻️ Refactor to use the helper method
 						<?php
 						foreach ( $sub_field['options'] as $opt_value => $opt_label ) {
-							$selected = isset( $default_value[ $sub_field['name'] ] ) && $default_value[ $sub_field['name'] ] === $opt_value ? 'selected' : '';
 							?>
-							<option value="<?php echo esc_attr( $opt_value ); ?>" <?php echo esc_attr( $selected ); ?>>
+							<option value="<?php echo esc_attr( $opt_value ); ?>" <?php FrmAppHelper::selected( $default_value[ $sub_field['name'] ] ?? '', $opt_value ); ?>>
 								<?php echo esc_html( $opt_label ); ?>
 							</option>
 							<?php
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@classes/views/frm-fields/back-end/combo-field/sub-field-options.php` at line
58, The current implementation uses a strict comparison operator (===) to
determine the selected state in the ternary operator, which can fail due to type
mismatches between $default_value and $opt_value. Replace the ternary operator
logic that checks for selected state with a call to FrmAppHelper::selected(),
passing the $default_value[$sub_field['name']] and $opt_value as arguments. This
helper method handles type-safe comparison internally and provides consistent
behavior across Lite and Pro versions by delegating to
FrmProAppHelper::selected() when available or falling back to WordPress's
selected() function otherwise.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/phpunit/fields/test_FrmFieldAddress.php`:
- Line 286: The PHPDoc return type annotation on line 286 has invalid syntax
with `void` (which cannot be used for data providers) and an extra closing
bracket. Remove the `void` keyword and correct the bracket matching so the
return type reads as a proper generic array type like `@return
array<(array<string> | string)>`, or alternatively remove the return type tag
entirely if the return type is clear from context.
- Around line 220-225: The assertArrayHasKey assertions in the test are checking
for CSV column keys with an incorrect format. The controller implementation
generates keys using the pattern field_id concatenated with underscore and the
column name (e.g., '10_line1'), but the test assertions are expecting keys with
a 'field_' prefix and hyphen separators (e.g., 'field_10-line1'). Update all six
assertArrayHasKey calls to use the correct key format by replacing 'field_10-'
with '10_' so the keys match the actual output from the controller, ensuring the
test properly validates the CSV column headers.

---

Nitpick comments:
In `@classes/views/frm-fields/back-end/combo-field/sub-field-options.php`:
- Line 58: The current implementation uses a strict comparison operator (===) to
determine the selected state in the ternary operator, which can fail due to type
mismatches between $default_value and $opt_value. Replace the ternary operator
logic that checks for selected state with a call to FrmAppHelper::selected(),
passing the $default_value[$sub_field['name']] and $opt_value as arguments. This
helper method handles type-safe comparison internally and provides consistent
behavior across Lite and Pro versions by delegating to
FrmProAppHelper::selected() when available or falling back to WordPress's
selected() function otherwise.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 69d0c870-ffe5-437f-9ce4-b6ccf1b9d987

📥 Commits

Reviewing files that changed from the base of the PR and between 3937b09 and 67a23bd.

📒 Files selected for processing (12)
  • classes/controllers/FrmAddressesController.php
  • classes/controllers/FrmComboFieldsController.php
  • classes/controllers/FrmHooksController.php
  • classes/models/fields/FrmFieldAddress.php
  • classes/models/fields/FrmFieldCombo.php
  • classes/models/fields/FrmFieldName.php
  • classes/views/combo-fields/input-form-builder.php
  • classes/views/combo-fields/input.php
  • classes/views/frm-fields/back-end/combo-field/sub-field-options.php
  • classes/views/frm-fields/front-end/address-field/address-field.php
  • square/controllers/FrmSquareLiteAppController.php
  • tests/phpunit/fields/test_FrmFieldAddress.php
🚧 Files skipped from review as they are similar to previous changes (5)
  • classes/views/combo-fields/input-form-builder.php
  • classes/views/combo-fields/input.php
  • classes/controllers/FrmComboFieldsController.php
  • classes/views/frm-fields/front-end/address-field/address-field.php
  • classes/controllers/FrmAddressesController.php

Comment thread tests/phpunit/fields/test_FrmFieldAddress.php Outdated
}

/**
* @return void array<(array<string> | string)>>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Malformed PHPDoc return type.

The return type @return void array<(array<string> | string)>> is invalid—data providers cannot return void, and the syntax has an extra closing bracket.

📝 Proposed fix
-	 * `@return` void array<(array<string> | string)>>
+	 * `@return` iterable<string, array{0: string, 1: array<string>}>

Or simply remove the tag if the return type is clear from context.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* @return void array<(array<string> | string)>>
* `@return` iterable<string, array{0: string, 1: array<string>}>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/phpunit/fields/test_FrmFieldAddress.php` at line 286, The PHPDoc return
type annotation on line 286 has invalid syntax with `void` (which cannot be used
for data providers) and an extra closing bracket. Remove the `void` keyword and
correct the bracket matching so the return type reads as a proper generic array
type like `@return array<(array<string> | string)>`, or alternatively remove the
return type tag entirely if the return type is clear from context.

$address_field = new FrmFieldAddress( $field );
$result = $address_field->get_export_headings();

$this->assertArrayHasKey( 'field_10', $result, 'Result should have main field column.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/phpunit/fields/test_FrmFieldAddress.php (1)

57-72: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep the US-address expectations aligned with the model contract.

Line 72 and the us provider case expect country to be absent, but classes/models/fields/FrmFieldAddress.php:get_processed_sub_fields() only removes country for generic; for us it keeps country and only turns state into a select. These assertions will drift the controller/model contract and fail if both layers stay aligned.

Suggested fix
-		$this->assertArrayNotHasKey( 'country', $result, 'Result should not have country for US address.' );
+		$this->assertArrayHasKey( 'country', $result, 'Result should have country for US address.' );
-		yield 'us' => array( 'us', array( 'line1', 'line2', 'city', 'state', 'zip' ) );
+		yield 'us' => array( 'us', array( 'line1', 'line2', 'city', 'state', 'zip', 'country' ) );

Also applies to: 269-270

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/phpunit/fields/test_FrmFieldAddress.php` around lines 57 - 72, Update
the US-address test expectations to match the
`FrmFieldAddress::get_processed_sub_fields()` contract: for the `us` provider,
`country` should still be present and only `state` should become a select.
Adjust the assertions in `test_get_sub_fields_us_returns_correct_fields()` so
they align with `FrmAddressesController::get_sub_fields()` and the model
behavior, and only assert `country` is removed for the `generic` case.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/phpunit/fields/test_FrmFieldAddress.php`:
- Around line 214-217: The test for FrmFieldAddress::get_export_headings is
asserting an aggregate field_10 export heading that the inherited
FrmFieldCombo::get_export_headings implementation does not produce. Remove the
main field column assertion from test_FrmFieldAddress and keep the checks
focused on the per-subfield keys returned by FrmFieldAddress, using the existing
$address_field and get_export_headings() call as the locator.

---

Outside diff comments:
In `@tests/phpunit/fields/test_FrmFieldAddress.php`:
- Around line 57-72: Update the US-address test expectations to match the
`FrmFieldAddress::get_processed_sub_fields()` contract: for the `us` provider,
`country` should still be present and only `state` should become a select.
Adjust the assertions in `test_get_sub_fields_us_returns_correct_fields()` so
they align with `FrmAddressesController::get_sub_fields()` and the model
behavior, and only assert `country` is removed for the `generic` case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 1efa16e5-ce04-465d-aadb-001777c7d802

📥 Commits

Reviewing files that changed from the base of the PR and between 67a23bd and d69ed83.

📒 Files selected for processing (5)
  • classes/controllers/FrmAddressesController.php
  • classes/models/fields/FrmFieldAddress.php
  • classes/models/fields/FrmFieldCombo.php
  • classes/views/frm-fields/back-end/combo-field/sub-field-options.php
  • tests/phpunit/fields/test_FrmFieldAddress.php
🚧 Files skipped from review as they are similar to previous changes (2)
  • classes/views/frm-fields/back-end/combo-field/sub-field-options.php
  • classes/models/fields/FrmFieldAddress.php

Comment thread tests/phpunit/fields/test_FrmFieldAddress.php Outdated

$this->set_private_property( $combo_field, 'field', $field );

$this->assertSame(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldCombo::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

* @return array
*/
public function get_export_headings() {
$field_id = $this->field->id ?? $this->field['id'];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Access to an undefined property array|int|object::$id


The property you are trying to access is not defined and will cause unexpected behavior when used.

*/
public function get_export_headings() {
$field_id = $this->field->id ?? $this->field['id'];
$field_name = $this->field->name ?? $this->field['name'];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Access to an undefined property array|int|object::$name


The property you are trying to access is not defined and will cause unexpected behavior when used.

@Crabcyborg Crabcyborg modified the milestones: 6.33, 6.34 Jul 14, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
classes/controllers/FrmAddressesController.php (2)

197-200: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Validate $country before using it as an array key.

get_country_code() maps $country before checking its type. If the caller passes an array or object, $country_codes[$country] raises a TypeError/“Illegal offset type” error. Return an empty string before the lookup for non-string values.

Suggested fix
 public static function get_country_code( $country ) {
+		if ( ! is_string( $country ) ) {
+			return '';
+		}
+
 		self::maybe_define_country_codes();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@classes/controllers/FrmAddressesController.php` around lines 197 - 200,
Update get_country_code() to return an empty string immediately when $country is
not a string, before using it as a key in self::$country_codes. Preserve the
existing country-code lookup and string-result fallback for valid string inputs.

152-165: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Align the US address contract across rendering paths.

FrmAddressesController::get_sub_fields() removes country for US addresses, but FrmFieldAddress::get_processed_sub_fields() omits the US country exclusion. This can make exported, displayed, submitted, or displayed saved address values include a country value even when the form never renders a country field for US addresses. Keep country out of the model’s US branch, or include it in both paths.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@classes/controllers/FrmAddressesController.php` around lines 152 - 165, The
US address handling is inconsistent between
FrmAddressesController::get_sub_fields() and
FrmFieldAddress::get_processed_sub_fields(). Update
FrmFieldAddress::get_processed_sub_fields() so its US-address branch excludes
country, matching the fields rendered by get_sub_fields() and preventing country
values from being processed or displayed for US addresses.
classes/models/fields/FrmFieldCombo.php (1)

465-466: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Keep get_export_headings() safe for partial field shapes.

get_export_headings() has no parent::get_export_headings() call, so non-object $this->field must be an array with both id and name. Constructing or passing a partial field can trigger array-offset notices before the export headings loop runs. Use null-safe/default fallbacks and make sure this method still calls the parent implementation when appropriate.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@classes/models/fields/FrmFieldCombo.php` around lines 465 - 466, Update
get_export_headings() so partial or non-array field values do not access missing
id/name offsets: use null-safe/default fallbacks for field_id and field_name.
Also invoke parent::get_export_headings() in the appropriate path, preserving
the existing export-heading behavior when a complete field is available.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@classes/models/fields/FrmFieldCombo.php`:
- Line 44: The combo-field sub-field lookup is inaccessible to the address
rendering flow. In classes/models/fields/FrmFieldCombo.php at line 44, make
get_sub_fields() publicly accessible or add a public compatibility accessor and
update show_in_form() to use it; in
classes/controllers/FrmAddressesController.php at line 97, keep the controller
method public so sub_fields can pass through the controller/API layer.

---

Outside diff comments:
In `@classes/controllers/FrmAddressesController.php`:
- Around line 197-200: Update get_country_code() to return an empty string
immediately when $country is not a string, before using it as a key in
self::$country_codes. Preserve the existing country-code lookup and
string-result fallback for valid string inputs.
- Around line 152-165: The US address handling is inconsistent between
FrmAddressesController::get_sub_fields() and
FrmFieldAddress::get_processed_sub_fields(). Update
FrmFieldAddress::get_processed_sub_fields() so its US-address branch excludes
country, matching the fields rendered by get_sub_fields() and preventing country
values from being processed or displayed for US addresses.

In `@classes/models/fields/FrmFieldCombo.php`:
- Around line 465-466: Update get_export_headings() so partial or non-array
field values do not access missing id/name offsets: use null-safe/default
fallbacks for field_id and field_name. Also invoke parent::get_export_headings()
in the appropriate path, preserving the existing export-heading behavior when a
complete field is available.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 81e6c49e-ae83-4e9f-aa78-41b51084f01a

📥 Commits

Reviewing files that changed from the base of the PR and between daeef13 and 2cf42da.

📒 Files selected for processing (7)
  • classes/controllers/FrmAddressesController.php
  • classes/controllers/FrmComboFieldsController.php
  • classes/models/fields/FrmFieldAddress.php
  • classes/models/fields/FrmFieldCombo.php
  • css/frm_admin.css
  • css/frm_testing_mode.css
  • tests/phpunit/fields/test_FrmFieldAddress.php
💤 Files with no reviewable changes (1)
  • classes/controllers/FrmComboFieldsController.php
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/phpunit/fields/test_FrmFieldAddress.php
  • classes/models/fields/FrmFieldAddress.php

Comment thread classes/models/fields/FrmFieldCombo.php Outdated
* @return array
*/
public function get_sub_fields() {
protected function get_sub_fields() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n -P '(->|::)\s*get_sub_fields\s*\(' --glob '*.php' .

Repository: Strategy11/formidable-forms

Length of output: 364


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== candidate files =="
git ls-files | rg '(^|/)Frm(FieldCombo|AddressesController)\.php$' || true

echo "== outlines =="
ast-grep outline classes/models/fields/FrmFieldCombo.php --view compact || true
ast-grep outline classes/controllers/FrmAddressesController.php --view compact || true

echo "== relevant sections =="
sed -n '1,150p' classes/models/fields/FrmFieldCombo.php
echo "---"
sed -n '1,140p' classes/controllers/FrmAddressesController.php

Repository: Strategy11/formidable-forms

Length of output: 6831


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== search get_sub_fields (all) =="
rg -n 'get_sub_fields' --glob '*.php' . || true
echo "== search frm_address/sub field APIs =="
rg -n "frm_.*address|combo field|sub_fields|register.*address|FieldAddress|FrmFieldAddress|get_sub_fields" --glob '*.php' . || true

echo "== locate FrmComboFieldsController =="
rg -n "class Frm ComboFieldsController|FrmComboFieldsController" --glob '*.php' . || true

Repository: Strategy11/formidable-forms

Length of output: 20041


Keep get_sub_fields() accessible for combo-field rendering.

get_sub_fields() has no public extension callers in this codebase, but the address field rendering path passes $args['sub_fields'] through the controller/API layer, while this method remains protected. Keep the controller method public, or add a public compatibility accessor used by show_in_form().

📍 Affects 2 files
  • classes/models/fields/FrmFieldCombo.php#L44-L44 (this comment)
  • classes/controllers/FrmAddressesController.php#L97-L97
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@classes/models/fields/FrmFieldCombo.php` at line 44, The combo-field
sub-field lookup is inaccessible to the address rendering flow. In
classes/models/fields/FrmFieldCombo.php at line 44, make get_sub_fields()
publicly accessible or add a public compatibility accessor and update
show_in_form() to use it; in classes/controllers/FrmAddressesController.php at
line 97, keep the controller method public so sub_fields can pass through the
controller/API layer.

<?php esc_html_e( 'Address', 'formidable' ); ?>
</label>
<?php
$action_control->show_fields_dropdown(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $action_control might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

</label>
<?php
$action_control->show_fields_dropdown(
$field_dropdown_atts,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field_dropdown_atts might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

?>
</p>
<p class="frm6">
<label for="<?php echo esc_attr( $action_control->get_field_id( 'shipping_first_name' ) ); ?>">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $action_control might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

<label for="<?php echo esc_attr( $action_control->get_field_id( 'shipping_first_name' ) ); ?>">
<?php esc_html_e( 'First Name', 'formidable' ); ?>
</label>
<?php $action_control->show_fields_dropdown( $field_dropdown_atts, array( 'name' => 'shipping_first_name' ) ); ?>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $action_control might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

<label for="<?php echo esc_attr( $action_control->get_field_id( 'shipping_first_name' ) ); ?>">
<?php esc_html_e( 'First Name', 'formidable' ); ?>
</label>
<?php $action_control->show_fields_dropdown( $field_dropdown_atts, array( 'name' => 'shipping_first_name' ) ); ?>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable $field_dropdown_atts might not be defined


A variable has been used but not defined, which may result in warnings during program execution. This can also cause bugs since the intended usage scope of the variable is not known.

)
);
$us_subs = $this->run_private_method( array( $us_field, 'get_processed_sub_fields' ), array() );
$this->assertSame( 'select', $us_subs['state']['type'], 'US state should be a dropdown.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

)
);
$sub_fields = $this->run_private_method( array( $field_type, 'get_processed_sub_fields' ), array() );
$this->assertSame( 'select', $sub_fields['country']['type'], "Country should be a dropdown for the {$address_type} type." );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

$field_type = new FrmFieldAddress();
$options = $this->run_private_method( array( $field_type, 'extra_field_opts' ), array() );

$this->assertSame( 'international', $options['address_type'], 'The default address type should be international.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

$options = $this->run_private_method( array( $field_type, 'extra_field_opts' ), array() );

$this->assertSame( 'international', $options['address_type'], 'The default address type should be international.' );
$this->assertArrayHasKey( 'city_desc', $options, 'Sub-field descriptions should be included.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertArrayHasKey()


The method you are trying to call is not defined, which can result in a fatal error.


$this->assertSame( 'international', $options['address_type'], 'The default address type should be international.' );
$this->assertArrayHasKey( 'city_desc', $options, 'Sub-field descriptions should be included.' );
$this->assertSame( '', $options['line1_desc'], 'line1 should default to an empty description.' );

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Call to an undefined method test_FrmFieldAddress::assertSame()


The method you are trying to call is not defined, which can result in a fatal error.

@codecov

codecov Bot commented Aug 3, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.97017% with 83 lines in your changes missing coverage. Please review.
✅ Project coverage is 28.46%. Comparing base (3ea3602) to head (fc0f091).
⚠️ Report is 7 commits behind head on master.

Files with missing lines Patch % Lines
classes/controllers/FrmComboFieldsController.php 5.26% 54 Missing ⚠️
classes/models/fields/FrmFieldAddress.php 93.45% 14 Missing ⚠️
classes/controllers/FrmAddressesController.php 97.15% 10 Missing ⚠️
classes/controllers/FrmFieldsController.php 0.00% 2 Missing ⚠️
classes/models/fields/FrmFieldCombo.php 60.00% 2 Missing ⚠️
classes/models/fields/FrmFieldName.php 0.00% 1 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##             master    #3171      +/-   ##
============================================
+ Coverage     26.26%   28.46%   +2.19%     
- Complexity     9464     9563      +99     
============================================
  Files           155      158       +3     
  Lines         31680    32306     +626     
============================================
+ Hits           8322     9196     +874     
+ Misses        23358    23110     -248     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Crabcyborg
Crabcyborg requested a review from garretlaxton August 5, 2026 17:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant