Server : LiteSpeed
System : Linux server104.web-hosting.com 4.18.0-513.24.1.lve.1.el8.x86_64 #1 SMP Thu May 9 15:10:09 UTC 2024 x86_64
User : saleoqej ( 6848)
PHP Version : 8.0.30
Disable Function : NONE
Directory :  /home/saleoqej/public_html/wp-content/plugins/thrive-leads/inc/
Upload File :
Current Directory [ Writeable ] Root Directory [ Writeable ]


Current File : /home/saleoqej/public_html/wp-content/plugins/thrive-leads/inc/helpers.php
<?php

/**
 * appends the WordPress tables prefix and the default tve_leads prefix to the table name
 *
 * @param string $table
 *
 * @return string the modified table name
 */
function tve_leads_table_name( $table ) {
	global $wpdb;

	return $wpdb->prefix . TVE_LEADS_DB_PREFIX . $table;
}

/**
 * return a list with all available form types
 * the keys in the array are internally used codes, and the values are the translations of the form type names
 *
 * @param bool $include_extra whether or not to include the shortcode type and 2-step type in the returned result
 *
 * @return array
 */
function tve_leads_get_default_form_types( $include_extra = false ) {
	$main = array(
		'in_content'    => array(
			'post_title'    => __( 'In content', 'thrive-leads' ),
			'tve_form_type' => 'in_content',
			'edit_selector' => '.thrv-leads-in-content', // selector for the element settings in editing mode
			'wp_hook'       => 'the_content',
			'priority'      => 20,
			'video_link'    => '9YS9EGUel98',
		),
		'lightbox'      => array(
			'post_title'    => __( 'Lightbox', 'thrive-leads' ),
			'tve_form_type' => 'lightbox',
			'edit_selector' => '.tve_p_lb_control', // selector for the element settings in editing mode
			'wp_hook'       => 'wp_footer',
			'video_link'    => '2SXwMnfIFXc',
		),
		'post_footer'   => array(
			'post_title'    => __( 'Post footer', 'thrive-leads' ),
			'tve_form_type' => 'post_footer',
			'edit_selector' => '.thrv-leads-form-box', // selector for the element settings in editing mode
			'wp_hook'       => 'the_content',
			'video_link'    => 'J9Tt42ts43s',
		),
		'ribbon'        => array(
			'post_title'    => __( 'Ribbon', 'thrive-leads' ),
			'tve_form_type' => 'ribbon',
			'edit_selector' => '.thrv-ribbon', // selector for the element settings in editing mode
			'wp_hook'       => 'wp_footer',
			'video_link'    => 'x8QGGaqxPDY',
		),
		'screen_filler' => array(
			'post_title'    => __( 'Screen filler lightbox', 'thrive-leads' ),
			'tve_form_type' => 'screen_filler',
			'edit_selector' => '.thrv-leads-screen-filler', // selector for the element settings in editing mode
			'wp_hook'       => 'wp_footer',
			'video_link'    => 'IdvjD6T4Xa4',
		),
		'greedy_ribbon' => array(
			'post_title'    => __( 'Scroll mat', 'thrive-leads' ),
			'tve_form_type' => 'greedy_ribbon',
			'edit_selector' => '.thrv-greedy-ribbon', // selector for the element settings in editing mode
			'wp_hook'       => 'wp_footer',
			'video_link'    => '4UHtgN8LZzI',
		),
		'slide_in'      => array(
			'post_title'    => __( 'Slide in', 'thrive-leads' ),
			'tve_form_type' => 'slide_in',
			'edit_selector' => '.thrv-leads-slide-in', // selector for the element settings in editing mode
			'wp_hook'       => 'wp_footer',
			'video_link'    => 'dhL4NEt84kk',
		),
		'widget'        => array(
			'post_title'    => __( 'Widget', 'thrive-leads' ),
			'edit_selector' => '.thrv-leads-widget', // selector for the element settings in editing mode
			'tve_form_type' => 'widget',
			'video_link'    => 'uSrD8lVbF5Q',
		),
		/**
		 * no wp_hook for php_inserts, these are to be added by the (advanced) user - as pieces of PHP code that can be directly inserted into
		 * the theme / sidebar etc
		 */
		'php_insert'    => array(
			'post_title'    => __( 'PHP Insert', 'thrive-leads' ),
			'tve_form_type' => 'php_insert',
			'edit_selector' => '.thrv-leads-form-box',
		),
	);

	if ( $include_extra ) {
		$main['shortcode'] = array(
			'post_title'    => __( 'Shortcode', 'thrive-leads' ),
			'tve_form_type' => 'shortcode',
			'edit_selector' => '.thrv-leads-form-box', // selector for the element settings in editing mode
			'wp_hook'       => '',
		);

		$main['two_step_lightbox'] = array(
			'post_title'    => __( 'ThriveBox', 'thrive-leads' ),
			'tve_form_type' => 'two_step_lightbox',
			'edit_selector' => '.tve_p_lb_control', // selector for the element settings in editing mode
			'wp_hook'       => '',
		);
	}

	return $main;
}

/**
 * prepare the default form types for the backbone application
 *
 * @return array()
 */
function tve_leads_prepare_default_form_types() {
	$types = tve_leads_get_default_form_types();

	return array_values( $types );
}

/**
 * return a formatted conversion rate based on $impressions and $conversions
 *
 * @param int $impressions
 * @param int $conversions
 * @param string $suffix
 * @param string $decimals
 * @param string $if_zero what to return if either of the values is 0
 *
 * @return string $rate the calculated conversion rate
 */
function tve_leads_conversion_rate( $impressions, $conversions, $suffix = '%', $decimals = '2', $if_zero = 'N/A' ) {
	$impressions = (int) $impressions;
	$conversions = (int) $conversions;
	if ( ! $impressions || ! $conversions ) {
		return $if_zero;
	}

	return round( 100 * ( $conversions / $impressions ), $decimals ) . $suffix;
}

/**
 * get the configuration array for a specific editor template for a form variation
 *
 * @param string $key
 *
 * @return array
 */
function tve_leads_get_editor_template_config( $key ) {
	if ( strpos( $key, '|' ) === false ) {
		return array();
	}
	list( $type, $key ) = explode( '|', $key );

	if ( $key === 'tcb2_blank' ) {
		return tve_leads_get_v2_blank_config( $type );
	}

	$config = require dirname( dirname( __FILE__ ) ) . '/editor-templates/_config.php';

	$type = Thrive_Leads_Template_Manager::tpl_type_map( $type );

	$cloud_config = tve_leads_get_downloaded_templates( $type );

	if ( ! empty( $cloud_config ) ) {
		$config[ $type ] = array_merge_recursive( $config[ $type ], $cloud_config );
	}

	if ( isset( $config[ $type ][ $key ] ) && isset( $config[ $type ][ $key ]['fonts'] ) && tve_dash_is_google_fonts_blocked() ) {
		$config[ $type ][ $key ]['fonts'] = array();
	}

	return isset( $config[ $type ][ $key ] ) ? $config[ $type ][ $key ] : array();
}

/**
 * get configuration for a specific variation (form) type
 *
 * @param string $variation_type ribbon, lightbox etc
 *
 * @return array
 */
function tve_leads_get_editor_template_type_config( $variation_type ) {
	$config         = require dirname( dirname( __FILE__ ) ) . '/editor-templates/_config.php';
	$variation_type = Thrive_Leads_Template_Manager::tpl_type_map( $variation_type );

	$cloud_config = tve_leads_get_downloaded_templates( $variation_type );

	if ( ! empty( $cloud_config ) ) {
		$config[ $variation_type ] = array_merge_recursive( $config[ $variation_type ], $cloud_config );
	}

	return isset( $config[ $variation_type ] ) ? $config[ $variation_type ] : array();
}

/**
 *
 * get the TCB editor EDIT URL for a form variation
 *
 * @param int $post_id
 * @param int $variation_key
 *
 * @return string the url to open the editor for this variation
 */
function tve_leads_get_editor_url( $post_id, $variation_key, $escape = true ) {
	$editor_link = set_url_scheme( get_edit_post_link( $post_id, '' ) );
	$editor_link = add_query_arg( array(
		'tve'    => 'true',
		'_key'   => $variation_key,
		'r'      => uniqid(),
		'action' => 'architect',
	), $editor_link );

	if ( $escape ) {
		$editor_link = esc_url( $editor_link );
	}

	/**
	 * we need to make sure that if the admin is https, then the editor link is also https, otherwise any ajax requests through wp ajax api will not work
	 */
	$admin_ssl = strpos( admin_url(), 'https' ) === 0;

	return $admin_ssl ? str_replace( 'http://', 'https://', $editor_link ) : $editor_link;
}

/**
 * get the TCB editor PREVIEW URL for a form variation
 *
 * @param int $post_id
 * @param int $variation_key
 * @param boolean escape
 *
 * @return string the url to open the editor for this variation
 */
function tve_leads_get_preview_url( $post_id, $variation_key, $escape = true ) {
	//$cache = isset( $GLOBALS['TVE_LEADS_CACHE_PERMALINKS'] ) ? $GLOBALS['TVE_LEADS_CACHE_PERMALINKS'] : array();
	$cache = array(); //reset cache cos it has only editor links
	if ( ! isset( $cache[ $post_id ] ) ) {
		$cache[ $post_id ]                     = set_url_scheme( get_permalink( $post_id ) );
		$GLOBALS['TVE_LEADS_CACHE_PERMALINKS'] = $cache;
	}
	/*
	 * We need the post to complete the full arguments
	 */
	$post        = get_post( $post_id );
	$editor_link = $cache[ $post_id ];
	$editor_link = apply_filters( 'preview_post_link', add_query_arg( array(
		'_key' => $variation_key,
		'r'    => uniqid()
	), $editor_link ), $post );

	if ( $escape ) {
		$editor_link = esc_url( $editor_link );
	}

	return $editor_link;
}

/**
 * generate a random number between 0 and $total-1
 *
 * @param int $total
 * @param int $multiplier for smaller values, it's better to extend the interval by a number of times,
 *                        example: to choose between 0 and 1 -> we think it's better to have a random number between 0 and 10000 and split that into halves
 *
 * @return int
 */
function tve_leads_get_random_index( $total, $multiplier = 1000 ) {
	$_rand = function_exists( 'mt_rand' ) ? mt_rand( 0, $total * $multiplier - 1 ) : rand( 0, $total * $multiplier - 1 );

	return intval( floor( $_rand / $multiplier ) );
}

/**
 * get a list of all available triggers (optional) grouped by a specific form type
 *
 * @param string|null $form_type , if present, it will only return triggers that apply to that specific form type
 *
 * @param bool $get_as_array whether or not to get the results as array instead of Trigger objects
 *
 * @return array the list of triggers
 */
function tve_leads_get_available_triggers( $form_type = null, $get_as_array = false ) {
	$return = array();
	foreach ( TVE_Leads_Trigger_Abstract::$AVAILABLE as $trigger ) {
		$item = TVE_Leads_Trigger_Abstract::factory( $trigger );
		if ( ! $item ) {
			continue;
		}
		if ( $form_type && ! $item->appliesTo( $form_type ) ) {
			continue;
		}
		$return[ $trigger ] = $get_as_array ? $item->to_array() : $item;
	}

	return $return;
}

/**
 * get a list of all available animations (optional) grouped by a specific form type
 *
 * @param bool $get_as_array whether or not to get the results as array instead of Animation objects
 *
 * @return array the list of animations
 */
function tve_leads_get_available_animations( $get_as_array = false ) {
	$return = array();
	foreach ( TVE_Leads_Animation_Abstract::$available as $animation ) {
		$item = TVE_Leads_Animation_Abstract::factory( $animation );
		if ( ! $item ) {
			continue;
		}

		$return[ $animation ] = $get_as_array ? $item->get_title() : $item;
	}

	return $return;
}

/**
 * get a list of all available positions
 *
 * @param String $form_type
 *
 * @return array the list of positions
 */
function tve_leads_get_available_positions( $form_type ) {
	switch ( $form_type ) {
		case 'slide_in':
			return array(
				'label'    => __( 'Position', 'thrive-leads' ),
				'position' => array(
					'bot_left'  => __( 'Bottom Left', 'thrive-leads' ),
					'bot_right' => __( 'Bottom Right', 'thrive-leads' ),
					'top_left'  => __( 'Top Left', 'thrive-leads' ),
					'top_right' => __( 'Top Right', 'thrive-leads' ),
				),
			);
		case 'ribbon':
			return array(
				'label'    => __( 'Position', 'thrive-leads' ),
				'position' => array(
					'above'  => __( 'Top over content', 'thrive-leads' ),
					'top'    => __( 'Top', 'thrive-leads' ),
					'bottom' => __( 'Bottom', 'thrive-leads' ),
				),
			);
		case 'in_content':
			return array(
				'label'    => __( 'Show after how many paragraphs?', 'thrive-leads' ),
				'position' => array(
					0  => 0,
					1  => 1,
					2  => 2,
					3  => 3,
					4  => 4,
					5  => 5,
					6  => 6,
					7  => 7,
					8  => 8,
					9  => 9,
					10 => 10
				),
			);
		default:
			return array();
	}
}

/**
 * get a unique cookie key based on a form that's being displayed now
 *
 * @param        $main_group
 * @param        $form_type
 * @param        $variation
 * @param string $type
 *
 * @return string
 */
function tve_leads_get_form_cookie_key( $main_group, $form_type, $variation, $type = 'impression' ) {

	$group_id      = is_object( $main_group ) ? $main_group->ID : $main_group;
	$form_type_id  = is_object( $form_type ) ? $form_type->ID : $form_type;
	$variation_key = is_array( $variation ) ? $variation['key'] : $variation;

	$key = 'tl' . ( $type ? '_' . $type : '' );
	if ( $group_id ) {
		$key .= '_' . $group_id;
	}
	if ( $form_type_id ) {
		$key .= '_' . $form_type_id;
	}
	$key .= '_' . $variation_key;

	return $key;
}

/**
 * flush and send the output buffer, for faster responses during the form submit
 * headers and some data are send and after this the main processing of data can be done without users knowing the difference
 *
 * thanks to http://stackoverflow.com/questions/10579116/how-to-flush-data-to-browser-but-continue-executing
 */
function tve_leads_send_output() {
	ob_start();

	/* generate some dummy output */
	echo '1' . str_pad( '', 4096 ) . "\n";

	/* Ignore connection-closing by the client */
	ignore_user_abort( true );

	/* send the contents */
	$content = ob_get_contents();        // Get the content of the output buffer
	ob_end_clean();                      // Close current output buffer
	$len = strlen( $content );             // Get the length
	header( 'Connection: close' );         // Tell the client to close connection
	header( "Content-Length: $len" );      // Close connection after $size characters
	echo $content;                       // Output content
	flush();                             // Force php-output-cache to flush to browser.

	// Kill all other output buffering
	while ( ob_get_level() > 0 ) {
		ob_end_clean();
	}
}

/**
 * Calculate the chance of a variation to beat the original during a test
 *
 * @param $variation_conversion_rate
 * @param $variation_unique_impressions
 * @param $control_conversion_rate
 * @param $control_unique_impressions
 *
 * @return string $confidence_level
 */
function tve_leads_test_item_beat_original(
	$variation_conversion_rate, $variation_unique_impressions, $control_conversion_rate, $control_unique_impressions, $suffix = '%'
) {
	if ( $variation_unique_impressions == 0 || $control_unique_impressions == 0 || ! is_numeric( $variation_conversion_rate ) || ! is_numeric( $control_conversion_rate ) ) {
		return 'N/A';
	}

	$variation_conversion_rate = $variation_conversion_rate / 100;
	$control_conversion_rate   = $control_conversion_rate / 100;

	//standard deviation = sqrt((conversionRate*(1-conversionRate)/uniqueImpressions)
	$variation_standard_deviation = sqrt( ( $variation_conversion_rate * ( 1 - $variation_conversion_rate ) / $variation_unique_impressions ) );
	$control_standard_deviation   = sqrt( ( $control_conversion_rate * ( 1 - $control_conversion_rate ) / $control_unique_impressions ) );

	if ( ( $variation_standard_deviation == 0 && $control_standard_deviation == 0 ) || ( is_nan( $variation_standard_deviation ) || is_nan( $control_standard_deviation ) ) ) {
		return 'N/A';
	}
	//z-score = (control_conversion_rate - variation_conversion_rate) / sqrt((controlStandardDeviation^2)+(variationStandardDeviation^2))
	$z_score = ( $control_conversion_rate - $variation_conversion_rate ) / sqrt( pow( $control_standard_deviation, 2 ) + pow( $variation_standard_deviation, 2 ) );

	if ( is_nan( $z_score ) ) {
		return 'N/A';
	}

	//Confidence_level (which is synonymous with “chance to beat original”)  = normdist(z-score)
	$confidence_level = tve_leads_norm_dist( $z_score );

	return number_format( round( ( 1 - $confidence_level ) * 100, 2 ), 2 ) . $suffix;
}

/**
 * Function that will generate a cumulative normal distribution and return the confidence level as a number between 0 and 1
 *
 * @param $x
 *
 * @return float
 */
function tve_leads_norm_dist( $x ) {
	$b1 = 0.319381530;
	$b2 = - 0.356563782;
	$b3 = 1.781477937;
	$b4 = - 1.821255978;
	$b5 = 1.330274429;
	$p  = 0.2316419;
	$c  = 0.39894228;

	if ( $x >= 0.0 ) {
		if ( ( 1.0 + $p * $x ) == 0 ) {
			return 'N/A';
		}
		$t = 1.0 / ( 1.0 + $p * $x );

		return ( 1.0 - $c * exp( - $x * $x / 2.0 ) * $t * ( $t * ( $t * ( $t * ( $t * $b5 + $b4 ) + $b3 ) + $b2 ) + $b1 ) );
	} else {
		if ( ( 1.0 - $p * $x ) == 0 ) {
			return 'N/A';
		}
		$t = 1.0 / ( 1.0 - $p * $x );

		return ( $c * exp( - $x * $x / 2.0 ) * $t * ( $t * ( $t * ( $t * ( $t * $b5 + $b4 ) + $b3 ) + $b2 ) + $b1 ) );
	}
}

/**
 * Render the form included in the shortcode
 * the received parameter should contain one element: the id of the TL shortcode
 *
 * @param array $attributes
 *
 * @return mixed the rendered form or return the array with shortcode prop
 */
function tve_leads_shortcode_render( $attributes = array() ) {
	if ( class_exists( 'PostGridHelper' ) && PostGridHelper::$render_post_grid === false ) {
		return '';
	}

	if (
		is_feed() ||
		doing_action( 'wpseo_head' ) || /* SUPP-13169 - don't load shortcodes in head while yoast changes meta tags */
		( ! empty( $_REQUEST['action'] ) && $_REQUEST['action'] === 'editpost' ) /* SUPP-14391 - yoast conflict - do not render during post save */
	) {
		return '';
	}
	// $attributes must be always array and from the parameter it can come with the empty string.
	if ( empty( $attributes ) ) {
		$attributes = array();
	}

	$defaults = array(
		'id'         => null,
		'for_editor' => false,
	);

	$content    = '';
	$attributes = array_merge( $defaults, $attributes );

	if ( empty( $attributes['for_editor'] ) && is_editor_page() ) {
		/* Case: shortcode is rendered somewhere outside the main content area - this causes TAr to take the wrong #tve_editor div as the main element */
		return tve_leads_template( 'shortcode-message', array(), true );
	}

	if ( empty( $attributes['id'] ) ) {
		return __( 'Invalid shortcode parameters', 'thrive-leads' );
	}

	$ajax_load_forms = tve_leads_get_option( 'ajax_load' );

	$shortcode = tve_leads_get_shortcode( $attributes['id'] );
	if ( ! $shortcode || $shortcode->post_status != TVE_LEADS_STATUS_PUBLISH ) {
		return '';
	}

	/**
	 * enqueue the default scripts and CSS (required for all forms)
	 */
	tve_leads_enqueue_default_scripts();

	/**
	 * hold the main shortcode ID in the page, in a javascript var to be able to load it afterwards
	 */
	$GLOBALS['tve_leads_form_config']['shortcode_ids']   = empty( $GLOBALS['tve_leads_form_config']['shortcode_ids'] ) ? array() : $GLOBALS['tve_leads_form_config']['shortcode_ids'];
	$GLOBALS['tve_leads_form_config']['shortcode_ids'][] = $attributes['id'];

	if ( get_post_meta( $attributes['id'], 'tve_leads_masonry', true ) ) {
		wp_enqueue_script( 'jquery-masonry' );
	}

	if ( ! empty( $attributes['for_editor'] ) || ! $ajax_load_forms ) {
		$variation = tve_leads_determine_variation( $shortcode, ! empty( $attributes['for_editor'] ) ); // if we render it in the TCB editor => do not use/store cookies
		if ( empty( $variation ) ) {
			return '';
		}
		$GLOBALS['tve_leads_detected_variation'] = $variation;
		/**
		 * prepare data for triggers
		 */
		$GLOBALS['tve_lead_shortcodes'][ $attributes['id'] ] = $variation;
	}

	$type_key = 'shortcode_' . $attributes['id'];
	if ( empty( $attributes['for_editor'] ) && $ajax_load_forms ) {
		/**
		 * return at this point, as we will load this via AJAX
		 * append just a placeholder to the $content
		 */
		$control_variation = tve_leads_get_form_variations( $attributes['id'], array(
			'tracking_data' => false,
			'get_control'   => true,
		) );

		$content .= tve_leads_get_form_placeholder( $type_key, $control_variation );

		return $content;
	}

	list( $type, $key ) = explode( '|', $variation[ TVE_LEADS_FIELD_TEMPLATE ] );
	$key = preg_replace( '#_v(\d)+#', '', $key );

	/**
	 * and the specific styles / fonts etc for this particular form variation
	 * TCB editor page -> ajax request to get the variation
	 */
	$variation_config = tve_leads_enqueue_variation_scripts( $variation );
	if ( ! empty( $attributes['for_editor'] ) ) {
		return array_merge(
			$variation_config,
			array(
				'html' => sprintf(
					'<div class="tve-leads-conversion-object" id="%s" data-tl-type="%s"><div class="tve-leads-shortcode %s tve-leads-track-%s">%s</div></div>',
					'tve_' . $key,
					$type_key,
					'tl-anim-' . $variation['display_animation'],
					$type_key,
					str_replace( array( "\n", "\r" ), '', tve_editor_custom_content( $variation ) )
				),
			)
		);
	}

	$GLOBALS['tve_leads_form_config']['forms'][ 'shortcode_' . $attributes['id'] ] = array(
		'_key'            => $variation['key'],
		'form_name'       => $variation['post_title'],
		'trigger'         => $variation['trigger'],
		'trigger_config'  => ! empty( $variation['trigger_config'] ) ? $variation['trigger_config'] : new stdClass(),
		'form_type_id'    => $attributes['id'],
		'main_group_id'   => $attributes['id'],
		'main_group_name' => get_the_title( $attributes['id'] ),
		'active_test_id'  => empty( $variation['test_model'] ) ? '' : $variation['test_model']->id,
	);

	/**
	 * register form impression
	 * the Lead_Group parameter is set to null
	 */

	$GLOBALS['tve_lead_impressions'][ 'shortcode_' . $attributes['id'] ] = array(
		'group_id'       => $attributes['id'],
		'form_type_id'   => $attributes['id'],
		'variation_key'  => $variation['key'],
		'active_test_id' => empty( $variation['test_model'] ) ? null : $variation['test_model']->id,
	);

	$content .= tve_leads_display_form_shortcode( '__return_content', tve_editor_custom_content( $variation ), $variation );

	/**
	 * we need to set the cookies inline using a <script> tag
	 */
	if ( ! empty( $variation['set_cookies'] ) ) {
		//$content .= tve_leads_inline_cookies($variation['set_cookies']);
		$GLOBALS['tve_leads_set_cookies'] = empty( $GLOBALS['tve_leads_set_cookies'] ) ? array() : $GLOBALS['tve_leads_set_cookies'];
		/**
		 * stack variation's cookies to be used later in print_footer_scripts action
		 */
		foreach ( $variation['set_cookies'] as $key => $value ) {
			$GLOBALS['tve_leads_set_cookies'][ $key ] = $value;
		}
	}

	tve_leads_display_js_impression_data( 'shortcode_' . $attributes['id'] );

	return $content;
}

/**
 * Display content locking shortcode.
 *
 * @param $attributes
 * @param $content
 *
 * @return String shortcode content
 */
function tve_leads_shortcode_lock_render( $attributes, $content ) {
	$content = do_shortcode( $content );
	if ( tve_leads_check_conversion_cookie( $attributes['id'] ) ) {
		return $content;
	}

	while ( preg_match( '#^([^<]*)</([^>]+)>#s', $content, $m, PREG_OFFSET_CAPTURE ) ) {
		$tag     = '</' . $m[2][0] . '>';
		$content = substr_replace( $content, '', $m[2][1] - 2, strlen( $tag ) ) . $tag;
	}
	$content   = force_balance_tags( $content );
	$shortcode = tve_leads_shortcode_render( $attributes );

	if ( ! isset( $GLOBALS['tve_leads_detected_variation'] ) ) {
		/**
		 * this means ajax_load is enabled - we need to output just the placeholder
		 */
		return sprintf(
			'<div class="tve_content_lock tve_lock_hide tve_lead_lock">
                <div class="tve_lead_lock_shortcode">%s</div>
                <div class="tve_lead_locked_content"><div class="tve_lead_locked_overlay"></div>%s</div>
            </div>',
			$shortcode,
			$content
		);
	}

	$variation = $GLOBALS['tve_leads_detected_variation'];

	$main_class = isset( $variation['display_animation'] ) && $variation['display_animation'] === 'blur' ? 'tve_lock_blur' : 'tve_lock_hide';

	$html = sprintf(
		'<div class="tve_content_lock %s tve_lead_lock">
            <div class="tve_lead_lock_shortcode">%s</div>
            <div class="tve_lead_locked_content"><div class="tve_lead_locked_overlay"></div>%s</div>
        </div>',
		$main_class,
		$shortcode,
		$content
	);

	return $html;
}

/**
 * Render the button / link etc contents that will trigger the opening of the lightbox
 * register the lightbox to be output in the footer (or just a placeholder in case AJAX-loading of forms is enabled)
 *
 * @param array $attributes
 * @param string $content
 *
 * @return string
 */
function tve_leads_two_step_render( $attributes, $content ) {
	if ( empty( $attributes['id'] ) ) {
		return __( 'Invalid shortcode attributes', 'thrive-leads' );
	}
	/**
	 * Filter to check if we want to show the two step lightbox
	 *
	 * @param $attributes ['id'] - the id of the two step lightbox
	 */
	if ( apply_filters( 'tve_leads_do_not_show_two_step', false, $attributes['id'] ) ) {
		return '';
	}

	$two_step = tve_leads_get_form_type( $attributes['id'], array( 'get_variations' => false ) );
	if ( ! $two_step || $two_step->post_status != TVE_LEADS_STATUS_PUBLISH ) {
		return '';
	}

	$ajax_load_forms = tve_leads_get_option( 'ajax_load' );

	if ( ! $ajax_load_forms ) {
		$variation = tve_leads_determine_variation( $two_step );
		if ( empty( $variation ) ) {
			return __( 'No form found', 'thrive-leads' );
		}

		/* If the subscribed state is hidden, we don't display the trigger for the two step lightbox */
		$already_subscribed_html = tve_leads_get_already_subscribed_html( $variation, 'lightbox', true );
		if ( $already_subscribed_html === TVE_ALREADY_SUBSCRIBED_HIDDEN ) {
			return '';
		}
	}

	/**
	 * hold the main shortcode ID in the page, in a javascript var to be able to load it afterwards
	 */
	$GLOBALS['tve_leads_form_config']['two_step_ids']   = empty( $GLOBALS['tve_leads_form_config']['two_step_ids'] ) ? array() : $GLOBALS['tve_leads_form_config']['two_step_ids'];
	$exists_on_page                                     = in_array( $attributes['id'], $GLOBALS['tve_leads_form_config']['two_step_ids'] );
	$GLOBALS['tve_leads_form_config']['two_step_ids'][] = $attributes['id'];

	/**
	 * enqueue the default scripts and CSS (required for all forms)
	 */
	tve_leads_enqueue_default_scripts();

	if ( get_post_meta( $attributes['id'], 'tve_leads_masonry', true ) ) {
		wp_enqueue_script( 'jquery-masonry' );
	}

	if ( $ajax_load_forms ) {
		$GLOBALS['tve_leads_footer_html'] = empty( $GLOBALS['tve_leads_footer_html'] ) ? '' : $GLOBALS['tve_leads_footer_html'];
		if ( ! $exists_on_page ) {
			$GLOBALS['tve_leads_footer_html'] .= sprintf( '<span style="display:none" class="tl-placeholder-f-type-%s"></span>', 'two_step_' . $attributes['id'] );
		}

		return sprintf(
			'<span class="tve-leads-two-step-trigger tl-2step-trigger-%s">%s</span>',
			$attributes['id'],
			do_shortcode( $content )
		);
	}

	$variation['trigger']        = 'click';
	$variation['trigger_config'] = array( 'c' => 'tl-2step-trigger-' . $attributes['id'] );

	/**
	 * prepare data for triggers
	 */
	$GLOBALS['tve_leads_two_step'][ $variation['key'] ] = $variation;

	/**
	 * and the specific styles / fonts etc for this particular form variation
	 */
	tve_leads_enqueue_variation_scripts( $variation );

	/**
	 * append javascript needed for triggers to the global JS variable
	 */
	$GLOBALS['tve_leads_form_config']['forms'][ 'two_step_' . $attributes['id'] ] = array(
		'_key'            => $variation['key'],
		'form_name'       => $variation['post_title'],
		'trigger'         => 'click', // ALWAYS click
		'trigger_config'  => array( 'c' => 'tl-2step-trigger-' . $attributes['id'] ),
		'form_type_id'    => $attributes['id'],
		'main_group_id'   => $attributes['id'],
		'main_group_name' => get_the_title( $attributes['id'] ),
		'active_test_id'  => ! empty( $variation['test_model'] ) ? $variation['test_model']->id : null,
	);

	$GLOBALS['tve_leads_two_step'][ $variation['key'] ]['form_output'] = tve_editor_custom_content( $variation );

	$type = 'two_step_' . $attributes['id'];

	$GLOBALS['tve_lead_impressions'][ 'two_step_' . $attributes['id'] ] = array(
		'group_id'       => $two_step->ID,
		'form_type_id'   => $two_step->ID,
		'variation_key'  => $variation['key'],
		'active_test_id' => ! empty( $variation['test_model'] ) ? $variation['test_model']->id : null,
	);

	$content = sprintf(
		'<span class="tve-leads-two-step-trigger tl-2step-trigger-%s">%s</span>',
		$attributes['id'],
		do_shortcode( $content )
	);

	/**
	 * we need to set the cookies inline using a <script> tag
	 */
	if ( ! empty( $variation['set_cookies'] ) ) {
		//$content .= tve_leads_inline_cookies($variation['set_cookies']);
		$GLOBALS['tve_leads_set_cookies'] = empty( $GLOBALS['tve_leads_set_cookies'] ) ? array() : $GLOBALS['tve_leads_set_cookies'];
		/**
		 * stack variation's cookies to be used later in print_footer_scripts action
		 */
		foreach ( $variation['set_cookies'] as $key => $value ) {
			$GLOBALS['tve_leads_set_cookies'][ $key ] = $value;
		}
	}

	tve_leads_display_js_impression_data( $type );

	return $content;

}

/**
 * get a human-friendly name for the trigger setup in $variation, based on trigger and trigger_config fields
 *
 * @param array $variation
 *
 * @return String
 */
function tve_leads_trigger_nice_name( $variation ) {
	$trigger = TVE_Leads_Trigger_Abstract::factory( $variation['trigger'], $variation['trigger_config'] );

	return $trigger ? $trigger->get_display_name() : '';
}

/**
 * check if there is a valid activated license for the TL plugin
 *
 * @return bool
 */
function tve_leads_license_activated() {
	return TVE_Dash_Product_LicenseManager::getInstance()->itemActivated( TVE_Dash_Product_LicenseManager::TL_TAG );
}

/**
 * check if the current TCB version is the one required by Thrive Leads
 *
 * @return bool
 */
function tve_leads_check_tcb_version() {
	if ( ! tve_in_architect() ) { // the internal TCB code will always be up to date
		return true;
	}

	$internal_architect_version = include TVE_LEADS_PATH . '/tcb/version.php';

	/* make sure that the we have the same version of architect inside the plugin and as individual plugin, otherwise conflicts can appear */
	if ( ! defined( 'TVE_VERSION' ) || ! version_compare( TVE_VERSION, $internal_architect_version, '=' ) ) {
		return false;
	}

	return true;
}

/**
 * show a box with a warning message and a link to take the user to the license activation page
 * this will be called only when no valid / activated license has been found
 *
 * @return mixed
 */
function tve_leads_license_warning() {
	return include dirname( dirname( __FILE__ ) ) . '/admin/views/license_inactive.php';
}

/**
 * show a box with a warning message notifying the user to update the TCB plugin to the latest version
 * this will be shown only when the TCB version is lower than a minimum required version
 */
function tve_leads_tcb_version_warning() {
	return include dirname( dirname( __FILE__ ) ) . '/admin/views/tcb_version_incompatible.php';
}

/**
 * returns whether or not a form_type allows frequency settings - how many days should pass before displaying it in the same browser
 *
 * @param int|WP_Post $form_type
 *
 * @return bool
 */
function tve_leads_form_type_has_frequency_settings( $form_type ) {
	if ( is_null( $form_type ) ) {
		return false;
	}

	if ( is_numeric( $form_type ) ) {
		$form_type = tve_leads_get_form_type( $form_type );
	}

	if ( is_object( $form_type ) ) {
		if ( empty( $form_type->tve_form_type ) ) {
			return false;
		}
		$form_type = $form_type->tve_form_type;
	}

	if ( empty( $form_type ) ) {
		return false;
	}

	return in_array( $form_type, array(
		'ribbon',
		'slide_in',
		'lightbox',
		'screen_filler',
		'greedy_ribbon',
	) );
}

/**
 * returns whether or not a form_type allows position settings
 * currently, position are enabled just for slide in
 *
 * @param int|WP_Post $form_type
 *
 * @return bool
 */
function tve_leads_form_type_has_position_settings( $form_type ) {
	if ( is_null( $form_type ) ) {
		return false;
	}

	if ( is_numeric( $form_type ) ) {
		$form_type = tve_leads_get_form_type( $form_type );
	}

	if ( is_object( $form_type ) ) {
		if ( empty( $form_type->tve_form_type ) ) {
			return false;
		}
		$form_type = $form_type->tve_form_type;
	}

	if ( empty( $form_type ) ) {
		return false;
	}

	return in_array( $form_type, array(
		'slide_in',
		'ribbon',
		'in_content',
	) );
}

/**
 * returns whether or not a form_type allows animation settings
 * currently, animations are enabled just for lightboxes and screen fillers
 *
 * @param int|WP_Post $form_type
 *
 * @return bool
 */
function tve_leads_form_type_has_animation_settings( $form_type ) {
	if ( is_null( $form_type ) ) {
		return false;
	}

	if ( is_numeric( $form_type ) ) {
		$form_type = tve_leads_get_form_type( $form_type );
	}

	if ( is_object( $form_type ) ) {
		if ( empty( $form_type->tve_form_type ) ) {
			return false;
		}
		$form_type = $form_type->tve_form_type;
	}

	if ( empty( $form_type ) ) {
		return false;
	}

	return in_array( $form_type, array(
		'lightbox',
		'screen_filler',
	) );
}

/**
 * returns whether a form_type allows trigger settings
 * currently, trigger settings are enabled for all form types, except for the Scroll mat form type
 *
 * @param int|WP_Post $form_type
 *
 * @return bool
 */
function tve_leads_form_type_has_trigger_settings( $form_type ) {
	if ( is_null( $form_type ) ) {
		return false;
	}

	if ( is_numeric( $form_type ) ) {
		$form_type = tve_leads_get_form_type( $form_type );
	}

	if ( is_object( $form_type ) ) {
		if ( empty( $form_type->tve_form_type ) ) {
			return false;
		}
		$form_type = $form_type->tve_form_type;
	}

	if ( empty( $form_type ) ) {
		return false;
	}

	return ! in_array( $form_type, array( 'greedy_ribbon' ) );
}

/**
 * get a human-friendly name for the Display Frequency setup for the $variation
 *
 * @param array $variation
 *
 * @return String
 */
function tve_leads_frequency_nice_name( $variation ) {
	return (int) $variation['display_frequency'] == 0
		?
		__( 'All the time', 'thrive-leads' )
		:
		sprintf( _n( 'Every %s day', 'Every %s days', $variation['display_frequency'], 'thrive-leads' ), $variation['display_frequency'] );
}

/**
 * get a human-friendly name for the Position setup for the $variation
 *
 * @param array $variation
 *
 * @return String
 */
function tve_leads_position_nice_name( $variation ) {
	switch ( $variation['position'] ) {
		case 'bot_right':
			return __( 'Bottom Right', 'thrive-leads' );
		case 'bot_left':
			return __( 'Bottom Left', 'thrive-leads' );
		case 'top_left':
			return __( 'Top Left', 'thrive-leads' );
		case 'top_right':
			return __( 'Top Right', 'thrive-leads' );
		case 'top':
			return __( 'Top', 'thrive-leads' );
		case 'above':
			return __( 'Top over content', 'thrive-leads' );
		case 'bottom':
			return __( 'Bottom', 'thrive-leads' );
		default:
			if ( is_numeric( $variation['position'] ) ) {
				if ( $variation['position'] == '0' ) {
					return __( 'At the beginning of the post', 'thrive-leads' );
				} elseif ( $variation['position'] == '1' ) {
					return __( 'After the first paragraph', 'thrive-leads' );
				} else {
					return __( 'After ' . $variation['position'] . ' paragraphs', 'thrive-leads' );
				}
			} else {
				return $variation['position'];
			}
	}

}

/**
 * get a human-friendly name for the Display Animation setup for the $variation
 *
 * @param array $variation
 *
 * @return String
 */
function tve_leads_animation_nice_name( $variation ) {
	$animation = TVE_Leads_Animation_Abstract::factory( $variation['display_animation'] );

	return $animation == null ? $variation['display_animation'] : $animation->get_translatable_title();
}

/**
 * get the default display frequency based on $form_type
 *
 * @param string $form_type
 *
 * @return int
 */
function tve_leads_get_default_display_frequency( $form_type ) {
	switch ( $form_type ) {
		case 'lightbox':
		case 'screen_filler':
		case 'slide_in':
			return 7;
		default:
			return 0;
	}
}

/**
 * get the default display frequency based on $form_type
 *
 * @param string $form_type
 *
 * @return int
 */
function tve_leads_get_default_position( $form_type ) {
	switch ( $form_type ) {
		case 'slide_in':
			return 'bot_right';
		case 'ribbon':
			return 'top';
		case 'in_content':
			return 2;
		default:
			return 'bot_right';
	}
}


/**
 * get the default display animation based on $form_type
 *
 * @param string $form_type
 *
 * @return int
 */
function tve_leads_get_default_animation( $form_type ) {
	switch ( $form_type ) {
		case 'ribbon':
			return TVE_Leads_Animation_Abstract::ANIM_SLIDE_IN_TOP;
			break;
		case 'lightbox':
		case 'screen_filler':
			return TVE_Leads_Animation_Abstract::ANIM_ZOOM_IN;
			break;
		case 'widget':
		case 'post_footer':
		case 'in_content':
		case 'shortcode':
			return TVE_Leads_Animation_Abstract::ANIM_INSTANT;
			break;
		case 'slide_in':
			return TVE_Leads_Animation_Abstract::ANIM_SLIDE_IN_RIGHT;
			break;
		default:
			return TVE_Leads_Animation_Abstract::ANIM_INSTANT;
	}
}

/**
 * wrapper over the wp_enqueue_script function
 * it will add the plugin version to the script source if no version is specified
 *
 * @param        $handle
 * @param string $src
 * @param array $deps
 * @param bool $ver
 * @param bool $in_footer
 */
function tve_leads_enqueue_script( $handle, $src = false, $deps = array(), $ver = false, $in_footer = false ) {
	if ( $ver === false ) {
		$ver = TVE_LEADS_VERSION;
	}

	if ( defined( 'TVE_DEBUG' ) && TVE_DEBUG ) {
		$src = str_replace( '/js-min/', '/js/', $src );
		$src = preg_replace( '#\.min\.js$#', '.js', $src );
	}

	wp_enqueue_script( $handle, $src, $deps, $ver, $in_footer );
}

/**
 * wrapper over the wp_enqueue_style function
 * it will add the plugin version to the style link if no version is specified
 *
 * @param             $handle
 * @param string $src
 * @param array $deps
 * @param bool|string $ver
 * @param string $media
 */
function tve_leads_enqueue_style( $handle, $src = false, $deps = array(), $ver = false, $media = 'all' ) {
	if ( $ver === false ) {
		$ver = TVE_LEADS_VERSION;
	}
	wp_enqueue_style( $handle, $src, $deps, $ver, $media );
}


/**
 *
 * gets the nice name for a form type
 *
 * @param WP_Post|int|string $form_type can either be a WP_Post object, a form type ID or a string in the form of 'ribbon' for example
 *
 * @return string the nice post name
 */
function tve_leads_get_form_type_name( $form_type ) {
	if ( is_numeric( $form_type ) || $form_type instanceof WP_Post ) {
		$form_type = get_post_meta( $form_type, 'tve_form_type', true );
	}

	if ( ! is_string( $form_type ) ) {
		return '';
	}

	$all = tve_leads_get_default_form_types( true );

	if ( ! isset( $all[ $form_type ] ) ) {
		return '';
	}

	return $all[ $form_type ]['post_title'];
}

/**
 *
 * get the equivalent test type based on post type of the form
 *
 * @param string $post_type
 *
 * @return string the test_type constant
 */
function tve_leads_get_test_type_from_post_type( $post_type ) {
	return $post_type == TVE_LEADS_POST_FORM_TYPE
		? TVE_LEADS_VARIATION_TEST_TYPE
		:
		( $post_type == TVE_LEADS_POST_SHORTCODE_TYPE
			? TVE_LEADS_SHORTCODE_TEST_TYPE
			: ( $post_type == TVE_LEADS_POST_TWO_STEP_LIGHTBOX ? TVE_LEADS_TWO_STEP_LIGHTBOX_TEST_TYPE : TVE_LEADS_GROUP_TEST_TYPE ) );
}

/**
 * wrapper over the wp get_option function - it appends the tve_leads_ prefix to the option name
 *
 * @param      $name
 * @param bool $default
 *
 * @return mixed
 */
function tve_leads_get_option( $name, $default = false ) {
	$name  = 'tve_leads_' . preg_replace( '/^tve_leads_/', '', $name );
	$value = get_option( $name, $default );
	if ( $name === 'tve_leads_ajax_load' ) {
		$value = (int) $value;
	}

	return $value;
}

/**
 * gets the page data - used to build the the breadcrumbs
 *
 * @return mixed
 */
function tve_leads_get_screen_data() {
	$current_screen = get_current_screen();
	if ( strpos( $current_screen->base, 'toplevel_page_' ) !== false ) {
		$url = '#dashboard';
	} else {
		$path = str_replace( 'thrive-leads_page_', '', $current_screen->base );
		$url  = menu_page_url( $path, false );
	}

	$screen_data[0]['name'] = 'Thrive Dashboard';
	$screen_data[0]['url']  = menu_page_url( 'tve_dash_section', false );
	$screen_data[1]['name'] = 'Thrive Leads';
	$screen_data[1]['url']  = menu_page_url( 'thrive_leads_dashboard', false );
	$screen_data[2]['name'] = str_replace( 'Thrive Leads ', '', get_admin_page_title() );
	$screen_data[2]['url']  = $url;
	$screen_data[2]['last'] = 1;

	return $screen_data;
}

/**
 * wrapper over the wp update_option() function
 * it ensures the option is prefixed with "tve_leads_" prefix
 *
 * @param string $name
 * @param mixed $value
 *
 * @return bool
 */
function tve_leads_update_option( $name, $value ) {
	$name = 'tve_leads_' . preg_replace( '/^tve_leads_/', '', $name );

	return update_option( $name, $value );
}

/**
 * get all form types that are to be shown on a page based on the $lead_group
 *
 * @param WP_Post $lead_group
 * @param bool $skip_group_tests whether or not to take into account any tests that are running at group level
 *
 * @return array
 */
function tve_leads_get_targeted_form_types( $lead_group, $skip_group_tests = false ) {
	$form_types_to_be_shown = array();

	$group_level_tests = $skip_group_tests ? array() : tve_leads_get_group_active_tests( $lead_group->ID );

	/* gather first all the available form types */
	foreach ( $lead_group->form_types as $form_type ) {
		if ( is_array( $form_type ) || ! $form_type->ID ) {
			continue;
		}
		$display_on_mobile = get_post_meta( $form_type->ID, 'display_on_mobile', true );
		$display_on_mobile = (string) $display_on_mobile === '' ? 1 : (int) $display_on_mobile;
		if ( $display_on_mobile === 0 && wp_is_mobile() ) {
			continue;
		}

		$display_status = get_post_meta( $form_type->ID, 'display_status', true );
		$display_status = (string) $display_status === '' ? 1 : (int) $display_status;
		/* since 05.09.2016 display status is display on desktop so we just check if this is not a mobile */
		if ( $display_status === 0 && ! wp_is_mobile() ) {
			continue;
		}
		/**
		 * eliminate screenfillers, lightboxes, ribbons and slideins from the customize preview screens
		 */
		if ( tve_leads_is_customize_preview() && in_array( $form_type->tve_form_type, array(
				'lightbox',
				'screen_filler',
				'ribbon',
				'slide_in'
			) ) ) {
			continue;
		}
		$form_types_to_be_shown[ $form_type->ID ] = $form_type;
	}
	/* bail early if no form type has been found */
	if ( empty( $form_types_to_be_shown ) ) {
		return array();
	}

	if ( empty( $group_level_tests ) ) {
		/* we need to show all form types, so there's nothing to be done here */

	} else {
		/* take every form_type that's not included in a test and ALL OTHER form types */
		foreach ( $group_level_tests as $test ) {

			$visited_form = tve_leads_get_visited_test_form( $lead_group->ID, $test->item_ids );

			/* if we previously visited one of the form types, we display the same one and not get a random index */
			$random_index = empty( $visited_form ) ? tve_leads_get_random_index( count( $test->item_ids ) ) : array_search( $visited_form, $test->item_ids );

			foreach ( $test->item_ids as $index => $_id ) {
				/* remove all other form types that are included in the test and have a different index in the test_items array */
				if ( $random_index != $index ) {
					unset( $form_types_to_be_shown[ $_id ] );
					continue;
				}
				if ( ! isset( $form_types_to_be_shown[ $_id ] ) ) {
					continue;
				}
				$form_types_to_be_shown[ $_id ]->group_level_test = $test;
			}
		}
	}

	return $form_types_to_be_shown;
}

/**
 * For a test at a group level, check in the cookies if we already saw one of the form types.
 * If we already have a unique impression for a form, we return the form id
 *
 * @param $lead_group_id
 * @param $test_items_ids
 *
 * @return int
 */
function tve_leads_get_visited_test_form( $lead_group_id, $test_items_ids ) {
	$cookies = array_keys( $_COOKIE );

	foreach ( $cookies as $cookie ) {
		/* search for cookies from our lead group */
		if ( strpos( $cookie, 'tl_' . $lead_group_id ) === 0 ) {
			/* cookie -> tl_{group_id}_{form_id}_{variation_id} */
			$parts = explode( '_', $cookie );

			if ( count( $parts ) !== 4 ) {
				/* make sure we have the right cookie */
				break;
			}

			$form_type_id = $parts[2];

			if ( in_array( $form_type_id, $test_items_ids ) ) {
				return (int) $form_type_id;
			}
		}
	}

	return 0;
}

/**
 * output inline setcookies using inline <script>s
 *
 * @param array $cookies
 *
 * @return string the inline javascript
 */
function tve_leads_inline_cookies( $cookies ) {
	if ( empty( $cookies ) ) {
		return '';
	}
	$output = '<script type="text/javascript">var _now = new Date(), sExpires;';
	foreach ( $cookies as $key => $cookie ) {
		$output .= '_now.setTime(_now.getTime() + (' . intval( $cookie['expires'] ) . ' * 24 * 3600 * 1000));sExpires = _now.toUTCString();';
		$output .= 'document.cookie=encodeURIComponent(' . json_encode( $key ) . ")+'='+encodeURIComponent(" . json_encode( $cookie['value'] ) . ")+';expires='+sExpires+';path=/';";
	}
	$output .= '</script>';

	return $output;
}

/**
 * output the JS code required for a trigger associated with a variation
 *
 * @param array $variation
 * @param string $form_id
 * @param string $form_type
 */
function tve_leads_output_trigger_js( $variation, $form_id, $form_type ) {
	$trigger = TVE_Leads_Trigger_Abstract::factory( $variation['trigger'], $variation['trigger_config'] );
	if ( is_null( $trigger ) ) {
		return;
	}
	$trigger->output_js( array(
		'form_id'   => 'tve-leads-track-' . $form_id,
		'form_type' => $form_type,
	) );
}

/**
 * determine which form variation to display from a $form_type
 * takes into account also the (possible) running tests between variations from the form type
 *
 * if a test is running and the user has visited the page before, we need to show him the same form
 * we do this by dropping a cookie with the generated variation index from the ones included in the test
 *
 * also, if we detect a mobile browser (using wp_is_mobile) and the user did not setup the form to be displayed on mobile, then the result will be empty
 *
 * for some forms, there is a display_frequency setting which prevents the form for displaying for a set amount of time (days)
 * this is also solved with a cookie, and also handled here
 *
 * @param WP_Post $form_type
 * @param bool $skip_cookie_check whether or not to skip the cookie check in case of an active test running
 *
 * @return array|null the form variation or empty for failure
 */
function tve_leads_determine_variation( $form_type, $skip_cookie_check = false ) {
	$_type      = $form_type->tve_form_type;
	$test_model = ! empty( $form_type->group_level_test ) ? $form_type->group_level_test : false;
	/**
	 * IF there is no active test at group level -> take into account tests at form type level
	 *
	 * If there is a test running at variation level, only get active test items for that test
	 */
	if ( empty( $test_model ) ) {
		$variation_active_test = tve_leads_get_form_active_test( $form_type->ID, array(
			'test_type' => null,
			'get_items' => false
		) );
	}

	$variations = tve_leads_get_form_variations( $form_type->ID, array(
		'tracking_data'      => false,
		'post_status'        => TVE_LEADS_STATUS_PUBLISH,
		'active_for_test_id' => ! empty( $variation_active_test ) && ! empty( $variation_active_test->id ) ? $variation_active_test->id : false,
	) );

	/* no active variation, nothing to do here */
	if ( empty( $variations ) ) {
		return array();
	}

	$cookies_to_set = array();
	/* if there's a test running at form type level and no test at group level -> choose a random form variation */
	if ( empty( $test_model ) && ! empty( $variation_active_test ) ) {
		$test_model = $variation_active_test;

		if ( ! $skip_cookie_check ) {
			/**
			 * if there's a previous cookie key setup for this variation and a test is running, then we should show the same variation to the user
			 */
			$same_variation_key = 't_' . $test_model->id . '_f_' . $form_type->ID;
			if ( isset( $_COOKIE[ $same_variation_key ] ) && isset( $variations[ $_COOKIE[ $same_variation_key ] ] ) ) {
				$variation_index = $_COOKIE[ $same_variation_key ];
			} else {
				$variation_index = tve_leads_get_random_index( count( $variations ) );
			}
			if ( ! headers_sent() ) {
				setcookie( $same_variation_key, $variation_index, time() + 3600 * 30, '/' );
			} else {
				$cookies_to_set[ $same_variation_key ] = array(
					'value'   => $variation_index,
					'expires' => 30,
				);
			}
		} else {
			$variation_index = tve_leads_get_random_index( count( $variations ) );
		}
	} else {
		/* else always choose the first published variation = the control */
		$variation_index = 0;
	}

	//just in case it does not find that index of variation
	$variation = isset( $variations[ $variation_index ] ) ? $variations[ $variation_index ] : $variations[0];
	/* some sanity checks - check if we have content / templates for the variation */
	if ( empty( $variation[ TVE_LEADS_FIELD_TEMPLATE ] ) ) {
		return array();
	}

	/**
	 * if the user has setup a display frequency (in days) for this particular form, we need to check if this form has been displayed
	 * in the past x days on this browser. We do this by checking the value of a cookie.
	 */
	if ( $variation['display_frequency'] && tve_leads_form_type_has_frequency_settings( $_type ) ) {

		$cookie_key = 'tlf_' . $variation['key'];
		/**
		 * if the cookie is set, then there's nothing more to do here
		 */
		if ( isset( $_COOKIE[ $cookie_key ] ) ) {
			unset( $GLOBALS['tve_lead_forms'][ $_type ] );

			return array();
		}

		/**
		 * otherwise, set the cookie to expire after the number of days setup for the form
		 */
		if ( ! headers_sent() ) {
			setcookie( $cookie_key, 1, time() + ( 3600 * 24 * (int) $variation['display_frequency'] ), '/' );
		} else {
			$cookies_to_set[ $cookie_key ] = array(
				'value'   => 1,
				'expires' => (int) $variation['display_frequency'],
			);
		}
	}

	$variation['test_model']  = $test_model;
	$variation['set_cookies'] = $cookies_to_set;

	return $variation;
}

/**
 * set a cookie (flag) that marks just that a user converted a form from $main_group_id
 * another cookie is set containing also the email address, that's a separate one, and allows us to track multiple conversions from the same browser
 * (if the emails are different)
 *
 * @param int $main_group_id the id for the main group
 */
function tve_leads_set_conversion_cookie( $main_group_id ) {
	setcookie( 'tl_conversion_' . $main_group_id, '1', time() + ( 365 * 24 * 3600 ), '/' );
}

/**
 * Check if a user has converted on a form from a lead group / shortcode / 2-step
 *
 * @param int $main_group_id the id for the main group
 *
 * @return bool
 */
function tve_leads_check_conversion_cookie( $main_group_id ) {
	return isset( $_COOKIE[ 'tl_conversion_' . $main_group_id ] );
}

/**
 * check if we are previewing a TL form
 */
function tve_leads_is_preview_page() {
	$post_type = get_post_type( get_the_ID() );
	if ( ! in_array( $post_type, array(
		TVE_LEADS_POST_FORM_TYPE,
		TVE_LEADS_POST_TWO_STEP_LIGHTBOX,
		TVE_LEADS_POST_SHORTCODE_TYPE
	) ) ) {
		return false;
	}

	global $variation;
	if ( empty( $variation ) ) {
		return false;
	}

	return true;
}

/**
 * check if we are editing a TL form
 */
function tve_leads_is_editor_page() {
	$post_type = get_post_type( get_the_ID() );
	if ( ! in_array( $post_type, array(
		TVE_LEADS_POST_FORM_TYPE,
		TVE_LEADS_POST_TWO_STEP_LIGHTBOX,
		TVE_LEADS_POST_SHORTCODE_TYPE
	) ) ) {
		return false;
	}

	global $variation;
	if ( empty( $variation ) ) {
		return false;
	}

	return isset( $_GET[ TVE_EDITOR_FLAG ] );
}

/**
 * check if a conversion has been registered for this variation and, if so, we need to check if there is an "Already subscribed" state defined and show that instead
 *
 * @param array $variation the main variation where the "Already Subscribed" state should have been setup
 * @param string $type type of form
 * @param bool $skip_inbound_link_check whether or not to skip the check for 'already_subscribed' state from the inbound link params
 * @param bool $for_shortcode whether the current call is done for a shortcode. if true and $skip_inbound_link_check is false, it checks that the "subscribed" state is checked for inbound links and all forms are targeted
 *
 * @return string
 */
function tve_leads_get_already_subscribed_html( $variation, $type, $skip_inbound_link_check = false, $for_shortcode = false ) {
	$show_already_subscribed = $skip_inbound_link_check ? false : tve_leads_force_subscribed_state( $for_shortcode );

	if ( empty( $variation ) || ! empty( $variation['parent_id'] ) || ( ! isset( $_COOKIE[ 'tl-conv-' . $variation['key'] ] ) && ! $show_already_subscribed ) ) {
		return '';
	}

	$done = tve_leads_get_already_subscribed_state( $variation );

	if ( empty( $done ) ) {
		return '';
	}

	/* Return empty when the content is hidden */
	if ( tve_leads_check_variation_visibility( $done ) ) {
		return TVE_ALREADY_SUBSCRIBED_HIDDEN;
	}

	/**
	 * enqueue the scripts / styles for the already subscribed state
	 */
	tve_leads_enqueue_variation_scripts( $done );

	$ajax_load_forms = tve_leads_get_option( 'ajax_load' );
	if ( $ajax_load_forms && wp_doing_ajax() ) {
		$GLOBALS['tve_leads_subscribed_states']   = isset( $GLOBALS['tve_leads_subscribed_states'] ) ? $GLOBALS['tve_leads_subscribed_states'] : array();
		$GLOBALS['tve_leads_subscribed_states'][] = $done;
		remove_filter( 'tve_leads_append_states_ajax', 'tve_leads_ajax_already_subscribed_state' );
		add_filter( 'tve_leads_append_states_ajax', 'tve_leads_ajax_already_subscribed_state' );
	}

	$fn = 'tve_leads_display_form_' . $type;

	return $fn( '__return_content', tve_editor_custom_content( $done ), $done, array(
		'wrap' => false,
	) );
}

/**
 * append any possible already_subscribed state to the list of variations that are to be processed and returned when lazy-loading is enabled
 *
 * @param array $output_variations
 *
 * @return array
 */
function tve_leads_ajax_already_subscribed_state( $output_variations ) {
	if ( empty( $GLOBALS['tve_leads_subscribed_states'] ) ) {
		return $output_variations;
	}

	if ( empty( $output_variations ) || ! is_array( $output_variations ) ) {
		$output_variations = array();
	}

	$output_variations = array_merge( $output_variations, $GLOBALS['tve_leads_subscribed_states'] );

	return $output_variations;
}

/**
 * return the html for a variation state
 * used in all form types except for lightboxes
 *
 * @param string $form_html
 * @param array $variation
 * @param array $control used to control pieces of html
 *
 * @return string
 */
function tve_leads_state_html( $form_html, $variation, $control ) {
	return sprintf(
		'<div%s class="tl-style" id="%s" data-state="%s" data-form-state="%s">%s</div>',
		! empty( $control['hide'] ) ? ' style="display:none"' : '',
		'tve_' . tve_leads_get_variation_style_key( $variation ),
		$variation['key'],
		$variation['form_state'],
		$form_html
	);
}

/**
 *
 * gets the CSS style key needed for a variation, based on the template
 *
 * @param array $variation
 *
 * @return string the style key
 */
function tve_leads_get_variation_style_key( &$variation ) {
	if ( ! isset( $variation['style_key'] ) ) {
		$parts                  = explode( '|', $variation[ TVE_LEADS_FIELD_TEMPLATE ] );
		$key                    = end( $parts );
		$variation['style_key'] = preg_replace( '#_v(.+)$#', '', $key );;
	}

	return $variation['style_key'];
}

/**
 * WP wrapper / shim over the WP is_customize_preview function (if available)
 *
 * @return bool
 */
function tve_leads_is_customize_preview() {
	if ( function_exists( 'is_customize_preview' ) ) {
		return is_customize_preview();
	}

	global $wp_customize;

	return is_a( $wp_customize, 'WP_Customize_Manager' ) && $wp_customize->is_preview();
}

/**
 * main entry-point for displaying a PHP_INSERT form type
 * users are able to use this php code to insert a form anywhere in the site
 *
 * @param string $main_group_id
 * @param string $form_type_or_shortcode_id
 */
function tve_leads_form_display( $main_group_id = null, $form_type_or_shortcode_id = null ) {
	if ( empty( $main_group_id ) && empty( $form_type_or_shortcode_id ) ) {
		echo __( 'There is a problem with this PHP insert: missing both parameters', 'thrive-leads' );

		return;
	}

	/**
	 * if ths form is a PHP insert and the main group is not targeted, bail early
	 */
	if ( ! empty( $main_group_id ) ) {
		global $tve_lead_group;
		if ( empty( $tve_lead_group ) || $tve_lead_group->ID != $main_group_id ) {
			return;
		}
	}

	$form_type = tve_leads_get_form_type( $form_type_or_shortcode_id, array( 'get_variations' => false ) );

	switch ( $form_type->tve_form_type ) {
		case 'shortcode':
			echo tve_leads_shortcode_render( array( 'id' => $form_type_or_shortcode_id ) );
			break;
		case 'php_insert':
			if ( empty( $GLOBALS['tve_lead_forms']['php_insert'] ) ) {
				return;
			}
			echo tve_leads_display_form_php_insert();
			break;
	}

}

/**
 * Checks to see if the current screen represents a page, post, blog, index, front and so on.
 * Returns an array with the ID and type.
 *
 * @return array
 */
function tve_get_current_screen() {
	$id = get_the_ID();
	if ( is_front_page() ) {
		$data = array(
			'screen_type' => TVE_SCREEN_HOMEPAGE,
			'screen_id'   => 0,
		);
	} elseif ( is_home() ) {
		$data = array(
			'screen_type' => TVE_SCREEN_BLOG,
			'screen_id'   => 0,
		);
	} elseif ( is_singular() ) {
		switch ( get_post_type( $id ) ) {
			case 'post':
				$type = TVE_SCREEN_POST;
				break;
			case 'page':
				$type = TVE_SCREEN_PAGE;
				break;
			default:
				$type = TVE_SCREEN_CUSTOM_POST;
		}
		$data = array(
			'screen_type' => $type,
			'screen_id'   => $id,
		);
	} elseif ( is_archive() ) {
		$data = array(
			'screen_type' => TVE_SCREEN_ARCHIVE,
			'screen_id'   => 0,
		);
	} else {
		$data = array(
			'screen_type' => TVE_SCREEN_OTHER,
			'screen_id'   => 0,
		);
	}

	return $data;
}


/**
 * Returns readable information for reporting table of the screen from where the log was made
 *
 * @param $screen_type
 * @param $screen_id
 *
 * @return array Array with url, type and name of the page
 * @see tve_get_current_screen()
 *
 */
function tve_get_current_screen_for_reporting_table( $screen_type, $screen_id ) {
	global $wp_rewrite;
	$wp_rewrite = new WP_Rewrite();
	switch ( $screen_type ) {
		case TVE_SCREEN_HOMEPAGE:
			return array(
				get_home_url(),
				__( 'Homepage', 'thrive-leads' ),
				__( 'Homepage', 'thrive-leads' ),
			);
			break;
		case TVE_SCREEN_BLOG:
			return array(
				get_permalink( get_option( 'page_for_posts' ) ),
				__( 'Blog', 'thrive-leads' ),
				__( 'Blog', 'thrive-leads' ),
			);
			break;
		case TVE_SCREEN_POST:
		case TVE_SCREEN_PAGE:
		case TVE_SCREEN_CUSTOM_POST:
			return array(
				get_permalink( $screen_id ),
				get_post_type( $screen_id ) ? get_post_type( $screen_id ) : '',
				get_the_title( $screen_id ),
			);
			break;
		case TVE_SCREEN_ARCHIVE:
			return array(
				'',
				__( 'Archive', 'thrive-leads' ),
				__( 'Archive', 'thrive-leads' ),
			);
			break;
		case TVE_SCREEN_OTHER:
			return array(
				'',
				__( 'Other', 'thrive-leads' ),
				__( 'Other', 'thrive-leads' ),
			);
			break;
		default:
			return array(
				'',
				__( 'Unknown', 'thrive-leads' ),
				__( 'Unknown', 'thrive-leads' ),
			);
	}
}

/**
 * Return an array with all the fields that we want to ignore when storing contacts in the database.
 * Email is already stored in another variable so we don't need it again
 *
 * @return array
 */
function tve_get_lead_generation_ignored_fields() {
	return array(
		'email',
		'_captcha_size',
		'_captcha_theme',
		'_captcha_type',
		'_submit_option',
		'_use_captcha',
		'g-recaptcha-response',
		'__tcb_lg_fc',
		'__tcb_lg_msg',
		'_state',
		'_form_type',
		'_error_message_option',
		'_back_url',
		'_submit_option',
		'url',
		'_asset_group',
		'_asset_option',
		'mailchimp_optin',
		'tcb_token',
		'tve_labels',
		'tve_mapping',
		'_api_custom_fields',
		'_sendParams',
		'_autofill',
	);
}

/**
 * check if there is a cookie set that forces the "Already Subscribed" state to be displayed.
 * this can only come from the inbound link functionality
 *
 * @param bool $for_shortcode whether or not this current form is a shortcode. If true, it ignores the lead group and checks if: All forms are targeted with inbound links and the option is "show already subscribed state"
 *
 * @return bool
 */
function tve_leads_force_subscribed_state( $for_shortcode = false ) {
	if ( $for_shortcode ) {
		return ! empty( $_COOKIE['tl_inbound_target_all'] );
	}
	global $tve_lead_group;
	if ( empty( $tve_lead_group ) ) {
		return false;
	}
	$group_cookie_name = 'tl_inbound_link_params_' . $tve_lead_group->ID;

	$show_already_subscribed = false;
	if ( isset( $_COOKIE[ $group_cookie_name ] ) ) {
		$inbound_link_params     = thrive_safe_unserialize( stripslashes( $_COOKIE[ $group_cookie_name ] ) );
		$show_already_subscribed = ! empty( $inbound_link_params['tl_form_type'] );
	}

	return $show_already_subscribed;
}

/**
 * Check if the current state of the variation is visible
 *
 * @param array $variation
 *
 * @return bool
 */
function tve_leads_check_variation_visibility( $variation = array() ) {
	return isset( $variation[ TVE_LEADS_FIELD_STATE_VISIBILITY ] ) && empty( $variation[ TVE_LEADS_FIELD_STATE_VISIBILITY ] );
}

/**
 * get a reliable timezone string, even if it's set to a manual time difference (UTC+/-)
 *
 * @return string
 */
function tve_get_timezone_string() {
	// if site timezone string exists, return it
	if ( $timezone = get_option( 'timezone_string' ) ) {
		return $timezone;
	}

	// get UTC offset, if it isn't set then return UTC
	if ( 0 === ( $utc_offset = get_option( 'gmt_offset', 0 ) ) ) {
		return 'UTC';
	}

	// adjust UTC offset from hours to seconds
	$utc_offset *= 3600;

	// attempt to guess the timezone string from the UTC offset
	if ( $timezone = timezone_name_from_abbr( '', $utc_offset, 0 ) ) {
		return $timezone;
	}

	// last try, guess timezone string manually
	$is_dst = date( 'I' );

	foreach ( timezone_abbreviations_list() as $abbr ) {
		foreach ( $abbr as $city ) {
			if ( $city['dst'] == $is_dst && $city['offset'] == $utc_offset ) {
				return $city['timezone_id'];
			}
		}
	}

	// fallback to UTC
	return 'UTC';
}

/**
 * get a list of all templates downloaded from the cloud based on form type
 *
 * @param string $form_type
 *
 * @return array
 */
function tve_leads_get_downloaded_templates( $form_type ) {
	return get_option( 'tve_leads_' . $form_type . '_downloaded_templates', array() );
}

/**
 * save the list of downloaded templates into the wp_option used for these
 *
 * @param string $form_type
 * @param array $templates
 */
function tve_leads_save_downloaded_templates( $form_type, $templates ) {
	update_option( 'tve_leads_' . $form_type . '_downloaded_templates', $templates );
}

function tve_leads_is_cloud_template( $form_type, $template ) {

	if ( strpos( $template, '|' ) !== false ) {
		$template = substr( $template, strpos( $template, '|' ) + 1 );
	}

	$cloud = tve_leads_get_downloaded_templates( $form_type );

	return ! empty( $cloud[ $template ] );
}

/**
 * Displays notices of inconclusive tests
 *
 * @param $id
 */
function tve_inconclusive_tests_notice() {
	$running_tests = tve_get_running_inconclusive_tests();

	$inconclusive_tests_option = get_option( 'tve_inconclusive_tests' );
	$inconclusive_tests        = array();
	if ( ! is_array( $inconclusive_tests_option ) ) {
		$inconclusive_tests = explode( ',', get_option( 'tve_inconclusive_tests' ) );
	}
	foreach ( $running_tests as $tests ) {
		$id = $tests->id;

		if ( ! in_array( $id, $inconclusive_tests ) ) {
			?>
            <div data-test-id="<?php echo $id; ?>"
                 class="notice-error notice tve_error_inconclusive_test_notice is-dismissible">
                <p><?php echo __( 'One of your active A/B tests in Thrive Leads appears to be inconclusive. The test has reached double the threshold time and conversion numbers, but no clear winner has been found. <a href="javascript:void(0);" onclick="ThriveLeadsInconclusive.inconclusive_tests.trigger_dismiss_notice(' . $id . ')">Click here to view the test</a>.', 'thrive-leads' ); ?></p>
            </div>
			<?php
		}
	}
}

/**
 * returns an array of error messages for default templates
 *
 * @return array
 */
function tve_leads_errors_config() {
	return array(
		'email'            => 'Please enter a valid email address',
		'phone'            => 'Please enter a valid phone number',
		'required'         => 'Name and Email fields are required',
		'password'         => 'Please enter a password',
		'passwordmismatch' => 'The passwords do not match',
	);
}

/**
 * Create a new editor instance so we can use it on the asset delivery system
 */
function tve_leads_output_wysiwyg_editor() {
	$screen = get_current_screen();

	if ( $screen->id !== 'admin_page_thrive_leads_asset_delivery' ) {
		return;
	}

	echo '<div id="tve-leads-asset-editor-wrapper" style="display: none">';
	wp_editor( '', 'default-editor', array(
		'dfw'               => true,
		'tabfocus_elements' => 'insert-media-button,save-post',
		'editor_height'     => 360,
		'textarea_rows'     => 15,
	) );
	echo '</div>';
}

function tve_leads_template( $file, $data = null, $return = false ) {
	if ( strpos( $file, '.php' ) === false ) {
		$file .= '.php';
	}

	$file      = ltrim( $file, '\\/' );
	$file_path = TVE_LEADS_PATH . 'inc/views/' . $file;
	$content   = null;

	if ( ! is_file( $file_path ) ) {
		return false;
	}

	if ( false !== $return ) {
		ob_start();
		include $file_path;
		$content = ob_get_contents();
		ob_end_clean();
	} else {
		include $file_path;
	}

	return $content;
}

/**
 * Gets a list of templates from Cloud to be usually shown on Templates Lightbox
 *
 * @param $form_type      string
 * @param $get_multi_step bool
 *
 * @return array
 */
function tve_leads_get_cloud_templates( $form_type, $get_multi_step ) {

	$transient_name = 'tve_leads_' . $form_type . '_template_cloud';

	if ( defined( 'TL_CLOUD_DEBUG' ) && TL_CLOUD_DEBUG ) {
		delete_transient( $transient_name );
	}

	if ( false === ( $templates = get_transient( $transient_name ) ) ) {

		try {

			$templates = Thrive_Leads_Cloud_Templates_APi::getInstance()->init( array( 'form_type' => $form_type ) )->getTemplateList( ! (bool) $get_multi_step );
			set_transient( $transient_name, $templates, 8 * HOUR_IN_SECONDS );

		} catch ( Exception $e ) {

			$templates = array();
		}

	}
	if ( empty( $templates['error'] ) ) {
		foreach ( $templates as &$tpl ) {
			$tpl['key']       = ( $tpl['multi_step'] ? 'multi_step|' : '' ) . $form_type . '|' . $tpl['key'];
			$tpl['form_type'] = $form_type;
			$tpl['cloud']     = true;
		}
	}

	return $templates;
}

/**
 * Check if a TL template is a cloud template or a local template
 *
 * @param string $template_key
 *
 * @return bool
 */
function tve_leads_is_v2_template( $template_key ) {

	return strpos( $template_key, 'tcb2_' ) === 0;
}

/**
 *
 * Get the default CSS for a TL template - only applicable for v2 templates
 * The CSS can either be stored locally, for the blank template, or downloaded from the cloud, stored in a file in the wp-uploads folder
 *
 * @param string $template_key
 * @param array $template_config
 *
 * @return string
 */
function tve_leads_get_default_template_css( $template_key, $template_config = array() ) {

	$head_css = '';
	list( $form_type, $template ) = explode( '|', $template_key );

	if ( tve_leads_is_v2_template( $template ) ) {
		if ( tve_leads_is_cloud_template( $form_type, $template ) ) {
			$css_file = tve_leads_get_cloud_folder_path( $form_type, $template ) . 'css/style.css';
			if ( file_exists( $css_file ) ) {
				$head_css = file_get_contents( $css_file );
				$head_css = str_replace( '{tve_leads_base_url}', tve_leads_get_cloud_folder_url( $form_type, $template ) . 'images/', $head_css );
			}
		} else {
			/**
			 * at this point, this is a default v2 template ( blank set v2 )
			 */
			$css_file = plugin_dir_path( dirname( __FILE__ ) ) . 'editor-templates/_tcb2_css/' . $form_type . '_' . $template . '.css';
			if ( file_exists( $css_file ) ) {
				$head_css = file_get_contents( $css_file );
			}
		}
	}

	return $head_css;
}

/**
 * Check if Setup of Asset Delivery is completed/valid
 *
 * @return bool
 */
function tve_leads_asset_delivery_setup_valid() {

	$connection     = get_option( 'tve_api_delivery_service', false );
	$email_body     = get_option( 'tve_leads_asset_mail_subject', false );
	$email_subject  = get_option( 'tve_leads_asset_mail_body', false );
	$connected_apis = Thrive_List_Manager::get_available_apis( true, [ 'include_types' => [ 'email' ] ] );

	return ! empty( $connection ) && ! empty( $email_body ) && ! empty( $email_subject ) && ! empty( $connected_apis );
}

/**
 *
 * Get the full path to the folder storing downloaded TL cloud templates
 *
 * @param string $form_type
 * @param string $template
 *
 * @return string
 */
function tve_leads_get_cloud_folder_path( $form_type = null, $template = null ) {
	$upload = wp_upload_dir();
	if ( ! empty( $upload['error'] ) ) {
		return '';
	}

	return trailingslashit( $upload['basedir'] ) . TVE_LEADS_CLOUD_FORM_FOLDER . '/' . ( $form_type ? $form_type . '/' : '' ) . ( $template ? $template . '/' : '' );
}

/**
 *
 * Get the full URL to the folder storing downloaded TL cloud templates
 *
 * @param string $form_type
 * @param string $template
 *
 * @return string
 */
function tve_leads_get_cloud_folder_url( $form_type = null, $template = null ) {
	$upload = wp_upload_dir();
	if ( ! empty( $upload['error'] ) ) {
		return '';
	}

	$base_url = str_replace( array( 'http://', 'https://' ), '//', $upload['baseurl'] );

	return trailingslashit( $base_url ) . TVE_LEADS_CLOUD_FORM_FOLDER . '/' . ( $form_type ? $form_type . '/' : '' ) . ( $template ? $template . '/' : '' );
}

/**
 * Get the default configuration for the new TCB2 blank template
 *
 * @return array
 */
function tve_leads_get_v2_blank_config( $form_type ) {

	return array(
		'key'  => $form_type . '|tcb2_blank',
		'name' => 'Blank Template',
		'meta' => array(
			TVE_LEADS_FIELD_USER_CSS => '.tve-leads-conversion-object .thrv_heading h1,.tve-leads-conversion-object .thrv_heading h2,.tve-leads-conversion-object .thrv_heading h3{margin:0;padding:0}.tve-leads-conversion-object .thrv_text_element p,.tve-leads-conversion-object .thrv_text_element h1,.tve-leads-conversion-object .thrv_text_element h2,.tve-leads-conversion-object .thrv_text_element h3{margin:0}',
		),
	);
}

/**
 *
 * Process the Custom CSS rules to be added to the page
 * SUPP-3939 - make sure the rules are only applied to TL forms, and not everywhere
 *
 * @param string $css
 */
function tve_leads_process_custom_css( $css ) {
	$css = preg_replace( '#^\.thrv_heading h1#', '.tve-leads-conversion-object .thrv_heading h1', $css );
	$css = str_replace( array( ',.thrv_heading', ',.thrv_text_element' ), array(
		',.tve-leads-conversion-object .thrv_heading',
		',.tve-leads-conversion-object .thrv_text_element',
	), $css );

	return $css;
}

/**
 * Format a date using a specific format, or the one setup from general settings
 *
 * @param string $date_string the date
 * @param null|string $format format. if not passed, it will take the default WordPress settings
 *
 * @return string the formatted date
 */
function tve_leads_format_date( $date_string, $format = null ) {
	if ( ! $format ) {
		$format = get_option( 'date_format' ) . ' ' . get_option( 'time_format' );
		if ( ! trim( $format ) ) {
			$format = 'd M, Y G:i'; // a default format
		}
	}

	return mysql2date( $format, $date_string );
}

/**
 * Prepare placeholder for ajax displayed forms
 *
 * @param      $type
 * @param null $control_variation
 *
 * @return string
 */
function tve_leads_get_form_placeholder( $type, $control_variation = null ) {

	$o_type = $type;
	if ( $type === 'before_widget' ) {
		$type = 'widget';
	}
	if ( empty( $GLOBALS['tve_lead_forms'][ $type ]['form_type'] ) && $control_variation === null ) {
		$placeholder = sprintf( '<span style="display:none" class="tl-placeholder-f-type-%s"></span>', $type );
	} else {
		$form_class = "tl-placeholder-f-type-$type";

		if ( $control_variation === null ) {
			foreach ( $GLOBALS['tve_lead_forms'][ $type ]['form_type']->variations as $variation ) {
				if ( $variation['is_control'] ) {
					/* read form heights from the control in case we run a test */
					$control_variation = $variation;
				}
			}
		}

		$placeholder_content = '';

		if (
			! empty( $control_variation['tcb_fields'][ TVE_LEADS_FIELD_FORM_HEIGHT ] ) &&
			( isset( $control_variation['trigger'] ) && in_array( $control_variation['trigger'], array(
					'page_load',
					'viewport'
				) ) ) &&
			! is_editor_page_raw() && /* don't show placeholder inside editor */
			( $type === 'post_footer' || $type === 'widget' || strpos( $type, 'shortcode_' ) === 0 )
		) {
			$form_style = '';

			foreach ( $control_variation['tcb_fields']['form-height'] as $device => $height ) {
				$form_style .= "--tl-form-height-{$device}:{$height}px;";
			}
			$form_class .= ' tl-preload-form';
			/* skeleton placeholder boxes */
			$placeholder_content = '<span></span>';
		} else {
			$form_style = 'display:none';
		}

		switch ( $o_type ) {
			case 'before_widget':
				$placeholder = sprintf( '<div style="%s" class="tl-widget-container %s">%s', $form_style, $form_class, $placeholder_content );
				break;

			default:
				$placeholder = sprintf( '<span style="%s" class="%s">%s</span>', $form_style, $form_class, $placeholder_content );
		}
	}

	return $placeholder;
}

/**
 * Get a generated thumbnail
 *
 * @param $design_id
 *
 * @return string|null
 */
function tl_get_design_thumbnail( $design_id ) {
	$url           = null;
	$wp_upload_dir = wp_get_upload_dir();
	$filename      = $design_id . '.png';
	$filename      = sanitize_file_name( $filename );
	$file_path     = $wp_upload_dir['basedir'] . '/thrive-leads/thumbnails/' . $filename;

	if ( is_file( $file_path ) ) {
		$url = $wp_upload_dir['baseurl'] . '/thrive-leads/thumbnails/' . $filename;
	}

	return $url;
}