: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
private function get_license_level( $template ) {
$licenses_pro = [ 'basic', 'plus', 'pro' ];
$licenses_template = (array) $template['license'];
empty( $template['license'] ) ||
in_array( 'lite', $licenses_template, true )
foreach ( $licenses_pro as $license ) {
if ( in_array( $license, $licenses_template, true ) ) {
public function get_categories() {
return $this->categories;
* Get subcategories data.
public function get_subcategories() {
return $this->subcategories;
public function get_templates(): array {
if ( ! empty( $templates ) ) {
// phpcs:disable WPForms.PHP.ValidateHooks.InvalidHookName
* Form templates available in the WPForms core plugin.
* @param array $templates Core templates data.
$core_templates = (array) apply_filters( 'wpforms_form_templates_core', [] );
* Form templates available with the WPForms addons.
* Allows developers to provide additional templates with an addons.
* @param array $templates Addons templates data.
$additional_templates = (array) apply_filters( 'wpforms_form_templates', [] );
// phpcs:enable WPForms.PHP.ValidateHooks.InvalidHookName
$templates = array_merge( $core_templates, $additional_templates );
// Generate and store the templates' hash.
$this->hash = wp_hash( wp_json_encode( $templates ) );
public function get_hash(): string {
* Get single template data.
* @param string $slug Template slug OR Id.
public function get_template( $slug ) {
$template = $this->get_template_by_slug( $slug );
$template = $this->get_template_by_id( $slug );
if ( empty( $template ) ) {
if ( empty( $template['id'] ) ) {
// Attempt to get template with form data (if available).
$full_template = wpforms()
->get( 'builder_template_single' )
->instance( $template['id'], $this->license )
if ( ! empty( $full_template['data'] ) ) {
* Get template data by slug.
* @param string $slug Template slug.
private function get_template_by_slug( $slug ) {
foreach ( $this->get_templates() as $template ) {
if ( ! empty( $template['slug'] ) && $template['slug'] === $slug ) {
* Get template data by Id.
* @param string $id Template id.
private function get_template_by_id( $id ) {
foreach ( $this->api_templates as $template ) {
if ( ! empty( $template['id'] ) && $template['id'] === $id ) {
* Add templates to the list on the Setup panel.
* @param array $templates Templates list.
public function add_templates_to_setup_panel( $templates ) {
return array_merge( $templates, $this->api_templates );
* Add template data when form is created.
* @param array $args Create form arguments.
* @param array $data Template data.
public function apply_to_new_form( $args, $data ) {
if ( empty( $data ) || empty( $data['template'] ) ) {
$template = $this->get_template( $data['template'] );
empty( $template['data'] ) ||
! $this->has_access( $template )
$template['data']['meta']['template'] = $template['id'] ?? $template['slug'];
$template['data']['meta']['category'] = $data['category'] ?? 'all';
$template['data']['meta']['subcategory'] = $data['subcategory'] ?? 'all';
// Enable Notifications by default.
$template['data']['settings']['notification_enable'] = isset( $template['data']['settings']['notification_enable'] )
? $template['data']['settings']['notification_enable']
// Unset settings that should be defined locally.
$template['data']['settings']['form_title'],
$template['data']['settings']['conversational_forms_title'],
$template['data']['settings']['form_pages_title']
// Unset certain values for each Notification, since:
// - Email Subject Line field (subject) depends on the form name that is generated from the template name and form_id.
// - From Name field (sender_name) depends on the blog name and can be replaced by WP Mail SMTP plugin.
// - From Email field (sender_address) depends on the internal logic and can be replaced by WP Mail SMTP plugin.
if ( ! empty( $template['data']['settings']['notifications'] ) ) {
foreach ( (array) $template['data']['settings']['notifications'] as $key => $notification ) {
$template['data']['settings']['notifications'][ $key ]['subject'],
$template['data']['settings']['notifications'][ $key ]['sender_name'],
$template['data']['settings']['notifications'][ $key ]['sender_address']
// Encode template data to post content.
$args['post_content'] = wpforms_encode( $template['data'] );
* Add template data when form is updated.
* @param array $form Form post data.
* @param array $data Form data.
* @param array $args Update form arguments.
public function apply_to_existing_form( $form, $data, $args ) {
if ( empty( $args ) || empty( $args['template'] ) ) {
$template = $this->get_template( $args['template'] );
empty( $template['data'] ) ||
! $this->has_access( $template )
$form_data = wpforms_decode( wp_unslash( $form['post_content'] ) );
// Something is wrong with the form data.
if ( empty( $form_data ) ) {
// Compile the new form data preserving needed data from the existing form.
$new = $template['data'];
$new['id'] = $form['ID'] ?? 0;
$new['field_id'] = $form_data['field_id'] ?? 0;
$new['settings'] = $form_data['settings'] ?? [];
$new['payments'] = $form_data['payments'] ?? [];
$new['meta'] = $form_data['meta'] ?? [];
$template_id = $template['id'] ?? '';
// Preserve template ID `wpforms-user-template-{$form_id}` when overwriting it with another template.
if ( wpforms_is_form_template( $form['ID'] ) ) {
$template_id = $form_data['meta']['template'] ?? '';
$new['meta']['template'] = $template_id;
$new['meta']['category'] = ! empty( $args['category'] ) ? sanitize_text_field( $args['category'] ) : 'all';
$new['meta']['subcategory'] = ! empty( $args['subcategory'] ) ? sanitize_text_field( $args['subcategory'] ) : 'all';
* Allow modifying form data when a new template is applied.
* @param array $new Updated form data.
* @param array $form_data Current form data.
* @param array $template Template data.
$new = (array) apply_filters( 'wpforms_admin_builder_templates_apply_to_existing_form_modify_data', $new, $form_data, $template );
// Update the form with new data.
$form['post_content'] = wpforms_encode( $new );
* Create a form on request.
public function create_form_on_request() {
$template = $this->get_template_on_request();
// Just return if template not found OR user doesn't have access.
if ( empty( $template['has_access'] ) ) {
// Check if the template requires some addons.
if ( $this->check_template_required_addons( $template ) ) {
// Set form title equal to the template's name.
$form_title = ! empty( $template['name'] ) ? $template['name'] : esc_html__( 'New form', 'wpforms-lite' );
$title_query = new WP_Query(
'post_type' => 'wpforms',
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
$title_exists = $title_query->post_count > 0;
$form_id = wpforms()->get( 'form' )->add(
'template' => $template['id'],
// Return if something wrong.
// Update form title if duplicated.
wpforms()->get( 'form' )->update(
'form_title' => $form_title . ' (ID #' . $form_id . ')',
$this->create_form_on_request_redirect( $form_id );
* Get template data before creating a new form on request.
* @return array|bool Template OR false.
private function get_template_on_request() {
if ( ! wpforms_is_admin_page( 'builder' ) || ! wpforms_is_admin_page( 'templates' ) ) {
if ( ! wpforms_current_user_can( 'create_forms' ) ) {
$form_id = isset( $_GET['form_id'] ) ? (int) $_GET['form_id'] : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! empty( $form_id ) ) {
$view = isset( $_GET['view'] ) ? sanitize_key( $_GET['view'] ) : 'setup'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( $view !== 'setup' ) {
$template_id = isset( $_GET['template_id'] ) ? sanitize_key( $_GET['template_id'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
// Attempt to get the template.
$template = $this->get_template( $template_id );
// Just return if template is not found.
if ( empty( $template ) ) {
* Redirect after creating the form.
* @param integer $form_id Form ID.
private function create_form_on_request_redirect( $form_id ) {
// Redirect to the builder if possible.
if ( wpforms_current_user_can( 'edit_form_single', $form_id ) ) {
admin_url( 'admin.php?page=wpforms-builder' )
// Redirect to the forms overview admin page if possible.
if ( wpforms_current_user_can( 'view_forms' ) ) {
admin_url( 'admin.php?page=wpforms-overview' )
// Finally, redirect to the admin dashboard.
wp_safe_redirect( admin_url() );
* Check if the template requires some addons and then redirect to the builder for further interaction if needed.
* @param array $template Template data.
* @return bool True if template requires some addons that are not yet installed and/or activated.
private function check_template_required_addons( $template ) {
// Return false if none addons required.
if ( empty( $template['addons'] ) ) {
$required_addons = wpforms()->get( 'addons' )->get_by_slugs( $template['addons'] );
foreach ( $required_addons as $i => $addon ) {
if ( empty( $addon['action'] ) || ! in_array( $addon['action'], [ 'install', 'activate' ], true ) ) {
unset( $required_addons[ $i ] );
// Return false if not need to install or activate any addons.
// We can proceed with creating the form directly in this process.
if ( empty( $required_addons ) ) {