PluginProbe
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) / 2.0.1
Darkify – Dark Mode & Night Mode for Website & Admin (Dark Theme Included) v2.0.1
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
darkify / src / Includes / DarkifyUtils.php

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

401 lines 17.4 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\Includes;
4
5 // If this file is called directly, abort.
6 if (!defined('WPINC')) {
7 die;
8 }
9
10 if (!class_exists('DarkifyUtils')) {
11 class DarkifyUtils
12 {
13
14 public $base_admin;
15 public function __construct($base_admin)
16 {
17 $this->base_admin = $base_admin;
18 }
19
20 public function isMobile()
21 {
22 if (function_exists("wp_is_mobile")) {
23 return wp_is_mobile();
24 } else {
25 return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $_SERVER["HTTP_USER_AGENT"]);
26 }
27 }
28 public function is_hidden_by_user_agent($hide_on_desktop, $hide_dark_mode_on_mobile, $type_of_hide_by)
29 {
30 if ($this->isMobile()) {
31 if ($hide_dark_mode_on_mobile) {
32 if ($type_of_hide_by == "user_agent" || $type_of_hide_by == "both") {
33 return True;
34 }
35 }
36 } else {
37 if ($hide_on_desktop) {
38 return True;
39 }
40 }
41 return False;
42 }
43
44 public function generateSwitchStyles($options)
45 {
46 $switch_background = isset($options['switch_background']) ? $options['switch_background'] : [];
47 $switch_light_mode_bg = !empty($switch_background) ? $switch_background['switch_light_mode_bg'] : '#121116';
48 $switch_dark_mode_bg = !empty($switch_background) ? $switch_background['switch_dark_mode_bg'] : '#ffffff';
49 $switch_icon_color = isset($options['switch_icon_color']) ? $options['switch_icon_color'] : [];
50
51 $switch_light_mode_color = !empty($switch_icon_color) ? $switch_icon_color['switch_light_mode_color'] : '#ffffff';
52 $switch_dark_mode_color = !empty($switch_icon_color) ? $switch_icon_color['switch_dark_mode_color'] : '#121116';
53 $switch_border = isset($options['switch_border']) ? $options['switch_border'] : [];
54 $switch_border_all = !empty($switch_border['all']) ? $switch_border['all'] : "0";
55 $switch_border_light_color = !empty($switch_border['color']) ? $switch_border['color'] : "#ffffff";
56 $switch_border_dark_color = !empty($switch_border['color3']) ? $switch_border['color3'] : "#121116";
57 $switch_border_radius = !empty($switch_border['radius']) ? $switch_border['radius'] : "7";
58
59 $styles = array(
60 "--darkify_switch_border" => $switch_border_all . "px",
61 "--darkify_switch_border_light_color" => $switch_border_light_color,
62 "--darkify_switch_border_dark_color" => $switch_border_dark_color,
63 "--darkify_switch_border_radius" => $switch_border_radius . "px",
64 "--darkify_switch_light_mode_bg" => $switch_light_mode_bg,
65 "--darkify_switch_dark_mode_bg" => $switch_dark_mode_bg,
66 "--darkify_switch_light_mode_color" => $switch_light_mode_color,
67 "--darkify_switch_dark_mode_color" => $switch_dark_mode_color,
68 );
69 return $styles;
70 }
71
72 public function generateSwitchStylesForShortcode($atts)
73 {
74 $styles = array();
75 foreach ($atts as $key => $value) {
76 if ($key == "switch") {
77 continue;
78 }
79 $styles["--darkify_switch_" . $key] = $value;
80 }
81 return $styles;
82 }
83
84 public function string_contains_any($string, $words, $caseSensitive = true)
85 {
86 foreach ($words as $word) {
87 $position = $caseSensitive ? stripos($string, $word) : strpos($string, $word);
88 if ($position !== false) {
89 return true;
90 }
91 }
92 return false;
93 }
94
95 public function extractCustomCssSelectorsForAutoExcluding($css, $custom_css_rules)
96 {
97 $pseudo_classes = array(":after", ":before", ":first-letter", ":first-line", ":selection", ":not-disallowed");
98 $css = str_replace(array("\r", "\n"), "", $css);
99 /* Convert to Array */
100 $exclude_elements = array();
101 $results = array();
102 preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $css, $matches);
103 foreach ($matches[0] as $i => $original) {
104 foreach (explode(';', $matches[2][$i]) as $attr) {
105 if (strlen(trim($attr)) > 0) // for missing semicolon on last element, which is legal
106 {
107 // Cap explode at 2 so legitimate CSS values containing `:`
108 // (e.g. background: url(https://…)) aren't broken, and skip
109 // malformed attributes lacking a `:` separator — both cases
110 // produced PHP 8.1+ "undefined index 1" + "trim(null)" notices.
111 if (strpos($attr, ':') === false) {
112 continue;
113 }
114 list($name, $value) = explode(':', $attr, 2);
115 $results[$matches[1][$i]][trim($name)] = trim($value);
116 }
117 }
118 }
119 /* Array to processed css string */
120 foreach ($results as $single_selector => $rules) {
121 $single_selector_arr = explode(",", $single_selector);
122 for ($i = 0; $i < sizeof($single_selector_arr); $i++) {
123 if (!$this->string_contains_any(trim($single_selector_arr[$i]), $pseudo_classes, false)) {
124 $exclude_elements[] = trim($single_selector_arr[$i]);
125 if ($custom_css_rules) {
126 $exclude_elements[] = trim($single_selector_arr[$i]) . " *";
127 }
128 }
129 }
130 }
131 return $exclude_elements;
132 }
133
134 public static function parseAndProcessCustomCSS($css, $custom_css_rules)
135 {
136 /* Decode any escaped HTML entities like &gt;, &lt;, &quot; */
137 $css = html_entity_decode($css, ENT_QUOTES | ENT_HTML5, 'UTF-8');
138
139 /* Replace : on https:// or http:// for detecting as background:black type */
140 $css = str_replace("://", "--colon--//", $css);
141
142 $css = str_replace(array("\r", "\n"), "", $css);
143
144 /* Convert to Array */
145 $results = array();
146 preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $css, $matches);
147 foreach ($matches[0] as $i => $original) {
148 foreach (explode(';', $matches[2][$i]) as $attr) {
149 if (strlen(trim($attr)) > 0) {
150 if (strpos($attr, ':') !== false) {
151 list($name, $value) = explode(':', $attr, 2); // FIXED
152 $results[$matches[1][$i]][trim($name)] = trim($value);
153 }
154 }
155 }
156 }
157
158 /* Array to processed css string */
159 $updated_css = "";
160 foreach ($results as $single_selector => $rules) {
161 $updated_single_selector = "";
162 $single_selector_arr = explode(",", $single_selector);
163 for ($i = 0; $i < sizeof($single_selector_arr); $i++) {
164 $selector = ".darkify_dark_mode_enabled " . trim($single_selector_arr[$i]);
165 if ($i > 0) {
166 $updated_single_selector .= ", ";
167 }
168
169 // Check if selector has :not-disallowed
170 if (strpos($selector, ':not-disallowed') !== false) {
171 $updated_single_selector .= str_replace(':not-disallowed', '', $selector);
172 } else {
173 $updated_single_selector .= $selector;
174 if ($custom_css_rules && !preg_match('/:{1,2}(after|before)\b/i', $selector)) {
175 $updated_single_selector .= ", .darkify_dark_mode_enabled " . $selector . " *";
176 }
177 }
178 }
179
180 $updated_css .= $updated_single_selector . "{";
181
182 foreach ($rules as $key => $value) {
183 if (strpos($value, "important") == false) {
184 $value = $value . " !important";
185 }
186 $updated_css .= $key . ": " . $value . ";";
187 }
188
189 $updated_css .= "}";
190 }
191
192 /* Replace --colon--// back to https:// or http:// format */
193 $updated_css = str_replace("--colon--//", "://", $updated_css);
194
195 return $updated_css;
196 }
197
198 public static function parseAndProcessNormalCustomCSS($css)
199 {
200 /* Replace : on https:// or http:// for detecting as background:black type */
201 $css = str_replace("://", "--colon--//", $css);
202
203 $css = str_replace(array("\r", "\n"), "", $css);
204 /* Convert to Array */
205 $results = array();
206 preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $css, $matches);
207 foreach ($matches[0] as $i => $original) {
208 foreach (explode(';', $matches[2][$i]) as $attr) {
209 if (strlen(trim($attr)) > 0) // for missing semicolon on last element, which is legal
210 {
211 // PATCH (community fix): same as in
212 // extractCustomCssSelectorsForAutoExcluding above —
213 // cap explode at 2 + skip if no colon, to avoid
214 // PHP 8.1+ undefined-index + trim(null) notices on
215 // malformed CSS attributes.
216 if (strpos($attr, ':') === false) {
217 continue;
218 }
219
220 list($name, $value) = explode(':', $attr, 2);
221 $results[$matches[1][$i]][trim($name)] = trim($value);
222 }
223 }
224 }
225 /* Array to processed css string */
226 $updated_css = "";
227 foreach ($results as $single_selector => $rules) {
228 $updated_css .= $single_selector . "{";
229
230 foreach ($rules as $key => $value) {
231 if (strpos($value, "important") == false) {
232 $value = $value . " !important";
233 }
234 $updated_css .= $key . ": " . $value . ";";
235 }
236
237 $updated_css .= "}";
238 }
239 /* Replace --colon--// back to https:// or http:// format */
240 $updated_css = str_replace("--colon--//", "://", $updated_css);
241 return $updated_css;
242 }
243
244 public function generateAllowedElementsStr($options)
245 {
246 $allowed_elements = isset($options["allowed_elements"]) ? self::normalize_restriction_class($options['allowed_elements']) : "";
247
248 if (strlen(trim($allowed_elements)) > 0) {
249 $allowed_elements_arr = explode(',', $allowed_elements);
250 if (is_array($allowed_elements_arr)) {
251 if (sizeof($allowed_elements_arr) > 0) {
252 foreach ($allowed_elements_arr as $single_element) {
253 $allowed_elements .= ($allowed_elements != "" ? ", " : "") . trim($single_element);
254 $allowed_elements .= ($allowed_elements != "" ? ", " : "") . trim($single_element) . ' *';
255 }
256 }
257 }
258 }
259 return $allowed_elements;
260 }
261
262 public function generateDisallowedElementsStr($options, $external_support_class_obj)
263 {
264 $disallowed_element = isset($options["disallowed_elements"]) ? self::normalize_restriction_class($options['disallowed_elements']) : "";
265 $custom_css_rules = isset($options["custom_css_rules"]) ? $options["custom_css_rules"] : "";
266 $custom_css = isset($options["custom_css"]) ? $options["custom_css"] : "";
267 $disallowed_elements = "";
268 if (strlen(trim($disallowed_element)) > 0) {
269 $disallowed_elements_arr = explode(',', $disallowed_element);
270 if (is_array($disallowed_elements_arr)) {
271 if (sizeof($disallowed_elements_arr) > 0) {
272 foreach ($disallowed_elements_arr as $single_element) {
273 $disallowed_elements .= ($disallowed_elements != "" ? ", " : "") . trim($single_element);
274 $disallowed_elements .= ($disallowed_elements != "" ? ", " : "") . trim($single_element) . ' *';
275 }
276 }
277 }
278 }
279
280 // Get Disallowed Elements from External Plugins
281 $disallowed_from_external = $external_support_class_obj->getDisallowedElementsByAvailablePlugins();
282 if (sizeof($disallowed_from_external) > 0) {
283 foreach ($disallowed_from_external as $single_element) {
284 $disallowed_elements .= ($disallowed_elements != "" ? ", " : "") . trim($single_element);
285 }
286 }
287
288 // Exclude selectors specified in Custom CSS
289 $custom_css_selectors = $this->extractCustomCssSelectorsForAutoExcluding($custom_css, $custom_css_rules);
290 if (is_array($custom_css_selectors)) {
291 if (sizeof($custom_css_selectors) > 0) {
292 foreach ($custom_css_selectors as $single_element) {
293 $disallowed_elements .= ($disallowed_elements != "" ? ", " : "") . trim($single_element);
294 }
295 }
296 }
297 return $disallowed_elements;
298 }
299
300 public function minify_string($buffer)
301 {
302 $search = array(
303 '/\>[^\S ]+/s', // strip whitespaces after tags, except space
304 '/[^\S ]+\</s', // strip whitespaces before tags, except space
305 '/(\s)+/s', // shorten multiple whitespace sequences
306 '/<!--(.|\s)*?-->/' // Remove HTML comments
307 );
308 $replace = array(
309 '>',
310 '<',
311 '\\1',
312 ''
313 );
314 $buffer = preg_replace($search, $replace, $buffer);
315 return $buffer;
316 }
317
318 public function isRestrictedByDisallowedAdminPages($disallowed_admin_pages)
319 {
320 if (strlen(trim($disallowed_admin_pages)) > 0) {
321 if (function_exists("get_current_screen")) {
322 $current_screen = get_current_screen();
323 $parts = explode('_page_', $current_screen->id);
324 if (count($parts) !== 2) {
325 return False;
326 } /* means it's something like invalid page slug */
327 $page_slug = $parts[1];
328
329 $disallowed_admin_pages_arr = explode(',', $disallowed_admin_pages);
330 if (is_array($disallowed_admin_pages_arr)) {
331 if (sizeof($disallowed_admin_pages_arr) > 0) {
332 foreach ($disallowed_admin_pages_arr as $single_page) {
333 if ($page_slug == trim($single_page)) {
334 return True;
335 }
336 }
337 }
338 }
339 }
340 }
341 return False;
342 }
343
344 /**
345 * Custom Template locator .
346 *
347 * @param mixed $template_name template name .
348 * @param mixed $template_path template path .
349 * @param mixed $default_path default path .
350 * @return string
351 */
352 public static function darkify_locate_template($template_name, $default_path = '')
353 {
354 if (!$default_path) {
355 $default_path = DARKIFY_PATH . 'src/Frontend/Templates/';
356 }
357 $template = locate_template($template_name);
358 // Get default template.
359 if (!$template) {
360 $template = $default_path . $template_name;
361 }
362 // Return what we found.
363 return $template;
364 }
365
366 /**
367 * Cleans up that sloppy list of URLs—tightens it up like a true warrior.
368 *
369 * @param string $input A comma-separated string of URLs, possibly with extra space.
370 * @return string Refined and battle-ready URL list—no excess baggage.
371 *
372 * @bardock No room for weakness. Clean your inputs before they get you killed.
373 */
374 public static function normalize_restriction_class($input)
375 {
376 $urls = preg_replace('/,\s+/', ',', $input);
377 return $urls;
378 }
379
380 public static function normalize_image_urls($input)
381 {
382 $urls = preg_split('/[\s,]+/', $input, -1, PREG_SPLIT_NO_EMPTY);
383 return implode(',', $urls);
384 }
385
386 /* =============== Darkify Add Button Class =============== */
387 public function addButtonClassByDarkify($options)
388 {
389 $darkfy_button_class = [
390 "elementor-button",
391 "gspb-buttonbox",
392 "fusion-button",
393 "wp-element-button",
394 "ct-header-search",
395 "stk-button"
396 ];
397 return $darkfy_button_class;
398 }
399 }
400 }
401