403Webshell
Server IP : 65.109.86.83  /  Your IP : 216.73.217.65
Web Server : nginx/1.14.1
System : Linux libra 4.18.0-553.51.1.el8_10.x86_64 #1 SMP Wed Apr 30 20:24:04 UTC 2025 x86_64
User : root ( 0)
PHP Version : 8.3.31
Disable Function : exec,passthru,shell_exec,system,proc_open,popen,parse_ini_file,show_source
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /var/www/html/wp-content/plugins/thrive-quiz-builder/tcb/inc/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/html/wp-content/plugins/thrive-quiz-builder/tcb/inc/compat.php
<?php
/**
 * this file handles known compatibility issues with other plugins / themes
 */

/**
 * general admin conflict notifications
 */
add_action( 'admin_notices', 'tve_admin_notices' );

/**
 * filter for including wp affiliates scripts and styles if the shortcode is found in TCB content
 */
add_filter( 'affwp_force_frontend_scripts', 'tve_compat_wp_affiliate_scripts' );

add_filter( 'fp5_filter_has_shortcode', 'tve_compat_flowplayer5_has_shortcode' );

/**
 *
 * Compatibility with S2Member plugin - it fails to include CSS / JS on pages / posts created with TCB
 */
add_filter( 'ws_plugin__s2member_lazy_load_css_js', '__return_true' );

/**
 *
 * Compatibility with Survey Funnel plugin - it fails to include CSS / JS on pages / posts created with TCB
 */
if ( function_exists( 'is_plugin_active' ) && is_plugin_active( 'surveyfunnel/survey_funnel.php' ) ) {
	add_action( 'wp_enqueue_scripts', 'tve_compat_survey_funnel', 11 );
}

/**
 * Compatibility with Total Themes & Advanced Custom Fields
 */
if ( isset( $_GET['tve'] ) && 'true' === $_GET['tve'] ) {
	add_filter( 'wpex_toggle_bar_active', '__return_false' );
	add_filter( 'acf/settings/enqueue_select2', '__return_false' );
}

/**
 * Checks if a post / page has a shortcode in TCB content
 *
 * @param string                  $shortcode
 * @param int|string|null|WP_Post $post_id
 * @param bool                    $use_wp_shortcode_check whether or not to use has_shortcode() or strpos
 *
 * @return bool
 */
function tve_compat_has_shortcode( $shortcode, $post_id = null, $use_wp_shortcode_check = false ) {
	if ( is_null( $post_id ) ) {
		$post_id = get_the_ID();
	} else {
		$post_id = is_a( $post_id, 'WP_Post' ) ? $post_id->ID : $post_id;
	}
	$content = tve_get_post_meta( $post_id, 'tve_updated_post' );
	if ( ! $use_wp_shortcode_check ) {
		return strpos( $content, $shortcode ) !== false;
	}
	if ( $post_id ) {
		return has_shortcode( $content, '[' . str_replace( [ '[', ']' ], '', $shortcode ) . ']' );
	}

	return false;
}

/**
 * display any possible conflicts with other plugins / themes as error notification in the admin panel
 */
function tve_admin_notices() {
	$has_wp_seo_conflict = tve_has_wordpress_seo_conflict();

	if ( $has_wp_seo_conflict ) {
		$link = sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=wpseo_advanced&tab=permalinks' ), __( 'WordPress SEO settings', 'thrive-cb' ) );
		$message
		      = sprintf( __( 'Thrive Architect and Thrive Leads cannot work with the current configuration of WordPress SEO. Please go to %s and disable the %s"Redirect ugly URL\'s to clean permalinks"%s option',
			'thrive-cb' ), $link, '<strong>', '</strong>' );
		echo sprintf( '<div class="error"><p>%s</p></div>', esc_html( $message ) );
	}
}

/**
 * check if the user has a known "Coming soon" or "Membership protection" plugin installed
 * our landing pages seem to overwrite their "Coming soon" functionality
 * this would check for any coming soon plugins that use the template_redirect hook
 */
function tve_hooked_in_template_redirect() {
	include_once ABSPATH . '/wp-admin/includes/plugin.php';

	$hooked_in_template_redirect = [
		'wishlist-member/wpm.php',
		'ultimate-coming-soon-page/ultimate-coming-soon-page.php',
		'easy-pie-coming-soon/easy-pie-coming-soon.php',
		'coming-soon-page/coming_soon.php',
		'cc-coming-soon/cc-coming-soon.php',
		'wordpress-seo/wp-seo.php',
		'wordpress-seo-premium/wp-seo-premium.php',
		'membermouse/index.php',
		'ultimate-member/index.php',
		'woocommerce/woocommerce.php',
		'maintenance/maintenance.php',
		'simply-schedule-appointments/simply-schedule-appointments.php',
		'borlabs-cookie/borlabs-cookie.php',
	];

	foreach ( $hooked_in_template_redirect as $plugin ) {
		if ( is_plugin_active( $plugin ) ) {
			return true;
		}
	}

	/**
	 * SUPP-1749 if the domain mapping plugin is installed, Landing Pages will not be redirected to the corresponding domain. This ensures that the redirection will take place
	 */
	if ( is_plugin_active( 'wordpress-mu-domain-mapping/domain_mapping.php' ) ) {
		return true;
	}

	return false;
}

/**
 * Check if the user has the WordPress SEO plugin installed and the "Redirect to clean URLs" option checked
 *
 * @return bool
 */
function tve_has_wordpress_seo_conflict() {
	return is_plugin_active( 'wordpress-seo/wp-seo.php' ) && ( $wpseo_options = get_option( 'wpseo_permalinks' ) ) && ! empty( $wpseo_options['cleanpermalinks'] );
}


/**
 * called inside the 'init' hook
 *
 * this is used to fix any plugin conflicts that might appear
 *
 * 1. YARPP - we need to disable their the_content filter when in editing mode,
 *      - they apply the_content filter automatically when querying the database for related posts
 *      - they have a filter for blacklisting a filters the_content, but that does not solve the issue - wp will never call our filter anymore
 *
 * 2. TheRetailer theme - they remove the WP media js files for some reason (??)
 *
 * 3. Enfold theme - tinymce buttons causing errors (localization)
 */
function tve_fix_plugin_conflicts() {

	global $yarpp;
	if ( is_editor_page_raw() ) {
		if ( $yarpp ) {
			remove_filter( 'the_content', [ $yarpp, 'the_content' ], 1200 );
		}
		/**
		 * Theretailer theme deregisters the mediaelement for some reason
		 */
		if ( function_exists( 'theretailer_deregister' ) ) {
			remove_action( 'wp_enqueue_scripts', 'theretailer_deregister' );
		}

		/**
		 * Removed Last Modified Plugin content from TAR Editor page
		 *
		 * https://wordpress.org/plugins/wp-last-modified-info/
		 */
		if ( function_exists( 'lmt_print_last_modified_info_post' ) ) {
			remove_filter( 'the_content', 'lmt_print_last_modified_info_post' );
		}

		/**
		 * Removed Last Modified Plugin content from TAR Editor pages
		 *
		 * https://wordpress.org/plugins/wp-last-modified-info/
		 */
		if ( function_exists( 'lmt_print_last_modified_info_page' ) ) {
			remove_filter( 'the_content', 'lmt_print_last_modified_info_page' );
		}
	}
}

/* hook to fix various conflicts that might appear. first one: YARPP */
add_action( 'init', 'tve_fix_plugin_conflicts', PHP_INT_MAX );

/**
 * Called on init - priority 11
 *
 */
function tve_compat_right_after_init() {

	if ( is_admin() ) {
		/**
		 * EventEspresso plugin hijacks the admin UI for editing posts - causing TAr to not load for a Event post type
		 * They overwrite the default WordPress post.php?post=3432&action=edit with a custom page & implementation
		 */
		if ( function_exists( 'espresso_version' ) ) {
			/**
			 * Identify TAr URL using:
			 * page => espresso_events / espresso_venues
			 * action => architect
			 * post => numeric
			 */
			$is_espresso_page  = ! empty( $_REQUEST['page'] ) && strpos( $_REQUEST['page'], 'espresso_' ) === 0; //phpcs:ignore
			$is_architect_link = ! empty( $_REQUEST['tve'] ) && ! empty( $_REQUEST['action'] ) && $_REQUEST['action'] === 'architect'; //phpcs:ignore
			$is_post           = ! empty( $_REQUEST['post'] ) && is_numeric( $_REQUEST['post'] );

			if ( $is_espresso_page && $is_architect_link && $is_post ) {
				$GLOBALS['post'] = get_post( absint( $_REQUEST['post'] ) );
				do_action( 'post_action_architect' );
			}
		}
	}
}

/* hook into init at priority 11 to allow fixing some conflicts with 3rd party plugins */
add_action( 'init', 'tve_compat_right_after_init', 11 );

/**
 * apply some of currently known 3rd party filters to the TCB saved_content
 *
 * Digital Access Pass: dap_*
 *
 * @param string $content
 *
 * @return string
 */
function tve_compat_content_filters_before_shortcode( $content ) {
	$content = tcb_dap_shortcode_in_content( $content );

	/**
	 * s3 amazon links - they don't handle shortcodes in the "WP" way
	 */
	if ( function_exists( 's3mv' ) ) {
		$content = s3mv( $content );
	}

	if ( function_exists( 'ec' ) ) {
		$content = ec( $content );
	}

	/**
	 * A3 Lazy Load plugin
	 * This plugin adds a filter on "the_content" inside of "wp" action callback -> the same as TCB does
	 * Its "the_content" filter callback is executed first because of its name -> A3
	 * We call its filter implementation on TCB content
	 */
	if ( class_exists( 'A3_Lazy_Load' ) && method_exists( 'A3_Lazy_Load', 'filter_content_images' ) ) {
		global $a3_lazy_load_global_settings;
		if ( $a3_lazy_load_global_settings['a3l_apply_image_to_content'] ) {
			$content = A3_Lazy_Load::filter_content_images( $content );
		}
	}

	/**
	 * EduSearch plugin not handling shortcodes in the "WP" way
	 * they search for [edu-search] strings and process those
	 */
	if ( function_exists( 'esn_filter_content' ) ) {
		$content = esn_filter_content( $content );
	}

	/**
	 * Paid Memberships pro has a really strange way of defining shortcodes
	 */
	if ( function_exists( 'pmpro_wp' ) ) {
		global $post;
		$o_content          = $post->post_content;
		$post->post_content = $content;
		pmpro_wp();
		$post->post_content = $o_content;
	}

	/**
	 * QuickLATEX plugin compatibility.
	 */
	if ( function_exists( 'quicklatex_parser' ) ) {
		$content = quicklatex_parser( $content );
	}

	/**
	 * if getting the excerpt, remove all shortcodes.
	 *
	 * @see wp_trim_excerpt()
	 */
	if ( doing_filter( 'get_the_excerpt' ) ) {
		$content = strip_shortcodes( $content );
	}

	/**
	 * SUPP-6382 Fixes a conflict with the SyntaxHighlighter plugin
	 */
	if ( class_exists( 'SyntaxHighlighter', false ) ) {
		/** @var SyntaxHighlighter $SyntaxHighlighter */
		// phpcs:disable
		global $SyntaxHighlighter;
		if ( ! empty( $SyntaxHighlighter ) && method_exists( $SyntaxHighlighter, 'parse_shortcodes' ) ) {
			$content = $SyntaxHighlighter->parse_shortcodes( $content );
		}
		// phpcs:enable
	}

	return $content;
}


/**
 * apply some of currently known 3rd party filters to the TCB saved_content - after do_shortcode is being called
 *
 * FormMaker: Form_maker_fornt_end_main
 *
 * @param string $content
 *
 * @return string
 */
function tve_compat_content_filters_after_shortcode( $content ) {
	/**
	 * FormMaker does not use WP shortcode as they should
	 */
	if ( function_exists( 'Form_maker_fornt_end_main' ) ) {
		$content = Form_maker_fornt_end_main( $content );
	}

	/**
	 * in case they will ever correct the function name
	 */
	if ( function_exists( 'Form_maker_front_end_main' ) ) {
		$content = Form_maker_front_end_main( $content );
	}

	/* Compat with TOC Plus plugin
	*/
	if ( class_exists( 'toc', false ) ) {
		global $tic;
		if ( ! empty( $tic ) && method_exists( $tic, 'the_content' ) ) {
			$content = $tic->the_content( $content );
		}
	}

	return $content;
}

/**
 * check if we are on a page / post and there is a [affiliate_area] shortcode in TCB content
 *
 * @param bool $bool current value
 *
 * @return bool
 */
function tve_compat_wp_affiliate_scripts( $bool ) {
	if ( $bool || ! is_singular() || is_editor_page() ) {
		return $bool;
	}

	$tve_saved_content = tve_get_post_meta( get_the_ID(), 'tve_updated_post' );

	return has_shortcode( $tve_saved_content, 'affiliate_area' ) || has_shortcode( $tve_saved_content, 'affiliate_creatives' );

}

/**
 * checks if the current post is protected by a membership plugin and cannot be displayed
 *
 * @return bool
 */
function tve_membership_plugin_can_display_content() {

	global $post;

	/**
	 * we should not apply this during the_excerpt filter
	 */
	if ( doing_filter( 'get_the_excerpt' ) ) {
		return true;
	}

	/**
	 *
	 * WooCommerce Membership compatibility - hide TCB content for non-members
	 */
	if ( function_exists( 'wc_memberships_is_post_content_restricted' ) && wc_memberships_is_post_content_restricted() && ! doing_filter( 'get_the_excerpt' ) ) {
		if ( ! current_user_can( 'wc_memberships_view_restricted_post_content', $post->ID ) || ! current_user_can( 'wc_memberships_view_delayed_post_content', $post->ID ) ) {
			return false;
		}
	}

	/**
	 * Simple Membership plugin compatibility - hide TCB content for non members
	 */
	if ( class_exists( 'BAccessControl' ) ) {
		$control = SwpmAccessControl::get_instance();

		if ( ! $control->can_i_read_post( $post ) ) {
			return false;
		}
	}

	/**
	 * Paid Memberships Pro plugin
	 */
	if ( function_exists( 'pmpro_has_membership_access' ) ) {
		$has_access = pmpro_has_membership_access();
		if ( ! $has_access ) {
			return false;
		}
	}

	/**
	 * MemberPress plugin compatibility - hide TCB content for protected posts/pages
	 */
	$uri = ! empty( $_SERVER['REQUEST_URI'] ) ? sanitize_text_field( $_SERVER['REQUEST_URI'] ) : '';
	if ( class_exists( 'MeprRule' ) && ( MeprRule::is_locked( $post ) || MeprRule::is_uri_locked( $uri ) ) ) {
		return false;
	}

	/**
	 * Filter hook that allows plugins to hook into TCB and prevent TCB content from being displayed if e.g. the user does not have access to this content
	 *
	 * @param bool $can_display
	 *
	 * @since 1.200.3
	 *
	 */
	return apply_filters( 'tcb_can_display_content', true );

}

/**
 * compatibility with flowplayer 5 shortcodes
 *
 * @param bool $has_shortcode
 */
function tve_compat_flowplayer5_has_shortcode( $has_shortcode ) {
	if ( is_editor_page_raw() ) {
		return $has_shortcode;
	}

	return tve_compat_has_shortcode( 'flowplayer' );
}

/**
 * compatibility with Survey Funnel
 */
function tve_compat_survey_funnel() {
	global $is_survey_page, $post;
	if ( $is_survey_page === true ) {
		return;
	}
	$content_updated = tve_get_post_meta( $post->ID, 'tve_updated_post' );

	if ( stristr( $content_updated, '[survey_funnel' ) ) {
		$is_survey_page = true;
		wp_script_is( 'survey_funnel_ajax' ) || wp_enqueue_script( 'survey_funnel_ajax', SF_PLUGIN_URL . '/js/ajax.js', [ 'jquery' ], '1.0', false );
		wp_script_is( 'survey_funnel' ) || wp_enqueue_script( 'survey_funnel', SF_PLUGIN_URL . '/js/survey_funnel.js', [ 'jquery' ], '1.0', false );
		wp_script_is( 'survey_funnel_fancybox' )
		|| wp_enqueue_script( 'survey_funnel_fancybox', SF_PLUGIN_URL . '/jquery/fancyBox-2.1.5/source/jquery.fancybox.pack.js', [ 'jquery' ], '1.0', false );

		wp_style_is( 'survey_funnel_styles' ) || wp_enqueue_style( 'survey_funnel_styles', SF_PLUGIN_URL . '/css/styles.css' );
		wp_style_is( 'survey_funnel_client_styles' ) || wp_enqueue_style( 'survey_funnel_client_styles', SF_PLUGIN_URL . '/css/survey_funnel.css' );
		wp_style_is( 'survey_funnel_client_styles_fancybox' )
		|| wp_enqueue_style( 'survey_funnel_client_styles_fancybox', SF_PLUGIN_URL . '/jquery/fancyBox-2.1.5/source/jquery.fancybox.css' );
	}

}

/**
 * Fix Thrive Architect conflicts before footer
 */
function tve_fix_page_conflicts_before_footer() {

	/**
	 *  For SlickQuiz plugin
	 */
	if ( class_exists( 'SlickQuiz' ) ) {

		remove_filter( 'the_content', 'tve_editor_content', 10 );

		if ( is_editor_page() ) {
			remove_filter( 'the_content', 'tve_editor_content', PHP_INT_MAX );
		}
	}
}

add_action( 'wp_footer', 'tve_fix_page_conflicts_before_footer', 2000 );

/**
 * Remove the content filter for sensei plugin
 */
function tve_wc_sensei_no_content_filter() {

	if ( class_exists( 'Sensei_Course' ) ) {

		if ( ! is_editor_page() ) {
			remove_filter( 'the_content', 'tve_editor_content', 10 );
		}
	}

}

add_action( 'wc_sensei_no_content_filter', 'tve_wc_sensei_no_content_filter', 2000 );

/**
 * Paid Memberships pro has a really strange way of defining shortcodes
 */
if ( function_exists( 'pmpro_wp' ) ) {
	function tve_pmpro_shortcodes() {
		global $post;
		if ( ! empty( $post ) ) {
			$tve_content                  = tve_get_post_meta( $post->ID, 'tve_updated_post' );
			$GLOBALS['tve_pmp_o_content'] = $post->post_content;
			$post->post_content           = $tve_content . $post->post_content;
		}
	}

	function tve_pmpro_shortcodes_cleanup() {
		global $post;
		if ( isset( $GLOBALS['tve_pmp_o_content'] ) ) {
			$post->post_content = $GLOBALS['tve_pmp_o_content'];
		}
	}

	add_action( 'wp', 'tve_pmpro_shortcodes', 0 );
	add_action( 'wp', 'tve_pmpro_shortcodes_cleanup', 100 );
}

/**
 * Event Manager compatibility
 */
function tve_em_remove_content_filter() {
	global $EM_Event;

	if ( ! empty( $EM_Event ) && get_post_type() === 'event' && is_singular() ) {
		remove_filter( 'the_content', 'tve_editor_content', 10 );
	}
}

add_action( 'wp', 'tve_em_remove_content_filter', 2000 );

function tve_em_event_output_placeholder( $replace, $em_event, $full_result, $target ) {
	if ( $full_result == '#_EVENTNOTES' ) {
		$replace = tve_editor_content( tve_clean_wp_editor_content( $em_event->post_content ) );
		$replace = do_shortcode( $replace );
	}

	return $replace;
}

add_filter( 'em_event_output_placeholder', 'tve_em_event_output_placeholder', 10, 4 );

/**
 * Solves a problem with shortcodes that span over multiple elements (e.g. conditional shortcodes).
 * Example:
 * [has_access] <div class="thrv-button">etc</div> [/has_access] - this would only show the button if somebody has access, or only show it after a javascript gets executed
 *
 * The problem is that when adding the shortcode using a test element, this turns into:
 * <div class="thrv_text_element"><p>[has_access]</p></div><div class="thrv-button">etc</div><div class="thrv_text_element"><p>[/has_access]</p></div>
 *
 * At this point, the content inside the shortcode is actually an invalid html. The shortcode function will receive this:
 * function has_access( $attr, $content ) {
 *      // $content = '</p></div><div class="thrv-button">etc</div><div class="thrv_text_element"><p>'
 * }
 *
 * This function will correct the $content, transforming it into:
 * <div class="thrv-button">etc</div><div class="thrv_text_element"><p></p></div>
 *
 * @param string $output
 * @param string $tag
 * @param array  $attr
 * @param array  $m
 *
 * @return string
 */
function tcb_ensure_shortcode_html_structure( $output, $tag, $attr, $m ) {

	if ( isset( $m[5] ) && ! empty( $m[5] ) && strpos( $output, 'thrv_text_element' ) !== false ) {
		$content     = $m[5];
		$closed_tags = '#^(</p>|</div>)#';
		while ( preg_match( $closed_tags, $content, $match ) === 1 ) {
			$content = substr( $content, strlen( $match[1] ) ) . $match[1];
		}
		$output = str_replace( $m[5], $content, $output );
	}

	return $output;
}

add_filter( 'do_shortcode_tag', 'tcb_ensure_shortcode_html_structure', 10, 4 );

/**
 * Re-Add template_include filters after remove_all_filters( 'template_include' );
 */
function tve_compat_re_add_template_include_filters() {
	if ( ! function_exists( 'is_plugin_active' ) ) {
		include_once( ABSPATH . 'wp-admin/includes/plugin.php' );
	}

	if ( is_plugin_active( 'maintenance/maintenance.php' ) ) {
		global $mtnc;
		if ( ! empty( $mtnc ) ) {
			add_action( 'template_include', [ $mtnc, 'mtnc_template_include' ], 999999 );
		}
	}
}

/**
 * Compat Function that contains compatibility fixes for Thrive Architect On plugins_loaded hook
 */
function tve_compat_plugins_loaded_hook() {
	global $sitepress;
	if ( ! empty( $sitepress ) && ! empty( $_REQUEST[ TVE_EDITOR_FLAG ] ) ) {
		remove_action( 'init', [ $sitepress, 'js_load' ], 2 );
	}
}

/**
 * Digital Access Pass %% links in the content, e.g.: %%LOGIN_FORM%%
 *
 * @param string $content content with possible shortcodes
 *
 * @return string updated content
 */
function tcb_dap_shortcode_in_content( $content ) {
	if ( function_exists( 'dap_login' ) ) {
		$content = dap_login( $content );
	}

	if ( function_exists( 'dap_personalize' ) ) {
		$content = dap_personalize( $content );
	}

	if ( function_exists( 'dap_personalize_error' ) ) {
		$content = dap_personalize_error( $content );
	}

	if ( function_exists( 'dap_product_links' ) ) {
		$content = dap_product_links( $content );
	}

	return $content;
}

add_action( 'plugins_loaded', 'tve_compat_plugins_loaded_hook' );


/**
 * Added hooks to ensure compatibility between TAR and WP Last Modified Info plugin
 */
add_filter( 'wplmi_display_priority_post', 'tve_wp_last_modified_info' );
add_filter( 'wplmi_display_priority_page', 'tve_wp_last_modified_info' );

/**
 * Compatibility with WP Last Modified Info plugin
 *
 * WP Market:
 * https://wordpress.org/plugins/wp-last-modified-info/
 *
 * GIT Source Code:
 * https://github.com/iamsayan/wp-last-modified-info
 *
 * @param int $hook_priority
 *
 * @return int
 */
function tve_wp_last_modified_info( $hook_priority = 10 ) {

	if ( ! is_editor_page_raw() ) {
		$hook_priority = PHP_INT_MAX;
	}

	return $hook_priority;
}

/**
 * Compatibility with Imagify plugin
 */
add_filter( 'imagify_allow_picture_tags_for_webp', 'tve_prevent_imagify_webp' );
/**
 * Don’t use `<picture>` tags when displaying the site in the editor’s iframe.
 *
 * @param bool $allow True to allow the use of <picture> tags (default). False to prevent their use.
 *
 * @return bool
 */
function tve_prevent_imagify_webp( $allow ) {
	return ! is_editor_page();
}


/**
 * WP-Rocket Compatibility - exclude files from caching
 */
add_filter( 'rocket_exclude_css', 'tve_rocket_exclude_css' );
add_filter( 'rocket_exclude_js', 'tve_rocket_exclude_js' );

/**
 * Exclude the js dist folder from caching and minify-ing
 *
 * @param $excluded_js
 *
 * @return array
 */
function tve_rocket_exclude_js( $excluded_js ) {

	$excluded_js[] = str_replace( home_url(), '', plugins_url( '/thrive-visual-editor/editor/js/dist' ) ) . '/(.*).js';

	return $excluded_js;
}

/**
 * Exclude the css files from caching and minify-ing
 *
 * @param $excluded_css
 *
 * @return array
 */
function tve_rocket_exclude_css( $excluded_css ) {

	$excluded_css[] = str_replace( home_url(), '', plugins_url( '/thrive-visual-editor/editor/css' ) ) . '/(.*).css';

	return $excluded_css;
}

/**
 * Compatibility with one signal push notification
 *
 * We don't need their scripts inside the editor
 * Added in wp_head because there is the place where they register their scripts
 */
add_action( 'wp_head', function () {
	if ( is_editor_page_raw() ) {
		wp_deregister_script( 'remote_sdk' );
		wp_dequeue_script( 'remote_sdk' );
	}
}, PHP_INT_MAX );

/**
 * Compatibility with:
 *  -> Oliver POS - A WooCommerce Point of Sale (POS)
 *  -> Quiz and Survey Master
 *
 * We don't need their styles inside the editor
 * Added in admin_enqueue_scripts because there is the place where they register their styles
 */
add_action( 'admin_enqueue_scripts', function () {
	if ( is_editor_page_raw() ) {
		wp_deregister_style( 'oliver-pos-feedback-css' );
		wp_dequeue_style( 'oliver-pos-feedback-css' );

		wp_deregister_style( 'qsm_admin_style' );
		wp_dequeue_style( 'qsm_admin_style' );
	}
}, PHP_INT_MAX );

/**
 * Compatibility with Rank Math
 *
 * We don't need their scripts inside the editor
 * Added in wp_enqueue_scripts because there is the place where they register their scripts
 */
add_action( 'wp_enqueue_scripts', function () {
	if ( is_editor_page_raw() ) {
		wp_deregister_script( 'rank-math-analytics-stats' );
		wp_dequeue_script( 'rank-math-analytics-stats' );
	}
}, PHP_INT_MAX );

/**
 * Fixes a compatibility issue with optimole that causes src attribute replacement to not function correctly on landing pages
 */
add_action( 'tcb_landing_page_template_redirect', function () {
	if ( ! is_editor_page() && did_action( 'optml_replacer_setup' ) ) {
		do_action( 'optml_after_setup' );
	}
} );

/**
 * Fixes compatibility with optimole that causes the Symbols not to render in the Globals dashboard
 */
add_filter( 'optml_should_replace_page', function ( $value ) {
	if ( ! empty( $_REQUEST['optimole_skip_processing'] ) ) {
		$value = true;
	}

	return $value;
} );

/**
 * Lazyload from optimole conflicts with autoplay videos
 */
add_filter( 'optml_iframe_lazyload_flags', function ( $strings ) {
	$strings [] = 'autoplay'; // disable optimole lazyload for autoplay videos
	$strings [] = 'autopause=0'; // vimeo uses autopause instead of autoplay, because why not

	return $strings;
} );

/**
 * Filter to add plugins to the TOC list.
 *
 * @param array TOC plugins.
 */
add_filter( 'rank_math/researches/toc_plugins', function ( $toc_plugins ) {
	$toc_plugins['thrive-visual-editor/thrive-visual-editor.php'] = 'Thrive Architect';

	return $toc_plugins;
} );

/**
 * Don't load metrics files on the editor page
 */
add_filter( 'tve_dash_metrics_should_enqueue', function ( $should_enqueue ) {
	if ( is_editor_page_raw( true ) || TCB_Editor()->is_main_frame() ) {
		$should_enqueue = false;
	}

	return $should_enqueue;
} );

/**
 * Fixes a custom menu regression that added these classes to all saved menus
 */
add_filter( 'tve_thrive_shortcodes', static function ( $content ) {
	return str_replace( ' tve-custom-menu-switch-icon-tablet tve-custom-menu-switch-icon-mobile', '', $content );
} );

/**
 * Do not generate sitemap for symbols
 */
add_filter( 'tve_dash_yoast_sitemap_exclude_post_types', static function ( $post_types ) {
	$post_types[] = TCB_Symbols_Post_Type::SYMBOL_POST_TYPE;

	return $post_types;
} );

/**
 * Do not generate sitemap for symbols taxonomy
 */
add_filter( 'tve_dash_yoast_sitemap_exclude_taxonomies', static function ( $taxonomies ) {
	$taxonomies[] = TCB_Symbols_Taxonomy::SYMBOLS_TAXONOMY;

	return $taxonomies;
} );

/**
 * Replace page & post identifiers
 *
 */
add_action( 'after_thrive_clone_item', static function ( $new_id, $old_id ) {
	$css = tve_get_post_meta( $new_id, 'tve_custom_css' );

	$css = str_replace( [ "page-id-$old_id", "postid-$old_id" ], [ "page-id-$new_id", "postid-$new_id" ], $css );

	tve_update_post_meta( $new_id, 'tve_custom_css', $css );
}, 10, 2 );

/**
 * Modify the page, header/footer, and template sections content so that Digital Access Pass shortcodes are rendered
 */
add_filter( 'thrive_template_structure', 'tcb_dap_shortcode_in_content' );
add_filter( 'thrive_template_header_content', 'tcb_dap_shortcode_in_content' );
add_filter( 'thrive_template_footer_content', 'tcb_dap_shortcode_in_content' );

add_action( 'current_screen', 'tcb_current_screen' );

/**
 * Some pages don't have a title, so we need to set it manually
 */
function tcb_current_screen() {
	$screen = tve_get_current_screen_key();
	global $title;
	if ( $screen && empty( $title ) && ( strpos( $screen, 'tcb_' ) !== false || strpos( $screen, 'tve_' ) !== false ) ) {
		$title = 'Thrive Architect';
	}
}

/**
 * Returns an array containing shortcode tags, this will be used to whitelist theses shortcodes when saving the plain content
 *
 * @return mixed|void
 */
function tcb_plain_content_whitelisted_shortcodes() {
	return apply_filters( 'tcb_plain_content_whitelisted_shortcodes', [ 'mepr-membership-registration-form' ] );
}

/**
 * Sometimes we do not want to do shortcodes while saving the playn text content(the one added in post content)
 * The reason we need to do this for MemberPress is because they only load the shortcode content IF it's shortcode tag is present in post content,
 * so we cannot do_shortcode on it on save because the shortcode tag will be replaced
 */
/**
 * In the actions bellow we remove the whitelisted shortcodes from the $shortcode_tags global(so they wont be computed on do_shortcode),
 * and restore the $shortcode_tags after the do_shortcode
 */
add_action( 'tcb_plain_content_do_shortcode_before', function () {
	global $shortcode_tags, $tcb_whitelisted_plain_content_shortcodes;

	if ( ! is_array( $tcb_whitelisted_plain_content_shortcodes ) ) {
		$tcb_whitelisted_plain_content_shortcodes = [];
	}

	$whitelisted_shortcodes = tcb_plain_content_whitelisted_shortcodes();

	foreach ( $whitelisted_shortcodes as $tag ) {
		if ( isset( $shortcode_tags[ $tag ] ) ) {
			$tcb_whitelisted_plain_content_shortcodes[ $tag ] = $shortcode_tags[ $tag ];

			unset( $shortcode_tags[ $tag ] );
		}
	}
} );

add_action( 'tcb_plain_content_do_shortcode_after', function () {
	global $shortcode_tags, $tcb_whitelisted_plain_content_shortcodes;

	if ( ! is_array( $tcb_whitelisted_plain_content_shortcodes ) ) {
		$tcb_whitelisted_plain_content_shortcodes = [];
	}

	$whitelisted_shortcodes = tcb_plain_content_whitelisted_shortcodes();

	foreach ( $whitelisted_shortcodes as $tag ) {
		if ( isset( $tcb_whitelisted_plain_content_shortcodes[ $tag ] ) ) {
			$shortcode_tags[ $tag ] = $tcb_whitelisted_plain_content_shortcodes[ $tag ];

			unset( $tcb_whitelisted_plain_content_shortcodes[ $tag ] );
		}
	}
} );

/**
 * Prevents the rendering of the specified shortcodes in the TAR editor to prevent rendering issues.
 */
/**
 * Prevents the rendering of the specified shortcodes in the TAR editor to prevent rendering issues.
 *
 * @param string $output The shortcode output. Default empty.
 * @param string $tag    The shortcode name.
 * @param array  $attr   The shortcode attributes array.
 * @param array  $m      The regex matches array.
 *
 * @return string The modified or original shortcode output.
 */
function tve_compat_pre_do_shortcode_tag( $output, $tag, $attr, $m ) {
	// Add shortcodes to the blacklist to prevent them from being rendered in the TAR editor.
	$blacklist = apply_filters( 'tcb_editor_shortcode_blacklist', array( 'fluentform' ) );

	// If the shortcode is in the blacklist and we are in the editor, output the shortcode itself.
	if ( 
		in_array( $tag, $blacklist, true ) && 
		TCB_Utils::in_editor_render( true ) 
	) {
		// Return the original shortcode match to prevent rendering in the TAR editor.
		return $m[0];
	}

	return $output;
}

add_filter( 'pre_do_shortcode_tag', 'tve_compat_pre_do_shortcode_tag', 10, 4 );

/**
 * Decode HTML entities in third-party shortcode attributes.
 * 
 * Thrive Architect HTML-encodes content when saving, which breaks third-party shortcodes
 * that use special characters in their attributes (e.g., MemberMouse uses & in conditions).
 * 
 * This function intercepts shortcode execution, decodes HTML entities in attributes,
 * and calls the shortcode callback directly with the corrected attributes.
 * 
 * @param string $output The shortcode output. Default empty.
 * @param string $tag    The shortcode name.
 * @param array  $attr   The shortcode attributes array.
 * @param array  $m      The regex matches array.
 *
 * @return string The modified or original shortcode output.
 */
function tve_compat_decode_shortcode_entities( $output, $tag, $attr, $m ) {
	/**
	 * Filter: List of exact shortcode names that need HTML entity decoding.
	 * 
	 * @param array $shortcodes Array of exact shortcode names to process.
	 */
	$shortcodes_to_decode = apply_filters( 'tcb_shortcodes_decode_entities', array(
		'MM_Member_Decision', // MemberMouse conditional display
	) );

	// Only process if this shortcode is in our whitelist
	if ( ! in_array( $tag, $shortcodes_to_decode, true ) ) {
		return $output;
	}

	// Validate attributes
	if ( ! is_array( $attr ) || empty( $attr ) ) {
		return $output;
	}

	// Decode attributes and check if any decoding was needed (single loop)
	$needs_decoding = false;
	$decoded_attr = array();

	foreach ( $attr as $key => $value ) {
		if ( ! is_string( $value ) ) {
			$decoded_attr[ $key ] = $value;
			continue;
		}

		// Decode HTML entities
		$decoded_value = html_entity_decode( $value, ENT_QUOTES | ENT_HTML5, 'UTF-8' );

		/**
		 * Security: Strip all HTML tags from decoded attributes.
		 * Shortcode attributes should not contain HTML - this prevents XSS attacks
		 * via encoded malicious content (e.g., &lt;script&gt; becoming <script>).
		 * 
		 * This is much more reliable than pattern matching and is WordPress-native.
		 */
		$decoded_value = wp_strip_all_tags( $decoded_value );

		$decoded_attr[ $key ] = $decoded_value;

		// Track if any decoding occurred
		if ( $decoded_value !== $value ) {
			$needs_decoding = true;
		}
	}

	// If no decoding was needed, return without processing
	if ( ! $needs_decoding ) {
		return $output;
	}

	// Get the shortcode callback
	global $shortcode_tags;

	if ( isset( $shortcode_tags[ $tag ] ) && is_callable( $shortcode_tags[ $tag ] ) ) {
		// Get content between shortcode tags (if any)
		$content = isset( $m[5] ) ? $m[5] : null;
		
		// Call the shortcode with decoded attributes
		return call_user_func( $shortcode_tags[ $tag ], $decoded_attr, $content, $tag );
	}

	return $output;
}

add_filter( 'pre_do_shortcode_tag', 'tve_compat_decode_shortcode_entities', 10, 4 );

/**
 * Check if content contains the SureCart cart menu icon shortcode
 *
 * @param string $content The content to check.
 *
 * @return bool True if content contains the shortcode.
 */
function tcb_contains_surecart_cart_shortcode( $content ) {
	// Early exit: Empty content check
	if ( empty( $content ) ) {
		return false;
	}

	return strpos( $content, 'sc_cart_menu_icon' ) !== false;
}

/**
 * Get and check content from a post for SureCart shortcode
 *
 * @param int $post_id The post ID to retrieve content from.
 *
 * @return bool True if post content contains the SureCart shortcode.
 */
function tcb_post_contains_surecart_shortcode( $post_id ) {
	// Sanitize post ID
	$post_id = absint( $post_id );

	if ( ! $post_id ) {
		return false;
	}

	$content = tve_get_post_meta( $post_id, 'tve_updated_post' );

	return tcb_contains_surecart_cart_shortcode( $content );
}

/**
 * Check if current page contains SureCart cart icon shortcode (directly or in headers/footers)
 *
 * @return bool True if the page needs SureCart cart compatibility.
 */
function tcb_is_surecart_cart_needed() {
	if ( ! class_exists( 'SureCart' ) ) {
		return false;
	}

	if ( ! function_exists( 'is_singular' ) || ! is_singular() ) {
		return false;
	}

	// Get post ID with fallback to global $post
	$post_id = get_the_ID();

	if ( ! $post_id ) {
		global $post;
		$post_id = isset( $post->ID ) ? absint( $post->ID ) : 0;
	}

	if ( ! $post_id ) {
		return false;
	}

	// Sanitize post ID
	$post_id = absint( $post_id );

	// Check if page content directly contains the cart shortcode
	$content = tve_get_post_meta( $post_id, 'tve_updated_post' );

	if ( tcb_contains_surecart_cart_shortcode( $content ) ) {
		return true;
	}

	// Check if page header contains the cart shortcode
	$header_id = absint( get_post_meta( $post_id, '_tve_header', true ) );

	if ( $header_id && tcb_post_contains_surecart_shortcode( $header_id ) ) {
		return true;
	}

	// Check if page footer contains the cart shortcode
	$footer_id = absint( get_post_meta( $post_id, '_tve_footer', true ) );

	if ( $footer_id && tcb_post_contains_surecart_shortcode( $footer_id ) ) {
		return true;
	}

	// Check if page uses symbols that contain the cart shortcode (backward compatibility).
	if ( empty( $content ) ) {
		return false;
	}

	// Check if page uses symbols that contain the cart shortcode (backward compatibility)
	$pattern = '/\[(thrive_symbol|tcb_symbol)\s+id=["\']?(\d+)["\']?/i';

	if ( ! preg_match_all( $pattern, $content, $matches ) ) {
		return false;
	}

	// Early exit: No symbol IDs found
	if ( empty( $matches[2] ) ) {
		return false;
	}

	// Check each symbol for the cart shortcode
	foreach ( $matches[2] as $symbol_id ) {
		if ( tcb_post_contains_surecart_shortcode( absint( $symbol_id ) ) ) {
			return true;
		}
	}

	return false;
}

/**
 * Enqueue SureCart scripts, styles, and modules for cart functionality
 *
 * @return void
 */
function tcb_enqueue_surecart_modules() {
	// Early exit: Check if SureCart plugin is active
	if ( ! class_exists( 'SureCart' ) ) {
		return;
	}

	// Enqueue main SureCart components (JS and CSS)
	\SureCart::assets()->enqueueComponents();

	// Early exit: Script module function not available
	if ( ! function_exists( 'wp_enqueue_script_module' ) ) {
		return;
	}

	// Enqueue script modules for cart and checkout
	wp_enqueue_script_module( '@surecart/cart' );
	wp_enqueue_script_module( '@surecart/checkout' );
}

/**
 * Render SureCart cart template in footer
 *
 * @return void
 */
function tcb_render_surecart_cart_template() {
	// Early exit: Check if SureCart plugin is active
	if ( ! class_exists( 'SureCart' ) ) {
		return;
	}

	// Get the cart template
	$template = get_block_template( 'surecart/surecart//cart', 'wp_template_part' );

	// Early exit: Template not found
	if ( ! $template ) {
		return;
	}

	// Early exit: Template has no content
	if ( empty( $template->content ) ) {
		return;
	}

	// Render the cart template blocks
	// Note: do_blocks() returns escaped HTML that should not be double-escaped
	// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
	echo do_blocks( $template->content );
}

/**
 * Initialize SureCart compatibility for TCB landing pages
 * Ensures cart drawer is properly added and WP Interactivity API works correctly
 *
 * @return void
 */
function tcb_init_surecart_compat() {
	// Early exit: SureCart cart not needed on this page
	if ( ! tcb_is_surecart_cart_needed() ) {
		return;
	}

	// Enqueue required scripts, styles, and modules
	add_action( 'wp_enqueue_scripts', 'tcb_enqueue_surecart_modules' );

	// Add cart template to footer with priority 1 for early initialization
	add_action( 'wp_footer', 'tcb_render_surecart_cart_template', 1 );

	// Output block support styles for landing pages
	add_action( 'wp_footer', 'tcb_output_surecart_block_support_styles', 0 );
}

add_action( 'wp', 'tcb_init_surecart_compat' );

/**
 * Output WordPress block support styles for SureCart on landing pages
 * Landing pages don't load core-block-supports-inline-css which contains essential flex layout styles
 * This function outputs those styles inline in the footer
 *
 * @return void
 */
function tcb_output_surecart_block_support_styles() {
	// Early exit: Not a landing page
	if ( ! function_exists( 'tve_post_is_landing_page' ) || ! tve_post_is_landing_page( get_the_ID() ) ) {
		return;
	}

	// Early exit: SureCart not active
	if ( ! class_exists( 'SureCart' ) ) {
		return;
	}

	// Check if core-block-supports styles are already loaded
	if ( wp_style_is( 'core-block-supports', 'done' ) || wp_style_is( 'core-block-supports', 'enqueued' ) ) {
		return;
	}

	// Get the cart template to extract block support styles
	$template = get_block_template( 'surecart/surecart//cart', 'wp_template_part' );
	if ( ! $template || empty( $template->content ) ) {
		return;
	}

	// Render the template to generate block support styles
	// This triggers WordPress to generate the wp-container-* classes in the style engine
	do_blocks( $template->content );

	// Get the generated block support styles from the style engine
	$block_support_styles = wp_style_engine_get_stylesheet_from_context( 'block-supports' );

	// Also get any stored styles that WordPress may have queued
	if ( function_exists( 'wp_style_engine_get_stylesheet_from_context' ) ) {
		$stored_styles = wp_style_engine_get_stylesheet_from_context( 'block-supports', array( 'prettify' => false ) );
		if ( ! empty( $stored_styles ) && $stored_styles !== $block_support_styles ) {
			$block_support_styles .= $stored_styles;
		}
	}

	if ( ! empty( $block_support_styles ) ) {
		// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- CSS output is safe
		echo '<style id="tcb-surecart-block-supports-css">' . $block_support_styles . '</style>';
	}
}

/**
 * Enqueue WordPress stored block styles for landing pages with SureCart
 * This ensures core-block-supports styles are properly enqueued
 *
 * @return void
 */
function tcb_enqueue_surecart_stored_styles() {
	// Early exit: Not a landing page
	if ( ! function_exists( 'tve_post_is_landing_page' ) || ! tve_post_is_landing_page( get_the_ID() ) ) {
		return;
	}

	// Early exit: SureCart not active
	if ( ! class_exists( 'SureCart' ) ) {
		return;
	}

	// Force WordPress to enqueue stored block styles
	if ( function_exists( 'wp_enqueue_stored_styles' ) ) {
		wp_enqueue_stored_styles( array( 'prettify' => false ) );
	}
}

add_action( 'wp_footer', 'tcb_enqueue_surecart_stored_styles', 5 );

/**
 * Whitelist SureCart CSS/JS from being stripped on landing pages
 * This ensures SureCart assets load even when "Do not strip CSS from <head>" is unchecked
 *
 * @param array            $tcb_style_classes List of CSS classes/IDs to preserve.
 * @param TCB_Landing_Page $landing_page      Landing page instance.
 *
 * @return array Modified list of CSS classes/IDs to preserve.
 */
function tcb_surecart_lp_strip_css_whitelist( $tcb_style_classes, $landing_page ) {
	// Early exit: SureCart not active
	if ( ! class_exists( 'SureCart' ) ) {
		return $tcb_style_classes;
	}

	// Add SureCart CSS identifiers to whitelist
	$surecart_styles = array(
		'surecart-',           // All SureCart style handles
		'sc-',                 // SureCart shorthand prefix
		'wp-block-surecart',   // SureCart block styles
		'core-block-supports', // WordPress block support styles (contains flex layout classes)
		'global-styles',       // WordPress global styles (contains .is-layout-flex etc.)
	);

	return array_merge( $tcb_style_classes, $surecart_styles );
}

add_filter( 'tcb_lp_strip_css_whitelist', 'tcb_surecart_lp_strip_css_whitelist', 10, 2 );
/**
 * Add SureCart theme body class to landing pages
 * Landing pages use remove_all_filters('body_class') which removes SureCart's filter
 * This re-adds the surecart-theme-{theme} class via the tcb_lp_body_class filter
 *
 * @param string $classes Current body classes for landing page.
 *
 * @return string Modified body classes with SureCart theme class.
 */
function tcb_surecart_lp_body_class( $classes ) {
	// Early exit: SureCart not active
	if ( ! class_exists( 'SureCart' ) ) {
		return $classes;
	}

	// Get SureCart theme setting (defaults to 'light')
	$theme = get_option( 'surecart_theme', 'light' );

	// Add the SureCart theme class
	$classes .= ' surecart-theme-' . sanitize_html_class( $theme );

	return $classes;
}

add_filter( 'tcb_lp_body_class', 'tcb_surecart_lp_body_class' );

/**
 * Compatibility with Google SiteKit - Google Tag Manager
 *
 * Ensures GTM scripts are properly output on Thrive landing pages when users
 * don't have Thrive Theme Builder installed (only Thrive Architect).
 *
 * Landing pages use custom hooks that SiteKit doesn't hook into.
 * This fix outputs GTM scripts at priority 1 to ensure they load before other scripts.
 *
 * Note: If Thrive Theme Builder is installed, the theme's compatibility.php handles this.
 */
if ( defined( 'GOOGLESITEKIT_PLUGIN_MAIN_FILE' ) && ! defined( 'THRIVE_THEME' ) ) {

	/**
	 * Get Google Tag Manager container ID from SiteKit settings
	 *
	 * @return string|false Container ID or false if not configured/disabled
	 */
	function tcb_get_sitekit_gtm_container_id() {
		$settings = get_option( 'googlesitekit_tagmanager_settings' );

		if ( empty( $settings ) || ! is_array( $settings ) ) {
			return false;
		}

		// Respect user's choice to disable SiteKit snippet output
		if ( isset( $settings['useSnippet'] ) && $settings['useSnippet'] === false ) {
			return false;
		}

		return ! empty( $settings['containerID'] ) ? $settings['containerID'] : false;
	}

	/**
	 * Output GTM head script
	 *
	 * @param string $container_id GTM container ID
	 */
	function tcb_output_gtm_head_script( $container_id ) {
		if ( empty( $container_id ) ) {
			return;
		}

		// Validate container ID format (GTM-XXXXXXX) - allows uppercase/lowercase letters and numbers
		if ( ! preg_match( '/^GTM-[A-Za-z0-9]+$/', $container_id ) ) {
			return;
		}

		?>
<!-- Google Tag Manager (Thrive Architect Compatibility) -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','<?php echo esc_js( $container_id ); ?>');</script>
<!-- End Google Tag Manager -->
		<?php
	}

	/**
	 * Output GTM noscript tag
	 *
	 * @param string $container_id GTM container ID
	 */
	function tcb_output_gtm_noscript( $container_id ) {
		if ( empty( $container_id ) ) {
			return;
		}

		// Validate container ID format - allows uppercase/lowercase letters and numbers
		if ( ! preg_match( '/^GTM-[A-Za-z0-9]+$/', $container_id ) ) {
			return;
		}

		?>
<!-- Google Tag Manager (noscript) (Thrive Architect Compatibility) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=<?php echo esc_attr( $container_id ); ?>"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
		<?php
	}

	/**
	 * Ensure GTM head script is output on landing pages (with duplicate prevention)
	 */
	function tcb_ensure_sitekit_gtm_head() {
		static $already_output = false;

		if ( $already_output ) {
			return;
		}

		// Skip in editor context
		if ( function_exists( 'is_editor_page_raw' ) && is_editor_page_raw() ) {
			return;
		}

		$container_id = tcb_get_sitekit_gtm_container_id();

		if ( empty( $container_id ) ) {
			return;
		}

		tcb_output_gtm_head_script( $container_id );
		$already_output = true;
	}

	/**
	 * Ensure GTM noscript is output on landing pages (with duplicate prevention)
	 */
	function tcb_ensure_sitekit_gtm_body_open() {
		static $already_output = false;

		if ( $already_output ) {
			return;
		}

		// Skip in editor context
		if ( function_exists( 'is_editor_page_raw' ) && is_editor_page_raw() ) {
			return;
		}

		$container_id = tcb_get_sitekit_gtm_container_id();

		if ( empty( $container_id ) ) {
			return;
		}

		tcb_output_gtm_noscript( $container_id );
		$already_output = true;
	}

	// Landing pages - output GTM script in landing page head
	add_action( 'tcb_landing_head_frontend', static function () {
		tcb_ensure_sitekit_gtm_head();
	}, 1 );

	// Landing pages - output noscript after landing page body opens
	add_action( 'tcb_landing_body_open_frontend', static function () {
		tcb_ensure_sitekit_gtm_body_open();
	}, 1 );
}

Youez - 2016 - github.com/yon3zu
LinuXploit