namespace WPForms\Integrations\Gutenberg;
use WPForms\Frontend\CSSVars;
use WPForms\Integrations\IntegrationInterface;
use WPForms\Admin\Education\StringsTrait;
* Form Selector Gutenberg block with a live preview.
abstract class FormSelector implements IntegrationInterface {
private const DEFAULT_ATTRIBUTES = [
'backgroundImage' => CSSVars::ROOT_VARS['background-image'],
'backgroundPosition' => CSSVars::ROOT_VARS['background-position'],
'backgroundRepeat' => CSSVars::ROOT_VARS['background-repeat'],
'backgroundSizeMode' => CSSVars::ROOT_VARS['background-size'],
'backgroundSize' => CSSVars::ROOT_VARS['background-size'],
'backgroundWidth' => CSSVars::ROOT_VARS['background-width'],
'backgroundHeight' => CSSVars::ROOT_VARS['background-height'],
'backgroundUrl' => CSSVars::ROOT_VARS['background-url'],
'backgroundColor' => CSSVars::ROOT_VARS['background-color'],
'fieldBorderRadius' => CSSVars::ROOT_VARS['field-border-radius'],
'fieldBorderStyle' => CSSVars::ROOT_VARS['field-border-style'],
'fieldBorderSize' => CSSVars::ROOT_VARS['field-border-size'],
'fieldBackgroundColor' => CSSVars::ROOT_VARS['field-background-color'],
'fieldBorderColor' => CSSVars::ROOT_VARS['field-border-color'],
'fieldTextColor' => CSSVars::ROOT_VARS['field-text-color'],
'fieldMenuColor' => CSSVars::ROOT_VARS['field-menu-color'],
'labelColor' => CSSVars::ROOT_VARS['label-color'],
'labelSublabelColor' => CSSVars::ROOT_VARS['label-sublabel-color'],
'labelErrorColor' => CSSVars::ROOT_VARS['label-error-color'],
'buttonSize' => 'medium',
'buttonBorderStyle' => CSSVars::ROOT_VARS['button-border-style'],
'buttonBorderSize' => CSSVars::ROOT_VARS['button-border-size'],
'buttonBorderRadius' => CSSVars::ROOT_VARS['button-border-radius'],
'buttonBackgroundColor' => CSSVars::ROOT_VARS['button-background-color'],
'buttonTextColor' => CSSVars::ROOT_VARS['button-text-color'],
'buttonBorderColor' => CSSVars::ROOT_VARS['button-border-color'],
'pageBreakColor' => CSSVars::ROOT_VARS['page-break-color'],
'containerPadding' => CSSVars::ROOT_VARS['container-padding'],
'containerBorderStyle' => CSSVars::ROOT_VARS['container-border-style'],
'containerBorderWidth' => CSSVars::ROOT_VARS['container-border-width'],
'containerBorderColor' => CSSVars::ROOT_VARS['container-border-color'],
'containerBorderRadius' => CSSVars::ROOT_VARS['container-border-radius'],
'containerShadowSize' => CSSVars::CONTAINER_SHADOW_SIZE['none']['box-shadow'],
'copyPasteJsonValue' => '',
* Rest API class instance.
* Rest API class instance.
protected $themes_data_obj;
protected $render_engine;
protected $disable_css_setting;
* Instance of CSSVars class.
* Callbacks registered for wpforms_frontend_container_class filter.
* Currently displayed form ID.
private $current_form_id = 0;
* Indicate if the current integration is allowed to load.
public function allow_load(): bool {
return function_exists( 'register_block_type' );
$this->render_engine = wpforms_get_render_engine();
$this->disable_css_setting = (int) wpforms_setting( 'disable-css', '1' );
$this->css_vars_obj = wpforms()->obj( 'css_vars' );
wpforms()->register_instance( 'formselector_themes_data', $this->themes_data_obj );
protected function hooks() {
add_action( 'init', [ $this, 'register_block' ] );
add_action( 'enqueue_block_editor_assets', [ $this, 'enqueue_block_editor_assets' ] );
add_action( 'wpforms_frontend_output_container_after', [ $this, 'replace_wpforms_frontend_container_class_filter' ] );
add_filter( 'wpforms_frontend_form_action', [ $this, 'form_action_filter' ], 10, 2 );
add_filter( 'wpforms_forms_anti_spam_v3_is_honeypot_enabled', [ $this, 'filter_is_honeypot_enabled' ] );
add_filter( 'wpforms_field_richtext_display_editor_is_media_enabled', [ $this, 'disable_richtext_media' ], 10, 2 );
* Disable honeypot in Gutenberg/Block editor.
* @param bool|mixed $is_enabled True if the honeypot is enabled, false otherwise.
* @return bool Whether to disable the honeypot.
public function filter_is_honeypot_enabled( $is_enabled ): bool {
if ( wpforms_is_wpforms_rest() ) {
return (bool) $is_enabled;
* Replace the filter registered for wpforms_frontend_container_class.
* @param array $form_data Form data.
public function replace_wpforms_frontend_container_class_filter( array $form_data ): void { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
if ( empty( $this->callbacks[ $form_data['id'] ] ) ) {
$callback = array_shift( $this->callbacks[ $form_data['id'] ] );
remove_filter( 'wpforms_frontend_container_class', $callback );
if ( ! empty( $this->callbacks[ $form_data['id'] ] ) ) {
add_filter( 'wpforms_frontend_container_class', reset( $this->callbacks[ $form_data['id'] ] ), 10, 2 );
* Register WPForms Gutenberg block on the backend.
public function register_block(): void {
$type_string = [ 'type' => 'string' ];
$type_boolean = [ 'type' => 'boolean' ];
'clientId' => $type_string,
'formId' => $type_string,
'displayTitle' => $type_boolean,
'displayDesc' => $type_boolean,
'className' => $type_string,
'themeName' => $type_string,
'fieldSize' => $type_string,
'fieldBorderRadius' => $type_string,
'fieldBorderStyle' => $type_string,
'fieldBorderSize' => $type_string,
'fieldBackgroundColor' => $type_string,
'fieldBorderColor' => $type_string,
'fieldTextColor' => $type_string,
'fieldMenuColor' => $type_string,
'labelSize' => $type_string,
'labelColor' => $type_string,
'labelSublabelColor' => $type_string,
'labelErrorColor' => $type_string,
'buttonSize' => $type_string,
'buttonBorderStyle' => $type_string,
'buttonBorderSize' => $type_string,
'buttonBorderRadius' => $type_string,
'buttonBackgroundColor' => $type_string,
'buttonBorderColor' => $type_string,
'buttonTextColor' => $type_string,
'pageBreakColor' => $type_string,
'backgroundImage' => $type_string,
'backgroundPosition' => $type_string,
'backgroundRepeat' => $type_string,
'backgroundSizeMode' => $type_string,
'backgroundSize' => $type_string,
'backgroundWidth' => $type_string,
'backgroundHeight' => $type_string,
'backgroundUrl' => $type_string,
'backgroundColor' => $type_string,
'containerPadding' => $type_string,
'containerBorderStyle' => $type_string,
'containerBorderWidth' => $type_string,
'containerBorderColor' => $type_string,
'containerBorderRadius' => $type_string,
'containerShadowSize' => $type_string,
'customCss' => $type_string,
'copyPasteJsonValue' => $type_string,
$this->register_styles();
* Modify WPForms block attributes.
* @param array $attributes Attributes.
$attributes = apply_filters( 'wpforms_gutenberg_form_selector_attributes', $attributes ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
'api_version' => $this->get_block_api_version(),
'attributes' => $attributes,
'style' => 'wpforms-gutenberg-form-selector',
'editor_style' => 'wpforms-integrations',
'render_callback' => [ $this, 'get_form_html' ],
* Register WPForms Gutenberg block styles.
protected function register_styles() {
$min = wpforms_get_min_suffix();
WPFORMS_PLUGIN_URL . "assets/css/admin-integrations{$min}.css",
if ( $this->disable_css_setting === 3 ) {
$css_file = $this->disable_css_setting === 2 ? 'base' : 'full';
$handle = 'wpforms-gutenberg-form-selector';
WPFORMS_PLUGIN_URL . "assets/css/frontend/{$this->render_engine}/wpforms-{$css_file}{$min}.css",
[ 'wp-edit-blocks', 'wpforms-integrations' ],
// Add root CSS variables for the Modern Markup mode for full styles.
if ( empty( $this->css_vars_obj ) || $this->render_engine !== 'modern' || $css_file !== 'full' ) {
wp_add_inline_style( $handle, $this->css_vars_obj->get_root_vars_css() );
* Load WPForms Gutenberg block scripts.
public function enqueue_block_editor_assets() {
$min = wpforms_get_min_suffix();
wp_enqueue_style( 'wpforms-integrations' );
wp_set_script_translations( 'wpforms-gutenberg-form-selector', 'wpforms-lite' );
// jQuery.Confirm Reloaded.
WPFORMS_PLUGIN_URL . 'assets/lib/jquery.confirm/jquery-confirm.min.css',
WPFORMS_PLUGIN_URL . 'assets/lib/jquery.confirm/jquery-confirm.min.js',
// Support for the legacy form selector.
// It is located in the common namespace.
if ( $this->is_legacy_block() ) {
'wpforms-gutenberg-form-selector',
WPFORMS_PLUGIN_URL . "assets/js/integrations/gutenberg/formselector-legacy.es5{$min}.js",
[ 'wp-blocks', 'wp-i18n', 'wp-element', 'jquery' ],
if ( $this->render_engine === 'modern' ) {
WPFORMS_PLUGIN_URL . "assets/js/frontend/wpforms-modern{$min}.js",
[ 'wpforms-gutenberg-form-selector' ],
'wpforms-admin-education-core',
WPFORMS_PLUGIN_URL . "assets/js/admin/education/core{$min}.js",
[ 'jquery', 'jquery-confirm' ],
'wpforms-admin-education-core',
* Whether the block is legacy.
protected function is_legacy_block() {
return version_compare( $GLOBALS['wp_version'], '6.0', '<' );
public function get_localize_data(): array {
'title' => esc_html__( 'WPForms', 'wpforms-lite' ),
'description' => esc_html__( 'Select and display one of your forms.', 'wpforms-lite' ),
esc_html__( 'form', 'wpforms-lite' ),
esc_html__( 'contact', 'wpforms-lite' ),
esc_html__( 'survey', 'wpforms-lite' ),
'form_select' => esc_html__( 'Select a Form', 'wpforms-lite' ),
'form_settings' => esc_html__( 'Form Settings', 'wpforms-lite' ),
'form_edit' => esc_html__( 'Edit Form', 'wpforms-lite' ),
'form_entries' => esc_html__( 'View Entries', 'wpforms-lite' ),
'themes' => esc_html__( 'Themes', 'wpforms-lite' ),
'theme_name' => esc_html__( 'Theme Name', 'wpforms-lite' ),
'theme_delete' => esc_html__( 'Delete Theme', 'wpforms-lite' ),
'theme_delete_title' => esc_html__( 'Delete Form Theme', 'wpforms-lite' ),
// Translators: %1$s: Theme name.
'theme_delete_confirm' => esc_html__( 'Are you sure you want to delete the %1$s theme?', 'wpforms-lite' ),
'theme_delete_cant_undone' => esc_html__( 'This cannot be undone.', 'wpforms-lite' ),
'theme_delete_yes' => esc_html__( 'Yes, Delete', 'wpforms-lite' ),
'theme_copy' => esc_html__( 'Copy', 'wpforms-lite' ),
'theme_custom' => esc_html__( 'Custom Theme', 'wpforms-lite' ),
'theme_noname' => esc_html__( 'Noname Theme', 'wpforms-lite' ),
'field_styles' => esc_html__( 'Field Styles', 'wpforms-lite' ),
'field_label' => esc_html__( 'Field Label', 'wpforms-lite' ),
'field_sublabel' => esc_html__( 'Field Sublabel', 'wpforms-lite' ),
'field_border' => esc_html__( 'Field Border', 'wpforms-lite' ),
'label_styles' => esc_html__( 'Label Styles', 'wpforms-lite' ),
'button_background' => esc_html__( 'Button Background', 'wpforms-lite' ),
'button_text' => esc_html__( 'Button Text', 'wpforms-lite' ),
'button_styles' => esc_html__( 'Button Styles', 'wpforms-lite' ),
'container_styles' => esc_html__( 'Container Styles', 'wpforms-lite' ),
'background_styles' => esc_html__( 'Background Styles', 'wpforms-lite' ),
'remove_image' => esc_html__( 'Remove Image', 'wpforms-lite' ),
'position' => esc_html__( 'Position', 'wpforms-lite' ),
'top_left' => esc_html__( 'Top Left', 'wpforms-lite' ),
'top_center' => esc_html__( 'Top Center', 'wpforms-lite' ),
'top_right' => esc_html__( 'Top Right', 'wpforms-lite' ),
'center_left' => esc_html__( 'Center Left', 'wpforms-lite' ),
'center_center' => esc_html__( 'Center Center', 'wpforms-lite' ),
'center_right' => esc_html__( 'Center Right', 'wpforms-lite' ),
'bottom_left' => esc_html__( 'Bottom Left', 'wpforms-lite' ),
'bottom_center' => esc_html__( 'Bottom Center', 'wpforms-lite' ),
'bottom_right' => esc_html__( 'Bottom Right', 'wpforms-lite' ),
'repeat' => esc_html__( 'Repeat', 'wpforms-lite' ),
'no_repeat' => esc_html__( 'No Repeat', 'wpforms-lite' ),
'repeat_x' => esc_html__( 'Repeat Horizontal', 'wpforms-lite' ),
'repeat_y' => esc_html__( 'Repeat Vertical', 'wpforms-lite' ),
'tile' => esc_html__( 'Tile', 'wpforms-lite' ),
'cover' => esc_html__( 'Cover', 'wpforms-lite' ),
'dimensions' => esc_html__( 'Dimensions', 'wpforms-lite' ),
'width' => esc_html__( 'Width', 'wpforms-lite' ),
'height' => esc_html__( 'Height', 'wpforms-lite' ),
'button_color_notice' => esc_html__( 'Also used for other fields like Multiple Choice, Checkboxes, Rating, and NPS Survey.', 'wpforms-lite' ),
'advanced' => esc_html__( 'Advanced', 'wpforms-lite' ),
'additional_css_classes' => esc_html__( 'Additional CSS Classes', 'wpforms-lite' ),
'form_selected' => esc_html__( 'Form', 'wpforms-lite' ),
'show_title' => esc_html__( 'Show Title', 'wpforms-lite' ),
'show_description' => esc_html__( 'Show Description', 'wpforms-lite' ),
'panel_notice_head' => esc_html__( 'Heads up!', 'wpforms-lite' ),
'panel_notice_text' => esc_html__( 'Do not forget to test your form.', 'wpforms-lite' ),
'panel_notice_link' => esc_url( wpforms_utm_link( 'https://wpforms.com/docs/how-to-properly-test-your-wordpress-forms-before-launching-checklist/', 'gutenberg' ) ),
'panel_notice_link_text' => esc_html__( 'Check out our complete guide!', 'wpforms-lite' ),
'update_wp_notice_head' => esc_html__( 'Want to customize your form styles without editing CSS?', 'wpforms-lite' ),
'update_wp_notice_text' => esc_html__( 'Update WordPress to the latest version to use our modern markup and unlock the controls below.', 'wpforms-lite' ),
'update_wp_notice_link' => esc_url( wpforms_utm_link( 'https://wpforms.com/docs/styling-your-forms/', 'Block Settings', 'Form Styles Documentation' ) ),
'learn_more' => esc_html__( 'Learn more', 'wpforms-lite' ),
'use_modern_notice_head' => esc_html__( 'Want to customize your form styles without editing CSS?', 'wpforms-lite' ),
'use_modern_notice_text' => esc_html__( 'Enable modern markup in your WPForms settings to unlock the controls below.', 'wpforms-lite' ),
'use_modern_notice_link' => esc_url( wpforms_utm_link( 'https://wpforms.com/docs/styling-your-forms/', 'Block Settings', 'Form Styles Documentation' ) ),
'lead_forms_panel_notice_head' => esc_html__( 'Form Styles are disabled because Lead Form Mode is turned on.', 'wpforms-lite' ),
'lead_forms_panel_notice_text' => esc_html__( 'To change the styling for this form, open it in the form builder and edit the options in the Lead Forms settings.', 'wpforms-lite' ),
'size' => esc_html__( 'Size', 'wpforms-lite' ),
'padding' => esc_html__( 'Padding', 'wpforms-lite' ),