-
Notifications
You must be signed in to change notification settings - Fork 42
Apply frm_setup_new_form_vars on the modal new-form flow #3333
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
859510e
327cc97
6119dea
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1066,6 +1066,27 @@ public static function build_new_form() { | |
| */ | ||
| $new_values = apply_filters( 'frm_new_form_values', $new_values ); | ||
|
|
||
| // Match the shape FrmFormsHelper::setup_new_vars() gives this filter, so a callback can | ||
| // safely read an existing key (e.g. before_html) before modifying it either way. | ||
| $new_values = FrmFormsHelper::fill_default_opts( $new_values, false, $new_values ); | ||
|
|
||
| /** | ||
| * Allows overriding a new form's default option values (before_html, submit_html, etc). | ||
| * | ||
| * @since 6.36 | ||
| * | ||
| * @param array $values Form values. | ||
| */ | ||
| $new_values = apply_filters( 'frm_setup_new_form_vars', $new_values ); | ||
|
|
||
| // FrmForm::create() reads default option values from $new_values['options'], not top level. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Non-blocking: this loop also newly activates the older Before this diff, This loop runs unconditionally on
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Acknowledged, no change here. This is inherent to the fold-back loop itself, not something the new fill_default_opts() call adds — confirmed by re-checking against the prior commit. Agree it is a behavior completion rather than a regression: FrmForm::create() already re-defaults every option key via fill_form_options() regardless, so a frm_new_form_values callback setting a top-level default key now reaches the same place get_default_opts() would have put it anyway. |
||
| foreach ( FrmFormsHelper::get_default_opts() as $var => $default ) { | ||
| if ( isset( $new_values[ $var ] ) ) { | ||
| $new_values['options'][ $var ] = $new_values[ $var ]; | ||
| } | ||
| unset( $var, $default ); | ||
| } | ||
|
|
||
| $form_id = FrmForm::create( $new_values ); | ||
| /** | ||
| * @since 5.3 | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -96,4 +96,69 @@ private function _check_updated_values( $form_id ) { | |
| $this->assertSame( $posted_val, $actual_val, 'The default value was not updated correctly for field ' . $field->field_key . '.' ); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * @covers FrmFormsController::build_new_form | ||
| * with ajax | ||
| */ | ||
| public function test_build_new_form_applies_frm_setup_new_form_vars_filter() { | ||
| add_filter( 'frm_setup_new_form_vars', array( $this, '_set_custom_before_html' ) ); | ||
|
|
||
| $_POST = array( | ||
| 'action' => 'frm_install_form', | ||
| 'nonce' => wp_create_nonce( 'frm_ajax' ), | ||
| 'name' => 'Vivi Setup New Form Vars Test', | ||
| 'desc' => '', | ||
| ); | ||
| $_REQUEST = $_POST; | ||
|
|
||
| $response = json_decode( $this->trigger_action( 'frm_install_form' ), true ); | ||
|
|
||
| remove_filter( 'frm_setup_new_form_vars', array( $this, '_set_custom_before_html' ) ); | ||
|
|
||
| $this->assertNotEmpty( $response['redirect'] ?? '', 'build_new_form did not return a redirect URL.' ); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| parse_str( (string) wp_parse_url( $response['redirect'], PHP_URL_QUERY ), $redirect_args ); | ||
|
|
||
| $form = FrmForm::getOne( $redirect_args['id'] ); | ||
| $this->assertNotEmpty( $form, 'Form not found with id ' . $redirect_args['id'] ); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| $this->assertSame( 'VIVI_TEST_MARKER', $form->options['before_html'], 'frm_setup_new_form_vars did not affect the created form.' ); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
|
||
| public function _set_custom_before_html( $values ) { | ||
| $values['before_html'] = 'VIVI_TEST_MARKER'; | ||
| return $values; | ||
| } | ||
|
|
||
| /** | ||
| * @covers FrmFormsController::build_new_form | ||
| * with ajax | ||
| */ | ||
| public function test_build_new_form_frm_setup_new_form_vars_callback_can_read_existing_key() { | ||
| add_filter( 'frm_setup_new_form_vars', array( $this, '_append_to_before_html' ) ); | ||
|
|
||
| $_POST = array( | ||
| 'action' => 'frm_install_form', | ||
| 'nonce' => wp_create_nonce( 'frm_ajax' ), | ||
| 'name' => 'Vivi Append Before Html Test', | ||
| 'desc' => '', | ||
| ); | ||
| $_REQUEST = $_POST; | ||
|
|
||
| $response = json_decode( $this->trigger_action( 'frm_install_form' ), true ); | ||
|
|
||
| remove_filter( 'frm_setup_new_form_vars', array( $this, '_append_to_before_html' ) ); | ||
|
|
||
| $this->assertNotEmpty( $response['redirect'] ?? '', 'build_new_form did not return a redirect URL.' ); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| parse_str( (string) wp_parse_url( $response['redirect'], PHP_URL_QUERY ), $redirect_args ); | ||
|
|
||
| $form = FrmForm::getOne( $redirect_args['id'] ); | ||
| $this->assertNotEmpty( $form, 'Form not found with id ' . $redirect_args['id'] ); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| $expected = FrmFormsHelper::get_default_html( 'before' ) . '_APPENDED'; | ||
| $this->assertSame( $expected, $form->options['before_html'], 'Callback could not read the existing before_html default.' ); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
|
|
||
| public function _append_to_before_html( $values ) { | ||
| $values['before_html'] .= '_APPENDED'; | ||
| return $values; | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Non-blocking: filter fires with a different
$valuesshape here than at its only other call site.FrmFormsHelper::setup_new_vars()(the pre-existing, only other place that fires this documented filter) callsfill_default_opts()first, so everyget_default_opts()key (submit_value,success_msg,custom_style,before_html,after_html,submit_html, etc.) already exists at the top level of$valuesby the time the filter runs. Here,$new_valueshas none of those keys set at this point (onlyantispam/on_submit_migrated, nested underoptions) — so a callback written against the documented/long-standing contract (e.g. one that reads an existing key before modifying it, like$values['before_html'] .= '...') would hit an undefined-array-key notice on this call path specifically, even though it works fine on the original path.Checked the one real-world consumer in-repo context (
FrmProFormsController::setup_new_vars→FrmProFormsHelper::setup_new_vars): it only assigns ($values[$var] = FrmAppHelper::get_param(...)), never reads first, so it's unaffected today. But the filter is documented/public, so a third-party callback isn't guaranteed to follow that same write-only pattern.Suggestion (non-blocking): populate
$new_valuesfromFrmFormsHelper::get_default_opts()(or callfill_default_opts()) before firingfrm_setup_new_form_vars, so the filter's$valuesshape is consistent across both call sites regardless of what a given callback happens to do with it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed: build_new_form() now calls FrmFormsHelper::fill_default_opts( $new_values, false, $new_values ) right before firing this filter, matching setup_new_vars()'s shape. New regression test (test_build_new_form_frm_setup_new_form_vars_callback_can_read_existing_key) covers a callback that reads-then-modifies an existing key. Verified red on unpatched code, green with the fix; full test_FrmForm/test_FrmFormsController/test_FrmFormsControllerAjax suite still green (9 tests, 114 assertions), no regressions.