: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
* Allow developers to disable Form Builder output.
* @param bool $is_enabled Is builder output enabled? Defaults to `true`.
if ( ! (bool) apply_filters( 'wpforms_builder_output', true ) ) {
$form_id = $this->form ? absint( $this->form->ID ) : '';
$field_id = ! empty( $this->form_data['field_id'] ) ? $this->form_data['field_id'] : '';
$revision = wpforms()->get( 'revisions' )->get_revision();
$preview_url = wpforms_get_form_preview_url( $form_id, true );
$allowed_caps = [ 'edit_posts', 'edit_other_posts', 'edit_private_posts', 'edit_published_posts', 'edit_pages', 'edit_other_pages', 'edit_published_pages', 'edit_private_pages' ];
$can_embed = array_filter( $allowed_caps, 'current_user_can' );
$preview_classes = [ 'wpforms-btn', 'wpforms-btn-toolbar', 'wpforms-btn-light-grey' ];
$builder_classes = [ 'wpforms-admin-page' ];
$preview_classes[] = 'wpforms-alone';
$revision_id = $revision->ID;
$builder_classes[] = 'wpforms-is-revision';
if ( $this->form && wp_revisions_enabled( $this->form ) ) {
$builder_classes[] = 'wpforms-revisions-enabled';
* Allow to modify builder container classes.
* @param array $classes List of classes.
* @param array $form_data Form data and settings.
$builder_classes = (array) apply_filters( 'wpforms_builder_output_classes', $builder_classes, $this->form_data );
* Allow developers to add content before the top toolbar in the Form Builder.
* @param string $content Content before toolbar. Defaults to empty string.
$before_toolbar = apply_filters( 'wpforms_builder_output_before_toolbar', '' );
<div id="wpforms-builder" class="<?php echo wpforms_sanitize_classes( $builder_classes, true ); ?>">
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo wpforms_render( 'builder/fullscreen/ie-notice' );
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( empty( $_GET['force_desktop_view'] ) ) {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo wpforms_render( 'builder/fullscreen/mobile-notice' );
<div id="wpforms-builder-overlay">
<div class="wpforms-builder-overlay-content">
name="wpforms-builder" id="wpforms-builder-form" method="post"
data-id="<?php echo esc_attr( $form_id ); ?>"
data-revision="<?php echo esc_attr( $revision_id ); ?>"
<input type="hidden" name="id" value="<?php echo esc_attr( $form_id ); ?>">
<input type="hidden" value="<?php echo wpforms_validate_field_id( $field_id ); ?>" name="field_id" id="wpforms-field-id">
<?php echo $before_toolbar; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<div class="wpforms-toolbar">
<div class="wpforms-left">
<img src="<?php echo esc_url( WPFORMS_PLUGIN_URL . 'assets/images/sullie-alt.png' ); ?>" alt="<?php esc_attr_e( 'Sullie the WPForms mascot', 'wpforms-lite' ); ?>">
<div class="wpforms-center">
<?php if ( $this->form ) : ?>
<span class="wpforms-center-form-name-prefix">
<?php esc_html_e( 'Now editing', 'wpforms-lite' ); ?>
<span class="wpforms-center-form-name wpforms-form-name">
<?php echo esc_html( isset( $this->form_data['settings']['form_title'] ) ? $this->form_data['settings']['form_title'] : $this->form->post_title ); ?>
<?php if ( $this->form->post_type === 'wpforms-template' ) : ?>
<span class="wpforms-center-form-template-badge">
<?php echo esc_html__( 'Template', 'wpforms-lite' ); ?>
<div class="wpforms-right">
<button id="wpforms-help"
class="wpforms-btn wpforms-btn-toolbar wpforms-btn-light-grey"
title="<?php esc_attr_e( 'Help Ctrl+H', 'wpforms-lite' ); ?>">
<i class="fa fa-question-circle-o"></i>
<span<?php echo $this->form ? ' class="screen-reader-text"' : ''; ?>>
<?php esc_html_e( 'Help', 'wpforms-lite' ); ?>
<?php if ( $this->form ) : ?>
<div id="wpforms-context-menu-container"
class="wpforms-btn wpforms-btn-toolbar wpforms-btn-light-grey">
<svg width="16" height="16" fill="currentColor">
<path d="M2 4a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2c0 1.1.9 2 2 2Zm6 12a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2c0 1.1.9 2 2 2Zm-6 0a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2c0 1.1.9 2 2 2Zm0-6a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2c0 1.1.9 2 2 2Zm6 0a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2c0 1.1.9 2 2 2Zm4-8c0 1.1.9 2 2 2a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2ZM8 4a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2c0 1.1.9 2 2 2Zm6 6a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2c0 1.1.9 2 2 2Zm0 6a2 2 0 0 0 2-2 2 2 0 0 0-2-2 2 2 0 0 0-2 2c0 1.1.9 2 2 2Z"/>
<?php echo wpforms_render( 'builder/context-menu', $this->get_context_menu_args(), true ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
<?php if ( ! $revision ) : ?>
<a href="<?php echo esc_url( $preview_url ); ?>"
class="<?php echo wpforms_sanitize_classes( $preview_classes, true ); ?>"
title="<?php esc_attr_e( 'Preview Form Ctrl+P', 'wpforms-lite' ); ?>"
rel="noopener noreferrer">
<i class="fa fa-eye"></i><span class="text"><?php esc_html_e( 'Preview', 'wpforms-lite' ); ?></span>
<?php if ( $can_embed && ! $revision ) : ?>
<?php if ( $this->form->post_type === 'wpforms-template' ) : ?>
<button id="wpforms-embed"
class="wpforms-btn wpforms-btn-toolbar wpforms-btn-light-grey wpforms-btn-light-grey-disabled"
title="<?php esc_attr_e( 'You cannot embed a form template', 'wpforms-lite' ); ?>">
<i class="fa fa-code"></i><span class="text"><?php esc_html_e( 'Embed', 'wpforms-lite' ); ?></span>
<button id="wpforms-embed"
class="wpforms-btn wpforms-btn-toolbar wpforms-btn-light-grey"
title="<?php esc_attr_e( 'Embed Form Ctrl+B', 'wpforms-lite' ); ?>">
<i class="fa fa-code"></i><span class="text"><?php esc_html_e( 'Embed', 'wpforms-lite' ); ?></span>
<button id="wpforms-save"
class="wpforms-btn wpforms-btn-toolbar wpforms-btn-orange"
title="<?php esc_attr_e( 'Save Form Ctrl+S', 'wpforms-lite' ); ?>">
<i class="fa fa-check"></i><i class="wpforms-loading-spinner wpforms-loading-white wpforms-loading-inline wpforms-hidden"></i><span class="text"><?php esc_html_e( 'Save', 'wpforms-lite' ); ?></span>
<button id="wpforms-exit" title="<?php esc_attr_e( 'Exit Ctrl+Q', 'wpforms-lite' ); ?>">
<i class="fa fa-times"></i>
<!-- Panel toggle buttons. -->
<div class="wpforms-panels-toggle" id="wpforms-panels-toggle">
* Outputs the buttons to toggle between Form Builder panels.
* @param WP_Post $form The form object.
* @param string $view Current view (panel) name.
do_action( 'wpforms_builder_panel_buttons', $this->form, $this->view );
<div class="wpforms-panels">
* Outputs the contents of Form Builder panels.
* @param WP_Post $form The form object.
* @param string $view Current view (panel) name.
do_action( 'wpforms_builder_panels', $this->form, $this->view );
* Display abort message using empty state page.
public function display_abort_message() {
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
'builder/fullscreen/abort-message',
'message' => $this->abort_message,
* Change default admin meta viewport tag upon request to force scrollable
* desktop view on small screens.
* @param string $value Default meta viewport tag value.
public function viewport_meta( $value ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! empty( $_GET['force_desktop_view'] ) ) {
return 'width=1024, initial-scale=1';
* Get localized currency strings for the builder.
* @param array $strings Array of localized strings.
private function add_localized_currencies( array $strings ) {
$currency = wpforms_get_currency();
$currencies = wpforms_get_currencies();
$strings['currency'] = sanitize_text_field( $currency );
$strings['currency_name'] = isset( $currencies[ $currency ]['name'] ) ? sanitize_text_field( $currencies[ $currency ]['name'] ) : '';
$strings['currency_decimals'] = wpforms_get_currency_decimals( $currencies[ $currency ] );
$strings['currency_decimal'] = isset( $currencies[ $currency ]['decimal_separator'] ) ? sanitize_text_field( $currencies[ $currency ]['decimal_separator'] ) : '.';
$strings['currency_thousands'] = isset( $currencies[ $currency ]['thousands_separator'] ) ? sanitize_text_field( $currencies[ $currency ]['thousands_separator'] ) : ',';
$strings['currency_symbol'] = isset( $currencies[ $currency ]['symbol'] ) ? sanitize_text_field( $currencies[ $currency ]['symbol'] ) : '$';
$strings['currency_symbol_pos'] = isset( $currencies[ $currency ]['symbol_pos'] ) ? sanitize_text_field( $currencies[ $currency ]['symbol_pos'] ) : 'left';
* Get context menu arguments, depending on the Lite/Pro version and form or form template type.
private function get_context_menu_args(): array {
'form_id' => $this->form->ID,
'is_form_template' => $this->form->post_type === 'wpforms-template',
'has_payments' => wpforms()->get( 'payment' )->get_by( 'form_id', $this->form->ID ) !== null,
'show_whats_new' => wpforms()->get( 'splash_screen' )->is_available_for_display(),
if ( wpforms()->is_pro() ) {
$args['has_entries'] = wpforms()->get( 'entry' )->get_entries( [ 'form_id' => $this->form->ID ], true ) > 0;
$args['can_duplicate'] = $this->can_duplicate();
* Check if the current user is allowed to duplicate the form.
private function can_duplicate(): bool {
if ( ! wpforms_current_user_can( 'create_forms' ) ) {
if ( ! wpforms_current_user_can( 'view_form_single', $this->form->ID ) ) {
WPForms_Builder::instance();