*/ class Frontend { /** * The ID of this plugin. * * @since 1.0.0 * @access private * @var string $plugin_name The ID of this plugin. */ private $plugin_name; /** * The version of this plugin. * * @since 1.0.0 * @access private * @var string $version The current version of this plugin. */ private $version; public $utils; public $settings; public $external_support; public $unique_id; /** * Initialize the class and set its properties. * * @since 1.0.0 * @param string $plugin_name The name of the plugin. * @param string $version The version of this plugin. */ public function __construct($plugin_name, $version) { $this->plugin_name = $plugin_name; $this->version = $version; $this->utils = new DarkifyUtils($this); $this->external_support = new DarkifyExternalSupport($this); new DarkifyShortcode($this); if (function_exists('wp_rand')) { $this->unique_id = wp_rand(); } $options = get_option('darkify'); $show_in_menu = isset($options['show_in_menu']) ? $options['show_in_menu'] : ""; $enable_switcher_in_menu = isset($show_in_menu["enable_switch_in_menu"]) ? $show_in_menu["enable_switch_in_menu"] : false; if ($enable_switcher_in_menu) { add_filter('wp_nav_menu_items', array($this, 'darkify_switch_in_menu'), 10, 2); } add_action('wp_enqueue_scripts', array($this, 'darkify_client_enqueue'), 100); add_action('login_enqueue_scripts', array($this, 'darkify_client_enqueue')); add_action('register_enqueue_scripts', array($this, 'darkify_client_enqueue')); add_action('wp_head', array($this, 'darkify_client_header_script'), 1); add_action('login_head', array($this, 'darkify_client_header_script'), 1); add_action('register_head', array($this, 'darkify_client_header_script'), 1); add_action('wp_footer', array($this, 'darkify_client_footer_script')); add_action('login_footer', array($this, 'darkify_client_footer_script')); add_action('register_footer', array($this, 'darkify_client_footer_script')); add_action('init', array($this, 'darkify_register_switcher_styles'), 5); add_filter('autoptimize_filter_js_exclude', array($this, 'darkify_exclude_js_from_cache_plugins')); } public function darkify_exclude_js_from_cache_plugins($excludes) { $excludes .= ',client_main.js,client_main.min.js'; return $excludes; } public function darkify_register_switcher_styles() { $min = (apply_filters('darkify_dev_mode', false) || WP_DEBUG) ? '' : '.min'; wp_register_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main' . $min . '.css', array(), DARKIFY_VERSION); wp_register_style('theme-classic', DARKIFY_DIR_URL . 'src/assets/css/switcher/classic' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); wp_register_style('theme-expand', DARKIFY_DIR_URL . 'src/assets/css/switcher/expand' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); wp_register_style('theme-inner-moon', DARKIFY_DIR_URL . 'src/assets/css/switcher/inner-moon' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); wp_register_style('theme-within', DARKIFY_DIR_URL . 'src/assets/css/switcher/within' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); wp_register_style('theme-orbit', DARKIFY_DIR_URL . 'src/assets/css/switcher/orbit' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); } function darkify_client_enqueue() { if ($this->darkify_is_dark_mode_allowed()) { $options = get_option('darkify'); $min = (apply_filters('darkify_dev_mode', false) || WP_DEBUG) ? '' : '.min'; wp_enqueue_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main' . $min . '.css', array(), DARKIFY_VERSION); wp_enqueue_script('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/js/client_main' . $min . '.js', array('jquery'), DARKIFY_VERSION); // Enqueue the global floating switcher style from settings $enable_dark_mode_switch = isset($options['enable_dark_mode_switch']) ? $options['enable_dark_mode_switch'] : true; if ($enable_dark_mode_switch) { $global_variant = isset($options['enable_dark_switcher']) ? $options['enable_dark_switcher'] : 'classic'; wp_enqueue_style('theme-' . $global_variant); } // Detect [darkify] shortcode usage in current post and enqueue its variant $post = get_post(); if ($post && !empty($post->post_content)) { if (has_shortcode($post->post_content, 'darkify')) { preg_match_all('/\[darkify\b[^\]]*\bswitch=["\']([^"\']+)["\'][^\]]*\]/i', $post->post_content, $matches); $used_switches = !empty($matches[1]) ? $matches[1] : []; foreach ($used_switches as $switch_val) { wp_enqueue_style('theme-' . $this->darkify_switch_to_variant($switch_val)); } // Shortcode without switch= attribute defaults to classic preg_match_all('/\[darkify\b/i', $post->post_content, $all_sc); if (count($all_sc[0]) > count($used_switches)) { wp_enqueue_style('theme-classic'); } } // Detect darkify/switcher Gutenberg block usage and enqueue its variant if (function_exists('has_block') && has_block('darkify/switcher', $post)) { foreach ($this->darkify_get_block_variants($post->post_content) as $variant) { wp_enqueue_style('theme-' . $variant); } } } // Detect switcher used in nav menus and enqueue its variant $show_in_menu = isset($options['show_in_menu']) ? $options['show_in_menu'] : []; $enable_in_menu = isset($show_in_menu['enable_switch_in_menu']) ? $show_in_menu['enable_switch_in_menu'] : false; if ($enable_in_menu) { $select_menus = isset($show_in_menu['select_menus']) ? $show_in_menu['select_menus'] : []; foreach ($select_menus as $select_menu) { $shortcode = $select_menu['darkify_menu_shortcode_helper'] ?? ''; if ($shortcode) { preg_match('/\bswitch=["\']([^"\']+)["\']/', $shortcode, $m); $switch_val = $m[1] ?? '1'; wp_enqueue_style('theme-' . $this->darkify_switch_to_variant($switch_val)); } } } } } private function darkify_switch_to_variant($switch_value) { $map = [ '1' => 'classic', '2' => 'expand', '3' => 'inner-moon', '4' => 'within', '5' => 'orbit', ]; if (is_numeric($switch_value)) { return $map[(string) $switch_value] ?? 'classic'; } return $switch_value ?: 'classic'; } private function darkify_get_block_variants($content) { $variants = []; $this->darkify_collect_block_variants(parse_blocks($content), $variants); return array_unique($variants); } private function darkify_collect_block_variants($blocks, &$variants) { foreach ($blocks as $block) { if ('darkify/switcher' === $block['blockName']) { $variants[] = $block['attrs']['style'] ?? 'classic'; } if (!empty($block['innerBlocks'])) { $this->darkify_collect_block_variants($block['innerBlocks'], $variants); } } $options = get_option('darkify'); $min = (apply_filters('darkify_dev_mode', false) || WP_DEBUG) ? '' : '.min'; // Always register all variant styles so page builders (Elementor, etc.) can reference them. wp_register_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main' . $min . '.css', array(), DARKIFY_VERSION); wp_register_style('theme-classic', DARKIFY_DIR_URL . 'src/assets/css/switcher/classic' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); wp_register_style('theme-expand', DARKIFY_DIR_URL . 'src/assets/css/switcher/expand' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); wp_register_style('theme-inner-moon', DARKIFY_DIR_URL . 'src/assets/css/switcher/inner-moon' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); wp_register_style('theme-orbit', DARKIFY_DIR_URL . 'src/assets/css/switcher/orbit' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); wp_register_style('theme-within', DARKIFY_DIR_URL . 'src/assets/css/switcher/within' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all'); // Determine which variants are actually needed on this page. $variants = $this->darkify_collect_page_variants($options); if (empty($variants)) { return; } // Enqueue main CSS + only the required variant CSS — all resolved before wp_head fires. wp_enqueue_style('darkify-client-main'); foreach ($variants as $variant) { wp_enqueue_style("theme-{$variant}"); } wp_enqueue_script('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/js/client_main' . $min . '.js', array('jquery'), DARKIFY_VERSION); } /** * Collects all switcher variants needed on the current page so they can be * enqueued during wp_enqueue_scripts (before wp_head), guaranteeing CSS loads * in the
regardless of page builder or theme. */ private function darkify_collect_page_variants($options) { $all_variants = array('classic', 'expand', 'inner-moon', 'orbit', 'within'); $num_map = array('1' => 'classic', '2' => 'expand', '3' => 'inner-moon', '4' => 'within', '5' => 'orbit'); $variants = array(); // 1. Global / floating switcher variant (always present when dark mode is active). $global_variant = isset($options['enable_dark_switcher']) ? $options['enable_dark_switcher'] : 'classic'; if (in_array($global_variant, $all_variants, true)) { $variants[] = $global_variant; } // 2. Menu switcher — parse variant from each saved shortcode helper string. $show_in_menu = isset($options['show_in_menu']) ? $options['show_in_menu'] : array(); if (!empty($show_in_menu['enable_switch_in_menu']) && !empty($show_in_menu['select_menus'])) { foreach ($show_in_menu['select_menus'] as $menu_item) { $helper = isset($menu_item['darkify_menu_shortcode_helper']) ? $menu_item['darkify_menu_shortcode_helper'] : ''; if ($helper && preg_match('/switch=["\']?([^"\'>\s\]]+)["\']?/', $helper, $m)) { $v = isset($num_map[$m[1]]) ? $num_map[$m[1]] : $m[1]; if (in_array($v, $all_variants, true)) { $variants[] = $v; } } } } // 3. Page-level detection — shortcodes, Gutenberg blocks, Elementor widget. global $post; if ($post) { $content = $post->post_content; // Shortcodes: parse switch attribute from every [darkify] tag. if (has_shortcode($content, 'darkify')) { preg_match_all('/\[darkify[^\]]*switch=["\']?([^"\'>\s\]]+)/', $content, $sc_matches); foreach ($sc_matches[1] as $switch_val) { $v = isset($num_map[$switch_val]) ? $num_map[$switch_val] : $switch_val; if (in_array($v, $all_variants, true)) { $variants[] = $v; } else { $variants[] = 'classic'; // default when no valid variant found } } // If [darkify] exists but has no switch attribute, default to classic. if (empty($sc_matches[1]) && has_shortcode($content, 'darkify')) { $variants[] = 'classic'; } } // Gutenberg blocks: walk the block tree and collect style attributes. if (function_exists('has_block') && has_block('darkify/switcher', $post)) { $blocks = parse_blocks($content); $variants = array_merge($variants, $this->darkify_extract_block_variants($blocks, $all_variants)); } // Elementor widget: if Darkify widget appears in the page's Elementor data, // load all variants — the specific style is stored as a control value that // would require deep JSON parsing to extract reliably. if (class_exists('\Elementor\Plugin')) { $elementor_data = get_post_meta($post->ID, '_elementor_data', true); if ($elementor_data && strpos($elementor_data, '"widgetType":"darkify"') !== false) { return $all_variants; } } } return array_values(array_unique(array_filter($variants))); } /** * Recursively walks a parsed block tree and collects darkify/darkify style values. */ private function darkify_extract_block_variants($blocks, $all_variants) { $variants = array(); foreach ($blocks as $block) { if ('darkify/switcher' === $block['blockName']) { $style = isset($block['attrs']['style']) ? $block['attrs']['style'] : 'classic'; if (in_array($style, $all_variants, true)) { $variants[] = $style; } } if (!empty($block['innerBlocks'])) { $variants = array_merge($variants, $this->darkify_extract_block_variants($block['innerBlocks'], $all_variants)); } } return $variants; } public function darkify_is_dark_mode_allowed() { $options = get_option('darkify'); /* Disable if Oxygen Builder is Opened */ if (isset($_GET['ct_builder'])) { if ($_GET['ct_builder'] == "true") { if (!isset($_GET['oxygen_iframe'])) { return False; } } } return True; } public function darkify_client_header_script() { if ($this->darkify_is_dark_mode_allowed()) { include_once DarkifyUtils::darkify_locate_template('header_script.php'); } } public function darkify_client_footer_script() { if ($this->darkify_is_dark_mode_allowed()) { include_once DarkifyUtils::darkify_locate_template('footer_script.php'); } } function darkify_switch_in_menu($items, $args) { $options = get_option('darkify'); $show_in_menu = $options['show_in_menu']; $select_menus = isset($show_in_menu['select_menus']) ? $show_in_menu['select_menus'] : []; $last_shortcode = ''; if ($this->darkify_is_dark_mode_allowed() && isset($args->menu->term_id)) { foreach ($select_menus as $select_menu) { $switch_in_menu_location = $select_menu['switch_in_menu_location'] ?? ''; $darkify_menu_shortcode_helper = $select_menu['darkify_menu_shortcode_helper'] ?? ''; $menu_position = isset($select_menu['select_menu_position']) ? $select_menu['select_menu_position'] : 'after'; if ($args->menu->term_id == $switch_in_menu_location) { $last_shortcode = $darkify_menu_shortcode_helper; } } if ($last_shortcode) { $items = ($menu_position == 'before') ? '