// phpcs:ignore Generic.Commenting.DocComment.MissingShort
/** @noinspection AutoloadingIssuesInspection */
if ( ! defined( 'ABSPATH' ) ) {
* Internal information field class.
class WPForms_Field_Internal_Information extends WPForms_Field {
* The key used to save form checkboxes in post meta table.
private const CHECKBOX_META_KEY = 'wpforms_iif_checkboxes';
* Class initialization method.
$this->name = $this->is_editable() ? esc_html__( 'Internal Information', 'wpforms-lite' ) : esc_html__( 'This field is not editable', 'wpforms-lite' );
$this->type = 'internal-information';
$this->icon = 'fa fa-sticky-note-o';
* @noinspection PhpUnnecessaryCurlyVarSyntaxInspection
private function hooks() {
add_filter( 'wpforms_entries_table_fields_disallow', [ $this, 'hide_column_in_entries_table' ], 10, 2 );
add_filter( 'wpforms_field_preview_class', [ $this, 'add_css_class_for_field_wrapper' ], 10, 2 );
add_filter( 'wpforms_field_new_class', [ $this, 'add_css_class_for_field_wrapper' ], 10, 2 );
add_filter( "wpforms_pro_admin_entries_edit_is_field_displayable_{$this->type}", '__return_false' );
add_filter( 'wpforms_builder_strings', [ $this, 'builder_strings' ], 10, 2 );
add_filter( 'wpforms_frontend_form_data', [ $this, 'remove_internal_fields_on_front_end' ] );
add_filter( 'wpforms_pro_fields_entry_preview_get_ignored_fields', [ $this, 'ignore_entry_preview' ] );
add_filter( 'wpforms_process_before_form_data', [ $this, 'process_before_form_data' ], 10, 2 );
add_filter( 'wpforms_field_preview_display_duplicate_button', [ $this, 'display_duplicate_button' ], 10, 3 );
add_action( 'wpforms_builder_enqueues', [ $this, 'builder_enqueues' ] );
add_action( 'wp_ajax_wpforms_builder_save_internal_information_checkbox', [ $this, 'save_internal_information_checkbox' ] );
* Whether the current field can be populated dynamically.
* @param array $properties Field properties.
* @param array $field Current field specific data.
public function is_dynamic_population_allowed( $properties, $field ): bool {
* Whether the current field can be populated using a fallback.
* @param array $properties Field properties.
* @param array $field Current field specific data.
public function is_fallback_population_allowed( $properties, $field ): bool {
* Define field options to display in the left panel.
* @param array $field Field data and settings.
public function field_options( $field ) {
$this->heading_option( $field );
$this->field_option( 'description', $field );
$this->expanded_description_option( $field );
$this->cta_label_option( $field );
$this->cta_link_option( $field );
$this->field_code( $field );
* Define field preview on the right side on builder.
* @param array $field Field data and settings.
public function field_preview( $field ) {
$class = wpforms_sanitize_classes( $field['class'] ?? '' );
'<div class="internal-information-wrap wpforms-clear %s">',
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
echo wpforms_render( 'fields/internal-information/icon-lightbulb' );
echo '<div class="internal-information-content">';
$this->render_preview( 'heading', $field );
$this->render_preview( 'description', $field );
$this->render_preview( 'expanded-description', $field );
$this->render_preview( 'addon', $field );
if ( $this->is_button_displayable( $field ) ) {
echo '<div class="wpforms-field-internal-information-row wpforms-field-internal-information-row-cta-button">';
echo $this->render_custom_preview( 'cta-button', $field );
// phpcs:enable WordPress.Security.EscapeOutput.OutputNotEscaped
* Checks if the button is displayable.
* @param array $field Field data.
private function is_button_displayable( $field ) {
return ! empty( $field['expanded-description'] ) ||
( ! empty( $field['cta-label'] ) && ! empty( $field['cta-link'] ) ) ||
* Stub to make the field not visible in the front-end.
* @param array $field Field data and settings.
* @param array $deprecated Field attributes.
* @param array $form_data Form data.
public function field_display( $field, $deprecated, $form_data ) {
* @param array $field Field data and settings.
private function heading_option( $field ) {
$output = $this->field_element(
'value' => esc_html__( 'Heading', 'wpforms-lite' ),
'tooltip' => esc_attr__( 'Enter text for the form field heading.', 'wpforms-lite' ),
$output .= $this->field_element(
'value' => ! empty( $field['label'] ) ? esc_attr( $field['label'] ) : '',
* Expanded description option.
* @param array $field Field data and settings.
private function expanded_description_option( $field ) {
$output = $this->field_element(
'slug' => 'expanded-description',
'value' => esc_html__( 'Expanded Content', 'wpforms-lite' ),
'tooltip' => esc_attr__( 'Enter text for the form field expanded description.', 'wpforms-lite' ),
$output .= $this->field_element(
'slug' => 'expanded-description',
'value' => ! empty( $field['expanded-description'] ) ? esc_html( $field['expanded-description'] ) : '',
'<p class="note">%s</p>',
esc_html__( 'Adds an expandable content area below the description.', 'wpforms-lite' )
'slug' => 'expanded-description',
* @param array $field Field data and settings.
private function cta_label_option( $field ) {
$output = $this->field_element(
'value' => esc_html__( 'CTA Label', 'wpforms-lite' ),
'tooltip' => esc_attr__( 'Enter label for the form field call to action button. The label will be ignored if the field has extended description content: in that case button will be used to expand the description content.', 'wpforms-lite' ),
$output .= $this->field_element(
'value' => ! empty( $field['cta-label'] ) ? esc_attr( $field['cta-label'] ) : esc_attr__( 'Learn More', 'wpforms-lite' ),
* @param array $field Field data and settings.
private function cta_link_option( $field ) {
$output = $this->field_element(
'value' => esc_html__( 'CTA Link', 'wpforms-lite' ),
'tooltip' => esc_attr__( 'Enter the URL for the form field call to action button. URL will be ignored if the field has extended description content: in that case button will be used to expand the description content.', 'wpforms-lite' ),
$output .= $this->field_element(
'value' => ! empty( $field['cta-link'] ) ? esc_url( $field['cta-link'] ) : '',
'<p class="note">%s</p>',
esc_html__( 'CTA is hidden if Expanded Content is used.', 'wpforms-lite' )
* Add hidden input with code identifier.
* @param array $field Field data and settings.
private function field_code( $field ) {
'<input type="hidden" name="fields[%1$s][code]" value="%2$s">',
! empty( $field['code'] ) ? esc_attr( $field['code'] ) : ''
* Add a CSS class to hide field settings when the field is not editable.
* @param string $option Field option to render.
* @param array $field Field data and settings.
* @param array $args Field preview arguments.
* @param bool $do_echo Print or return the value. Print by default.
public function field_element( $option, $field, $args = [], $do_echo = true ) {
if ( ! isset( $args['class'] ) ) {
if ( ! $this->is_editable() ) {
$args['class'] .= ' wpforms-hidden ';
return parent::field_element( $option, $field, $args, $do_echo );
* Render a custom option preview on the right side of the builder.
* @param string $option Field option to render.
* @param array $field Field data and settings.
* @param array $args Field arguments.
* @noinspection HtmlUnknownTarget
private function render_custom_preview( $option, $field, $args = [] ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
$class = ! empty( $args['class'] ) ? wpforms_sanitize_classes( $args['class'] ) : '';
$allowed_tags = $this->get_allowed_tags();
$label = isset( $field['label'] ) && ! wpforms_is_empty_string( $field['label'] ) ? esc_html( $field['label'] ) : '';
'<label class="label-title heading %s"><span class="text">%s</span><span class="required">*</span></label>',
case 'description': // phpcs:ignore WPForms.Formatting.Switch.AddEmptyLineBefore
$description = ! empty( $field['description'] ) ? wp_kses( $field['description'], $allowed_tags ) : '';
$description = wpautop( $this->replace_checkboxes( $description, $field ) );
$description = $this->add_link_attributes( $description );
return sprintf( '<div class="description %s">%s</div>', $class, $description );
case 'expanded-description': // phpcs:ignore WPForms.Formatting.Switch.AddEmptyLineBefore
$description = isset( $field['expanded-description'] ) && ! wpforms_is_empty_string( $field['expanded-description'] ) ? wp_kses( $field['expanded-description'], $allowed_tags ) : '';
$description = wpautop( $this->replace_checkboxes( $description, $field ) );
$description = $this->add_link_attributes( $description );
return sprintf( '<div class="expanded-description %s">%s</div>', esc_attr( $class ), wp_kses( $description, $allowed_tags ) );
case 'cta-button': // phpcs:ignore WPForms.Formatting.Switch.AddEmptyLineBefore
$label = ! empty( $field['cta-label'] ) && empty( $field['expanded-description'] ) ? esc_attr( $field['cta-label'] ) : esc_attr__( 'Learn More', 'wpforms-lite' );
if ( ! empty( $field['expanded-description'] ) ) {
'<div class="cta-button cta-expand-description not-expanded %s"><a href="#" target="_blank" rel="noopener noreferrer"><span class="button-label">%s</span> %s %s</a></div>',
wpforms_render( 'fields/internal-information/icon-not-expanded' ),
wpforms_render( 'fields/internal-information/icon-expanded' )
if ( ! empty( $field['cta-link'] ) ) {
return sprintf( '<div class="cta-button cta-link-external %s"><a href="%s" target="_blank" rel="noopener noreferrer">%s</a></div>', esc_attr( $class ), esc_url( $this->add_url_utm( $field ) ), esc_html( $label ) );
return sprintf( '<div class="cta-button cta-link-external %s"><a href="" target="_blank" rel="noopener noreferrer" class="hidden"><span class="button-label"></span></a></div>', esc_attr( $class ) );
if ( empty( $field['addon'] ) ) {
return sprintf( '<input type="hidden" name="fields[%1$s][addon]" value="%2$s">', esc_attr( $field['id'] ), esc_attr( $field['addon'] ) );
* Display the field button in the left panel only if the field is editable.
* @param array $fields All fields to display in the left panel.
public function field_button( $fields ) {
if ( $this->is_editable() ) {
return parent::field_button( $fields );