PluginProbe
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) / 1.3.2
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) v1.3.2
2.1.3 2.1.2 2.1.1 2.1.0 2.0.4 2.0.3 2.0.2 2.0.1 2.0.0 1.5.5 1.5.4 1.5.3 1.5.2 1.5.1 1.5.0 trunk 1.0.1 1.1.0 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.3.0 All 57 releases
← All changes | src/Frontend/Frontend.php +75 -354 1.5.51.3.2 View file →
@@ -1,15 +1,12 @@
1 1 <?php
2 2
3 3 namespace ThemeAtelier\Darkify\Frontend;
4 4
5 -use ThemeAtelier\Darkify\Includes\DarkifyExternalSupport;
6 -use ThemeAtelier\Darkify\Includes\DarkifyUtils;
5 +use ThemeAtelier\Darkify\Helpers\DarkifyExternalSupport;
6 +use ThemeAtelier\Darkify\Helpers\DarkifyUtils;
7 +use ThemeAtelier\Darkify\Helpers\Helpers;
7 8
8 -if (!defined('ABSPATH')) {
9 - die;
10 -} // Cannot access directly.
11 -
12 9 /**
13 10 * The public-facing functionality of the plugin.
14 11 *
15 12 * @link https://themeatelier.net
@@ -83,9 +80,9 @@
83 80 if ($enable_switcher_in_menu) {
84 81 add_filter('wp_nav_menu_items', array($this, 'darkify_switch_in_menu'), 10, 2);
85 82 }
86 83
87 - add_action('wp_enqueue_scripts', array($this, 'darkify_client_enqueue'), 100);
84 + add_action('wp_enqueue_scripts', array($this, 'darkify_client_enqueue'));
88 85 add_action('login_enqueue_scripts', array($this, 'darkify_client_enqueue'));
89 86 add_action('register_enqueue_scripts', array($this, 'darkify_client_enqueue'));
90 87 add_action('wp_head', array($this, 'darkify_client_header_script'), 1);
91 88 add_action('login_head', array($this, 'darkify_client_header_script'), 1);
@@ -92,351 +89,84 @@
92 89 add_action('register_head', array($this, 'darkify_client_header_script'), 1);
93 90 add_action('wp_footer', array($this, 'darkify_client_footer_script'));
94 91 add_action('login_footer', array($this, 'darkify_client_footer_script'));
95 92 add_action('register_footer', array($this, 'darkify_client_footer_script'));
96 -
97 - add_action('init', array($this, 'darkify_register_switcher_styles'), 5);
98 - add_filter('autoptimize_filter_js_exclude', array($this, 'darkify_exclude_js_from_cache_plugins'));
99 93 }
100 94
101 - public function darkify_exclude_js_from_cache_plugins($excludes)
102 - {
103 - $excludes .= ',client_main.js,client_main.min.js';
104 - return $excludes;
105 - }
106 95
107 - public function darkify_register_switcher_styles()
96 + public function darkify_client_enqueue()
108 97 {
109 - $min = (apply_filters('darkify_dev_mode', false) || WP_DEBUG) ? '' : '.min';
110 - wp_register_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main' . $min . '.css', array(), DARKIFY_VERSION);
111 - wp_register_style('theme-classic', DARKIFY_DIR_URL . 'src/assets/css/switcher/classic' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
112 - wp_register_style('theme-expand', DARKIFY_DIR_URL . 'src/assets/css/switcher/expand' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
113 - wp_register_style('theme-inner-moon', DARKIFY_DIR_URL . 'src/assets/css/switcher/inner-moon' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
114 - wp_register_style('theme-within', DARKIFY_DIR_URL . 'src/assets/css/switcher/within' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
115 - wp_register_style('theme-orbit', DARKIFY_DIR_URL . 'src/assets/css/switcher/orbit' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
116 - }
117 -
118 - function darkify_client_enqueue()
119 - {
120 98 if ($this->darkify_is_dark_mode_allowed()) {
121 99 $options = get_option('darkify');
122 - $min = (apply_filters('darkify_dev_mode', false) || WP_DEBUG) ? '' : '.min';
100 + $enable_dark_switcher = $options['enable_dark_switcher'];
101 + $enable_time = $options['enable_time'];
123 102
124 - wp_enqueue_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main' . $min . '.css', array(), DARKIFY_VERSION);
125 - wp_enqueue_script('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/js/client_main' . $min . '.js', array('jquery'), DARKIFY_VERSION);
103 + $enable_default_dark_mode = $options['enable_default_dark_mode'];
104 + $enable_time = $options['enable_time'];
105 + $enable_time_based_dark = isset($enable_time['enable_time_based_dark']) ? $enable_time['enable_time_based_dark'] : "";
106 + $time_based_dark_start = isset($enable_time['time_based_dark_start']['from']) ? $enable_time['time_based_dark_start']['from'] : "";
107 + $time_based_dark_stop = isset($enable_time['time_based_dark_start']['to']) ? $enable_time['time_based_dark_start']['to'] : "";
108 + $grayscale = $options['brightness'];
109 + $enable_low_image_brightness = isset($grayscale['enable_low_image_brightness']) ? $grayscale['enable_low_image_brightness'] : "";
110 + $low_image_brightness_label = isset($grayscale['low_image_brightness_label']) ? $grayscale['low_image_brightness_label'] : "";
111 + $grayscale = isset($options['grayscale']);
112 + $enable_image_grayscale = isset($grayscale['enable_image_grayscale']) ? $grayscale['enable_image_grayscale'] : "";
113 + $image_grayscale_label = isset($grayscale['image_grayscale_label']) ? $grayscale['image_grayscale_label'] : "";
114 + $disallowed_low_grayscale_images = isset($grayscale['disallowed_low_grayscale_images']) ? $grayscale['disallowed_low_grayscale_images'] : "";
115 + $darken_background = isset($options['darken_background']);
116 + $enable_low_image_darken = isset($darken_background['enable_low_image_darken']) ? $darken_background['enable_low_image_darken'] : "";
117 + $low_image_darken_label = isset($darken_background['low_image_darken_label']) ? $darken_background['low_image_darken_label'] : "";
118 + $video_brightness = isset($options['video_brightness']);
119 + $enable_low_video_brightness = isset($video_brightness['enable_low_video_brightness']) ? $video_brightness['enable_low_video_brightness'] : "";
120 + $low_video_brightness_label = isset($video_brightness['low_video_brightness_label']) ? $video_brightness['low_video_brightness_label'] : "";
121 + $video_grayscale = isset($options['video_grayscale']);
122 + $enable_video_grayscale = isset($video_grayscale['enable_video_grayscale']) ? $video_grayscale['enable_video_grayscale'] : "";
126 123
127 - // When "Frontend Iframe Dark Mode" is OFF, use a two-stage inline script
128 - // strategy that covers all scenarios — source JS, minified JS,
129 - // cross-origin iframes, and same-origin WP pages embedded as iframes.
130 - //
131 - // ROOT CAUSE: a same-origin WP page loaded inside an <iframe> has its
132 - // OWN copy of client_main[.min].js running. That copy calls
133 - // darkify_check_preloading() → localStorage.darkify_last_state="1" →
134 - // adds darkify_dark_mode_enabled to the iframe's <html> → goes dark.
135 - // The parent's darkify_process_iframes guard is irrelevant here.
136 - //
137 - // Stage 1 — 'before' (runs BEFORE client_main[.min].js on EVERY page):
138 - // If this page is rendering inside a frontend iframe, intercept the
139 - // localStorage.darkify_last_state property via Object.defineProperty so
140 - // that darkify_check_preloading() always reads "0" and returns false.
141 - // This prevents the iframe page's own Darkify from initialising dark
142 - // mode at all — works with both source and minified JS because
143 - // darkify_check_preloading() always reads the property directly.
144 - // The source JS also has a _dkf_iframe_disabled guard for belt-and-
145 - // suspenders coverage.
146 - //
147 - // Stage 2 — 'after' (runs AFTER client_main[.min].js on EVERY page):
148 - // • Cleans up the localStorage property intercept from Stage 1.
149 - // • Overrides the five injection helpers so the PARENT page's
150 - // darkify_apply_dark_to_iframe() applyDirect() closures (which look
151 - // up these functions by name in the global scope at call time) become
152 - // no-ops for cross-origin and not-yet-loaded iframes.
153 - $enable_frontend_iframe = isset($options['enable_frontend_iframe_dark_mode']) ? $options['enable_frontend_iframe_dark_mode'] : true;
154 - if (!$enable_frontend_iframe) {
155 124
156 - // Stage 1 — intercept localStorage.darkify_last_state BEFORE client_main.
157 - wp_add_inline_script(
158 - 'darkify-client-main',
159 - '(function(){' .
160 - // Only apply when this window is a child frame, the setting
161 - // exists and is OFF, and it is not the admin panel context.
162 - 'if(window===window.top)return;' .
163 - 'if(typeof darkify_enable_frontend_iframe_dark_mode==="undefined"' .
164 - '||darkify_enable_frontend_iframe_dark_mode==="1")return;' .
165 - 'if(typeof darkify_is_this_admin_panel!=="undefined"' .
166 - '&&darkify_is_this_admin_panel==="1")return;' .
167 - // Define an own property on localStorage that intercepts reads
168 - // of darkify_last_state. darkify_check_preloading() uses
169 - // localStorage.darkify_last_state (property access, not getItem),
170 - // so this getter is hit every time the function runs.
171 - // Returning "0" makes the function take the "was explicitly set
172 - // to 0 → not preloaded" branch and return false.
173 - // The setter is silently ignored so state writes in the iframe
174 - // don't pollute the shared localStorage for other tabs/pages.
175 - 'try{' .
176 - 'Object.defineProperty(localStorage,"darkify_last_state",{' .
177 - 'get:function(){return"0";},set:function(){},configurable:true' .
178 - '});' .
179 - '}catch(e){' .
180 - // Fallback for environments where Object.defineProperty on
181 - // Storage objects is not supported: temporarily set the value.
182 - 'try{window._dkf_ls_bk=localStorage.darkify_last_state;' .
183 - 'localStorage.darkify_last_state="0";}catch(e2){}' .
184 - '}' .
185 - '})();',
186 - 'before'
187 - );
188 125
189 - // Stage 2 — cleanup + injection helper overrides AFTER client_main.
190 - wp_add_inline_script(
191 - 'darkify-client-main',
192 - '(function(){' .
193 - // Remove the own-property intercept so subsequent reads of
194 - // localStorage.darkify_last_state return the real stored value.
195 - // "delete" removes the own property, restoring prototype lookup.
196 - 'if(window!==window.top){' .
197 - 'try{delete localStorage.darkify_last_state;}catch(e){' .
198 - // Fallback: restore saved value
199 - 'try{if(typeof window._dkf_ls_bk!=="undefined"){' .
200 - 'if(window._dkf_ls_bk)localStorage.darkify_last_state=window._dkf_ls_bk;' .
201 - 'else localStorage.removeItem("darkify_last_state");' .
202 - '}delete window._dkf_ls_bk;}catch(e2){}' .
203 - '}' .
204 - '}' .
205 - // Override injection helpers so the PARENT page's applyDirect()
206 - // closures (which already hold references to these global
207 - // functions) become no-ops for frontend iframes.
208 - 'function _dkfAdmin(){' .
209 - 'return typeof darkify_is_this_admin_panel!=="undefined"&&darkify_is_this_admin_panel==="1";' .
210 - '}' .
211 - 'if(typeof darkify_process_iframes==="function"){' .
212 - 'var _op=darkify_process_iframes;' .
213 - 'darkify_process_iframes=function(){if(_dkfAdmin())return _op();};' .
214 - '}' .
215 - 'if(typeof darkify_inject_css_into_iframe==="function"){' .
216 - 'var _oi=darkify_inject_css_into_iframe;' .
217 - 'darkify_inject_css_into_iframe=function(d){if(_dkfAdmin())return _oi(d);};' .
218 - '}' .
219 - 'if(typeof darkify_sync_iframe_vars==="function"){' .
220 - 'var _ov=darkify_sync_iframe_vars;' .
221 - 'darkify_sync_iframe_vars=function(d){if(_dkfAdmin())return _ov(d);};' .
222 - '}' .
223 - 'if(typeof darkify_run_engine_on_iframe==="function"){' .
224 - 'var _oe=darkify_run_engine_on_iframe;' .
225 - 'darkify_run_engine_on_iframe=function(d){if(_dkfAdmin())return _oe(d);};' .
226 - '}' .
227 - 'if(typeof darkify_inject_block_editor_css_into_iframe==="function"){' .
228 - 'var _ob=darkify_inject_block_editor_css_into_iframe;' .
229 - 'darkify_inject_block_editor_css_into_iframe=function(d){if(_dkfAdmin())return _ob(d);};' .
230 - '}' .
231 - '})();',
232 - 'after'
233 - );
234 - }
126 + wp_enqueue_style("theme-{$enable_dark_switcher}", DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/$enable_dark_switcher.css", array(), DARKIFY_VERSION, 'all');
127 + wp_register_style('theme-around', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/around.css", array(), DARKIFY_VERSION, 'all');
128 + wp_register_style('theme-classic', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/classic.css", array(), DARKIFY_VERSION, 'all');
129 + wp_register_style('theme-dark-inner', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/dark-inner.css", array(), DARKIFY_VERSION, 'all');
130 + wp_register_style('theme-dark-side', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/dark-side.css", array(), DARKIFY_VERSION, 'all');
131 + wp_register_style('theme-eclipse', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/eclipse.css", array(), DARKIFY_VERSION, 'all');
132 + wp_register_style('theme-expand', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/expand.css", array(), DARKIFY_VERSION, 'all');
133 + wp_register_style('theme-half-sun', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/half-sun.css", array(), DARKIFY_VERSION, 'all');
134 + wp_register_style('theme-horizon', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/horizon.css", array(), DARKIFY_VERSION, 'all');
135 + wp_register_style('theme-inner-moon', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/inner-moon.css", array(), DARKIFY_VERSION, 'all');
136 + wp_register_style('theme-lightbulb', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/lightbulb.css", array(), DARKIFY_VERSION, 'all');
137 + wp_register_style('theme-simple', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/simple.css", array(), DARKIFY_VERSION, 'all');
138 + wp_register_style('theme-within', DARKIFY_DIR_URL . "src/Frontend/assets/css/switcher/within.css", array(), DARKIFY_VERSION, 'all');
139 + wp_enqueue_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main.css', array(), DARKIFY_VERSION);
140 + wp_enqueue_style('ico-font', DARKIFY_DIR_URL . 'src/assets/css/icofont.css', array(), DARKIFY_VERSION);
141 + wp_enqueue_script('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/js/client_main.js', array('jquery'), DARKIFY_VERSION);
235 142
236 - // Enqueue the global floating switcher style from settings
237 - $enable_dark_mode_switch = isset($options['enable_dark_mode_switch']) ? $options['enable_dark_mode_switch'] : true;
238 - if ($enable_dark_mode_switch) {
239 - $global_variant = isset($options['enable_dark_switcher']) ? $options['enable_dark_switcher'] : 'classic';
240 - wp_enqueue_style('theme-' . $global_variant);
241 -
242 - // Separate mobile floating switcher (Different Switch in Mobile) — its toggler
243 - // style may differ from the default, so enqueue that variant's CSS as well.
244 - if (!empty($options['dark_switcher_switch_in_mobile'])) {
245 - $mobile_variant = isset($options['enable_dark_switcher_in_mobile']) ? $options['enable_dark_switcher_in_mobile'] : 'classic';
246 - wp_enqueue_style('theme-' . $this->darkify_switch_to_variant($mobile_variant));
247 - }
248 - }
249 -
250 - // Detect [darkify] shortcode usage in current post and enqueue its variant
251 - $post = get_post();
252 - if ($post && !empty($post->post_content)) {
253 - if (has_shortcode($post->post_content, 'darkify')) {
254 - preg_match_all('/\[darkify\b[^\]]*\bswitch=["\']([^"\']+)["\'][^\]]*\]/i', $post->post_content, $matches);
255 - $used_switches = !empty($matches[1]) ? $matches[1] : [];
256 - foreach ($used_switches as $switch_val) {
257 - wp_enqueue_style('theme-' . $this->darkify_switch_to_variant($switch_val));
258 - }
259 - // Shortcode without switch= attribute defaults to classic
260 - preg_match_all('/\[darkify\b/i', $post->post_content, $all_sc);
261 - if (count($all_sc[0]) > count($used_switches)) {
262 - wp_enqueue_style('theme-classic');
263 - }
264 - }
265 -
266 - // Detect darkify/switcher Gutenberg block usage and enqueue its variant
267 - if (function_exists('has_block') && has_block('darkify/switcher', $post)) {
268 - foreach ($this->darkify_get_block_variants($post->post_content) as $variant) {
269 - wp_enqueue_style('theme-' . $variant);
270 - }
271 - }
272 - }
273 -
274 - // Detect switcher used in nav menus and enqueue its variant
275 - $show_in_menu = isset($options['show_in_menu']) ? $options['show_in_menu'] : [];
276 - $enable_in_menu = isset($show_in_menu['enable_switch_in_menu']) ? $show_in_menu['enable_switch_in_menu'] : false;
277 - if ($enable_in_menu) {
278 - $select_menus = isset($show_in_menu['select_menus']) ? $show_in_menu['select_menus'] : [];
279 - foreach ($select_menus as $select_menu) {
280 - $shortcode = $select_menu['darkify_menu_shortcode_helper'] ?? '';
281 - if ($shortcode) {
282 - preg_match('/\bswitch=["\']([^"\']+)["\']/', $shortcode, $m);
283 - $switch_val = $m[1] ?? '1';
284 - wp_enqueue_style('theme-' . $this->darkify_switch_to_variant($switch_val));
285 - }
286 - }
287 - }
143 + $darkify_data = array(
144 + 'darkify_switch_unique_id' => $this->unique_id,
145 + 'darkify_is_this_admin_panel' => is_admin() ? "1" : "0",
146 + 'darkify_enable_default_dark_mode' => $enable_default_dark_mode,
147 + 'darkify_enable_os_aware' => $options["enable_os_aware"],
148 + 'darkify_enable_keyboard_shortcut' => $options["enable_keyboard_shortcut"],
149 + 'darkify_enable_time_based_dark' => $enable_time_based_dark,
150 + 'darkify_time_based_dark_start' => $time_based_dark_start ? $time_based_dark_start : "19:00",
151 + 'darkify_time_based_dark_stop' => $time_based_dark_stop ? $time_based_dark_stop : "07:00",
152 + 'darkify_alternative_dark_mode_switch' => $options["alternative_dark_mode_switcher"],
153 + 'darkify_enable_low_image_brightness' => $enable_low_image_brightness,
154 + 'darkify_image_brightness_to' => $low_image_brightness_label,
155 + 'darkify_enable_image_grayscale' => $enable_image_grayscale,
156 + 'darkify_image_grayscale_to' => $image_grayscale_label,
157 + 'darkify_disallowed_grayscale_images' => $disallowed_low_grayscale_images,
158 + 'darkify_enable_bg_image_darken' => $enable_low_image_darken,
159 + 'darkify_bg_image_darken_to' => $low_image_darken_label,
160 + 'darkify_enable_invert_inline_svg' => $options["enable_invert_inline_svg"],
161 + 'darkify_enable_low_video_brightness' => $enable_low_video_brightness,
162 + 'darkify_video_brightness_to' => $low_video_brightness_label,
163 + 'darkify_enable_video_grayscale' => $enable_video_grayscale,
164 + // Add more variables as needed...
165 + );
166 + wp_localize_script('darkify-client-main', 'darkify_data', $darkify_data);
288 167 }
289 168 }
290 -
291 - private function darkify_switch_to_variant($switch_value)
292 - {
293 - $map = [
294 - '1' => 'classic', '2' => 'expand', '3' => 'inner-moon',
295 - '4' => 'within', '5' => 'orbit',
296 - ];
297 - if (is_numeric($switch_value)) {
298 - return $map[(string) $switch_value] ?? 'classic';
299 - }
300 - return $switch_value ?: 'classic';
301 - }
302 -
303 - private function darkify_get_block_variants($content)
304 - {
305 - $variants = [];
306 - $this->darkify_collect_block_variants(parse_blocks($content), $variants);
307 - return array_unique($variants);
308 - }
309 -
310 - private function darkify_collect_block_variants($blocks, &$variants)
311 - {
312 - foreach ($blocks as $block) {
313 - if ('darkify/switcher' === $block['blockName']) {
314 - $variants[] = $block['attrs']['style'] ?? 'classic';
315 - }
316 - if (!empty($block['innerBlocks'])) {
317 - $this->darkify_collect_block_variants($block['innerBlocks'], $variants);
318 - }
319 - }
320 -
321 - $options = get_option('darkify');
322 - $min = (apply_filters('darkify_dev_mode', false) || WP_DEBUG) ? '' : '.min';
323 -
324 - // Always register all variant styles so page builders (Elementor, etc.) can reference them.
325 - wp_register_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main' . $min . '.css', array(), DARKIFY_VERSION);
326 - wp_register_style('theme-classic', DARKIFY_DIR_URL . 'src/assets/css/switcher/classic' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
327 - wp_register_style('theme-expand', DARKIFY_DIR_URL . 'src/assets/css/switcher/expand' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
328 - wp_register_style('theme-inner-moon', DARKIFY_DIR_URL . 'src/assets/css/switcher/inner-moon' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
329 - wp_register_style('theme-orbit', DARKIFY_DIR_URL . 'src/assets/css/switcher/orbit' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
330 - wp_register_style('theme-within', DARKIFY_DIR_URL . 'src/assets/css/switcher/within' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
331 -
332 - // Determine which variants are actually needed on this page.
333 - $variants = $this->darkify_collect_page_variants($options);
334 -
335 - if (empty($variants)) {
336 - return;
337 - }
338 -
339 - // Enqueue main CSS + only the required variant CSS — all resolved before wp_head fires.
340 - wp_enqueue_style('darkify-client-main');
341 - foreach ($variants as $variant) {
342 - wp_enqueue_style("theme-{$variant}");
343 - }
344 - wp_enqueue_script('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/js/client_main' . $min . '.js', array('jquery'), DARKIFY_VERSION);
345 - }
346 -
347 - /**
348 - * Collects all switcher variants needed on the current page so they can be
349 - * enqueued during wp_enqueue_scripts (before wp_head), guaranteeing CSS loads
350 - * in the <head> regardless of page builder or theme.
351 - */
352 - private function darkify_collect_page_variants($options)
353 - {
354 - $all_variants = array('classic', 'expand', 'inner-moon', 'orbit', 'within');
355 - $num_map = array('1' => 'classic', '2' => 'expand', '3' => 'inner-moon', '4' => 'within', '5' => 'orbit');
356 - $variants = array();
357 -
358 - // 1. Global / floating switcher variant (always present when dark mode is active).
359 - $global_variant = isset($options['enable_dark_switcher']) ? $options['enable_dark_switcher'] : 'classic';
360 - if (in_array($global_variant, $all_variants, true)) {
361 - $variants[] = $global_variant;
362 - }
363 -
364 - // 2. Menu switcher — parse variant from each saved shortcode helper string.
365 - $show_in_menu = isset($options['show_in_menu']) ? $options['show_in_menu'] : array();
366 - if (!empty($show_in_menu['enable_switch_in_menu']) && !empty($show_in_menu['select_menus'])) {
367 - foreach ($show_in_menu['select_menus'] as $menu_item) {
368 - $helper = isset($menu_item['darkify_menu_shortcode_helper']) ? $menu_item['darkify_menu_shortcode_helper'] : '';
369 - if ($helper && preg_match('/switch=["\']?([^"\'>\s\]]+)["\']?/', $helper, $m)) {
370 - $v = isset($num_map[$m[1]]) ? $num_map[$m[1]] : $m[1];
371 - if (in_array($v, $all_variants, true)) {
372 - $variants[] = $v;
373 - }
374 - }
375 - }
376 - }
377 -
378 - // 3. Page-level detection — shortcodes, Gutenberg blocks, Elementor widget.
379 - global $post;
380 - if ($post) {
381 - $content = $post->post_content;
382 -
383 - // Shortcodes: parse switch attribute from every [darkify] tag.
384 - if (has_shortcode($content, 'darkify')) {
385 - preg_match_all('/\[darkify[^\]]*switch=["\']?([^"\'>\s\]]+)/', $content, $sc_matches);
386 - foreach ($sc_matches[1] as $switch_val) {
387 - $v = isset($num_map[$switch_val]) ? $num_map[$switch_val] : $switch_val;
388 - if (in_array($v, $all_variants, true)) {
389 - $variants[] = $v;
390 - } else {
391 - $variants[] = 'classic'; // default when no valid variant found
392 - }
393 - }
394 - // If [darkify] exists but has no switch attribute, default to classic.
395 - if (empty($sc_matches[1]) && has_shortcode($content, 'darkify')) {
396 - $variants[] = 'classic';
397 - }
398 - }
399 -
400 - // Gutenberg blocks: walk the block tree and collect style attributes.
401 - if (function_exists('has_block') && has_block('darkify/switcher', $post)) {
402 - $blocks = parse_blocks($content);
403 - $variants = array_merge($variants, $this->darkify_extract_block_variants($blocks, $all_variants));
404 - }
405 -
406 - // Elementor widget: if Darkify widget appears in the page's Elementor data,
407 - // load all variants — the specific style is stored as a control value that
408 - // would require deep JSON parsing to extract reliably.
409 - if (class_exists('\Elementor\Plugin')) {
410 - $elementor_data = get_post_meta($post->ID, '_elementor_data', true);
411 - if ($elementor_data && strpos($elementor_data, '"widgetType":"darkify"') !== false) {
412 - return $all_variants;
413 - }
414 - }
415 - }
416 -
417 - return array_values(array_unique(array_filter($variants)));
418 - }
419 -
420 - /**
421 - * Recursively walks a parsed block tree and collects darkify/darkify style values.
422 - */
423 - private function darkify_extract_block_variants($blocks, $all_variants)
424 - {
425 - $variants = array();
426 - foreach ($blocks as $block) {
427 - if ('darkify/switcher' === $block['blockName']) {
428 - $style = isset($block['attrs']['style']) ? $block['attrs']['style'] : 'classic';
429 - if (in_array($style, $all_variants, true)) {
430 - $variants[] = $style;
431 - }
432 - }
433 - if (!empty($block['innerBlocks'])) {
434 - $variants = array_merge($variants, $this->darkify_extract_block_variants($block['innerBlocks'], $all_variants));
435 - }
436 - }
437 - return $variants;
438 - }
439 169 public function darkify_is_dark_mode_allowed()
440 170 {
441 171 $options = get_option('darkify');
442 172 /* Disable if Oxygen Builder is Opened */
@@ -454,9 +184,9 @@
454 184
455 185 public function darkify_client_header_script()
456 186 {
457 187 if ($this->darkify_is_dark_mode_allowed()) {
458 - include_once DarkifyUtils::darkify_locate_template('header_script.php');
188 + include_once Helpers::darkify_locate_template('header_script.php');
459 189 }
460 190 }
461 191
462 192 public function darkify_client_footer_script()
@@ -461,34 +191,25 @@
461 191
462 192 public function darkify_client_footer_script()
463 193 {
464 194 if ($this->darkify_is_dark_mode_allowed()) {
465 - include_once DarkifyUtils::darkify_locate_template('footer_script.php');
195 + include_once Helpers::darkify_locate_template('footer_script.php');
466 196 }
467 197 }
468 198
469 - function darkify_switch_in_menu($items, $args)
199 + public function darkify_switch_in_menu($items, $args)
470 200 {
471 201 $options = get_option('darkify');
472 202 $show_in_menu = $options['show_in_menu'];
473 - $select_menus = isset($show_in_menu['select_menus']) ? $show_in_menu['select_menus'] : [];
203 + $switch_in_menu_location = $show_in_menu['switch_in_menu_location'];
204 + $darkify_menu_shortcode_helper = $show_in_menu['darkify_menu_shortcode_helper'];
474 205
475 - $last_shortcode = '';
476 -
477 - if ($this->darkify_is_dark_mode_allowed() && isset($args->menu->term_id)) {
478 - foreach ($select_menus as $select_menu) {
479 -
480 - $switch_in_menu_location = $select_menu['switch_in_menu_location'] ?? '';
481 - $darkify_menu_shortcode_helper = $select_menu['darkify_menu_shortcode_helper'] ?? '';
482 - $menu_position = isset($select_menu['select_menu_position']) ? $select_menu['select_menu_position'] : 'after';
206 + if ($this->darkify_is_dark_mode_allowed()) {
207 + if (isset($args->menu->term_id)) {
483 208 if ($args->menu->term_id == $switch_in_menu_location) {
484 - $last_shortcode = $darkify_menu_shortcode_helper;
209 + $items .= '<li class="menu-item">' . do_shortcode($darkify_menu_shortcode_helper) . '</li>';
485 210 }
486 211 }
487 - if ($last_shortcode) {
488 - $items = ($menu_position == 'before') ? '<li class="menu-item">' . do_shortcode($last_shortcode) . '</li>' . $items : $items . '<li class="menu-item">' . do_shortcode($last_shortcode) . '</li>';
489 - }
490 212 }
491 -
492 213 return $items;
493 214 }
494 215 }