PluginProbe
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) / 2.1.3
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) v2.1.3
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/Includes/Darkify.php +84 -5 1.5.4 → 2.1.3 View file →
@@ -11,8 +11,13 @@
11 11
12 12 namespace ThemeAtelier\Darkify\Includes;
13 13
14 14 use ThemeAtelier\Darkify\Admin\Admin;
15 +use ThemeAtelier\Darkify\Admin\Assets;
16 +use ThemeAtelier\Darkify\Admin\Menu;
17 +use ThemeAtelier\Darkify\Admin\Rest\HelpRest;
18 +use ThemeAtelier\Darkify\Admin\Rest\PreviewRest;
19 +use ThemeAtelier\Darkify\Admin\Rest\SettingsRest;
15 20 use ThemeAtelier\Darkify\Frontend\Frontend;
16 21
17 22
18 23 // don't call the file directly.
@@ -73,8 +78,16 @@
73 78 $this->define_public_hooks();
74 79 $this->init_action();
75 80 add_action('plugin_loaded', array($this, 'init_plugin'));
76 81
82 + // Translations load on `after_setup_theme`, not alongside the boot action
83 + // above. `plugin_loaded` fires while plugin files are still being
84 + // included, before the pluggable functions exist, so `determine_locale()`
85 + // cannot yet see a per-user admin language. Priority 1 puts this ahead of
86 + // Admin::init_components (same hook, priority 10), which is where the
87 + // settings schema evaluates its `__()` calls.
88 + add_action('after_setup_theme', array($this, 'load_textdomain'), 1);
89 +
77 90 add_action('elementor/controls/register', [$this, 'register_controls']);
78 91 add_action('elementor/widgets/register', array($this, 'register_darkify_widget'));
79 92
80 93 add_action('init', [$this, 'create_darkify_block_init']);
@@ -149,9 +162,9 @@
149 162 define('DARKIFY_ADMIN', DARKIFY_URL . '/src/Admin');
150 163 }
151 164
152 165 /**
153 - * Load the plugin after all plugins are loaded.
166 + * Fire the plugin's own boot action.
154 167 *
155 168 * @return void
156 169 */
157 170 public function init_plugin()
@@ -156,12 +169,32 @@
156 169 */
157 170 public function init_plugin()
158 171 {
159 172 do_action('darkify_loaded');
160 - load_plugin_textdomain('darkify', false, DARKIFY_DIR_NAME . "/languages");
161 173 }
162 174
163 175 /**
176 + * Load the plugin's translations.
177 + *
178 + * @return void
179 + */
180 + public function load_textdomain()
181 + {
182 + // `load_plugin_textdomain()` wants a path *relative to WP_PLUGIN_DIR* —
183 + // it does `WP_PLUGIN_DIR . '/' . $path`. DARKIFY_DIR_NAME is an absolute
184 + // path (`dirname(__FILE__)`), so the old call built a nonsense path like
185 + // `/wp-content/plugins//Users/…/plugins/darkify/languages` and the .mo
186 + // was never found. `wp_set_script_translations()` in Admin/Assets.php
187 + // does take an absolute path and got it right, which is why the React
188 + // strings translated and nothing from PHP ever did.
189 + load_plugin_textdomain(
190 + 'darkify',
191 + false,
192 + dirname(plugin_basename(DARKIFY_FILE)) . '/languages'
193 + );
194 + }
195 +
196 + /**
164 197 * Load the required dependencies for this plugin.
165 198 *
166 199 * Include the following files that make up the plugin:
167 200 *
@@ -197,8 +230,21 @@
197 230 $plugin_admin = new Admin($this->get_plugin_name(), $this->get_version());
198 231 $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_styles');
199 232 $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts');
200 233 $this->loader->add_action('admin_enqueue_scripts', $plugin_admin, 'admin_dequeue_for_specefic_pages', 999);
234 +
235 + // The React admin: its menu page, its bundle, and the REST endpoints it
236 + // talks to. The controllers hook themselves onto `rest_api_init`, so they
237 + // must be constructed on every request, not only in wp-admin.
238 + new Menu();
239 + new Assets();
240 + new SettingsRest();
241 + // Backs the Get Help page's Recommended tab (ThemeAtelier plugin
242 + // directory with one-click install/activate).
243 + new HelpRest();
244 + // Constructed unconditionally (not admin-only): its `init` hook also has
245 + // to fire on the frontend iframe request to swap in the preview values.
246 + new PreviewRest();
201 247 }
202 248
203 249 /**
204 250 * Register all of the hooks related to the public-facing functionality
@@ -230,9 +276,23 @@
230 276
231 277 public static function switcher_wrapper($type, $unique_id, $variant, $switch_size, $position_class = '', $floating_switch_position = '', $tooltip_classes = '', $hide_dark_mode_on_mobile_screen = '', $floating_switch_width = '', $tooltip_on_floating_switch = '')
232 278 {
233 279
234 - return '<div style="--darkify-switch-scale: ' . esc_attr($switch_size) . ';" id="darkify_switch_' . esc_attr($unique_id) . '" onclick="darkify_switch_trigger()" class="darkify_switch darkify_switch_style switch-' . esc_attr($variant) . ' ' . ($type !== 'shortcode' ? esc_attr($position_class) . ' ' . esc_attr($floating_switch_position) . ' ' . esc_attr($tooltip_classes) . ' ' . esc_attr($hide_dark_mode_on_mobile_screen) : '') . '" ' . ($type === 'shortcode' ? 'style="--darkify-switch-scale: ' . esc_attr($switch_size) . '; position: relative;"' : '') . '><div class="theme-toggle">' . self::switcher($variant, $unique_id) . '</div>' . ($type !== 'shortcode' && $floating_switch_width ? '<span class="darkify_tooltiptext">' . esc_attr($tooltip_on_floating_switch) . '</span>' : '') . '</div>';
280 + // A single `style` attribute: this used to be emitted TWICE (once with
281 + // just the scale variable, then — for `shortcode` — a second `style="..."`
282 + // appended after `class`). HTML only honors the FIRST of two duplicate
283 + // attributes, so that second one (the only place `position: relative` was
284 + // set) was silently dropped by every browser. Without it, an absolutely-
285 + // positioned inner element (e.g. a pill variant's sliding thumb) has no
286 + // guarantee of being positioned relative to THIS wrapper — it falls back
287 + // to whatever positioned ancestor happens to exist (or none), which is
288 + // exactly the kind of thing a page's content wrapper (often already
289 + // `position: relative`) can accidentally paper over while a theme's nav
290 + // `<li>` — the Menu Switch's actual context — usually doesn't.
291 + $style = '--darkify-switch-scale: ' . esc_attr($switch_size) . ';' . ($type === 'shortcode' ? ' position: relative;' : '');
292 + $classes = 'darkify_switch darkify_switch_style switch-' . esc_attr($variant)
293 + . ($type !== 'shortcode' ? ' ' . esc_attr($position_class) . ' ' . esc_attr($floating_switch_position) . ' ' . esc_attr($tooltip_classes) . ' ' . esc_attr($hide_dark_mode_on_mobile_screen) : '');
294 + return '<div style="' . $style . '" id="darkify_switch_' . esc_attr($unique_id) . '" onclick="darkify_switch_trigger()" class="' . $classes . '"><div class="theme-toggle">' . self::switcher($variant, $unique_id) . '</div>' . ($type !== 'shortcode' && $floating_switch_width ? '<span class="darkify_tooltiptext">' . esc_attr($tooltip_on_floating_switch) . '</span>' : '') . '</div>';
235 295 }
236 296
237 297 private function init_action()
238 298 {
@@ -253,8 +313,19 @@
253 313 'darkify-switcher-editor-script',
254 314 'darkify',
255 315 array(
256 316 'dir_url' => DARKIFY_DIR_URL,
317 + /*
318 + * How many of the block's switch styles this plugin may select,
319 + * counted from the start of the list in blocks/src/edit.js.
320 + * The rest are shown as locked Pro previews.
321 + *
322 + * Sent from here rather than decided in the editor's CSS: the
323 + * old lock was a `:nth-child` rule, which a mouse respected but
324 + * the keyboard walked straight past, and which silently changed
325 + * meaning if the style list were ever reordered.
326 + */
327 + 'unlocked_styles' => 5,
257 328 )
258 329 );
259 330 }
260 331
@@ -284,9 +355,11 @@
284 355 } else {
285 356 $switcher_size = (float) $size * 100;
286 357 }
287 358
288 - return '<div style="display: flex; justify-content: ' . esc_attr($alignment) . '">' . do_shortcode(wp_sprintf(
359 + // The shortcode returns an empty string when dark mode is off for the
360 + // front end; don't leave a stray flex wrapper behind in that case.
361 + $switch = do_shortcode(wp_sprintf(
289 362 '[darkify switch="%s" icon_size="40px" light_mode_bg="%s" dark_mode_bg="%s" light_mode_color="%s" dark_mode_color="%s" border="%spx" border_light_color="%s" border_dark_color="%s" border_radius="%spx" text_light_mode_color="%s" text_dark_mode_color="%s" switch_size="%s"]',
290 363 $style,
291 364 $bg_light,
292 365 $bg_dark,
@@ -298,7 +371,13 @@
298 371 $border_radius,
299 372 $light_text_color,
300 373 $dark_text_color,
301 374 $switcher_size
302 - )) . '</div>';
375 + ));
376 +
377 + if ('' === trim($switch)) {
378 + return '';
379 + }
380 +
381 + return '<div style="display: flex; justify-content: ' . esc_attr($alignment) . '">' . $switch . '</div>';
303 382 }
304 383 }