<?php
/**
 * Kadence\Base_Support\Component class
 *
 * @package kadence
 */

namespace Kadence\Base_Support;

use Kadence\Component_Interface;
use Kadence\Templating_Component_Interface;
use Kadence_Blocks_Frontend;
use Kadence_Blocks_Pro_Frontend;
use WP_Upgrader;
use WP_Ajax_Upgrader_Skin;
use Plugin_Upgrader;
use function Kadence\kadence;
use function add_action;
use function add_filter;
use function add_theme_support;
use function is_singular;
use function pings_open;
use function esc_url;
use function get_bloginfo;
use function wp_scripts;
use function wp_get_theme;
use function get_template;
use function plugins_api;
use function activate_plugin;
use function get_site_option;
use function is_customize_preview;

/**
 * Class for adding basic theme support, most of which is mandatory to be implemented by all themes.
 *
 * Exposes template tags:
 * * `kadence()->get_version()`
 * * `kadence()->get_post_types()`
 * * `kadence()->get_asset_version( string $filepath )`
 */
class Component implements Component_Interface, Templating_Component_Interface {

	/**
	 * Holds post types.
	 *
	 * @var values of all the post types.
	 */
	protected static $post_types = null;

	/**
	 * Holds post types.
	 *
	 * @var values of all the post types.
	 */
	protected static $post_types_objects = null;

	/**
	 * Holds ignore post types.
	 *
	 * @var values of all the post types.
	 */
	protected static $ignore_post_types = null;

	/**
	 * Holds ignore post types.
	 *
	 * @var values of all the post types.
	 */
	protected static $public_ignore_post_types = null;

	/**
	 * Holds ignore post types.
	 *
	 * @var values of all the post types.
	 */
	protected static $transparent_ignore_post_types = null;

	/**
	 * Static var active plugins
	 *
	 * @var $active_plugins
	 */
	private static $active_plugins;

	/**
	 * Gets the unique identifier for the theme component.
	 *
	 * @return string Component slug.
	 */
	public function get_slug() : string {
		return 'base_support';
	}

	/**
	 * Adds the action and filter hooks to integrate with WordPress.
	 */
	public function initialize() {
		add_action( 'after_setup_theme', array( $this, 'action_essential_theme_support' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'install_starter_script' ) );
		add_action( 'admin_notices', array( $this, 'kadence_starter_templates_notice' ) );
		add_action( 'admin_notices', array( $this, 'kadence_turn_off_gutenberg_plugin_notice' ) );
		add_action( 'wp_ajax_kadence_dismiss_notice', array( $this, 'ajax_dismiss_starter_notice' ) );
		add_action( 'wp_ajax_kadence_dismiss_gutenberg_notice', array( $this, 'ajax_dismiss_gutenberg_notice' ) );
		add_action( 'wp_ajax_kadence_install_starter', array( $this, 'install_plugin_ajax_callback' ) );
		add_action( 'wp_head', array( $this, 'action_add_pingback_header' ) );
		add_action( 'wp_head', array( $this, 'action_add_no_js_remove_script' ), 2 );
		add_action( 'wp_footer', array( $this, 'action_add_scrollbar_offset_script' ), 2 );
		add_filter( 'body_class', array( $this, 'filter_body_classes_add_hfeed' ) );
		add_filter( 'embed_defaults', array( $this, 'filter_embed_dimensions' ) );
		add_filter( 'theme_scandir_exclusions', array( $this, 'filter_scandir_exclusions_for_optional_templates' ) );
		add_filter( 'script_loader_tag', array( $this, 'filter_script_loader_tag' ), 10, 2 );
		add_filter( 'body_class', array( $this, 'filter_body_classes_add_link_style' ) );
		add_filter( 'get_search_form', array( $this, 'add_search_icon' ), 99 );
		add_filter( 'get_product_search_form', array( $this, 'add_search_icon' ), 99 );
		add_filter( 'embed_oembed_html', array( $this, 'classic_embed_wrap' ), 90, 4 );
		add_filter( 'excerpt_length', array( $this, 'custom_excerpt_length' ) );
		add_filter( 'the_author_description', 'wpautop' );
		add_action( 'admin_init', array( $this, 'set_theme_initial_version' ) );
		add_action( 'init', array( $this, 'setup_content_filter' ), 9 );
		add_action( 'wp', array( $this, 'setup_header_block_css' ), 99 );
	}
	/**
	 * Add the header block css to the head tag.
	 */
	public function setup_header_block_css() {
		if ( is_admin() ) {
			return;
		}
		if ( kadence()->option( 'blocks_header' ) && defined( 'KADENCE_BLOCKS_VERSION' ) ) {
			$header_id = kadence()->option( 'blocks_header_id' );
			if ( ! empty( $header_id ) ) {
				$header_block = get_post( $header_id );
				if ( ! $header_block || 'kadence_header' !== $header_block->post_type ) {
					return;
				}
				if ( 'publish' !== $header_block->post_status || ! empty( $header_block->post_password ) ) {
					return;
				}
				$header_block->post_content = '<!-- wp:kadence/header {"uniqueID":"header-replace","id":' . $header_id . '} /-->';
				if ( class_exists( 'Kadence_Blocks_Frontend' ) ) {
					$kadence_blocks = \Kadence_Blocks_Frontend::get_instance();
					if ( method_exists( $kadence_blocks, 'frontend_build_css' ) ) {
						$kadence_blocks->frontend_build_css( $header_block );
					}
					if ( class_exists( 'Kadence_Blocks_Pro_Frontend' ) ) {
						$kadence_blocks_pro = \Kadence_Blocks_Pro_Frontend::get_instance();
						if ( method_exists( $kadence_blocks_pro, 'frontend_build_css' ) ) {
							$kadence_blocks_pro->frontend_build_css( $header_block );
						}
					}
				}
			}
		}
	}
	/**
	 * Add filters for element content output.
	 */
	public function setup_content_filter() {
		global $wp_embed;
		add_filter( 'kadence_theme_the_content', array( $wp_embed, 'run_shortcode' ), 8 );
		add_filter( 'kadence_theme_the_content', array( $wp_embed, 'autoembed'     ), 8 );
		add_filter( 'kadence_theme_the_content', 'do_blocks' );
		add_filter( 'kadence_theme_the_content', 'wptexturize' );
		add_filter( 'kadence_theme_the_content', 'shortcode_unautop' );
		add_filter( 'kadence_theme_the_content', 'wp_filter_content_tags' );
		add_filter( 'kadence_theme_the_content', 'do_shortcode', 11 );
		add_filter( 'kadence_theme_the_content', 'convert_smilies', 20 );
	}
	/**
	 * Set the initial theme version.
	 */
	public function set_theme_initial_version() {
		$initial_version = get_theme_mod( 'initial_version', false );
		if ( ! $initial_version ) {
			set_theme_mod( 'initial_version', KADENCE_VERSION );
		}
	}
	/**
	 * Add Notice for Kadence Starter templates
	 */
	public function kadence_starter_templates_notice() {
		if ( defined( 'KADENCE_STARTER_TEMPLATES_VERSION' ) || get_option( 'kadence_starter_plugin_notice' ) || ! current_user_can( 'install_plugins' ) ) {
			return;
		}
		$installed_plugins = get_plugins();
		if ( ! isset( $installed_plugins['kadence-starter-templates/kadence-starter-templates.php'] ) ) {
			$button_label = esc_html__( 'Install AI Starter Templates', 'kadence' );
			$data_action  = 'install';
		} elseif ( ! self::active_plugin_check( 'kadence-starter-templates/kadence-starter-templates.php' ) ) {
			$button_label = esc_html__( 'Activate AI Starter Templates', 'kadence' );
			$data_action  = 'activate';
		} else {
			return;
		}
		$starter_link = class_exists( '\\KadenceWP\\KadenceBlocks\\StellarWP\\Uplink\\Register' ) ? admin_url( 'admin.php?page=kadence-starter-templates' ) : admin_url( 'themes.php?page=kadence-starter-templates' );
		?>
		<div id="kadence-notice-starter-templates" class="notice is-dismissible notice-info">
			<div class="sub-notice-title"><?php echo esc_html__( 'Thanks for choosing the Kadence Theme!', 'kadence' ); ?></div>
			<h2 class="notice-title"><?php echo esc_html__( 'Get Started with an AI Powered Website!', 'kadence' ); ?></h2>
			<p class="kadence-notice-description"><?php /* translators: %s: <strong> <a> */ printf( esc_html__( 'Want to get started with a beautiful AI Powered %1$sstarter template%2$s? Install the Kadence AI Powered Starter Templates plugin to launch an AI optimized website in minutes.', 'kadence' ), '<a href="https://wordpress.org/plugins/kadence-starter-templates/" target="_blank">', '</a>', '<strong>', '</strong>' ); ?></p>
			<p class="install-submit">
				<button class="button button-primary kadence-install-starter-btn" data-redirect-url="<?php echo esc_url( $starter_link ); ?>" data-activating-label="<?php echo esc_attr__( 'Activating...', 'kadence' ); ?>" data-activated-label="<?php echo esc_attr__( 'Activated', 'kadence' ); ?>" data-installing-label="<?php echo esc_attr__( 'Installing...', 'kadence' ); ?>" data-installed-label="<?php echo esc_attr__( 'Installed', 'kadence' ); ?>" data-action="<?php echo esc_attr( $data_action ); ?>"><?php echo esc_html( $button_label ); ?></button>
			</p>
		</div>
		<style>#kadence-notice-starter-templates {padding: 24px;}#kadence-notice-starter-templates .kadence-notice-description {max-width: 600px;font-size: 15px;margin-bottom: 12px;}#kadence-notice-starter-templates button.kadence-install-starter-btn {padding: 4px 16px;font-size: 15px;}#kadence-notice-starter-templates h2.notice-title {font-size: 24px;margin-bottom: 8px;}</style>
		<?php
		wp_enqueue_script( 'kadence-starter-install' );
		wp_localize_script(
			'kadence-starter-install',
			'kadenceStarterInstall',
			array(
				'ajax_url'   => admin_url( 'admin-ajax.php' ),
				'ajax_nonce' => wp_create_nonce( 'kadence-ajax-verification' ),
				'status'     => $data_action,
			)
		);
	}
	/**
	 * Add Notice for to not use the Gutenberg Plugin
	 */
	public function kadence_turn_off_gutenberg_plugin_notice() {
		if ( ! defined( 'GUTENBERG_VERSION' ) || get_option( 'kadence_disable_gutenberg_notice' ) || ! current_user_can( 'install_plugins' ) ) {
			return;
		}
		?>
		<div id="kadence-notice-gutenberg-plugin" class="notice is-dismissible notice-warning">
			<h2 class="notice-title"><?php echo esc_html__( 'Gutenberg Plugin Detected', 'kadence' ); ?></h2>
			<p class="kadence-notice-description"><?php /* translators: %s: <a> */ printf( esc_html__( 'The %1$sGutenberg plugin%2$s is not recommended for use in a production site. Many things may be broken by using this plugin. Please deactivate.', 'kadence' ), '<a href="https://wordpress.org/plugins/gutenberg/" target="_blank">', '</a>' ); ?></p>
		</div>
		<?php
		wp_enqueue_script( 'kadence-gutenberg-deactivate' );
		wp_localize_script(
			'kadence-gutenberg-deactivate',
			'kadenceGutenbergDeactivate',
			array(
				'ajax_url'   => admin_url( 'admin-ajax.php' ),
				'ajax_nonce' => wp_create_nonce( 'kadence-ajax-verification' ),
			)
		);
	}
	/**
	 * Run check to see if we need to dismiss the notice.
	 * If all tests are successful then call the dismiss_notice() method.
	 *
	 * @access public
	 * @since 1.0
	 * @return void
	 */
	public function ajax_dismiss_gutenberg_notice() {

		// Sanity check: Early exit if we're not on a wptrt_dismiss_notice action.
		if ( ! isset( $_POST['action'] ) || 'kadence_dismiss_gutenberg_notice' !== $_POST['action'] ) {
			return;
		}
		// Security check: Make sure nonce is OK.
		check_ajax_referer( 'kadence-ajax-verification', 'security', true );

		// If we got this far, we need to dismiss the notice.
		update_option( 'kadence_disable_gutenberg_notice', true, false );
	}
	/**
	 * Run check to see if we need to dismiss the notice.
	 * If all tests are successful then call the dismiss_notice() method.
	 *
	 * @access public
	 * @since 1.0
	 * @return void
	 */
	public function ajax_dismiss_starter_notice() {

		// Sanity check: Early exit if we're not on a wptrt_dismiss_notice action.
		if ( ! isset( $_POST['action'] ) || 'kadence_dismiss_notice' !== $_POST['action'] ) {
			return;
		}
		// Security check: Make sure nonce is OK.
		check_ajax_referer( 'kadence-ajax-verification', 'security', true );

		// If we got this far, we need to dismiss the notice.
		update_option( 'kadence_starter_plugin_notice', true, false );
	}

	/**
	 * Option to Install Starter Templates
	 */
	public function install_starter_script() {
		wp_register_script( 'kadence-starter-install', get_template_directory_uri() . '/assets/js/admin-activate.min.js', array( 'jquery' ), KADENCE_VERSION, false );
		wp_register_script( 'kadence-gutenberg-deactivate', get_template_directory_uri() . '/assets/js/gutenberg-notice.min.js', array( 'jquery' ), KADENCE_VERSION, false );
	}
	/**
	 * Active Plugin Check
	 *
	 * @param string $plugin_base_name is plugin folder/filename.php.
	 */
	public static function active_plugin_check( $plugin_base_name ) {

		if ( ! self::$active_plugins ) {
			self::get_active_plugins();
		}
		return in_array( $plugin_base_name, self::$active_plugins, true ) || array_key_exists( $plugin_base_name, self::$active_plugins );
	}
	/**
	 * Initialize getting the active plugins list.
	 */
	public static function get_active_plugins() {

		self::$active_plugins = (array) get_option( 'active_plugins', array() );

		if ( is_multisite() ) {
			self::$active_plugins = array_merge( self::$active_plugins, get_site_option( 'active_sitewide_plugins', array() ) );
		}
	}
	/**
	 * AJAX callback to install a plugin.
	 */
	public function install_plugin_ajax_callback() {
		if ( ! check_ajax_referer( 'kadence-ajax-verification', 'security', false ) ) {
			wp_send_json_error( __( 'Security Error, Please reload the page.', 'kadence' ) );
		}
		if ( ! current_user_can( 'install_plugins' ) ) {
			wp_send_json_error( __( 'Security Error, Need higher Permissions to install plugin.', 'kadence' ) );
		}
		// Get selected file index or set it to 0.
		$status = empty( $_POST['status'] ) ? 'install' : sanitize_text_field( $_POST['status'] );
		if ( ! function_exists( 'plugins_api' ) ) {
			require_once ABSPATH . 'wp-admin/includes/plugin-install.php';
		}
		if ( ! class_exists( 'WP_Upgrader' ) ) {
			require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
		}
		$install = true;
		if ( 'install' === $status ) {
			$api = plugins_api(
				'plugin_information',
				array(
					'slug' => 'kadence-starter-templates',
					'fields' => array(
						'short_description' => false,
						'sections' => false,
						'requires' => false,
						'rating' => false,
						'ratings' => false,
						'downloaded' => false,
						'last_updated' => false,
						'added' => false,
						'tags' => false,
						'compatibility' => false,
						'homepage' => false,
						'donate_link' => false,
					),
				)
			);
			if ( ! is_wp_error( $api ) ) {

				// Use AJAX upgrader skin instead of plugin installer skin.
				// ref: function wp_ajax_install_plugin().
				$upgrader = new \Plugin_Upgrader( new \WP_Ajax_Upgrader_Skin() );

				$installed = $upgrader->install( $api->download_link );
				if ( $installed ) {
					$activate = activate_plugin( 'kadence-starter-templates/kadence-starter-templates.php', '', false, true );
					if ( is_wp_error( $activate ) ) {
						$install = false;
					}
				} else {
					$install = false;
				}
			} else {
				$install = false;
			}
		} elseif ( 'activate' === $status ) {
			$activate = activate_plugin( 'kadence-starter-templates/kadence-starter-templates.php', '', false, true );
			if ( is_wp_error( $activate ) ) {
				$install = false;
			}
		}

		if ( false === $install ) {
			wp_send_json_error( __( 'Error, plugin could not be installed, please install manually.', 'kadence' ) );
		} else {
			wp_send_json_success();
		}
	}
	/**
	 * Filter the excerpt length to 30 words.
	 *
	 * @param int $length Excerpt length.
	 * @return int (Maybe) modified excerpt length.
	 */
	public function custom_excerpt_length( $length ) {
		if ( is_admin() ) {
			return $length;
		}
		if ( is_search() ) {
			if ( kadence()->sub_option( 'search_archive_element_excerpt', 'words' ) ) {
				$length = intval( kadence()->sub_option( 'search_archive_element_excerpt', 'words' ) );
			}
		} else if ( 'post' === get_post_type() ) {
			if ( kadence()->sub_option( 'post_archive_element_excerpt', 'words' ) ) {
				$length = intval( kadence()->sub_option( 'post_archive_element_excerpt', 'words' ) );
			}
		} else {
			if ( kadence()->sub_option( get_post_type() . '_archive_element_excerpt', 'words' ) ) {
				$length = intval( kadence()->sub_option( get_post_type() . '_archive_element_excerpt', 'words' ) );
			}
		}
		return $length;
	}
	/**
	 * Remove comment date.
	 *
	 * @param string|int $date      The comment time, formatted as a date string or Unix timestamp.
	 * @param string     $format    Date format.
	 * @param bool       $gmt       Whether the GMT date is in use.
	 * @param bool       $translate Whether the time is translated.
	 * @param WP_Comment $comment   The comment object.
	 */
	public function remove_comment_time( $date, $format, $gmt, $translate, $comment ) {
		if ( ! is_admin() ) {
			return '';
		}
		return $date;
	}
	/**
	 * Remove comment date.
	 *
	 * @param string|int $date    Formatted date string or Unix timestamp.
	 * @param string     $format  The format of the date.
	 * @param WP_Comment $comment The comment object.
	 */
	public function remove_comment_date( $date, $format, $comment ) {
		if ( ! is_admin() ) {
			return '';
		}
		return $date;
	}
	/**
	 * Wrap embedded media for responsive embeds, pre blocks.
	 *
	 * @param  string $cache The oEmbed markup.
	 * @param  string $url The URL being embedded.
	 * @param  array  $attr An array of attributes.
	 * @param  string $post_ID the post id.
	 */
	public function classic_embed_wrap( $cache, $url, $attr = array(), $post_ID = '' ) {
		if ( doing_filter( 'the_content' ) && ! has_blocks() && ! empty( $cache ) && ! empty( $url ) ) {
			$do_wrap = false;
			$patterns = array(
				'#http://((m|www)\.)?youtube\.com/watch.*#i',
				'#https://((m|www)\.)?youtube\.com/watch.*#i',
				'#http://((m|www)\.)?youtube\.com/playlist.*#i',
				'#https://((m|www)\.)?youtube\.com/playlist.*#i',
				'#http://youtu\.be/.*#i',
				'#https://youtu\.be/.*#i',
				'#https?://(.+\.)?vimeo\.com/.*#i',
				'#https?://(www\.)?dailymotion\.com/.*#i',
				'#https?://dai.ly/*#i',
				'#https?://(www\.)?hulu\.com/watch/.*#i',
				'#https?://wordpress.tv/.*#i',
				'#https?://(www\.)?funnyordie\.com/videos/.*#i',
				'#https?://vine.co/v/.*#i',
				'#https?://(www\.)?collegehumor\.com/video/.*#i',
				'#https?://(www\.|embed\.)?ted\.com/talks/.*#i'
			);
			$patterns = apply_filters( 'kadence_maybe_wrap_embed_patterns', $patterns );
			foreach ( $patterns as $pattern ) {
				$do_wrap = preg_match( $pattern, $url );
				if ( $do_wrap ) {
					return '<div class="entry-content-asset videofit">' . $cache . '</div>';
				}
			}
		}
		return $cache;
	}

	/**
	 * Gets template tags to expose as methods on the Template_Tags class instance, accessible through `kadence()`.
	 *
	 * @return array Associative array of $method_name => $callback_info pairs. Each $callback_info must either be
	 *               a callable or an array with key 'callable'. This approach is used to reserve the possibility of
	 *               adding support for further arguments in the future.
	 */
	public function template_tags() : array {
		return array(
			'get_version'                          => array( $this, 'get_version' ),
			'get_asset_version'                    => array( $this, 'get_asset_version' ),
			'get_post_types'                       => array( $this, 'get_post_types' ),
			'get_post_types_objects'               => array( $this, 'get_post_types_objects' ),
			'get_post_types_to_ignore'             => array( $this, 'get_post_types_to_ignore' ),
			'get_transparent_post_types_to_ignore' => array( $this, 'get_transparent_post_types_to_ignore' ),
			'get_public_post_types_to_ignore'      => array( $this, 'get_public_post_types_to_ignore' ),
			'customizer_quick_link'                => array( $this, 'customizer_quick_link' ),
		);
	}
	/**
	 * If in customizer output the quicklink.
	 */
	public static function customizer_quick_link() {
		if ( is_customize_preview() ) {
			?>
			<div class="customize-partial-edit-shortcut kadence-custom-partial-edit-shortcut">
				<button aria-label="<?php esc_attr_e( 'Click to edit this element.', 'kadence' ); ?>" title="<?php esc_attr_e( 'Click to edit this element.', 'kadence' ); ?>" class="customize-partial-edit-shortcut-button item-customizer-focus"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M13.89 3.39l2.71 2.72c.46.46.42 1.24.03 1.64l-8.01 8.02-5.56 1.16 1.16-5.58s7.6-7.63 7.99-8.03c.39-.39 1.22-.39 1.68.07zm-2.73 2.79l-5.59 5.61 1.11 1.11 5.54-5.65zm-2.97 8.23l5.58-5.6-1.07-1.08-5.59 5.6z"></path></svg></button>
			</div>
			<?php
		}
	}
	/**
	 * Get array of post types we want to exclude from use in customizer custom post type settings.
	 *
	 * @return array of post types.
	 */
	public static function get_post_types_to_ignore() {
		if ( is_null( self::$ignore_post_types ) ) {
			$ignore_post_types = array(
				'post',
				'page',
				'product',
				'kadence_element',
				'kadence_adv_page',
				'kadence_conversions',
				'kadence_cloud',
				'kadence_wootemplate',
				'elementor_library',
				'kt_size_chart',
				'kt_cart_notice',
				'kt_reviews',
				'kt_product_tabs',
				'ele-product-template',
				'ele-p-arch-template',
				'ele-p-loop-template',
				'ele-check-template',
				'shop_order',
				'jet-menu',
				'jet-popup',
				'jet-smart-filters',
				'jet-theme-core',
				'jet-woo-builder',
				'jet-engine',
				'course',
				'lesson',
				'llms_quiz',
				'llms_membership',
				'llms_certificate',
				'llms_my_certificate',
				'sfwd-quiz',
				'sfwd-certificates',
				'sfwd-lessons',
				'sfwd-topic',
				'sfwd-transactions',
				'sfwd-essays',
				'sfwd-assignment',
				'sfwd-courses',
				'tutor_quiz',
				'tutor_assignments',
				'courses',
				'groups',
				'forum',
				'topic',
				'reply',
				'tribe_events',
			);
			self::$ignore_post_types = apply_filters( 'kadence_customizer_post_type_ignore_array', $ignore_post_types );
		}

		return self::$ignore_post_types;
	}

	/**
	 * Get array of post types we want to exclude from use in customizer transparent header settings.
	 *
	 * @return array of post types.
	 */
	public static function get_transparent_post_types_to_ignore() {
		if ( is_null( self::$transparent_ignore_post_types ) ) {
			$transparent_ignore_post_types = array(
				'post',
				'page',
				'product',
				'kadence_element',
				'kadence_adv_page',
				'kadence_conversions',
				'kadence_cloud',
				'kadence_wootemplate',
				'elementor_library',
				'fl-theme-layout',
				'kt_size_chart',
				'kt_cart_notice',
				'kt_reviews',
				'kt_product_tabs',
				'shop_order',
				'ele-product-template',
				'ele-p-arch-template',
				'ele-p-loop-template',
				'ele-check-template',
				'jet-menu',
				'jet-popup',
				'jet-smart-filters',
				'jet-theme-core',
				'jet-woo-builder',
				'jet-engine',
				'llms_certificate',
				'llms_my_certificate',
				'sfwd-quiz',
				'ld-exam',
				'sfwd-certificates',
				'sfwd-lessons',
				'sfwd-topic',
				'sfwd-transactions',
				'sfwd-essays',
				'sfwd-assignment',
				'tutor_quiz',
				'tutor_assignments',
			);
			self::$transparent_ignore_post_types = apply_filters( 'kadence_transparent_post_type_ignore_array', $transparent_ignore_post_types );
		}

		return self::$transparent_ignore_post_types;
	}

	/**
	 * Get array of post types we want to exclude from use in non public areas.
	 *
	 * @return array of post types.
	 */
	public static function get_public_post_types_to_ignore() {
		if ( is_null( self::$public_ignore_post_types ) ) {
			$public_ignore_post_types = array(
				'elementor_library',
				'fl-theme-layout',
				'kt_size_chart',
				'kt_cart_notice',
				'kt_reviews',
				'kt_product_tabs',
				'shop_order',
				'kadence_element',
				'kadence_adv_page',
				'kadence_conversions',
				'kadence_cloud',
				'kadence_wootemplate',
				'ele-product-template',
				'ele-p-arch-template',
				'ele-p-loop-template',
				'ele-check-template',
				'jet-menu',
				'jet-popup',
				'jet-smart-filters',
				'jet-theme-core',
				'jet-woo-builder',
				'jet-engine',
				'llms_certificate',
				'llms_my_certificate',
				'sfwd-certificates',
				'sfwd-transactions',
				'reply',
			);
			self::$public_ignore_post_types = apply_filters( 'kadence_public_post_type_ignore_array', $public_ignore_post_types );
		}

		return self::$public_ignore_post_types;
	}

	/**
	 * Get all public post types.
	 *
	 * @return array of post types.
	 */
	public static function get_post_types() {
		if ( is_null( self::$post_types ) ) {
			$args             = array(
				'public' => true,
				'show_in_rest' => true,
				'_builtin' => false,
			);
			$builtin = array(
				'post',
				'page',
			);
			$output           = 'names'; // names or objects, note names is the default.
			$operator         = 'and';
			$post_types       = get_post_types( $args, $output, $operator );
			self::$post_types = apply_filters( 'kadence_public_post_type_array', array_merge( $builtin, $post_types ) );
		}

		return self::$post_types;
	}

	/**
	 * Get all public post types.
	 *
	 * @return array of post types.
	 */
	public static function get_post_types_objects() {
		if ( is_null( self::$post_types_objects ) ) {
			$args             = array(
				'public' => true,
				'_builtin' => false,
			);
			$output           = 'objects'; // names or objects, note names is the default.
			$operator         = 'and';
			$post_types       = get_post_types( $args, $output, $operator );
			self::$post_types_objects = apply_filters( 'kadence_public_post_type_objects', $post_types );
		}

		return self::$post_types_objects;
	}

	/**
	 * Adds theme support for essential features.
	 */
	public function action_essential_theme_support() {
		if ( 'em' === kadence()->sub_option( 'content_width', 'unit' ) || 'rem' === kadence()->sub_option( 'content_width', 'unit' ) ) {
			$kadence_content_width = intval( kadence()->sub_option( 'content_width', 'size' ) * 17 );
		} else {
			$kadence_content_width = kadence()->sub_option( 'content_width', 'size' );
		}
		$GLOBALS['content_width'] = intval( $kadence_content_width ); // phpcs:ignore WPThemeReview.CoreFunctionality.PrefixAllGlobals.NonPrefixedVariableFound

		// Add default RSS feed links to head.
		add_theme_support( 'automatic-feed-links' );

		// Ensure WordPress manages the document title.
		add_theme_support( 'title-tag' );

		// Ensure WordPress theme features render in HTML5 markup.
		add_theme_support(
			'html5',
			array(
				'search-form',
				'comment-form',
				'comment-list',
				'gallery',
				'caption',
				'script',
				'style',
			)
		);

		add_theme_support( 'custom-units' );
		add_theme_support( 'custom-line-height' );

		// Add support for selective refresh for widgets.
		add_theme_support( 'customize-selective-refresh-widgets' );

		// Add support for responsive embedded content.
		add_theme_support( 'responsive-embeds' );

		if ( ! kadence()->option( 'post_comments_date' ) ) {
			add_filter( 'get_comment_date', array( $this, 'remove_comment_date' ), 20, 3 );
			add_filter( 'get_comment_time', array( $this, 'remove_comment_time' ), 20, 5 );
		}

	}
	/**
	 * Adds a tiny script to remove no-js class.
	 */
	public function action_add_no_js_remove_script() {
		if ( ! kadence()->is_amp() ) {
			?>
			<script>document.documentElement.classList.remove( 'no-js' );</script>
			<?php
		}
	}
	/**
	 * Adds a tiny script to set scrollbar offset.
	 */
	public function action_add_scrollbar_offset_script() {
		if ( ! kadence()->is_amp() ) {
			?>
			<script>document.documentElement.style.setProperty('--scrollbar-offset', window.innerWidth - document.documentElement.clientWidth + 'px' );</script>
			<?php
		}
	}
	/**
	 * Adds a pingback url auto-discovery header for singularly identifiable articles.
	 */
	public function action_add_pingback_header() {
		if ( is_singular() && pings_open() ) {
			echo '<link rel="pingback" href="', esc_url( get_bloginfo( 'pingback_url' ) ), '">';
		}
	}
	/**
	 * Add
	 *
	 * @param string $markup search form markup.
	 *
	 * @return mixed
	 */
	public function add_search_icon( $markup ) {
		$markup = str_replace( '</form>', '<div class="kadence-search-icon-wrap">' . kadence()->get_icon( 'search', '', false ) . '</div></form>', $markup );
		return $markup;
	}
	/**
	 * Adds a 'hfeed' class to the array of body classes for non-singular pages.
	 *
	 * @param array $classes Classes for the body element.
	 * @return array Filtered body classes.
	 */
	public function filter_body_classes_add_hfeed( array $classes ) : array {
		// Check if we should add the hfeed class.
		if ( ! kadence()->option( 'microdata' ) || ! apply_filters( 'kadence_microdata', true, 'body-class' ) ) {
			return $classes;
		}
		if ( ! is_singular() ) {
			$classes[] = 'hfeed';
		}

		return $classes;
	}

	/**
	 * Adds a link style class to the array of body classes.
	 *
	 * @param array $classes Classes for the body element.
	 * @return array Filtered body classes.
	 */
	public function filter_body_classes_add_link_style( array $classes ) : array {
		if ( ! kadence()->option( 'enable_scroll_to_id' ) ) {
			$classes[] = 'no-anchor-scroll';
		}
		if ( kadence()->option( 'enable_footer_on_bottom' ) ) {
			$classes[] = 'footer-on-bottom';
		}
		if ( kadence()->option( 'enable_popup_body_animate' ) ) {
			$classes[] = 'animate-body-popup';
		}
		if ( '' !== kadence()->option( 'header_social_brand' ) || '' !== kadence()->option( 'header_mobile_social_brand' ) || '' !== kadence()->option( 'footer_social_brand' ) ) {
			$classes[] = 'social-brand-colors';
		}
		$classes[] = 'hide-focus-outline';
		$classes[] = 'link-style-' . kadence()->sub_option( 'link_color', 'style' );

		return $classes;
	}

	/**
	 * Sets the embed width in pixels, based on the theme's design and stylesheet.
	 *
	 * @param array $dimensions An array of embed width and height values in pixels (in that order).
	 * @return array Filtered dimensions array.
	 */
	public function filter_embed_dimensions( array $dimensions ) : array {
		$dimensions['width'] = 720;
		return $dimensions;
	}

	/**
	 * Excludes any directory named 'optional' from being scanned for theme template files.
	 *
	 * @link https://developer.wordpress.org/reference/hooks/theme_scandir_exclusions/
	 *
	 * @param array $exclusions the default directories to exclude.
	 * @return array Filtered exclusions.
	 */
	public function filter_scandir_exclusions_for_optional_templates( array $exclusions ) : array {
		return array_merge(
			$exclusions,
			array( 'optional' )
		);
	}

	/**
	 * Adds async/defer attributes to enqueued / registered scripts.
	 *
	 * If #12009 lands in WordPress, this function can no-op since it would be handled in core.
	 *
	 * @link https://core.trac.wordpress.org/ticket/12009
	 *
	 * @param string $tag    The script tag.
	 * @param string $handle The script handle.
	 * @return string Script HTML string.
	 */
	public function filter_script_loader_tag( $tag, $handle ) {

		foreach ( array( 'async', 'defer' ) as $attr ) {
			if ( ! wp_scripts()->get_data( $handle, $attr ) ) {
				continue;
			}

			// Prevent adding attribute when already added in #12009.
			if ( ! preg_match( ":\s$attr(=|>|\s):", $tag ) ) {
				$tag = preg_replace( ':(?=></script>):', " $attr", $tag, 1 );
			}

			// Only allow async or defer, not both.
			break;
		}

		return $tag;
	}

	/**
	 * Gets the theme version.
	 *
	 * @return string Theme version number.
	 */
	public function get_version() : string {
		static $theme_version = null;

		if ( null === $theme_version ) {
			$theme_version = wp_get_theme( get_template() )->get( 'Version' );
		}

		return $theme_version;
	}

	/**
	 * Gets the version for a given asset.
	 *
	 * Returns filemtime when WP_DEBUG is true, otherwise the theme version.
	 *
	 * @param string $filepath Asset file path.
	 * @return string Asset version number.
	 */
	public function get_asset_version( string $filepath ) : string {
		if ( WP_DEBUG ) {
			return (string) filemtime( $filepath );
		}

		return $this->get_version();
	}
}
