PluginProbe
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) / trunk
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) vtrunk
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 1.3.1 All 56 releases
darkify / src / Frontend / Frontend.php

Frontend.php in Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) trunk, at src/Frontend/Frontend.php

517 lines 25.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace ThemeAtelier\Darkify\Frontend;
4
5 use ThemeAtelier\Darkify\Includes\DarkifyExternalSupport;
6 use ThemeAtelier\Darkify\Includes\DarkifyUtils;
7
8 if (!defined('ABSPATH')) {
9 die;
10 } // Cannot access directly.
11
12 /**
13 * The public-facing functionality of the plugin.
14 *
15 * @link https://themeatelier.net
16 * @since 1.0.0
17 *
18 * @package Darkify
19 * @subpackage Darkify/public
20 */
21
22 /**
23 * The public-facing functionality of the plugin.
24 *
25 * Defines the plugin name, version, and two examples hooks for how to
26 * enqueue the public-facing stylesheet and JavaScript.
27 *
28 * @package Darkify
29 * @subpackage Darkify/public
30 * @author ThemeAtelier <themeatelierbd@gmail.com>
31 */
32 class Frontend
33 {
34
35 /**
36 * The ID of this plugin.
37 *
38 * @since 1.0.0
39 * @access private
40 * @var string $plugin_name The ID of this plugin.
41 */
42 private $plugin_name;
43
44 /**
45 * The version of this plugin.
46 *
47 * @since 1.0.0
48 * @access private
49 * @var string $version The current version of this plugin.
50 */
51 private $version;
52
53 public $utils;
54 public $settings;
55 public $external_support;
56 public $unique_id;
57
58 /**
59 * Initialize the class and set its properties.
60 *
61 * @since 1.0.0
62 * @param string $plugin_name The name of the plugin.
63 * @param string $version The version of this plugin.
64 */
65 public function __construct($plugin_name, $version)
66 {
67 $this->plugin_name = $plugin_name;
68 $this->version = $version;
69
70 $this->utils = new DarkifyUtils($this);
71 $this->external_support = new DarkifyExternalSupport($this);
72
73 new DarkifyShortcode($this);
74
75 if (function_exists('wp_rand')) {
76 $this->unique_id = wp_rand();
77 }
78
79 // Register unconditionally and gate inside the callback. The constructor
80 // runs at plugin boot (before `init`), so the option read here is always
81 // the SAVED value — deciding registration here means the admin Live
82 // Preview, which swaps in unsaved values only on `init` (see
83 // PreviewRest::maybe_enable_preview), could never show a newly enabled
84 // menu switch until saved. The filter runs at render time, after `init`,
85 // so re-reading the option in the callback sees the preview values.
86 add_filter('wp_nav_menu_items', array($this, 'darkify_switch_in_menu'), 10, 2);
87
88 add_action('wp_enqueue_scripts', array($this, 'darkify_client_enqueue'), 100);
89 add_action('login_enqueue_scripts', array($this, 'darkify_client_enqueue'));
90 add_action('register_enqueue_scripts', array($this, 'darkify_client_enqueue'));
91 add_action('wp_head', array($this, 'darkify_client_header_script'), 1);
92 add_action('login_head', array($this, 'darkify_client_header_script'), 1);
93 add_action('register_head', array($this, 'darkify_client_header_script'), 1);
94 add_action('wp_footer', array($this, 'darkify_client_footer_script'));
95 add_action('login_footer', array($this, 'darkify_client_footer_script'));
96 add_action('register_footer', array($this, 'darkify_client_footer_script'));
97
98 add_action('init', array($this, 'darkify_register_switcher_styles'), 5);
99 add_filter('autoptimize_filter_js_exclude', array($this, 'darkify_exclude_js_from_cache_plugins'));
100 }
101
102 public function darkify_exclude_js_from_cache_plugins($excludes)
103 {
104 $excludes .= ',client_main.js,client_main.min.js';
105 return $excludes;
106 }
107
108 public function darkify_register_switcher_styles()
109 {
110 $min = (apply_filters('darkify_dev_mode', false) || WP_DEBUG) ? '' : '.min';
111 wp_register_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main' . $min . '.css', array(), DARKIFY_VERSION);
112 wp_register_style('theme-classic', DARKIFY_DIR_URL . 'src/assets/css/switcher/classic' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
113 wp_register_style('theme-expand', DARKIFY_DIR_URL . 'src/assets/css/switcher/expand' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
114 wp_register_style('theme-inner-moon', DARKIFY_DIR_URL . 'src/assets/css/switcher/inner-moon' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
115 wp_register_style('theme-within', DARKIFY_DIR_URL . 'src/assets/css/switcher/within' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
116 wp_register_style('theme-orbit', DARKIFY_DIR_URL . 'src/assets/css/switcher/orbit' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
117 }
118
119 function darkify_client_enqueue()
120 {
121 if ($this->darkify_is_dark_mode_allowed()) {
122 $options = get_option('darkify');
123 $min = (apply_filters('darkify_dev_mode', false) || WP_DEBUG) ? '' : '.min';
124
125 wp_enqueue_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main' . $min . '.css', array(), DARKIFY_VERSION);
126 wp_enqueue_script('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/js/client_main' . $min . '.js', array(), DARKIFY_VERSION);
127
128 // When "Frontend Iframe Dark Mode" is OFF, use a two-stage inline script
129 // strategy that covers all scenarios — source JS, minified JS,
130 // cross-origin iframes, and same-origin WP pages embedded as iframes.
131 //
132 // ROOT CAUSE: a same-origin WP page loaded inside an <iframe> has its
133 // OWN copy of client_main[.min].js running. That copy calls
134 // darkify_check_preloading() → localStorage.darkify_last_state="1" →
135 // adds darkify_dark_mode_enabled to the iframe's <html> → goes dark.
136 // The parent's darkify_process_iframes guard is irrelevant here.
137 //
138 // Stage 1 — 'before' (runs BEFORE client_main[.min].js on EVERY page):
139 // If this page is rendering inside a frontend iframe, intercept the
140 // localStorage.darkify_last_state property via Object.defineProperty so
141 // that darkify_check_preloading() always reads "0" and returns false.
142 // This prevents the iframe page's own Darkify from initialising dark
143 // mode at all — works with both source and minified JS because
144 // darkify_check_preloading() always reads the property directly.
145 // The source JS also has a _dkf_iframe_disabled guard for belt-and-
146 // suspenders coverage.
147 //
148 // Stage 2 — 'after' (runs AFTER client_main[.min].js on EVERY page):
149 // • Cleans up the localStorage property intercept from Stage 1.
150 // • Overrides the five injection helpers so the PARENT page's
151 // darkify_apply_dark_to_iframe() applyDirect() closures (which look
152 // up these functions by name in the global scope at call time) become
153 // no-ops for cross-origin and not-yet-loaded iframes.
154 $enable_frontend_iframe = isset($options['enable_frontend_iframe_dark_mode']) ? $options['enable_frontend_iframe_dark_mode'] : true;
155 if (!$enable_frontend_iframe) {
156
157 // Stage 1 — intercept localStorage.darkify_last_state BEFORE client_main.
158 wp_add_inline_script(
159 'darkify-client-main',
160 '(function(){' .
161 // Only apply when this window is a child frame, the setting
162 // exists and is OFF, and it is not the admin panel context.
163 'if(window===window.top)return;' .
164 'if(typeof darkify_enable_frontend_iframe_dark_mode==="undefined"' .
165 '||darkify_enable_frontend_iframe_dark_mode==="1")return;' .
166 'if(typeof darkify_is_this_admin_panel!=="undefined"' .
167 '&&darkify_is_this_admin_panel==="1")return;' .
168 // Define an own property on localStorage that intercepts reads
169 // of darkify_last_state. darkify_check_preloading() uses
170 // localStorage.darkify_last_state (property access, not getItem),
171 // so this getter is hit every time the function runs.
172 // Returning "0" makes the function take the "was explicitly set
173 // to 0 → not preloaded" branch and return false.
174 // The setter is silently ignored so state writes in the iframe
175 // don't pollute the shared localStorage for other tabs/pages.
176 'try{' .
177 'Object.defineProperty(localStorage,"darkify_last_state",{' .
178 'get:function(){return"0";},set:function(){},configurable:true' .
179 '});' .
180 '}catch(e){' .
181 // Fallback for environments where Object.defineProperty on
182 // Storage objects is not supported: temporarily set the value.
183 'try{window._dkf_ls_bk=localStorage.darkify_last_state;' .
184 'localStorage.darkify_last_state="0";}catch(e2){}' .
185 '}' .
186 '})();',
187 'before'
188 );
189
190 // Stage 2 — cleanup + injection helper overrides AFTER client_main.
191 wp_add_inline_script(
192 'darkify-client-main',
193 '(function(){' .
194 // Remove the own-property intercept so subsequent reads of
195 // localStorage.darkify_last_state return the real stored value.
196 // "delete" removes the own property, restoring prototype lookup.
197 'if(window!==window.top){' .
198 'try{delete localStorage.darkify_last_state;}catch(e){' .
199 // Fallback: restore saved value
200 'try{if(typeof window._dkf_ls_bk!=="undefined"){' .
201 'if(window._dkf_ls_bk)localStorage.darkify_last_state=window._dkf_ls_bk;' .
202 'else localStorage.removeItem("darkify_last_state");' .
203 '}delete window._dkf_ls_bk;}catch(e2){}' .
204 '}' .
205 '}' .
206 // Override injection helpers so the PARENT page's applyDirect()
207 // closures (which already hold references to these global
208 // functions) become no-ops for frontend iframes.
209 'function _dkfAdmin(){' .
210 'return typeof darkify_is_this_admin_panel!=="undefined"&&darkify_is_this_admin_panel==="1";' .
211 '}' .
212 'if(typeof darkify_process_iframes==="function"){' .
213 'var _op=darkify_process_iframes;' .
214 'darkify_process_iframes=function(){if(_dkfAdmin())return _op();};' .
215 '}' .
216 'if(typeof darkify_inject_css_into_iframe==="function"){' .
217 'var _oi=darkify_inject_css_into_iframe;' .
218 'darkify_inject_css_into_iframe=function(d){if(_dkfAdmin())return _oi(d);};' .
219 '}' .
220 'if(typeof darkify_sync_iframe_vars==="function"){' .
221 'var _ov=darkify_sync_iframe_vars;' .
222 'darkify_sync_iframe_vars=function(d){if(_dkfAdmin())return _ov(d);};' .
223 '}' .
224 'if(typeof darkify_run_engine_on_iframe==="function"){' .
225 'var _oe=darkify_run_engine_on_iframe;' .
226 'darkify_run_engine_on_iframe=function(d){if(_dkfAdmin())return _oe(d);};' .
227 '}' .
228 'if(typeof darkify_inject_block_editor_css_into_iframe==="function"){' .
229 'var _ob=darkify_inject_block_editor_css_into_iframe;' .
230 'darkify_inject_block_editor_css_into_iframe=function(d){if(_dkfAdmin())return _ob(d);};' .
231 '}' .
232 '})();',
233 'after'
234 );
235 }
236
237 // Enqueue the global floating switcher style from settings
238 $enable_dark_mode_switch = isset($options['enable_dark_mode_switch']) ? $options['enable_dark_mode_switch'] : true;
239 if ($enable_dark_mode_switch) {
240 $global_variant = isset($options['enable_dark_switcher']) ? $options['enable_dark_switcher'] : 'classic';
241 wp_enqueue_style('theme-' . $global_variant);
242
243 // Separate mobile floating switcher (Different Switch in Mobile) — its toggler
244 // style may differ from the default, so enqueue that variant's CSS as well.
245 if (!empty($options['dark_switcher_switch_in_mobile'])) {
246 $mobile_variant = isset($options['enable_dark_switcher_in_mobile']) ? $options['enable_dark_switcher_in_mobile'] : 'classic';
247 wp_enqueue_style('theme-' . $this->darkify_switch_to_variant($mobile_variant));
248 }
249 }
250
251 // Detect [darkify] shortcode usage in current post and enqueue its variant
252 $post = get_post();
253 if ($post && !empty($post->post_content)) {
254 if (has_shortcode($post->post_content, 'darkify')) {
255 preg_match_all('/\[darkify\b[^\]]*\bswitch=["\']([^"\']+)["\'][^\]]*\]/i', $post->post_content, $matches);
256 $used_switches = !empty($matches[1]) ? $matches[1] : [];
257 foreach ($used_switches as $switch_val) {
258 wp_enqueue_style('theme-' . $this->darkify_switch_to_variant($switch_val));
259 }
260 // Shortcode without switch= attribute defaults to classic
261 preg_match_all('/\[darkify\b/i', $post->post_content, $all_sc);
262 if (count($all_sc[0]) > count($used_switches)) {
263 wp_enqueue_style('theme-classic');
264 }
265 }
266
267 // Detect darkify/switcher Gutenberg block usage and enqueue its variant
268 if (function_exists('has_block') && has_block('darkify/switcher', $post)) {
269 foreach ($this->darkify_get_block_variants($post->post_content) as $variant) {
270 wp_enqueue_style('theme-' . $variant);
271 }
272 }
273 }
274
275 // Detect switcher used in nav menus and enqueue its variant
276 $show_in_menu = isset($options['show_in_menu']) ? $options['show_in_menu'] : [];
277 $enable_in_menu = isset($show_in_menu['enable_switch_in_menu']) ? $show_in_menu['enable_switch_in_menu'] : false;
278 if ($enable_in_menu) {
279 $select_menus = isset($show_in_menu['select_menus']) ? $show_in_menu['select_menus'] : [];
280 foreach ($select_menus as $select_menu) {
281 $shortcode = $select_menu['darkify_menu_shortcode_helper'] ?? '';
282 if ($shortcode) {
283 preg_match('/\bswitch=["\']([^"\']+)["\']/', $shortcode, $m);
284 $switch_val = $m[1] ?? '1';
285 wp_enqueue_style('theme-' . $this->darkify_switch_to_variant($switch_val));
286 }
287 }
288 }
289 }
290 }
291
292 private function darkify_switch_to_variant($switch_value)
293 {
294 $map = [
295 '1' => 'classic', '2' => 'expand', '3' => 'inner-moon',
296 '4' => 'within', '5' => 'orbit',
297 ];
298 if (is_numeric($switch_value)) {
299 return $map[(string) $switch_value] ?? 'classic';
300 }
301 return $switch_value ?: 'classic';
302 }
303
304 private function darkify_get_block_variants($content)
305 {
306 $variants = [];
307 $this->darkify_collect_block_variants(parse_blocks($content), $variants);
308 return array_unique($variants);
309 }
310
311 private function darkify_collect_block_variants($blocks, &$variants)
312 {
313 foreach ($blocks as $block) {
314 if ('darkify/switcher' === $block['blockName']) {
315 $variants[] = $block['attrs']['style'] ?? 'classic';
316 }
317 if (!empty($block['innerBlocks'])) {
318 $this->darkify_collect_block_variants($block['innerBlocks'], $variants);
319 }
320 }
321
322 $options = get_option('darkify');
323 $min = (apply_filters('darkify_dev_mode', false) || WP_DEBUG) ? '' : '.min';
324
325 // Always register all variant styles so page builders (Elementor, etc.) can reference them.
326 wp_register_style('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/css/client_main' . $min . '.css', array(), DARKIFY_VERSION);
327 wp_register_style('theme-classic', DARKIFY_DIR_URL . 'src/assets/css/switcher/classic' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
328 wp_register_style('theme-expand', DARKIFY_DIR_URL . 'src/assets/css/switcher/expand' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
329 wp_register_style('theme-inner-moon', DARKIFY_DIR_URL . 'src/assets/css/switcher/inner-moon' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
330 wp_register_style('theme-orbit', DARKIFY_DIR_URL . 'src/assets/css/switcher/orbit' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
331 wp_register_style('theme-within', DARKIFY_DIR_URL . 'src/assets/css/switcher/within' . $min . '.css', array('darkify-client-main'), DARKIFY_VERSION, 'all');
332
333 // Determine which variants are actually needed on this page.
334 $variants = $this->darkify_collect_page_variants($options);
335
336 if (empty($variants)) {
337 return;
338 }
339
340 // Enqueue main CSS + only the required variant CSS — all resolved before wp_head fires.
341 wp_enqueue_style('darkify-client-main');
342 foreach ($variants as $variant) {
343 wp_enqueue_style("theme-{$variant}");
344 }
345 wp_enqueue_script('darkify-client-main', DARKIFY_DIR_URL . 'src/assets/js/client_main' . $min . '.js', array(), DARKIFY_VERSION);
346 }
347
348 /**
349 * Collects all switcher variants needed on the current page so they can be
350 * enqueued during wp_enqueue_scripts (before wp_head), guaranteeing CSS loads
351 * in the <head> regardless of page builder or theme.
352 */
353 private function darkify_collect_page_variants($options)
354 {
355 $all_variants = array('classic', 'expand', 'inner-moon', 'orbit', 'within');
356 $num_map = array('1' => 'classic', '2' => 'expand', '3' => 'inner-moon', '4' => 'within', '5' => 'orbit');
357 $variants = array();
358
359 // 1. Global / floating switcher variant (always present when dark mode is active).
360 $global_variant = isset($options['enable_dark_switcher']) ? $options['enable_dark_switcher'] : 'classic';
361 if (in_array($global_variant, $all_variants, true)) {
362 $variants[] = $global_variant;
363 }
364
365 // 2. Menu switcher — parse variant from each saved shortcode helper string.
366 $show_in_menu = isset($options['show_in_menu']) ? $options['show_in_menu'] : array();
367 if (!empty($show_in_menu['enable_switch_in_menu']) && !empty($show_in_menu['select_menus'])) {
368 foreach ($show_in_menu['select_menus'] as $menu_item) {
369 $helper = isset($menu_item['darkify_menu_shortcode_helper']) ? $menu_item['darkify_menu_shortcode_helper'] : '';
370 if ($helper && preg_match('/switch=["\']?([^"\'>\s\]]+)["\']?/', $helper, $m)) {
371 $v = isset($num_map[$m[1]]) ? $num_map[$m[1]] : $m[1];
372 if (in_array($v, $all_variants, true)) {
373 $variants[] = $v;
374 }
375 }
376 }
377 }
378
379 // 3. Page-level detection — shortcodes, Gutenberg blocks, Elementor widget.
380 global $post;
381 if ($post) {
382 $content = $post->post_content;
383
384 // Shortcodes: parse switch attribute from every [darkify] tag.
385 if (has_shortcode($content, 'darkify')) {
386 preg_match_all('/\[darkify[^\]]*switch=["\']?([^"\'>\s\]]+)/', $content, $sc_matches);
387 foreach ($sc_matches[1] as $switch_val) {
388 $v = isset($num_map[$switch_val]) ? $num_map[$switch_val] : $switch_val;
389 if (in_array($v, $all_variants, true)) {
390 $variants[] = $v;
391 } else {
392 $variants[] = 'classic'; // default when no valid variant found
393 }
394 }
395 // If [darkify] exists but has no switch attribute, default to classic.
396 if (empty($sc_matches[1]) && has_shortcode($content, 'darkify')) {
397 $variants[] = 'classic';
398 }
399 }
400
401 // Gutenberg blocks: walk the block tree and collect style attributes.
402 if (function_exists('has_block') && has_block('darkify/switcher', $post)) {
403 $blocks = parse_blocks($content);
404 $variants = array_merge($variants, $this->darkify_extract_block_variants($blocks, $all_variants));
405 }
406
407 // Elementor widget: if Darkify widget appears in the page's Elementor data,
408 // load all variants — the specific style is stored as a control value that
409 // would require deep JSON parsing to extract reliably.
410 if (class_exists('\Elementor\Plugin')) {
411 $elementor_data = get_post_meta($post->ID, '_elementor_data', true);
412 if ($elementor_data && strpos($elementor_data, '"widgetType":"darkify"') !== false) {
413 return $all_variants;
414 }
415 }
416 }
417
418 return array_values(array_unique(array_filter($variants)));
419 }
420
421 /**
422 * Recursively walks a parsed block tree and collects darkify/darkify style values.
423 */
424 private function darkify_extract_block_variants($blocks, $all_variants)
425 {
426 $variants = array();
427 foreach ($blocks as $block) {
428 if ('darkify/switcher' === $block['blockName']) {
429 $style = isset($block['attrs']['style']) ? $block['attrs']['style'] : 'classic';
430 if (in_array($style, $all_variants, true)) {
431 $variants[] = $style;
432 }
433 }
434 if (!empty($block['innerBlocks'])) {
435 $variants = array_merge($variants, $this->darkify_extract_block_variants($block['innerBlocks'], $all_variants));
436 }
437 }
438 return $variants;
439 }
440 public function darkify_is_dark_mode_allowed()
441 {
442 $options = get_option('darkify');
443
444 // "Frontend Dark Mode" (enable_dark_mode_switch) is the MASTER control
445 // for the whole frontend feature. When it's off, load NOTHING on the
446 // front end — no CSS, no JS, no inline output — since every asset and
447 // inline script path is gated through this method. (Admin dark mode is a
448 // separate option handled elsewhere and is unaffected.)
449 $enable_dark_mode_switch = isset($options['enable_dark_mode_switch'])
450 ? $options['enable_dark_mode_switch']
451 : true;
452 if (! $enable_dark_mode_switch) {
453 return False;
454 }
455
456 /* Disable if Oxygen Builder is Opened */
457 if (isset($_GET['ct_builder'])) {
458 if ($_GET['ct_builder'] == "true") {
459 if (!isset($_GET['oxygen_iframe'])) {
460 return False;
461 }
462 }
463 }
464
465 return True;
466 }
467
468
469 public function darkify_client_header_script()
470 {
471 if ($this->darkify_is_dark_mode_allowed()) {
472 include_once DarkifyUtils::darkify_locate_template('header_script.php');
473 }
474 }
475
476 public function darkify_client_footer_script()
477 {
478 if ($this->darkify_is_dark_mode_allowed()) {
479 include_once DarkifyUtils::darkify_locate_template('footer_script.php');
480 }
481 }
482
483 function darkify_switch_in_menu($items, $args)
484 {
485 $options = get_option('darkify');
486 $show_in_menu = isset($options['show_in_menu']) ? $options['show_in_menu'] : '';
487
488 // Gate here (not at filter registration) so the live preview's unsaved
489 // "Enable Menu Switch" toggle takes effect without saving.
490 $enable_switcher_in_menu = isset($show_in_menu["enable_switch_in_menu"]) ? $show_in_menu["enable_switch_in_menu"] : false;
491 if (! $enable_switcher_in_menu) {
492 return $items;
493 }
494
495 $select_menus = isset($show_in_menu['select_menus']) ? $show_in_menu['select_menus'] : [];
496
497 $last_shortcode = '';
498
499 if ($this->darkify_is_dark_mode_allowed() && isset($args->menu->term_id)) {
500 foreach ($select_menus as $select_menu) {
501
502 $switch_in_menu_location = $select_menu['switch_in_menu_location'] ?? '';
503 $darkify_menu_shortcode_helper = $select_menu['darkify_menu_shortcode_helper'] ?? '';
504 $menu_position = isset($select_menu['select_menu_position']) ? $select_menu['select_menu_position'] : 'after';
505 if ($args->menu->term_id == $switch_in_menu_location) {
506 $last_shortcode = $darkify_menu_shortcode_helper;
507 }
508 }
509 if ($last_shortcode) {
510 $items = ($menu_position == 'before') ? '<li class="menu-item">' . do_shortcode($last_shortcode) . '</li>' . $items : $items . '<li class="menu-item">' . do_shortcode($last_shortcode) . '</li>';
511 }
512 }
513
514 return $items;
515 }
516 }
517