File: /home/globfdxw/www/wp-content/plugins/wpforms-conversational-forms/src/Frontend.php
<?php
namespace WPFormsConversationalForms;
use WP;
use WPForms_Field_File_Upload;
use WPForms_Field_Select;
use WPFormsConversationalForms\Helpers\Colors;
use WP_Post;
/**
* Conversational Forms frontend functionality.
*
* @since 1.0.0
*/
class Frontend {
/**
* Current form data.
*
* @since 1.0.0
*
* @var array
*/
protected $form_data;
/**
* Color helper instance.
*
* @since 1.0.0
*
* @var Colors
*/
public $colors;
/**
* Color string.
*
* @since 1.7.1
*
* @var string
*/
private $color = '';
/**
* Color scheme string.
*
* @since 1.7.1
*
* @var string
*/
private $color_scheme = '';
/**
* Constructor.
*
* @since 1.0.0
*/
public function __construct() {
$this->colors = new Colors();
$this->init();
}
/**
* Initialize.
*
* @since 1.0.0
*/
public function init(): void { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
if ( wp_doing_ajax() ) {
add_action( 'wpforms_ajax_submit_before_processing', [ $this, 'handle_ajax_request' ] );
return;
}
add_action( 'parse_request', [ $this, 'handle_request' ] );
}
/**
* Handle the request.
*
* @since 1.0.0
*
* @param WP $wp WP instance.
*/
public function handle_request( $wp ): void { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( ! empty( $wp->query_vars['name'] ) ) {
$request = $wp->query_vars['name'];
}
if ( empty( $request ) && ! empty( $wp->query_vars['pagename'] ) ) {
$request = $wp->query_vars['pagename'];
}
if ( empty( $request ) ) {
$request = ! empty( $_SERVER['REQUEST_URI'] ) ? esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) : '';
$request = ! empty( $request ) ? sanitize_key( basename( wp_parse_url( $request, PHP_URL_PATH ) ) ) : '';
}
$forms = [];
if ( ! empty( $request ) ) {
$form_handler = wpforms()->obj( 'form' );
$args = [
'name' => $request,
];
// @WPFormsBackCompatStart User Generated Templates since WPForms v1.8.8
if ( defined( get_class( $form_handler ?? '' ) . '::POST_TYPES' ) ) {
$args['post_type'] = $form_handler::POST_TYPES;
}
// @WPFormsBackCompatEnd
$forms = $form_handler->get( '', $args );
}
$form = ! empty( $forms[0] ) ? $forms[0] : null;
if ( ! $this->is_conversational_form( $form ) ) {
return;
}
// Form templates are only allowed for logged-in users that have permissions to view them.
if ( $form->post_type === 'wpforms-template' && ! wpforms_current_user_can( 'view_forms' ) ) {
return;
}
$form_data = wpforms_decode( $form->post_content );
/**
* This filter allows overwriting form data for frontend handle request.
*
* @since 1.7.0
*
* @param array $form_data Form data array.
*/
$this->form_data = apply_filters( 'wpforms_conversational_forms_frontend_handle_request_form_data', $form_data ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
// Override page URLs with the same slug.
if ( ! empty( $wp->query_vars['pagename'] ) ) {
$wp->query_vars['name'] = $wp->query_vars['pagename'];
unset( $wp->query_vars['pagename'] );
}
if ( empty( $wp->query_vars['name'] ) ) {
$wp->query_vars['name'] = $request;
}
$wp->query_vars['post_type'] = $form->post_type;
// Unset the 'error' query var that may appear if custom permalink structures used.
unset( $wp->query_vars['error'] );
/**
* Execute after detecting the Conversational Form.
*
* @since 1.5.9.5
*
* @param array $form_data Form data array.
* @param WP_Post $form Form data.
*/
do_action( 'wpforms_conversational_form_detected', $this->form_data, $form ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
// Enabled conversational form detected. Adding the hooks.
$this->conversational_form_hooks();
// Force the classic render engine for WPForms version starting from 1.8.1.
if ( function_exists( 'wpforms_get_render_engine' ) ) {
$frontend_obj = wpforms()->obj( 'frontend' );
if ( $frontend_obj ) {
$frontend_obj->init_render_engine( 'classic' );
}
}
}
/**
* Conversational form-specific hooks.
*
* @since 1.0.0
*/
public function conversational_form_hooks(): void { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
add_filter( 'template_include', [ $this, 'get_form_template' ], PHP_INT_MAX );
add_filter( 'document_title_parts', [ $this, 'change_form_page_title' ] );
add_filter( 'post_type_link', [ $this, 'modify_permalink' ], 10, 2 );
add_filter( 'wpforms_get_render_engine', [ $this, 'set_render_engine_classic' ], PHP_INT_MAX );
add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
add_action( 'wp_enqueue_scripts', [ $this, 'dequeue_scripts' ], 20 );
add_action( 'wp_print_scripts', [ $this, 'dequeue_scripts' ], 5 );
add_action( 'wpforms_wp_footer', [ $this, 'dequeue_scripts' ] );
add_action( 'wpforms_frontend_confirmation', [ $this, 'dequeue_scripts' ] );
add_action( 'wp_print_styles', [ $this, 'css_compatibility_mode' ] );
add_action( 'wp_head', [ $this, 'print_form_styles' ] );
add_filter( 'body_class', [ $this, 'set_body_classes' ] );
add_filter( 'wpforms_frontend_form_data', [ $this, 'ignore_pagebreaks' ] );
add_filter( 'wpforms_frontend_form_data', [ $this, 'change_multiple_dropdown_type' ] );
add_filter( 'wpforms_field_data', [ $this, 'ignore_date_dropdowns' ], 10, 2 );
add_filter( 'wpforms_field_data', [ $this, 'select_field_data' ], 10, 2 );
add_filter( 'wpforms_field_properties', [ $this, 'ignore_multi_column_layout' ], 10, 3 );
add_filter( 'wpforms_field_properties', [ $this, 'add_data_field_type_attr' ], 10, 3 );
add_filter( 'wpforms_field_properties', [ $this, 'field_properties' ], 10, 3 );
add_filter( 'wpforms_pro_fields_entry_preview_is_fields_ignored', '__return_true' );
add_action( 'wpforms_display_field_after', [ $this, 'add_file_upload_html' ], 10, 2 );
add_filter( 'wpforms_datetime_limits_available', '__return_false', 100 );
add_action( 'wpforms_conversational_forms_content_before', [ $this, 'form_loader_html' ] );
add_action( 'wpforms_conversational_forms_content_before', [ $this, 'form_header_html' ] );
add_action( 'wpforms_conversational_forms_footer', [ $this, 'form_footer_html' ] );
add_filter( 'tiny_mce_before_init', [ $this, 'add_styles_for_rich_text_field' ], 10, 2 );
add_action( 'wp', [ $this, 'meta_tags' ] );
add_action( 'wpforms_frontend_confirmation_message_before', [ $this, 'open_confirmation_wrapper' ], -1000 );
add_action( 'wpforms_frontend_confirmation_message_after', [ $this, 'close_confirmation_wrapper' ], 1000 );
add_filter(
'wpforms_smarttags_process_page_title_value',
[ $this, 'filter_page_title_smart_tag_value' ],
10,
2
);
// We need to remove some hooks as well.
$this->remove_conflicting_hooks();
// Disable Monster Insights loading to prevent conflicts, e.g., Date Picker Styles.
add_filter( 'monsterinsights_get_option_hide_admin_bar_reports', '__return_true' );
}
/**
* Remove unnecessary or conflicting hooks.
*
* @since 1.6.0
*/
public function remove_conflicting_hooks(): void { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' );
remove_action( 'wp_head', 'wp_oembed_add_discovery_links' );
remove_action( 'wp_head', 'wp_oembed_add_host_js' );
remove_action( 'wp_enqueue_scripts', 'twentyseventeen_scripts' );
remove_action( 'wp_enqueue_scripts', 'twentytwenty_register_scripts' );
remove_action( 'wp_enqueue_scripts', 'twentytwenty_register_styles' );
}
/**
* Set render engine to `classic`.
*
* @since 1.10.0
*
* @param string $engine Render engine slug.
*
* @return string
* @noinspection PhpMissingParamTypeInspection
* @noinspection PhpUnusedParameterInspection
*/
public function set_render_engine_classic( $engine ): string { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.Found
return 'classic';
}
/**
* Handle AJAX request.
*
* @since 1.7.0
*/
public function handle_ajax_request(): void { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
global $post;
if ( ! $this->is_conversational_form( $post ) ) {
return;
}
add_filter( 'wpforms_get_render_engine', [ $this, 'set_render_engine_classic' ], PHP_INT_MAX );
// Force the classic render engine for WPForms version starting from 1.8.1.
if ( function_exists( 'wpforms_get_render_engine' ) ) {
$frontend_obj = wpforms()->obj( 'frontend' );
if ( $frontend_obj ) {
$frontend_obj->init_render_engine( 'classic' );
}
}
add_action( 'wpforms_frontend_confirmation_message_before', [ $this, 'open_confirmation_wrapper' ], -1000 );
add_action( 'wpforms_frontend_confirmation_message_after', [ $this, 'close_confirmation_wrapper' ], 1000 );
add_filter(
'wpforms_smarttags_process_page_title_value',
[ $this, 'filter_page_title_smart_tag_value' ],
10,
2
);
}
/**
* Determine whether it is a conversational form.
*
* @since 1.7.0
*
* @param WP_Post $form Form post.
*
* @return bool
*/
private function is_conversational_form( $form ): bool {
$form_handler = wpforms()->obj( 'form' );
$post_types = [ 'wpforms' ];
// @WPFormsBackCompatStart User Generated Templates since WPForms v1.8.8
if ( defined( get_class( $form_handler ?? '' ) . '::POST_TYPES' ) ) {
$post_types = $form_handler::POST_TYPES;
}
// @WPFormsBackCompatEnd
if ( ! isset( $form->post_type ) || ! in_array( $form->post_type, $post_types, true ) ) {
return false;
}
$form_data = wpforms_decode( $form->post_content );
return ! empty( $form_data['settings']['conversational_forms_enable'] );
}
/**
* Conversational form template.
*
* @since 1.0.0
*/
public function get_form_template(): string {
return plugin_dir_path( WPFORMS_CONVERSATIONAL_FORMS_FILE ) . 'templates/single-form.php';
}
/**
* Change the document title to a custom form title.
*
* @since 1.0.0
*
* @param array|mixed $title Original document title parts.
*
* @return array
*/
public function change_form_page_title( $title ): array {
$title = (array) $title;
$title['title'] = $this->get_title();
return $title;
}
/**
* Modify the permalink for a conversational form.
*
* @since 1.0.0
*
* @param string|mixed $post_link The post's permalink.
* @param WP_Post $post The post object.
*
* @return string
*/
public function modify_permalink( $post_link, $post ): string {
$post_link = (string) $post_link;
if ( empty( $this->form_data['id'] ) || absint( $this->form_data['id'] ) !== $post->ID ) {
return $post_link;
}
if ( empty( $this->form_data['settings']['conversational_forms_enable'] ) ) {
return $post_link;
}
return (string) home_url( $post->post_name );
}
/**
* Enqueue scripts and styles.
*
* @since 1.0.0
*/
public function enqueue_scripts(): void {
$min = wpforms_get_min_suffix();
if ( wpforms_has_field_type( 'date-time', $this->form_data ) ) {
wp_enqueue_script(
'wpforms-maskedinput',
WPFORMS_PLUGIN_URL . 'assets/lib/jquery.inputmask.min.js',
[ 'jquery' ],
'5.0.9',
true
);
}
wp_enqueue_script(
'wpforms-conversational-forms-mobile-detect',
wpforms_conversational_forms()->url . "assets/js/vendor/mobile-detect{$min}.js",
[],
'1.4.3',
true
);
wp_enqueue_script(
'wpforms-conversational-forms',
wpforms_conversational_forms()->url . "assets/js/conversational-forms.es5{$min}.js",
[ 'jquery', 'wpforms-conversational-forms-mobile-detect' ],
WPFORMS_CONVERSATIONAL_FORMS_VERSION,
true
);
wp_enqueue_style(
'wpforms-conversational-forms',
wpforms_conversational_forms()->url . "assets/css/conversational-forms{$min}.css",
[ 'wpforms-font-awesome' ],
WPFORMS_CONVERSATIONAL_FORMS_VERSION
);
wp_localize_script(
'wpforms-conversational-forms',
'wpforms_conversational_forms',
[
'html' => $this->get_field_additional_html(),
'i18n' => [
'select_placeholder' => esc_html__( 'Type or select an option', 'wpforms-conversational-forms' ),
'select_list_empty' => esc_html__( 'No suggestions found', 'wpforms-conversational-forms' ),
'select_option_helper' => wp_kses( __( '<strong>Enter</strong> to select an option', 'wpforms-conversational-forms' ), [ 'strong' => [] ] ),
'no_file_chosen' => esc_html__( 'No file chosen', 'wpforms-conversational-forms' ),
],
]
);
// FontAwesome.
wp_enqueue_style(
'wpforms-font-awesome',
WPFORMS_PLUGIN_URL . 'assets/lib/font-awesome/css/all.min.css',
null,
'7.0.1'
);
// FontAwesome v4 compatibility shims.
wp_enqueue_style(
'wpforms-font-awesome-v4-shim',
WPFORMS_PLUGIN_URL . 'assets/lib/font-awesome/css/v4-shims.min.css',
null,
'4.7.0'
);
}
/**
* Dequeue scripts and styles.
*
* @since 1.0.0
*/
public function dequeue_scripts(): void {
wp_dequeue_script( 'wpforms-jquery-timepicker' );
wp_dequeue_style( 'wpforms-jquery-timepicker' );
wp_dequeue_script( 'wpforms-flatpickr' );
wp_dequeue_style( 'wpforms-flatpickr' );
wp_dequeue_script( 'popup-maker-site' );
// Dequeue WPForms Core styles.
wp_dequeue_style( 'wpforms-full' );
wp_dequeue_style( 'wpforms-base' );
wp_dequeue_style( 'wpforms-classic-full' );
wp_dequeue_style( 'wpforms-classic-base' );
wp_dequeue_style( 'wpforms-pro-classic-full' );
wp_dequeue_style( 'wpforms-pro-classic-base' );
wp_dequeue_style( 'wpforms-modern-full' );
wp_dequeue_style( 'wpforms-modern-base' );
wp_dequeue_style( 'wpforms-pro-modern-full' );
wp_dequeue_style( 'wpforms-pro-modern-base' );
// Dequeue OceanWP theme scripts that cause conflicts.
wp_dequeue_script( 'oceanwp-main' );
wp_deregister_script( 'oceanwp-main' );
wp_dequeue_script( 'oceanwp-scroll-effect' );
wp_deregister_script( 'oceanwp-scroll-effect' );
wp_dequeue_script( 'oceanwp-scroll-top' );
wp_deregister_script( 'oceanwp-scroll-top' );
}
/**
* Unload CSS potentially interfering with the Conversational Forms layout.
*
* @since 1.0.0
*/
public function css_compatibility_mode(): void {
/**
* Filter to disable CSS compatibility mode.
*
* @since 1.0.0
*
* @param bool $compat_mode CSS compatibility mode. Default is true.
*/
if ( ! apply_filters( 'wpforms_conversational_forms_css_compatibility_mode', true ) ) { // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
return;
}
$styles = wp_styles();
if ( empty( $styles->queue ) ) {
return;
}
$theme_uri = wp_make_link_relative( get_stylesheet_directory_uri() );
$parent_theme_uri = wp_make_link_relative( get_template_directory_uri() );
$upload_uri = wp_get_upload_dir();
$upload_uri = isset( $upload_uri['baseurl'] ) ? wp_make_link_relative( $upload_uri['baseurl'] ) : $theme_uri;
foreach ( $styles->queue as $handle ) {
if ( ! isset( $styles->registered[ $handle ]->src ) ) {
continue;
}
$src = wp_make_link_relative( $styles->registered[ $handle ]->src );
// Dequeue theme or upload folder CSS.
foreach ( [ $theme_uri, $parent_theme_uri, $upload_uri ] as $uri ) {
if ( strpos( $src, $uri ) !== false ) {
wp_dequeue_style( $handle );
break;
}
}
}
/**
* Action to enqueue custom styles on the Conversational Form page.
*
* @since 1.0.0
*/
do_action( 'wpforms_conversational_forms_enqueue_styles' ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
}
/**
* Print dynamic form styles.
*
* @since 1.0.0
*/
public function print_form_styles(): void { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( empty( $this->form_data['settings']['conversational_forms_color_scheme'] ) ) {
return;
}
$color = sanitize_hex_color( $this->form_data['settings']['conversational_forms_color_scheme'] );
if ( empty( $color ) ) {
$color = '#448ccb';
}
$this->color = $color;
$min = wpforms_get_min_suffix();
switch ( $color ) {
case '#448ccb':
$theme = 'color-scheme-blue';
break;
case '#1a3c5a':
$theme = 'color-scheme-dark_blue';
break;
case '#4aa891':
$theme = 'color-scheme-teal';
break;
case '#9178b3':
$theme = 'color-scheme-purple';
break;
case '#cccccc':
$theme = 'color-scheme-light';
break;
case '#363636':
$theme = 'color-scheme-dark';
break;
default:
$theme = '';
}
if ( ! $theme ) {
require plugin_dir_path( WPFORMS_CONVERSATIONAL_FORMS_FILE ) . 'templates/dynamic-color-scheme-styles.php';
return;
}
wp_enqueue_style(
"wpforms-conversational-forms-{$theme}",
wpforms_conversational_forms()->url . "assets/css/color-schemes/{$theme}{$min}.css",
[ 'wpforms-conversational-forms' ],
WPFORMS_CONVERSATIONAL_FORMS_VERSION
);
$this->color_scheme = $theme;
wp_localize_script(
'wpforms-conversational-forms',
'wpforms_conversational_form_appearance',
$this->get_theme_appearance()
);
}
/**
* Get theme appearance data.
*
* @since 1.16.0
*
* @return array
*/
private function get_theme_appearance(): array {
$themes = [
'color-scheme-blue' => [
'colorBackground' => '#e2edf7',
'colorText' => '#1a3d5c',
],
'color-scheme-dark_blue' => [
'colorBackground' => '#193c5b',
'colorText' => '#d7e6f3',
],
'color-scheme-teal' => [
'colorBackground' => '#cce8e1',
'colorText' => '#317162',
],
'color-scheme-purple' => [
'colorBackground' => '#e6e1ed',
'colorText' => '#5d497d',
],
'color-scheme-light' => [
'colorBackground' => '#f6f6f6',
'colorText' => '#333333',
],
'color-scheme-dark' => [
'colorBackground' => '#161616',
'colorText' => '#cccccc',
],
];
return $themes[ $this->color_scheme ] ?? [];
}
/**
* Set body classes to apply different form styling.
*
* @since 1.0.0
*
* @param array|mixed $classes Body classes.
*
* @return array
*/
public function set_body_classes( $classes ): array {
$classes = (array) $classes;
if ( ! empty( $this->form_data['settings']['conversational_forms_custom_logo'] ) ) {
$classes[] = 'wpforms-conversational-form-custom-logo';
}
return $classes;
}
/**
* Ignore pagebreak elements on render.
*
* @since 1.0.0
*
* @param array|mixed $form_data Form data and settings.
*
* @return array
*/
public function ignore_pagebreaks( $form_data ): array {
$form_data = (array) $form_data;
foreach ( $form_data['fields'] as $id => $field ) {
if ( $field['type'] !== 'pagebreak' ) {
continue;
}
unset( $form_data['fields'][ $id ] );
}
return $form_data;
}
/**
* Ignore the date dropdown style on render.
*
* @since 1.0.0
*
* @param array|mixed $field Field settings.
* @param array $form_data Form data and settings.
*
* @return array
* @noinspection PhpMissingParamTypeInspection
* @noinspection PhpUnusedParameterInspection
*/
public function ignore_date_dropdowns( $field, $form_data ): array { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
$field = (array) $field;
if ( $field['type'] === 'date-time' && $field['date_type'] === 'dropdown' ) {
$field['date_type'] = 'datepicker';
}
return $field;
}
/**
* Convert the date type from `dropdown` to `datepicker` before processing.
*
* @since 1.6.0
* @deprecated 1.7.0
*
* @param array $form_data Form data and settings.
*
* @return array Updated form data.
* @noinspection PhpMissingReturnTypeInspection
* @noinspection ReturnTypeCanBeDeclaredInspection
*/
public function prepare_date_dropdowns( $form_data ) {
_deprecated_function( __METHOD__, '1.7.0 of the WPForms Conversational Forms addon', '\WPFormsConversationalForms\Process::prepare_date_dropdowns()' );
return ( new Process() )->prepare_date_dropdowns( $form_data, [] );
}
/**
* Change modern and multiple styles on render for `Dropdown` and `Dropdown Items` fields.
*
* @since 1.6.0
*
* @param array|mixed $field Field settings.
* @param array $form_data Form data and settings.
*
* @return array
* @noinspection PhpMissingParamTypeInspection
* @noinspection PhpUnusedParameterInspection
*/
public function select_field_data( $field, $form_data ): array { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
$field = (array) $field;
if ( ! in_array( $field['type'], [ 'select', 'payment-select' ], true ) ) {
return $field;
}
// Modern select style should look like a Classic style.
if (
! empty( $field['style'] ) &&
$field['style'] === WPForms_Field_Select::STYLE_MODERN
) {
$field['style'] = WPForms_Field_Select::STYLE_CLASSIC;
}
// Multiple select has the same logic as checkboxes.
if ( ! empty( $field['multiple'] ) ) {
$field['type'] = 'checkbox';
}
return $field;
}
/**
* Ignore multi-column fields layout.
*
* @since 1.0.0
*
* @param array|mixed $properties Field properties.
* @param array $field Field settings.
* @param array $form_data Form data and settings.
*
* @return array
* @noinspection PhpMissingParamTypeInspection
* @noinspection PhpUnusedParameterInspection
*/
public function ignore_multi_column_layout( $properties, $field, $form_data ): array { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
$properties = (array) $properties;
if ( empty( $properties['container']['class'] ) ) {
return $properties;
}
foreach ( $properties['container']['class'] as $i => $class ) {
if ( in_array(
$class,
[
'wpforms-first',
'wpforms-one-half',
'wpforms-one-third',
'wpforms-two-thirds',
'wpforms-one-fourth',
'wpforms-two-fourths',
'wpforms-one-fifth',
'wpforms-two-fifths',
],
true
) ) {
unset( $properties['container']['class'][ $i ] );
}
}
return $properties;
}
/**
* Add a data-field-type attribute to field elements.
*
* @since 1.0.0
*
* @param array|mixed $properties Field properties.
* @param array $field Field settings.
* @param array $form_data Form data and settings.
*
* @return array
* @noinspection PhpMissingParamTypeInspection
* @noinspection PhpUnusedParameterInspection
*/
public function add_data_field_type_attr( $properties, $field, $form_data ): array { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
$properties = (array) $properties;
$properties['container']['data']['field-type'] = $field['type'];
return $properties;
}
/**
* Various field properties filters.
*
* @since 1.6.0
*
* @param array|mixed $properties Field properties.
* @param array $field Field settings.
* @param array $form_data Form data and settings.
*
* @return array
* @noinspection PhpMissingParamTypeInspection
* @noinspection PhpUnusedParameterInspection
*/
public function field_properties( $properties, $field, $form_data ): array { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
$properties = (array) $properties;
// Numerate fields with empty labels.
$properties['label']['value'] = empty( $properties['label']['value'] ) ? ' ' : $properties['label']['value'];
// Apply the "Hide label" advanced option.
$properties['label']['value'] = ! empty( $field['label_hide'] ) ? ' ' : $properties['label']['value'];
return $properties;
}
/**
* Add HTML to the file upload field.
*
* @since 1.0.0
*
* @param array $field Field settings.
* @param array $form_data Form data and settings.
*
* @noinspection PhpMissingParamTypeInspection
* @noinspection PhpUnusedParameterInspection
* @noinspection PhpClassConstantAccessedViaChildClassInspection
*/
public function add_file_upload_html( $field, $form_data ): void { // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundAfterLastUsed
// Display only for the file uploader field.
if ( empty( $field['type'] ) || $field['type'] !== 'file-upload' ) {
return;
}
// Ignore the modern style.
if ( ! empty( $field['style'] ) && $field['style'] === WPForms_Field_File_Upload::STYLE_MODERN ) {
return;
}
?>
<label
class="wpforms-field-file-upload-label wpforms-conversational-btn"
for="<?php echo esc_attr( $field['properties']['inputs']['primary']['id'] ); ?>">
<?php esc_html_e( 'Choose File', 'wpforms-conversational-forms' ); ?>
</label>
<span class="wpforms-field-file-upload-file-name wpforms-conversational-form-btn-desc">
<?php esc_html_e( 'No file chosen', 'wpforms-conversational-forms' ); ?>
</span>
<?php
}
/**
* Form Loader HTML.
*
* @since 1.0.0
*/
public function form_loader_html(): void {
$brand_disable = ! empty( $this->form_data['settings']['conversational_forms_brand_disable'] ) ? $this->form_data['settings']['conversational_forms_brand_disable'] : '';
?>
<div id="wpforms-conversational-form-loader-container">
<div class="wpforms-conversational-form-loader-content">
<div class="wpforms-conversational-form-loader">
<?php esc_html_e( 'Loading...', 'wpforms-conversational-forms' ); ?>
</div>
<?php if ( ! $brand_disable ) : ?>
<div class="wpforms-conversational-form-loader-powered-by">
<span class="wpforms-conversational-form-loader-powered-by-text">
<?php esc_html_e( 'powered by', 'wpforms-conversational-forms' ); ?>
</span>
<?php
readfile( plugin_dir_path( WPFORMS_CONVERSATIONAL_FORMS_FILE ) . 'assets/images/wpforms-text-logo.svg' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile
?>
</div>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Form header HTML.
*
* @since 1.0.0
*/
public function form_header_html(): void {
if ( $this->is_form_submit_success( $this->form_data['id'] ) ) {
return;
}
?>
<div class="wpforms-conversational-form-header">
<?php $this->form_logo_html(); ?>
<?php $this->form_head_html(); ?>
<?php $this->form_template_notice_html(); ?>
<?php
// phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName, WPForms.Comments.PHPDocHooks.RequiredHookDocumentation
if ( ! apply_filters( 'wpforms_conversational_forms_start_button_disabled', false, $this->form_data ) ) :
$start_button_text = ! empty( $this->form_data['settings']['conversational_forms_start_button_text'] )
? $this->form_data['settings']['conversational_forms_start_button_text']
: __( 'Start', 'wpforms-conversational-forms' );
?>
<div class="wpforms-conversational-form-btn-container">
<button class="wpforms-conversational-btn-start wpforms-conversational-btn"><?php echo esc_html( $start_button_text ); ?></button>
<div class="wpforms-conversational-form-btn-desc">
<?php echo wp_kses( __( 'press <strong>Enter</strong>', 'wpforms-conversational-forms' ), [ 'strong' => [] ] ); ?>
</div>
</div>
<?php endif; ?>
</div>
<?php
}
/**
* Form custom logo HTML.
*
* @since 1.0.0
*/
public function form_logo_html(): void {
if ( empty( $this->form_data['settings']['conversational_forms_custom_logo'] ) ) {
return;
}
$custom_logo_url = wp_get_attachment_image_src( $this->form_data['settings']['conversational_forms_custom_logo'], 'full' );
$custom_logo_url = $custom_logo_url[0] ?? '';
?>
<div class="wpforms-conversational-form-logo">
<img
src="<?php echo esc_url( $custom_logo_url ); ?>"
alt="<?php esc_html_e( 'Form Logo', 'wpforms-conversational-forms' ); ?>">
</div>
<?php
}
/**
* Form head area HTML.
*
* @since 1.0.0
*/
public function form_head_html(): void {
$settings = $this->form_data['settings'];
$title = ! empty( $settings['conversational_forms_title'] ) ? $settings['conversational_forms_title'] : '';
$description = ! empty( $settings['conversational_forms_description'] ) ? $settings['conversational_forms_description'] : '';
if ( empty( $title ) && empty( $description ) ) {
return;
}
$settings['form_title'] = $title;
$settings['form_desc'] = $description;
$frontend_obj = wpforms()->obj( 'frontend' );
if ( $frontend_obj ) {
$frontend_obj->head( array_merge( $this->form_data, [ 'settings' => $settings ] ), null, true, true, [] );
}
}
/**
* Display a notice about the form template.
*
* @since 1.15.0
*/
public function form_template_notice_html(): void {
if ( ! isset( $this->form_data['settings']['template_description'] ) ) {
return;
}
$content = '<div class="wpforms-preview-notice">';
$content .= sprintf(
'<strong>%s</strong> %s',
esc_html__( 'Heads up!', 'wpforms-conversational-forms' ),
esc_html__( 'You\'re viewing a preview of a form template.', 'wpforms-conversational-forms' )
);
if ( wpforms()->is_pro() ) {
/** This filter is documented in wpforms/src/Pro/Tasks/Actions/PurgeTemplateEntryTask.php */
$delay = (int) apply_filters( 'wpforms_pro_tasks_actions_purge_template_entry_task_delay', DAY_IN_SECONDS ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
$message = sprintf( /* translators: %s - time period, e.g., 24 hours. */
__( 'Entries are automatically deleted after %s.', 'wpforms-conversational-forms' ),
human_time_diff( time(), time() + $delay - 1 )
);
$content .= sprintf( '<p>%s</p>', esc_html( $message ) );
}
$content .= '</div>';
echo wp_kses_post( $content );
}
/**
* Field additional HTML.
*
* @since 1.0.0
*/
public function get_field_additional_html(): array {
$html = [];
ob_start();
?>
<div class="wpforms-conversational-form-btn-container wpforms-conversational-form-next-field-btns">
<button class="wpforms-conversational-btn-next wpforms-conversational-btn"><?php esc_html_e( 'Done', 'wpforms-conversational-forms' ); ?></button>
<div class="wpforms-conversational-form-btn-desc">
<?php echo wp_kses( __( 'press <strong>Enter</strong>', 'wpforms-conversational-forms' ), [ 'strong' => [] ] ); ?>
</div>
</div>
<?php
$html['general']['action_buttons'] = ob_get_clean();
ob_start();
?>
<div class="wpforms-conversational-form-field-info">
<?php echo wp_kses( __( '<strong>Enter</strong> or <strong>⬇</strong> to go to the next field', 'wpforms-conversational-forms' ), [ 'strong' => [] ] ); ?>
</div>
<?php
$html['general']['next_field'] = ob_get_clean();
ob_start();
?>
<div class="wpforms-conversational-form-field-info">
<?php echo wp_kses( __( '<strong>Shift+Enter</strong> to make a line break', 'wpforms-conversational-forms' ), [ 'strong' => [] ] ); ?>
</div>
<?php
$html['textarea'] = ob_get_clean();
ob_start();
?>
<div class="wpforms-conversational-form-field-info">
<?php echo wp_kses( __( '<strong>Tab</strong> or <strong>⬇</strong> to switch the line', 'wpforms-conversational-forms' ), [ 'strong' => [] ] ); ?>
</div>
<?php
$html['likert_scale'] = ob_get_clean();
ob_start();
?>
<div class="wpforms-conversational-form-field-info">
<?php echo wp_kses( __( '<strong>Shift+Enter</strong> to open a file', 'wpforms-conversational-forms' ), [ 'strong' => [] ] ); ?>
</div>
<?php
$html['file_upload'] = ob_get_clean();
ob_start();
?>
<div class="wpforms-conversational-form-field-info">
<?php echo wp_kses( __( '<strong>Shift+Enter</strong> to go to the next field', 'wpforms-conversational-forms' ), [ 'strong' => [] ] ); ?>
</div>
<?php
$html['checkbox'] = ob_get_clean();
return $html;
}
/**
* Form footer HTML.
*
* @since 1.0.0
*/
public function form_footer_html(): void {
$this->form_footer_progress_block_html();
$this->form_footer_right_block_html();
}
/**
* Form footer progress block HTML.
*
* @since 1.0.0
*/
public function form_footer_progress_block_html(): void {
$progress_style = ! empty( $this->form_data['settings']['conversational_forms_progress_bar'] ) ? $this->form_data['settings']['conversational_forms_progress_bar'] : '';
?>
<div class="wpforms-conversational-form-footer-progress">
<div class="wpforms-conversational-form-footer-progress-status">
<?php
if ( $progress_style === 'proportion' ) {
$this->form_footer_progress_status_proportion_html();
} else {
$this->form_footer_progress_status_percentage_html();
}
?>
</div>
<div class="wpforms-conversational-form-footer-progress-bar">
<div class="wpforms-conversational-form-footer-progress-completed"></div>
</div>
</div>
<?php
}
/**
* Form footer progress status (proportion) HTML.
*
* @since 1.0.0
*/
public function form_footer_progress_status_proportion_html(): void {
?>
<div class="wpforms-conversational-form-footer-progress-status-proportion">
<?php
printf(
/* translators: %1$s - Number of fields completed; %2$s - Number of fields in total. */
esc_html__(
'%1$s of %2$s completed',
'wpforms-conversational-forms'
),
'<span class="completed"></span>',
'<span class="completed-of"></span>'
);
?>
</div>
<div class="wpforms-conversational-form-footer-progress-status-proportion-completed" style="display: none">
<?php esc_html_e( 'Form completed', 'wpforms-conversational-forms' ); ?>
</div>
<?php
}
/**
* Form footer progress status (percentage) HTML.
*
* @since 1.0.0
*/
public function form_footer_progress_status_percentage_html(): void {
?>
<div class="wpforms-conversational-form-footer-progress-status-percentage">
<?php
printf(
/* translators: %s - Percentage of fields completed. */
esc_html__(
'%s%% completed',
'wpforms-conversational-forms'
),
'<span class="completed">100</span>'
);
?>
</div>
<?php
}
/**
* Open the wrapper for confirmation elements.
*
* @since 1.7.0
*/
public function open_confirmation_wrapper(): void {
echo '<div class="wpforms-confirmation-container-wrapper">';
}
/**
* Close the wrapper for confirmation elements.
*
* @since 1.7.0
*/
public function close_confirmation_wrapper(): void {
echo '</div>';
}
/**
* Form footer right block HTML.
*
* @since 1.0.0
*/
public function form_footer_right_block_html(): void {
$brand_disable = ! empty( $this->form_data['settings']['conversational_forms_brand_disable'] ) ? $this->form_data['settings']['conversational_forms_brand_disable'] : '';
?>
<div class="wpforms-conversational-form-footer-right-container">
<?php if ( ! $brand_disable ) : ?>
<div class="wpforms-conversational-form-footer-powered-by">
<span>
<?php esc_html_e( 'powered by', 'wpforms-conversational-forms' ); ?>
</span>
<?php
readfile( plugin_dir_path( WPFORMS_CONVERSATIONAL_FORMS_FILE ) . 'assets/images/wpforms-text-logo.svg' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile
?>
</div>
<?php endif; ?>
<div class="wpforms-conversational-form-footer-switch-step">
<div class="wpforms-conversational-form-footer-switch-step-up">
<i class="fa fa-angle-up" aria-hidden="true"></i>
</div>
<div class="wpforms-conversational-form-footer-switch-step-down">
<i class="fa fa-angle-down" aria-hidden="true"></i>
</div>
</div>
</div>
<?php
}
/**
* Check if the form was submitted successfully.
*
* @since 1.0.0
*
* @param int $id Form id.
*/
public function is_form_submit_success( $id ): bool {
// TODO: Code needs revision. Copy-paste from class-frontend.php.
$form_obj = wpforms()->obj( 'form' );
$form = $form_obj ? $form_obj->get( (int) $id ) : null;
if ( empty( $form ) ) {
return false;
}
$form_id = absint( $form->ID );
$form_data = apply_filters( 'wpforms_frontend_form_data', wpforms_decode( $form->post_content ) ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName, WPForms.Comments.PHPDocHooks.RequiredHookDocumentation
$errors = empty( wpforms()->obj( 'process' )->errors[ $form_id ] ) ? [] : wpforms()->obj( 'process' )->errors[ $form_id ];
// Check for return hash.
if (
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
! empty( $_GET['wpforms_return'] ) &&
wpforms()->obj( 'process' )->valid_hash &&
absint( wpforms()->obj( 'process' )->form_data['id'] ) === $form_id
) {
return true;
}
// Check for error-free completed form.
// phpcs:disable WordPress.Security.NonceVerification.Missing
if (
empty( $errors ) &&
! empty( $form_data ) &&
! empty( $_POST['wpforms']['id'] ) &&
absint( $_POST['wpforms']['id'] ) === $form_id
) {
return true;
}
// phpcs:enable WordPress.Security.NonceVerification.Missing
return false;
}
/**
* Meta robots.
*
* @since 1.3.2
* @deprecated 1.6.0
*/
public function meta_robots(): void { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
_deprecated_function( __METHOD__, '1.6.0 of the WPForms Conversational Forms addon', __CLASS__ . '::meta_tags()' );
$seo_plugin_enabled = false;
if ( class_exists( 'WPSEO_Options' ) ) {
add_filter( 'wpseo_robots', [ $this, 'get_meta_robots' ], PHP_INT_MAX );
$seo_plugin_enabled = true;
}
if ( class_exists( 'All_in_One_SEO_Pack' ) ) {
add_filter( 'aioseop_robots_meta', [ $this, 'get_meta_robots' ], PHP_INT_MAX );
$seo_plugin_enabled = true;
}
if ( ! $seo_plugin_enabled ) {
add_action( 'wp_head', [ $this, 'output_meta_robots_tag' ] );
}
}
/**
* Get meta robots value.
*
* @since 1.3.2
*
* @return string Meta robots value.
*/
public function get_meta_robots(): string {
/**
* Filter the meta-robots value for the Conversational Form page.
*
* @since 1.3.2
*
* @param string $value Meta robots value.
*/
return (string) apply_filters( 'wpforms_conversational_forms_meta_robots_value', 'noindex,nofollow' ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
}
/**
* Output meta robots tag.
*
* @since 1.3.2
*/
public function output_meta_robots_tag(): void {
printf(
'<meta name="robots" content="%s"/>%s',
esc_attr( $this->get_meta_robots() ),
"\n"
);
}
/**
* Rank Math robots filter.
*
* @since 1.6.0
*
* @return array Robots data.
*/
public function get_rank_math_meta_robots(): array {
return explode( ',', $this->get_meta_robots() );
}
/**
* Meta tags.
*
* @since 1.6.0
*/
public function meta_tags(): void { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
$seo_plugin_enabled = false;
if ( class_exists( 'WPSEO_Options' ) ) {
add_filter( 'wpseo_title', [ $this, 'get_seo_title' ], PHP_INT_MAX );
add_filter( 'wpseo_opengraph_desc', [ $this, 'get_description' ], PHP_INT_MAX );
add_filter( 'wpseo_opengraph_url', [ $this, 'get_seo_url' ], PHP_INT_MAX );
add_filter( 'wpseo_canonical', [ $this, 'get_seo_url' ], PHP_INT_MAX );
add_filter( 'wpseo_twitter_description', [ $this, 'get_description' ], PHP_INT_MAX );
add_filter( 'wpseo_robots', [ $this, 'get_meta_robots' ], PHP_INT_MAX );
$seo_plugin_enabled = true;
}
if ( class_exists( 'All_in_One_SEO_Pack' ) ) {
add_filter( 'aioseop_title', [ $this, 'get_seo_title' ], PHP_INT_MAX );
add_filter( 'aioseop_description_override', [ $this, 'get_description' ], PHP_INT_MAX );
add_filter( 'aioseop_robots_meta', [ $this, 'get_meta_robots' ], PHP_INT_MAX );
$seo_plugin_enabled = true;
}
if ( class_exists( 'AIOSEO\Plugin\AIOSEO' ) && function_exists( 'aioseo' ) ) {
// Disable AIOSEO in Conversational Form page.
add_filter( 'aioseo_disable', '__return_true' );
add_action( 'wp_head', [ $this, 'output_aioseo_alternative_meta_tags' ], 3 );
$seo_plugin_enabled = true;
}
if ( defined( 'SEOPRESS_VERSION' ) ) {
add_filter( 'seopress_titles_desc', [ $this, 'get_description' ], PHP_INT_MAX );
add_filter( 'seopress_social_twitter_card_title', [ $this, 'get_twitter_meta_title' ], PHP_INT_MAX );
add_filter( 'seopress_social_og_title', [ $this, 'get_fb_meta_title' ], PHP_INT_MAX );
$seo_plugin_enabled = true;
}
if ( class_exists( 'RankMath' ) ) {
add_filter( 'rank_math/frontend/title', [ $this, 'get_seo_title' ], PHP_INT_MAX );
add_filter( 'rank_math/frontend/description', [ $this, 'get_rank_math_description' ], PHP_INT_MAX );
add_filter( 'rank_math/frontend/robots', [ $this, 'get_rank_math_meta_robots' ], PHP_INT_MAX );
add_filter(
'rank_math/opengraph/facebook/og_description',
[ $this, 'get_rank_math_description' ],
PHP_INT_MAX
);
$seo_plugin_enabled = true;
}
// Handle 'SEO Plugin by Squirrly'.
if ( defined( 'SQ_VERSION' ) ) {
add_filter( 'sq_description', [ $this, 'get_sq_description' ], 90 );
/*
* Priority is set to `90` because 'SEO Plugin by Squirrly' plugin has a filter
* that converts the `array` args to string at priority `99`.
* See `packOpenGraph()` and `packTwitterCard()`.
*/
add_filter( 'sq_open_graph', [ $this, 'filter_social_tags' ], 90 );
add_filter( 'sq_twitter_card', [ $this, 'filter_social_tags' ], 90 );
$seo_plugin_enabled = true;
}
if ( ! $seo_plugin_enabled ) {
add_action( 'wp_head', [ $this, 'output_meta_robots_tag' ] );
}
}
/**
* Get title value.
*
* @since 1.6.0
*
* @return string Title value.
*/
public function get_title(): string {
$title = ! empty( $this->form_data['settings']['form_title'] ) ? $this->form_data['settings']['form_title'] : '';
if ( ! empty( $this->form_data['settings']['conversational_forms_title'] ) ) {
$title = $this->form_data['settings']['conversational_forms_title'];
}
return wp_strip_all_tags( $title, true );
}
/**
* Get SEO plugin title value.
*
* @since 1.6.0
*
* @param string|mixed $title Original title.
*
* @return string Title value.
*/
public function get_seo_title( $title = '' ): string {
$title = (string) $title;
if ( ! empty( $this->form_data['settings']['form_title'] ) ) {
$title = str_replace( $this->form_data['settings']['form_title'], $this->get_title(), $title );
}
return $title;
}
/**
* Get description value.
*
* @since 1.6.0
*
* @return string Description value.
*/
public function get_description(): string {
return ! empty( $this->form_data['settings']['conversational_forms_description'] )
? wp_strip_all_tags( $this->form_data['settings']['conversational_forms_description'], true )
: '';
}
/**
* Get description value for the Rank Math plugin.
*
* @since 1.6.0
*
* @return string Description value.
*/
public function get_rank_math_description() {
$description = $this->get_description();
return ! empty( $description ) ?
$description :
false; // `false` means that Rank Math will not generate a description automatically.
}
/**
* Force Yoast SEO og/twitter descriptions.
*
* @since 1.0.0
* @deprecated 1.6.0
*
* @return string
*/
public function yoast_seo_description(): string {
_deprecated_function( __METHOD__, '1.6.0 of the WPForms Conversational Forms addon', __CLASS__ . '::get_description()' );
return ! empty( $this->form_data['settings']['conversational_forms_description'] ) ? wp_strip_all_tags( $this->form_data['settings']['conversational_forms_description'], true ) : '';
}
/**
* Get SEO url value for Yoast SEO plugin.
*
* @since 1.7.0
*
* @return string
*/
public function get_seo_url(): string {
return (string) get_the_permalink();
}
/**
* Add extra styles for the Rich Text field.
*
* @since 1.7.0
*
* @param array|mixed $mce_init An array with TinyMCE config.
* @param string $editor_id Unique editor identifier.
*
* @return array
*/
public function add_styles_for_rich_text_field( $mce_init, $editor_id ): array {
$mce_init = (array) $mce_init;
if ( strpos( $editor_id, 'wpforms-' ) !== 0 ) {
return $mce_init;
}
// If we have a color scheme, load the color scheme stylesheet. Otherwise, set custom styles.
if ( $this->color_scheme !== '' ) {
$min = wpforms_get_min_suffix();
$styles = wpforms_conversational_forms()->url . "assets/css/color-schemes/{$this->color_scheme}{$min}.css";
if ( ! isset( $mce_init['content_css'] ) ) {
$mce_init['content_css'] = $styles;
} else {
$mce_init['content_css'] .= ',' . $styles;
}
} else {
$styles = '.mce-content-body { background-color: transparent; color: ' . $this->color . ' }';
if ( ! isset( $mce_init['content_style'] ) ) {
$mce_init['content_style'] = $styles . ' ';
} else {
$mce_init['content_style'] .= ' ' . $styles . ' ';
}
}
return $mce_init;
}
/**
* Change a field type to checkbox for multiple dropdown.
*
* @since 1.7.0
*
* @param array|mixed $form_data Form data and settings.
*
* @return array
*/
public function change_multiple_dropdown_type( $form_data ): array {
$form_data = (array) $form_data;
foreach ( $form_data['fields'] as $id => $field ) {
if ( isset( $field['multiple'], $field['type'] ) && $field['type'] === 'select' ) {
$form_data['fields'][ $id ]['type'] = 'checkbox';
}
}
return $form_data;
}
/**
* Output meta-tags when using AIOSEO plugin.
*
* @since 1.7.1
*
* @noinspection PhpUndefinedFunctionInspection
*/
public function output_aioseo_alternative_meta_tags(): void {
?>
<meta name="description" content="<?php echo esc_attr( $this->get_description() ); ?>"/>
<meta name="robots" content="max-image-preview:large"/>
<?php
if ( property_exists( aioseo(), 'helpers' ) && method_exists( aioseo()->helpers, 'canonicalUrl' ) ) {
?>
<link rel="canonical" href="<?php echo esc_url( aioseo()->helpers->canonicalUrl() ); ?>"/>
<?php
}
$this->output_aioseo_facebook_meta();
$this->output_aioseo_twitter_meta();
}
/**
* Output Facebook meta-tags when AIOSEO plugin is installed.
*
* @since 1.7.1
*/
private function output_aioseo_facebook_meta(): void {
?>
<meta property="og:title" content="<?php echo esc_attr( $this->get_title() ); ?>"/>
<meta property="og:description" content="<?php echo esc_attr( $this->get_description() ); ?>"/>
<?php
$this->maybe_output_aioseo_social_meta(
'getFacebookMeta',
[
'og:locale',
'og:site_name',
'og:type',
'og:url',
],
'property'
);
}
/**
* Output social meta-tags using AIOSEO.
*
* @since 1.7.1
*
* @param string $get_social_meta_function_name Name of the function in AIOSEO to fetch social meta-tags.
* @param array $meta_tags_to_output Meta-tags to output.
* @param string $name_or_property Whether to 'name' or 'property' as the meta-tag attribute.
* Accepts 'name' or 'property'.
*
* @noinspection PhpUndefinedFunctionInspection
* @noinspection HtmlUnknownAttribute
*/
private function maybe_output_aioseo_social_meta( $get_social_meta_function_name, $meta_tags_to_output, $name_or_property ): void {
if (
! property_exists( aioseo(), 'social' ) ||
! property_exists( aioseo()->social, 'output' ) ||
! method_exists( aioseo()->social->output, $get_social_meta_function_name )
) {
return;
}
$meta_tags = call_user_func( [ aioseo()->social->output, $get_social_meta_function_name ] );
if ( empty( $meta_tags ) || empty( $meta_tags_to_output ) ) {
return;
}
$meta_tag_attribute = 'property';
if ( $name_or_property === 'name' ) {
$meta_tag_attribute = 'name';
}
foreach ( $meta_tags_to_output as $meta_to_output ) {
if ( empty( $meta_tags[ $meta_to_output ] ) ) {
continue;
}
printf(
'<meta %1$s="%2$s" content="%3$s" />' . "\n",
esc_attr( $meta_tag_attribute ),
esc_attr( $meta_to_output ),
esc_attr( $meta_tags[ $meta_to_output ] )
);
}
}
/**
* Output Twitter meta tags when AIOSEO plugin is installed.
*
* @since 1.7.1
*/
private function output_aioseo_twitter_meta(): void {
?>
<meta name="twitter:title" content="<?php echo esc_attr( $this->get_title() ); ?>"/>
<meta name="twitter:description" content="<?php echo esc_attr( $this->get_description() ); ?>"/>
<?php
$this->maybe_output_aioseo_social_meta(
'getTwitterMeta',
[
'twitter:card',
'twitter:site',
],
'name'
);
}
/**
* Returns the Twitter meta-title.
*
* @since 1.7.1
*
* @return string
*/
public function get_twitter_meta_title(): string {
return '<meta name="twitter:title" content="' . esc_attr( $this->get_title() ) . '" />';
}
/**
* Returns the Facebook meta-title.
*
* @since 1.7.1
*
* @return string
*/
public function get_fb_meta_title(): string {
return '<meta property="og:title" content="' . esc_attr( $this->get_title() ) . '" />';
}
/**
* This function returns `false` if nothing was passed to retain Squirrly's behavior not to
* output anything if "No SEO Configuration" was selected and returns CF's description
* if anything truthy was passed.
*
* @since 1.7.1
*
* @param mixed $desc Description passed to sq_description filter from Squirrly plugin.
*
* @return false|string
*/
public function get_sq_description( $desc ) {
if ( empty( $desc ) ) {
return false;
}
return $this->get_description();
}
/**
* Filter social tags.
*
* @since 1.7.1
*
* @param array $meta_tags Social meta tags.
*
* @return mixed
*/
public function filter_social_tags( $meta_tags ) {
if ( ! is_array( $meta_tags ) ) {
return $meta_tags;
}
$social_tags = [
[
'tags_to_replace' => [
'twitter:description',
'og:description',
],
'new_value' => $this->get_description(),
],
[
'tags_to_replace' => [
'twitter:title',
'og:title',
],
'new_value' => $this->get_title(),
],
];
foreach ( $social_tags as $social_tag ) {
$meta_tags = $this->replace_array_keys_with_new_value(
$meta_tags,
$social_tag['tags_to_replace'],
$social_tag['new_value']
);
}
return array_filter( $meta_tags );
}
/**
* Replace the value of keys in an array.
*
* @since 1.7.1
*
* @param array $arr Array with keys to be replaced with a new value.
* @param array $keys_to_replace Keys to be replaced with new value.
* @param mixed $new_value New value.
*
* @return array
*/
private function replace_array_keys_with_new_value( $arr, $keys_to_replace, $new_value ): array {
if ( ! is_array( $arr ) ) {
return $arr;
}
foreach ( $keys_to_replace as $key ) {
if ( array_key_exists( $key, $arr ) ) {
$arr[ $key ] = $new_value;
}
}
return $arr;
}
/**
* Change the `{page_title}` value to Conversational Forms title.
*
* @since 1.7.1
*
* @param string|mixed $value The page title.
* @param array $form_data Form data.
*
* @return string
*/
public function filter_page_title_smart_tag_value( $value, $form_data ): string {
$value = (string) $value;
if ( empty( $form_data['settings']['conversational_forms_title'] ) ) {
return $value;
}
return esc_html( wp_strip_all_tags( $form_data['settings']['conversational_forms_title'], true ) );
}
}