diff --git a/classes/controllers/FrmFormsController.php b/classes/controllers/FrmFormsController.php index 8eef149989..6af5c064b8 100644 --- a/classes/controllers/FrmFormsController.php +++ b/classes/controllers/FrmFormsController.php @@ -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. + 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 diff --git a/tests/phpunit/forms/test_FrmFormsControllerAjax.php b/tests/phpunit/forms/test_FrmFormsControllerAjax.php index 31ba3c56a7..b9522c83ed 100644 --- a/tests/phpunit/forms/test_FrmFormsControllerAjax.php +++ b/tests/phpunit/forms/test_FrmFormsControllerAjax.php @@ -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.' ); + 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'] ); + $this->assertSame( 'VIVI_TEST_MARKER', $form->options['before_html'], 'frm_setup_new_form_vars did not affect the created form.' ); + } + + 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.' ); + 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'] ); + $expected = FrmFormsHelper::get_default_html( 'before' ) . '_APPENDED'; + $this->assertSame( $expected, $form->options['before_html'], 'Callback could not read the existing before_html default.' ); + } + + public function _append_to_before_html( $values ) { + $values['before_html'] .= '_APPENDED'; + return $values; + } }