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

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

370 lines 15.9 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 list($name, $value) = explode(':', $attr);
108 $results[$matches[1][$i]][trim($name)] = trim($value);
109 }
110 }
111 }
112 /* Array to processed css string */
113 foreach ($results as $single_selector => $rules) {
114 $single_selector_arr = explode(",", $single_selector);
115 for ($i = 0; $i < sizeof($single_selector_arr); $i++) {
116 if (!$this->string_contains_any(trim($single_selector_arr[$i]), $pseudo_classes, false)) {
117 $exclude_elements[] = trim($single_selector_arr[$i]);
118 if ($custom_css_rules) {
119 $exclude_elements[] = trim($single_selector_arr[$i]) . " *";
120 }
121 }
122 }
123 }
124 return $exclude_elements;
125 }
126
127 public static function parseAndProcessCustomCSS($css, $custom_css_rules)
128 {
129 /* Decode any escaped HTML entities like &gt;, &lt;, &quot; */
130 $css = html_entity_decode($css, ENT_QUOTES | ENT_HTML5, 'UTF-8');
131
132 /* Replace : on https:// or http:// for detecting as background:black type */
133 $css = str_replace("://", "--colon--//", $css);
134
135 $css = str_replace(array("\r", "\n"), "", $css);
136
137 /* Convert to Array */
138 $results = array();
139 preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $css, $matches);
140 foreach ($matches[0] as $i => $original) {
141 foreach (explode(';', $matches[2][$i]) as $attr) {
142 if (strlen(trim($attr)) > 0) {
143 if (strpos($attr, ':') !== false) {
144 list($name, $value) = explode(':', $attr, 2); // FIXED
145 $results[$matches[1][$i]][trim($name)] = trim($value);
146 }
147 }
148 }
149 }
150
151 /* Array to processed css string */
152 $updated_css = "";
153 foreach ($results as $single_selector => $rules) {
154 $updated_single_selector = "";
155 $single_selector_arr = explode(",", $single_selector);
156 for ($i = 0; $i < sizeof($single_selector_arr); $i++) {
157 $selector = ".darkify_dark_mode_enabled " . trim($single_selector_arr[$i]);
158 if ($i > 0) {
159 $updated_single_selector .= ", ";
160 }
161
162 // Check if selector has :not-disallowed
163 if (strpos($selector, ':not-disallowed') !== false) {
164 $updated_single_selector .= str_replace(':not-disallowed', '', $selector);
165 } else {
166 $updated_single_selector .= $selector;
167 if ($custom_css_rules && !preg_match('/:{1,2}(after|before)\b/i', $selector)) {
168 $updated_single_selector .= ", .darkify_dark_mode_enabled " . $selector . " *";
169 }
170 }
171 }
172
173 $updated_css .= $updated_single_selector . "{";
174
175 foreach ($rules as $key => $value) {
176 if (strpos($value, "important") == false) {
177 $value = $value . " !important";
178 }
179 $updated_css .= $key . ": " . $value . ";";
180 }
181
182 $updated_css .= "}";
183 }
184
185 /* Replace --colon--// back to https:// or http:// format */
186 $updated_css = str_replace("--colon--//", "://", $updated_css);
187
188 return $updated_css;
189 }
190
191 public static function parseAndProcessNormalCustomCSS($css)
192 {
193 /* Replace : on https:// or http:// for detecting as background:black type */
194 $css = str_replace("://", "--colon--//", $css);
195
196 $css = str_replace(array("\r", "\n"), "", $css);
197 /* Convert to Array */
198 $results = array();
199 preg_match_all('/(.+?)\s?\{\s?(.+?)\s?\}/', $css, $matches);
200 foreach ($matches[0] as $i => $original) {
201 foreach (explode(';', $matches[2][$i]) as $attr) {
202 if (strlen(trim($attr)) > 0) // for missing semicolon on last element, which is legal
203 {
204 // PATCH (community fix): same as in
205 // extractCustomCssSelectorsForAutoExcluding above —
206 // cap explode at 2 + skip if no colon, to avoid
207 // PHP 8.1+ undefined-index + trim(null) notices on
208 // malformed CSS attributes.
209 if (strpos($attr, ':') === false) {
210 continue;
211 }
212
213 list($name, $value) = explode(':', $attr);
214 $results[$matches[1][$i]][trim($name)] = trim($value);
215 }
216 }
217 }
218 /* Array to processed css string */
219 $updated_css = "";
220 foreach ($results as $single_selector => $rules) {
221 $updated_css .= $single_selector . "{";
222
223 foreach ($rules as $key => $value) {
224 if (strpos($value, "important") == false) {
225 $value = $value . " !important";
226 }
227 $updated_css .= $key . ": " . $value . ";";
228 }
229
230 $updated_css .= "}";
231 }
232 /* Replace --colon--// back to https:// or http:// format */
233 $updated_css = str_replace("--colon--//", "://", $updated_css);
234 return $updated_css;
235 }
236
237 public function generateDisallowedElementsStr($options, $external_support_class_obj)
238 {
239 $disallowed_element = isset($options["disallowed_elements"]) ? self::normalize_restriction_class($options['disallowed_elements']) : "";
240 $custom_css_rules = isset($options["custom_css_rules"]) ? $options["custom_css_rules"] : "";
241 $custom_css = isset($options["custom_css"]) ? $options["custom_css"] : "";
242 $disallowed_elements = "";
243 if (strlen(trim($disallowed_element)) > 0) {
244 $disallowed_elements_arr = explode(',', $disallowed_element);
245 if (is_array($disallowed_elements_arr)) {
246 if (sizeof($disallowed_elements_arr) > 0) {
247 foreach ($disallowed_elements_arr as $single_element) {
248 $disallowed_elements .= ($disallowed_elements != "" ? ", " : "") . trim($single_element);
249 $disallowed_elements .= ($disallowed_elements != "" ? ", " : "") . trim($single_element) . ' *';
250 }
251 }
252 }
253 }
254
255 // Get Disallowed Elements from External Plugins
256 $disallowed_from_external = $external_support_class_obj->getDisallowedElementsByAvailablePlugins();
257 if (sizeof($disallowed_from_external) > 0) {
258 foreach ($disallowed_from_external as $single_element) {
259 $disallowed_elements .= ($disallowed_elements != "" ? ", " : "") . trim($single_element);
260 }
261 }
262
263 // Exclude selectors specified in Custom CSS
264 $custom_css_selectors = $this->extractCustomCssSelectorsForAutoExcluding($custom_css, $custom_css_rules);
265 if (is_array($custom_css_selectors)) {
266 if (sizeof($custom_css_selectors) > 0) {
267 foreach ($custom_css_selectors as $single_element) {
268 $disallowed_elements .= ($disallowed_elements != "" ? ", " : "") . trim($single_element);
269 }
270 }
271 }
272 return $disallowed_elements;
273 }
274
275 public function minify_string($buffer)
276 {
277 $search = array(
278 '/\>[^\S ]+/s', // strip whitespaces after tags, except space
279 '/[^\S ]+\</s', // strip whitespaces before tags, except space
280 '/(\s)+/s', // shorten multiple whitespace sequences
281 '/<!--(.|\s)*?-->/' // Remove HTML comments
282 );
283 $replace = array(
284 '>',
285 '<',
286 '\\1',
287 ''
288 );
289 $buffer = preg_replace($search, $replace, $buffer);
290 return $buffer;
291 }
292
293 public function isRestrictedByDisallowedAdminPages($disallowed_admin_pages)
294 {
295 if (strlen(trim($disallowed_admin_pages)) > 0) {
296 if (function_exists("get_current_screen")) {
297 $current_screen = get_current_screen();
298 $parts = explode('_page_', $current_screen->id);
299 if (count($parts) !== 2) {
300 return False;
301 } /* means it's something like invalid page slug */
302 $page_slug = $parts[1];
303
304 $disallowed_admin_pages_arr = explode(',', $disallowed_admin_pages);
305 if (is_array($disallowed_admin_pages_arr)) {
306 if (sizeof($disallowed_admin_pages_arr) > 0) {
307 foreach ($disallowed_admin_pages_arr as $single_page) {
308 if ($page_slug == trim($single_page)) {
309 return True;
310 }
311 }
312 }
313 }
314 }
315 }
316 return False;
317 }
318
319 /**
320 * Custom Template locator .
321 *
322 * @param mixed $template_name template name .
323 * @param mixed $template_path template path .
324 * @param mixed $default_path default path .
325 * @return string
326 */
327 public static function darkify_locate_template($template_name, $default_path = '')
328 {
329 if (!$default_path) {
330 $default_path = DARKIFY_PATH . 'src/Frontend/Templates/';
331 }
332 $template = locate_template($template_name);
333 // Get default template.
334 if (!$template) {
335 $template = $default_path . $template_name;
336 }
337 // Return what we found.
338 return $template;
339 }
340
341 /**
342 * Cleans up that sloppy list of URLs—tightens it up like a true warrior.
343 *
344 * @param string $input A comma-separated string of URLs, possibly with extra space.
345 * @return string Refined and battle-ready URL list—no excess baggage.
346 *
347 * @bardock No room for weakness. Clean your inputs before they get you killed.
348 */
349 public static function normalize_restriction_class($input)
350 {
351 $urls = preg_replace('/,\s+/', ',', $input);
352 return $urls;
353 }
354
355 /* =============== Darkify Add Button Class =============== */
356 public function addButtonClassByDarkify($options)
357 {
358 $darkfy_button_class = [
359 "elementor-button",
360 "gspb-buttonbox",
361 "fusion-button",
362 "wp-element-button",
363 "ct-header-search",
364 "stk-button"
365 ];
366 return $darkfy_button_class;
367 }
368 }
369 }
370