PluginProbe
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar / 3.2.10
NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar v3.2.10
3.3.1 3.3.0 3.2.14 3.2.13 3.2.12 3.2.11 3.2.10 3.2.9 3.2.8 3.2.7 trunk 0.2.5.5 0.2.5.6 0.2.5.7 1.0.0 1.0.1 1.0.2 1.0.3 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.2.0 1.2.1 All 156 releases
notificationx / includes / Core / Helper.php

Helper.php in NotificationX – FOMO, Live Sales Notification, WooCommerce Sales Popup, GDPR, Social Proof, Announcement Banner & Floating Notification Bar 3.2.10, at includes/Core/Helper.php

1,327 lines 47.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace NotificationX\Core;
4
5 use NotificationX\Extensions\GlobalFields;
6 use NotificationX\Types\TypeFactory;
7 use NotificationX\Admin\Settings;
8
9 /**
10 * This class will provide all kind of helper methods.
11 */
12 class Helper {
13 /**
14 * Get all post types
15 *
16 * @param array $exclude
17 * @return array
18 */
19 public static function post_types($exclude = array()) {
20 $post_types = get_post_types(array(
21 'public' => true,
22 'show_ui' => true
23 ), 'objects');
24
25 unset($post_types['attachment']);
26
27 if (count($exclude)) {
28 foreach ($exclude as $type) {
29 if (isset($post_types[$type])) {
30 unset($post_types[$type]);
31 }
32 }
33 }
34
35 return apply_filters('nx_post_types', $post_types);
36 }
37
38 /**
39 * Get all taxonomies
40 *
41 * @param string $post_type
42 * @param array $exclude
43 * @return array
44 */
45 public static function taxonomies($post_type = '', $exclude = array()) {
46 if (empty($post_type)) {
47 $taxonomies = get_taxonomies(
48 array(
49 'public' => true,
50 '_builtin' => false
51 ),
52 'objects'
53 );
54 } else {
55 $taxonomies = get_object_taxonomies($post_type, 'objects');
56 }
57
58 $data = array();
59 if (is_array($taxonomies)) {
60 foreach ($taxonomies as $tax_slug => $tax) {
61 if (!$tax->public || !$tax->show_ui) {
62 continue;
63 }
64 if (in_array($tax_slug, $exclude)) {
65 continue;
66 }
67 $data[$tax_slug] = $tax;
68 }
69 }
70 return apply_filters('nx_loop_taxonomies', $data, $taxonomies, $post_type);
71 }
72
73 /**
74 * This function is responsible for the data sanitization
75 *
76 * @param array $field
77 * @param string|array $value
78 * @return string|array
79 */
80 public static function sanitize_field($field, $value) {
81 if (isset($field['sanitize']) && !empty($field['sanitize'])) {
82 if (function_exists($field['sanitize'])) {
83 $value = call_user_func($field['sanitize'], $value);
84 }
85 return $value;
86 }
87
88 if (is_array($field) && isset($field['type'])) {
89 switch ($field['type']) {
90 case 'text':
91 $value = sanitize_text_field($value);
92 break;
93 case 'textarea':
94 $value = sanitize_textarea_field($value);
95 break;
96 case 'email':
97 $value = sanitize_email($value);
98 break;
99 default:
100 return $value;
101 break;
102 }
103 } else {
104 $value = sanitize_text_field($value);
105 }
106
107 return $value;
108 }
109
110
111 /**
112 * Sorting Data
113 * by their type
114 *
115 * @param array $value
116 * @param string $key
117 * @return void
118 */
119 public static function sortBy(&$value, $key = 'comments') {
120 switch ($key) {
121 case 'comments':
122 return self::sorter($value, 'key', 'DESC');
123 break;
124 default:
125 return self::sorter($value, 'timestamp', 'DESC');
126 break;
127 }
128 }
129
130 /**
131 * This function is responsible for making an array sort by their key
132 * @param array $data
133 * @param string $using
134 * @param string $way
135 * @return array
136 */
137 public static function sorter($data, $using = 'time_date', $way = 'DESC') {
138 if (!is_array($data)) {
139 return $data;
140 }
141 $new_array = [];
142 if ($using === 'key') {
143 if ($way !== 'ASC') {
144 krsort($data);
145 } else {
146 ksort($data);
147 }
148 } else {
149 foreach ($data as $key => $value) {
150 if (!is_array($value)) continue;
151 foreach ($value as $inner_key => $single) {
152 if ($inner_key == $using) {
153 $value['tempid'] = $key;
154 $single = self::numeric_key_gen($new_array, $single);
155 $new_array[$single] = $value;
156 }
157 }
158 }
159
160 if ($way !== 'ASC') {
161 krsort($new_array);
162 } else {
163 ksort($new_array);
164 }
165
166 if (!empty($new_array)) {
167 foreach ($new_array as $array) {
168 $index = $array['tempid'];
169 unset($array['tempid']);
170 $new_data[$index] = $array;
171 }
172 $data = $new_data;
173 }
174 }
175
176 return $data;
177 }
178
179 /**
180 * This function is responsible for generate unique numeric key for a given array.
181 *
182 * @param array $data
183 * @param integer $index
184 * @return integer
185 */
186 protected static function numeric_key_gen($data, $index = 0) {
187 if (isset($data[$index])) {
188 $index += 1;
189 return self::numeric_key_gen($data, $index);
190 }
191 return $index;
192 }
193
194
195
196
197 /**
198 * Contact Forms Key Name filter for Name Selectbox
199 * @since 1.4.*
200 * @param string
201 * @return boolean
202 */
203 public static function filter_contactform_key_names($name) {
204 $validKey = true;
205 $filterWords = array(
206 "checkbox",
207 "color",
208 "date",
209 "datetime-local",
210 "file",
211 "image",
212 "month",
213 "number",
214 "password",
215 "radio",
216 "range",
217 "reset",
218 "submit",
219 "tel",
220 "time",
221 "week",
222 "Comment",
223 "message",
224 "address",
225 "phone",
226 );
227 foreach ($filterWords as $word) {
228 if (!empty($name) && stripos($name, $word) === false) {
229 $validKey = true;
230 } else {
231 $validKey = false;
232 break;
233 }
234 }
235 return $validKey;
236 }
237
238 /**
239 * Contact Forms Key Name remove special characters and meaningless words for Name Selectbox
240 * @since 1.4.*
241 * @param string
242 * @return string
243 */
244 public static function rename_contactform_key_names($name) {
245 $result = preg_split("/[_,\-]+/", $name);
246 $returnName = ucfirst($result[0]);
247 return $returnName;
248 }
249
250
251 /**
252 * Formating Number in a Nice way
253 * @since 1.2.1
254 * @param int|string $n
255 * @return string
256 */
257 public static function nice_number($n) {
258 $temp_number = !empty( $n ) ? str_replace(",", "", $n) : '';
259 if (!empty($temp_number)) {
260 $n = (0 + (int) $temp_number);
261 } else {
262 $n = (int) $n;
263 }
264 if (!is_numeric($n)) return 0;
265 $is_neg = false;
266 if ($n < 0) {
267 $is_neg = true;
268 $n = abs($n);
269 }
270 $number = 0;
271 $suffix = '';
272 switch (true) {
273 case $n >= 1000000000000:
274 $number = ($n / 1000000000000);
275 $suffix = $n > 1000000000000 ? 'T+' : 'T';
276 break;
277 case $n >= 1000000000:
278 $number = ($n / 1000000000);
279 $suffix = $n > 1000000000 ? 'B+' : 'B';
280 break;
281 case $n >= 1000000:
282 $number = ($n / 1000000);
283 $suffix = $n > 1000000 ? 'M+' : 'M';
284 break;
285 case $n >= 1000:
286 $number = ($n / 1000);
287 $suffix = $n > 1000 ? 'K+' : 'K';
288 break;
289 default:
290 $number = $n;
291 break;
292 }
293 if (strpos($number, '.') !== false && strpos($number, '.') >= 0) {
294 $number = number_format($number, 1);
295 }
296 return ($is_neg ? '-' : '') . $number . $suffix;
297 }
298
299 public static function write_log($log) {
300 if (true === WP_DEBUG) {
301 if (is_array($log) || is_object($log)) {
302 error_log(print_r($log, true));
303 } else {
304 error_log($log);
305 }
306 }
307 }
308
309 public static function get_theme_or_plugin_list($api_data = null) {
310 $data = array();
311 $new_data = array();
312
313 $needed_key = array('slug', 'title', 'installs_count', 'active_installs_count', 'free_releases_count', 'premium_releases_count', 'total_purchases', 'total_subscriptions', 'total_renewals', 'accepted_payments', 'id', 'created', 'icon');
314
315 if (!empty($api_data->plugins)) {
316 foreach ($api_data->plugins as $single_data) {
317 $type = $single_data->type;
318 foreach ($needed_key as $key) {
319 if ($key == 'created') {
320 if (isset($single_data->$key)) {
321 $new_data['timestamp'] = strtotime($single_data->$key);
322 }
323 continue;
324 }
325 if (isset($single_data->$key)) {
326 $new_data[$key] = $single_data->$key;
327 }
328 }
329 $data[$type . 's'][$new_data['id']] = $new_data;
330 $new_data = array();
331 }
332 }
333
334 return $data;
335 }
336
337 public static function today_to_last_week($data) {
338 if (empty($data)) {
339 return array();
340 }
341 $new_data = array();
342 $timestamp = current_time('timestamp');
343 $date = date('Y-m-d', $timestamp);
344 $date_7_days_back = date('Y-m-d', strtotime($date . ' -8 days'));
345 $counter_7days = 0;
346 $counter_todays = 0;
347 foreach ($data as $single_install) {
348 date('Y-m-d', strtotime($single_install->created)) > $date_7_days_back ? $counter_7days++ : $counter_7days;
349 date('Y-m-d', strtotime($single_install->created)) == $date ? $counter_todays++ : $counter_todays;
350 }
351 return array(
352 'last_week' => $counter_7days,
353 'today' => $counter_todays,
354 );
355 }
356
357 public static function current_timestamp( $date = null, $timezone = 'UTC' ){
358 $timezone = new \DateTimeZone( $timezone );
359 $datetime = new \DateTime($date, $timezone);
360 return $datetime->getTimestamp();
361 }
362
363 public static function current_time($timestamp = null) {
364 $type = 'Y-m-d H:i:s';
365 if (empty($timestamp)) {
366 $timestamp = time();
367 }
368
369 $timezone = new \DateTimeZone('UTC');
370 if (is_numeric($timestamp)) {
371 $datetime = new \DateTime();
372 $datetime->setTimezone($timezone);
373 $datetime->setTimestamp($timestamp);
374 }
375 else{
376 $datetime = new \DateTime($timestamp);
377 $datetime->setTimezone($timezone);
378 }
379 return $datetime->format($type);
380 }
381
382 public static function get_utc_time($timestamp = null) {
383 $type = 'Y-m-d H:i:s';
384 if (empty($timestamp)) {
385 $timestamp = time();
386 }
387
388 // Get the WP timezone as a DateTimeZone object
389 $wp_timezone = wp_timezone();
390 $timezone = new \DateTimeZone('UTC');
391
392 if (is_numeric($timestamp)) {
393 $datetime = new \DateTime(null, $wp_timezone);
394 $datetime->setTimezone($timezone);
395 $datetime->setTimestamp($timestamp);
396 }
397 else{
398 $datetime = new \DateTime($timestamp, $wp_timezone);
399 $datetime->setTimezone($timezone);
400 }
401 return $datetime->format($type);
402 }
403
404 public static function mysql_time($timestamp = null) {
405 $type = 'Y-m-d H:i:s';
406 if (empty($timestamp)) {
407 $timestamp = time();
408 }
409
410 if (is_numeric($timestamp)) {
411 $datetime = new \DateTime();
412 $datetime->setTimestamp($timestamp);
413 }
414 else{
415 $datetime = new \DateTime($timestamp);
416 }
417 return $datetime->format($type);
418 }
419
420 /**
421 * Generating Full Name with one letter from last name
422 * @since 1.3.9
423 * @param string $first_name
424 * @param string $last_name
425 * @return string
426 */
427 public static function name($first_name = '', $last_name = '') {
428 $name = $first_name;
429 $name .= !empty($last_name) ? ' ' . mb_substr($last_name, 0, 1) : '';
430 return $name;
431 }
432
433 public static function get_type_title( $type ){
434 $_type = TypeFactory::get_instance()->get($type);
435 return ! empty( $_type->title ) ? $_type->title : $type;
436 }
437
438 public static function is_plugin_installed( $plugin ){
439 if ( ! function_exists( 'get_plugins' ) ) {
440 require_once ABSPATH . 'wp-admin/includes/plugin.php';
441 }
442 $plugins = get_plugins();
443 return isset( $plugins[ $plugin ] );
444 }
445
446 public static function is_plugin_active( $plugin ) {
447 return in_array( $plugin, (array) get_option( 'active_plugins', array() ), true ) || self::is_plugin_active_for_network( $plugin );
448 }
449
450 public static function is_plugin_active_for_network( $plugin ) {
451 if ( ! is_multisite() ) {
452 return false;
453 }
454
455 $plugins = get_site_option( 'active_sitewide_plugins' );
456 if ( isset( $plugins[ $plugin ] ) ) {
457 return true;
458 }
459
460 return false;
461 }
462 public static function remove_old_notice(){
463 global $wp_filter;
464 if( isset( $wp_filter['admin_notices']->callbacks[10] ) && is_array( $wp_filter['admin_notices']->callbacks[10] ) ) {
465 foreach( $wp_filter['admin_notices']->callbacks[10] as $hash => $callbacks ) {
466 if( is_array( $callbacks['function'] ) && ! empty( $callbacks['function'][0] ) && is_object( $callbacks['function'][0] ) && $callbacks['function'][0] instanceof \NotificationX_Licensing ) {
467 remove_action( 'admin_notices', $hash );
468 break;
469 }
470 }
471 }
472 }
473
474 public static function remote_get($url, $args = array(), $raw = false, $assoc = null) {
475 $defaults = array(
476 'timeout' => 20,
477 'redirection' => 5,
478 'httpversion' => '1.1',
479 'user-agent' => 'NotificationX/' . NOTIFICATIONX_VERSION . '; ' . home_url(),
480 'body' => null,
481 'sslverify' => false,
482 'stream' => false,
483 'filename' => null
484 );
485 $args = wp_parse_args($args, $defaults);
486 $response = wp_remote_get($url, $args);
487
488 if (is_wp_error($response)) {
489 return false;
490 }
491 if($raw){
492 return $response;
493 }
494
495 $body = wp_remote_retrieve_body( $response );
496 $response = json_decode($body, $assoc);
497 $_response = (array) $response;
498 if (isset($_response['status']) && $_response['status'] == 'fail') {
499 return false;
500 }
501 return $response;
502 }
503
504 /**
505 * Get File Modification Time or URL
506 *
507 * @param string $file File relative path for Admin
508 * @param boolean $url true for URL return
509 * @return void|string|integer
510 */
511 public static function file( $file, $url = false ){
512 $base = '';
513 if(defined('NX_DEBUG') && NX_DEBUG){
514 if( $url ) {
515 $base = NOTIFICATIONX_DEV_ASSETS;
516 }
517 else{
518 $base = NOTIFICATIONX_DEV_ASSETS_PATH;
519 }
520 if(!file_exists(path_join(NOTIFICATIONX_DEV_ASSETS_PATH, $file))){
521 $base = '';
522 }
523 }
524 if(empty($base)){
525 if( $url ) {
526 $base = NOTIFICATIONX_ASSETS;
527 }
528 else{
529 $base = NOTIFICATIONX_ASSETS_PATH;
530 }
531 }
532 return path_join($base, $file);
533 }
534
535
536 /**
537 * This function returns an array of post titles by searching the post type and the input value
538 *
539 * @param string $post_type The post type to search
540 * @param string|array $inputValue The input value to search by title or ID
541 * @param integer $numberposts The number of posts to return
542 * @return array An associative array of post IDs and titles
543 */
544 public static function get_post_titles_by_search($post_type, $inputValue = '', $numberposts = 10, $args = []) {
545 global $wpdb;
546 $product_list = [];
547 $numberposts = intval( $numberposts );
548 $args = wp_parse_args( $args, [
549 'prefix' => '',
550 ] );
551
552 // Generate a unique cache key based on the input parameters
553 $cache_key = 'get_post_titles_by_search_' . md5( $post_type . serialize( $inputValue ) . $numberposts );
554
555 // Try to get the cached data from the object cache
556 $cached_data = wp_cache_get( $cache_key );
557
558 // If the cached data exists and is not expired, return it
559 if ( false !== $cached_data ) {
560 return $cached_data;
561 }
562
563 // Otherwise, run the original query
564 // Start with the common part of the query
565 $sql = "SELECT ID, post_title FROM {$wpdb->posts} WHERE post_type = %s AND post_status = 'publish'";
566 $query_args = array( $post_type );
567
568 if ( is_array( $inputValue ) && count( $inputValue ) ) {
569 // If the input value is an array of post IDs, use IN clause with placeholders
570 // Generate a string of placeholders like %d,%d,%d
571 $placeholders = implode( ',', array_fill( 0, count( $inputValue ), '%d' ) );
572
573 // Add the IN clause to the query
574 $sql .= " AND ID IN ($placeholders)";
575
576 // Merge the input values to the query arguments
577 $query_args = array_merge( $query_args, array_map( 'intval', $inputValue ) );
578 } else {
579 // If the input value is a string, use LIKE clause with placeholder
580 if ( ! empty( $inputValue ) ) {
581 // Add the LIKE clause to the query
582 $sql .= " AND post_title LIKE %s";
583
584 // Add the input value to the query arguments with wildcards
585 $query_args[] = '%' . $wpdb->esc_like( $inputValue ) . '%';
586 }
587 }
588
589 // Add order and limit clauses
590 $sql .= " ORDER BY post_date DESC LIMIT %d";
591
592 // Add the number of posts to the query arguments
593 $query_args[] = $numberposts;
594
595 // Prepare and execute the query using wpdb methods
596 $sql = $wpdb->prepare( $sql, $query_args );
597 $products = $wpdb->get_results( $sql );
598
599 if ( ! empty( $products ) ) {
600 // Loop through the results and build the output array
601 foreach ( $products as $product ) {
602 $key = $args['prefix'] . $product->ID;
603 $product_list[ $key ] = $product->post_title;
604 }
605 }
606
607 // Store the query result in the object cache with an expiration time of one hour
608 wp_cache_set( $cache_key, $product_list, '', MINUTE_IN_SECONDS );
609
610 // Return the query result
611 return $product_list;
612 }
613
614 /**
615 * Checks if WPML (WordPress Multilingual Plugin) is properly set up and loaded.
616 *
617 * @return bool True if WPML is set up, false otherwise.
618 */
619 public static function is_wpml_setup()
620 {
621 $wpml_has_run = get_option('WPML(TM-has-run)');
622 if (!empty($wpml_has_run['WPML\TM\ATE\Sitekey\Sync']) && did_action('wpml_loaded') && function_exists('load_wpml_st_basics')) {
623 return true;
624 }
625 return false;
626 }
627
628 /**
629 * Returns a list of common fields for GDPR cookie configuration settings.
630 *
631 * @return array An associative array of common GDPR cookie fields.
632 */
633 public static function gdpr_common_fields()
634 {
635 return [
636 'enabled' => array(
637 'type' => 'toggle',
638 'name' => 'enabled',
639 'label' => __('Enabled', 'notificationx'),
640 'priority' => 5,
641 ),
642 'discovered' => array(
643 'type' => 'toggle',
644 'name' => 'discovered',
645 'label' => __('Discovered', 'notificationx'),
646 'priority' => 5,
647 ),
648 'cookies_id' => array(
649 'type' => 'text',
650 'name' => 'cookies_id',
651 'label' => __('Cookie ID', 'notificationx'),
652 'priority' => 10,
653 ),
654 'domain' => array(
655 'type' => 'text',
656 'name' => 'domain',
657 'label' => __('Domain', 'notificationx'),
658 'priority' => 15,
659 ),
660 'duration' => array(
661 'type' => 'number',
662 'name' => 'duration',
663 'label' => __('Duration', 'notificationx'),
664 'min' => 1,
665 'priority' => 20,
666 'suggestions' => [
667 [
668 'value' => 30,
669 'unit' => 'days',
670 ],
671 [
672 'value' => 90,
673 'unit' => 'days',
674 ],
675 [
676 'value' => 180,
677 'unit' => 'days',
678 ],
679 [
680 'value' => 365,
681 'unit' => 'days',
682 ],
683 ],
684 ),
685 'description' => array(
686 'type' => 'textarea',
687 'name' => 'description',
688 'label' => __('Description', 'notificationx-pro'),
689 'priority' => 30,
690 ),
691 'is_add_script' => array(
692 'type' => 'toggle',
693 'name' => 'is_add_script',
694 'label' => __('Add Script', 'notificationx'),
695 'priority' => 35,
696 ),
697 'load_inside' => array(
698 'label' => __('Add Script on', 'notificationx'),
699 'name' => 'product_control',
700 'type' => 'select',
701 'priority' => 40,
702 'default' => 'head',
703 'options' => GlobalFields::get_instance()->normalize_fields([
704 'head' => __('Header', 'notificationx'),
705 'body' => __('Body', 'notificationx'),
706 'footer' => __('Footer', 'notificationx'),
707 ]),
708 ),
709 'script_url_pattern' => array(
710 'type' => 'codeviewer',
711 'name' => 'script_url_pattern',
712 'label' => __('Script', 'notificationx-pro'),
713 'priority' => 45,
714 ),
715 ];
716 }
717
718 /**
719 * Specifies the fields to be shown in the GDPR cookie list.
720 *
721 * @return array An array of field names visible in the GDPR cookie list.
722 */
723 public static function gdpr_cookie_list_visible_fields()
724 {
725 return ['cookies_id', 'domain', 'script_url_pattern', 'duration', 'load_inside','description'];
726 }
727
728 /**
729 * Deletes specific cookies on the server and returns a list of removed cookies.
730 *
731 * @return void Outputs a JSON-encoded list of removed cookies.
732 */
733 public static function delete_server_cookies()
734 {
735 $urlparts = wp_parse_url(site_url('/'));
736 $domain = preg_replace('/www\./i', '', $urlparts['host']);
737 $cookies_removed = array();
738 $d_domains = array('_ga', '_fbp', '_gid', '_gat', '__utma', '__utmb', '__utmc', '__utmt', '__utmz');
739 $d_domains = apply_filters('gdpr_d_domains_filter', $d_domains);
740
741 // Iterate over all cookies and remove them if they match specific conditions.
742 if (isset($_COOKIE) && is_array($_COOKIE) && $domain) :
743 foreach ($_COOKIE as $key => $value) {
744 if ($key !== 'moove_gdpr_popup' && strpos($key, 'woocommerce') === false && strpos($key, 'wc_') === false && strpos($key, 'wordpress') === false) :
745 if ('language' === $key || 'currency' === $key) {
746 setcookie($key, null, -1, '/', 'www.' . $domain);
747 $cookies_removed[$key] = $domain;
748 } elseif (in_array($key, $d_domains) || strpos($key, '_ga') !== false || strpos($key, '_fbp') !== false) {
749 setcookie($key, null, -1, '/', '.' . $domain);
750 $cookies_removed[$key] = $domain;
751 }
752 endif;
753 }
754 endif;
755
756 // Parse and remove cookies from the HTTP header.
757 $cookies = isset($_SERVER['HTTP_COOKIE']) ? explode(';', sanitize_text_field(wp_unslash($_SERVER['HTTP_COOKIE']))) : false;
758 if (is_array($cookies)) :
759 foreach ($cookies as $cookie) {
760 $parts = explode('=', $cookie);
761 $name = trim($parts[0]);
762 if ($name && $name !== 'moove_gdpr_popup' && strpos($name, 'woocommerce') === false && strpos($name, 'wc_') === false && strpos($name, 'wordpress') === false) :
763 setcookie($name, '', time() - 1000);
764 setcookie($name, '', time() - 1000, '/');
765 if ('language' === $name || 'currency' === $name) {
766 setcookie($name, null, -1, '/', 'www.' . $domain);
767 $cookies_removed[$name] = $domain;
768 } elseif (in_array($key, $d_domains) || strpos($name, '_ga') !== false || strpos($name, '_fbp') !== false) {
769 setcookie($name, null, -1, '/', '.' . $domain);
770 $cookies_removed[$name] = '.' . $domain;
771 } else {
772 setcookie($name, null, -1, '/');
773 $cookies_removed[$name] = $domain;
774 }
775 endif;
776 }
777 endif;
778
779 // Output the list of removed cookies as a JSON response.
780 echo json_encode($cookies_removed);
781 }
782
783 public static function tab_info_title($name, $title_default, $modal = false)
784 {
785 return [
786 'type' => 'text',
787 'name' => "{$name}_tab_title",
788 'default' => $title_default,
789 'label' => __('Name', 'notificationx'),
790 'autoFocus' => true,
791 ];
792 }
793
794 public static function tab_info_desc($name, $desc_default, $modal = false)
795 {
796 return [
797 'type' => 'textarea',
798 'row' => 3,
799 'name' => "{$name}_tab_desc",
800 'default' => $desc_default,
801 'label' => __('Description', 'notificationx'),
802 ];
803 }
804
805
806 public static function default_cookie_list()
807 {
808 return [
809 [
810 'enabled' => true,
811 'default' => true,
812 'cookies_id' => 'wordpress_logged_in',
813 'load_inside' => 'head',
814 'script_url_pattern' => '',
815 'description' => __('Indicates when a user is logged in and who they are, for most interface use.','notificationx'),
816 'index' => wp_generate_uuid4(),
817 ],
818 [
819 'enabled' => true,
820 'default' => true,
821 'cookies_id' => 'wordpress_sec',
822 'load_inside' => 'head',
823 'script_url_pattern' => '',
824 'description' => __('Used for security purposes for logged-in users.', 'notificationx'),
825 'index' => wp_generate_uuid4(),
826 ],
827 [
828 'enabled' => true,
829 'default' => true,
830 'cookies_id' => 'wp-settings-{user_id}',
831 'load_inside' => 'head',
832 'script_url_pattern' => '',
833 'description' => __('Used to persist a user\'s WordPress admin settings.','notificationx'),
834 'index' => wp_generate_uuid4(),
835 ],
836 [
837 'enabled' => true,
838 'default' => true,
839 'cookies_id' => 'wp-settings-time-{user_id}',
840 'load_inside' => 'head',
841 'script_url_pattern' => '',
842 'description' => __('Records the time that wp-settings-{user_id} was set.', 'notificationx'),
843 'index' => wp_generate_uuid4(),
844 ],
845 [
846 'enabled' => true,
847 'default' => true,
848 'cookies_id' => 'wp-settings-time-{user_id}',
849 'load_inside' => 'head',
850 'script_url_pattern' => '',
851 'description' => __('Records the time that wp-settings-{user_id} was set.', 'notificationx'),
852 'index' => wp_generate_uuid4(),
853 ],
854 [
855 'enabled' => true,
856 'default' => true,
857 'cookies_id' => 'nx_cookie_manager',
858 'script_url_pattern' => '',
859 'description' => __('Manages the cookies on the site, ensuring user consent for GDPR compliance.', 'notificationx'),
860 'index' => wp_generate_uuid4(),
861 ],
862 ];
863
864 }
865
866 // Helper function to get the image ID from data
867 public static function get_image_id_from_settings($data) {
868 return isset($data['image']['id']) ? $data['image']['id'] : null;
869 }
870
871 // Helper function to get custom image size
872 public static function get_custom_image_size() {
873 $default_size = '100_100'; // Default size
874 $image_size = (string) Settings::get_instance()->get('settings.notification_image_size', $default_size);
875 $image_size_parts = explode('_', $image_size);
876
877 if (!empty($image_size_parts[0]) && is_numeric($image_size_parts[0]) && !empty($image_size_parts[1]) && is_numeric($image_size_parts[1])) {
878 return [
879 'width' => (int) $image_size_parts[0],
880 'height' => (int) $image_size_parts[1],
881 ];
882 }
883
884 return [
885 'width' => 100, // Default width
886 'height' => 100, // Default height
887 ];
888 }
889
890 // Helper function to get resized image URL
891 public static function get_resized_image_url($image_id, $custom_size) {
892 if (!$image_id || empty($custom_size['width']) || empty($custom_size['height'])) {
893 return null;
894 }
895
896 $image = wp_get_attachment_image_src(
897 $image_id,
898 [$custom_size['width'], $custom_size['height']],
899 true // Crop the image to exact dimensions
900 );
901
902 return $image && isset($image[0]) ? $image[0] : null;
903 }
904
905 public static function nx_allowed_html()
906 {
907 return [
908 'a' => [
909 'href' => [],
910 'title' => [],
911 'target' => [],
912 'rel' => [],
913 'class' => [],
914 'id' => [],
915 ],
916 'abbr' => [
917 'title' => [],
918 'class' => [],
919 ],
920 'style' => [],
921 'b' => [
922 'class' => [],
923 ],
924 'blockquote' => [
925 'cite' => [],
926 'class' => [],
927 ],
928 'br' => [],
929 'cite' => [
930 'class' => [],
931 ],
932 'code' => [
933 'class' => [],
934 ],
935 'del' => [
936 'datetime' => [],
937 'class' => [],
938 ],
939 'div' => [
940 'class' => [],
941 'id' => [],
942 'style' => [],
943 ],
944 'em' => [
945 'class' => [],
946 ],
947 'h1' => [
948 'class' => [],
949 'id' => [],
950 ],
951 'h2' => [
952 'class' => [],
953 'id' => [],
954 ],
955 'h3' => [
956 'class' => [],
957 'id' => [],
958 ],
959 'h4' => [
960 'class' => [],
961 'id' => [],
962 ],
963 'h5' => [
964 'class' => [],
965 'id' => [],
966 ],
967 'h6' => [
968 'class' => [],
969 'id' => [],
970 ],
971 'hr' => [
972 'class' => [],
973 ],
974 'i' => [
975 'class' => [],
976 ],
977 'img' => [
978 'src' => [],
979 'alt' => [],
980 'title' => [],
981 'width' => [],
982 'height' => [],
983 'class' => [],
984 'id' => [],
985 ],
986 'li' => [
987 'class' => [],
988 ],
989 'ol' => [
990 'class' => [],
991 ],
992 'p' => [
993 'class' => [],
994 'style' => [],
995 ],
996 'pre' => [
997 'class' => [],
998 ],
999 'q' => [
1000 'cite' => [],
1001 'class' => [],
1002 ],
1003 'span' => [
1004 'class' => [],
1005 'style' => [],
1006 ],
1007 'strong' => [
1008 'class' => [],
1009 ],
1010 'table' => [
1011 'class' => [],
1012 'style' => [],
1013 ],
1014 'tbody' => [
1015 'class' => [],
1016 ],
1017 'td' => [
1018 'colspan' => [],
1019 'rowspan' => [],
1020 'class' => [],
1021 'style' => [],
1022 ],
1023 'tfoot' => [
1024 'class' => [],
1025 ],
1026 'th' => [
1027 'colspan' => [],
1028 'rowspan' => [],
1029 'scope' => [],
1030 'class' => [],
1031 'style' => [],
1032 ],
1033 'thead' => [
1034 'class' => [],
1035 ],
1036 'tr' => [
1037 'class' => [],
1038 ],
1039 'ul' => [
1040 'class' => [],
1041 ],
1042 ];
1043 }
1044 public static function generate_time_string($data) {
1045 $timeString = '';
1046 if (isset($data['display_from']) && intval($data['display_from']) > 0) {
1047 $timeString .= intval($data['display_from']) . ' days ';
1048 }
1049
1050 if (isset($data['display_from_hour']) && intval($data['display_from_hour']) > 0) {
1051 $timeString .= intval($data['display_from_hour']) . ' hours ';
1052 }
1053
1054 if (isset($data['display_from_minute']) && intval($data['display_from_minute']) > 0) {
1055 $timeString .= intval($data['display_from_minute']) . ' minutes ';
1056 }
1057
1058 if (!empty($timeString)) {
1059 $time = strtotime($timeString . ' ago');
1060 } else {
1061 $time = time(); // Default to current time if no valid inputs
1062 }
1063 return $time;
1064 }
1065
1066 /**
1067 * Get the current datetime based on the WordPress site's timezone.
1068 *
1069 * @return string Formatted datetime in 'Y-m-d H:i:s' format.
1070 */
1071 public static function nx_get_current_datetime() {
1072 // Get the WordPress timezone setting
1073 $timezone = get_option('timezone_string');
1074
1075 if (!$timezone) {
1076 // If timezone_string is empty, fallback to gmt_offset
1077 $gmt_offset = get_option('gmt_offset');
1078
1079 if ($gmt_offset !== false) {
1080 $timezone = timezone_name_from_abbr("", (int) $gmt_offset * 3600, false);
1081 }
1082
1083 // If timezone_name_from_abbr fails, manually handle GMT offsets
1084 if (!$timezone) {
1085 $timezone = sprintf('Etc/GMT%+d', -$gmt_offset); // Example: GMT+6 → Etc/GMT-6
1086 }
1087 }
1088
1089 try {
1090 $date = new \DateTime('now', new \DateTimeZone($timezone));
1091 return $date->format('Y-m-d H:i:s'); // Format as MySQL datetime
1092 } catch (\Exception $e) {
1093 // If an error occurs, return UTC time as a fallback
1094 return gmdate('Y-m-d H:i:s');
1095 }
1096 }
1097
1098 public static function nx_get_visitor_country_code() {
1099 $ip = '';
1100 if (!empty($_SERVER['HTTP_CLIENT_IP'])) {
1101 $ip = $_SERVER['HTTP_CLIENT_IP'];
1102 } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) {
1103 $ip = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR'])[0];
1104 } else {
1105 $ip = $_SERVER['REMOTE_ADDR'];
1106 }
1107
1108 // Prevent localhost IP from erroring
1109 if ($ip === '127.0.0.1' || $ip === '::1') {
1110 return 'all'; // default fallback for local testing
1111 }
1112
1113 $response = wp_remote_get("http://ip-api.com/json/{$ip}?fields=countryCode");
1114
1115 if (is_wp_error($response)) {
1116 return null;
1117 }
1118
1119 $data = json_decode(wp_remote_retrieve_body($response), true);
1120
1121 return isset($data['countryCode']) ? $data['countryCode'] : null;
1122 }
1123
1124 public static function nx_get_all_country($search = '') {
1125 $countries = [
1126 'all' => __('All Countries', 'notificationx'),
1127 'AF' => __('Afghanistan', 'notificationx'),
1128 'AL' => __('Albania', 'notificationx'),
1129 'DZ' => __('Algeria', 'notificationx'),
1130 'AS' => __('American Samoa', 'notificationx'),
1131 'AD' => __('Andorra', 'notificationx'),
1132 'AO' => __('Angola', 'notificationx'),
1133 'AI' => __('Anguilla', 'notificationx'),
1134 'AQ' => __('Antarctica', 'notificationx'),
1135 'AG' => __('Antigua and Barbuda', 'notificationx'),
1136 'AR' => __('Argentina', 'notificationx'),
1137 'AM' => __('Armenia', 'notificationx'),
1138 'AW' => __('Aruba', 'notificationx'),
1139 'AU' => __('Australia', 'notificationx'),
1140 'AT' => __('Austria', 'notificationx'),
1141 'AZ' => __('Azerbaijan', 'notificationx'),
1142 'BS' => __('Bahamas', 'notificationx'),
1143 'BH' => __('Bahrain', 'notificationx'),
1144 'BD' => __('Bangladesh', 'notificationx'),
1145 'BB' => __('Barbados', 'notificationx'),
1146 'BY' => __('Belarus', 'notificationx'),
1147 'BE' => __('Belgium', 'notificationx'),
1148 'BZ' => __('Belize', 'notificationx'),
1149 'BJ' => __('Benin', 'notificationx'),
1150 'BM' => __('Bermuda', 'notificationx'),
1151 'BT' => __('Bhutan', 'notificationx'),
1152 'BO' => __('Bolivia', 'notificationx'),
1153 'BA' => __('Bosnia and Herzegovina', 'notificationx'),
1154 'BW' => __('Botswana', 'notificationx'),
1155 'BR' => __('Brazil', 'notificationx'),
1156 'BN' => __('Brunei', 'notificationx'),
1157 'BG' => __('Bulgaria', 'notificationx'),
1158 'BF' => __('Burkina Faso', 'notificationx'),
1159 'BI' => __('Burundi', 'notificationx'),
1160 'KH' => __('Cambodia', 'notificationx'),
1161 'CM' => __('Cameroon', 'notificationx'),
1162 'CA' => __('Canada', 'notificationx'),
1163 'CV' => __('Cape Verde', 'notificationx'),
1164 'CF' => __('Central African Republic', 'notificationx'),
1165 'TD' => __('Chad', 'notificationx'),
1166 'CL' => __('Chile', 'notificationx'),
1167 'CN' => __('China', 'notificationx'),
1168 'CO' => __('Colombia', 'notificationx'),
1169 'KM' => __('Comoros', 'notificationx'),
1170 'CG' => __('Congo (Brazzaville)', 'notificationx'),
1171 'CD' => __('Congo (Kinshasa)', 'notificationx'),
1172 'CR' => __('Costa Rica', 'notificationx'),
1173 'HR' => __('Croatia', 'notificationx'),
1174 'CU' => __('Cuba', 'notificationx'),
1175 'CY' => __('Cyprus', 'notificationx'),
1176 'CZ' => __('Czech Republic', 'notificationx'),
1177 'DK' => __('Denmark', 'notificationx'),
1178 'DJ' => __('Djibouti', 'notificationx'),
1179 'DM' => __('Dominica', 'notificationx'),
1180 'DO' => __('Dominican Republic', 'notificationx'),
1181 'EC' => __('Ecuador', 'notificationx'),
1182 'EG' => __('Egypt', 'notificationx'),
1183 'SV' => __('El Salvador', 'notificationx'),
1184 'GQ' => __('Equatorial Guinea', 'notificationx'),
1185 'ER' => __('Eritrea', 'notificationx'),
1186 'EE' => __('Estonia', 'notificationx'),
1187 'ET' => __('Ethiopia', 'notificationx'),
1188 'FJ' => __('Fiji', 'notificationx'),
1189 'FI' => __('Finland', 'notificationx'),
1190 'FR' => __('France', 'notificationx'),
1191 'GA' => __('Gabon', 'notificationx'),
1192 'GM' => __('Gambia', 'notificationx'),
1193 'GE' => __('Georgia', 'notificationx'),
1194 'DE' => __('Germany', 'notificationx'),
1195 'GH' => __('Ghana', 'notificationx'),
1196 'GR' => __('Greece', 'notificationx'),
1197 'GD' => __('Grenada', 'notificationx'),
1198 'GT' => __('Guatemala', 'notificationx'),
1199 'GN' => __('Guinea', 'notificationx'),
1200 'GW' => __('Guinea-Bissau', 'notificationx'),
1201 'GY' => __('Guyana', 'notificationx'),
1202 'HT' => __('Haiti', 'notificationx'),
1203 'HN' => __('Honduras', 'notificationx'),
1204 'HK' => __('Hong Kong', 'notificationx'),
1205 'HU' => __('Hungary', 'notificationx'),
1206 'IS' => __('Iceland', 'notificationx'),
1207 'IN' => __('India', 'notificationx'),
1208 'ID' => __('Indonesia', 'notificationx'),
1209 'IR' => __('Iran', 'notificationx'),
1210 'IQ' => __('Iraq', 'notificationx'),
1211 'IE' => __('Ireland', 'notificationx'),
1212 'IL' => __('Israel', 'notificationx'),
1213 'IT' => __('Italy', 'notificationx'),
1214 'JM' => __('Jamaica', 'notificationx'),
1215 'JP' => __('Japan', 'notificationx'),
1216 'JO' => __('Jordan', 'notificationx'),
1217 'KZ' => __('Kazakhstan', 'notificationx'),
1218 'KE' => __('Kenya', 'notificationx'),
1219 'KI' => __('Kiribati', 'notificationx'),
1220 'KR' => __('Korea, South', 'notificationx'),
1221 'KW' => __('Kuwait', 'notificationx'),
1222 'KG' => __('Kyrgyzstan', 'notificationx'),
1223 'LA' => __('Laos', 'notificationx'),
1224 'LV' => __('Latvia', 'notificationx'),
1225 'LB' => __('Lebanon', 'notificationx'),
1226 'LS' => __('Lesotho', 'notificationx'),
1227 'LR' => __('Liberia', 'notificationx'),
1228 'LY' => __('Libya', 'notificationx'),
1229 'LI' => __('Liechtenstein', 'notificationx'),
1230 'LT' => __('Lithuania', 'notificationx'),
1231 'LU' => __('Luxembourg', 'notificationx'),
1232 'MG' => __('Madagascar', 'notificationx'),
1233 'MW' => __('Malawi', 'notificationx'),
1234 'MY' => __('Malaysia', 'notificationx'),
1235 'MV' => __('Maldives', 'notificationx'),
1236 'ML' => __('Mali', 'notificationx'),
1237 'MT' => __('Malta', 'notificationx'),
1238 'MH' => __('Marshall Islands', 'notificationx'),
1239 'MR' => __('Mauritania', 'notificationx'),
1240 'MU' => __('Mauritius', 'notificationx'),
1241 'MX' => __('Mexico', 'notificationx'),
1242 'FM' => __('Micronesia', 'notificationx'),
1243 'MD' => __('Moldova', 'notificationx'),
1244 'MC' => __('Monaco', 'notificationx'),
1245 'MN' => __('Mongolia', 'notificationx'),
1246 'ME' => __('Montenegro', 'notificationx'),
1247 'MA' => __('Morocco', 'notificationx'),
1248 'MZ' => __('Mozambique', 'notificationx'),
1249 'MM' => __('Myanmar (Burma)', 'notificationx'),
1250 'NA' => __('Namibia', 'notificationx'),
1251 'NR' => __('Nauru', 'notificationx'),
1252 'NP' => __('Nepal', 'notificationx'),
1253 'NL' => __('Netherlands', 'notificationx'),
1254 'NZ' => __('New Zealand', 'notificationx'),
1255 'NI' => __('Nicaragua', 'notificationx'),
1256 'NE' => __('Niger', 'notificationx'),
1257 'NG' => __('Nigeria', 'notificationx'),
1258 'MK' => __('North Macedonia', 'notificationx'),
1259 'NO' => __('Norway', 'notificationx'),
1260 'OM' => __('Oman', 'notificationx'),
1261 'PK' => __('Pakistan', 'notificationx'),
1262 'PW' => __('Palau', 'notificationx'),
1263 'PA' => __('Panama', 'notificationx'),
1264 'PG' => __('Papua New Guinea', 'notificationx'),
1265 'PY' => __('Paraguay', 'notificationx'),
1266 'PE' => __('Peru', 'notificationx'),
1267 'PH' => __('Philippines', 'notificationx'),
1268 'PL' => __('Poland', 'notificationx'),
1269 'PT' => __('Portugal', 'notificationx'),
1270 'QA' => __('Qatar', 'notificationx'),
1271 'RO' => __('Romania', 'notificationx'),
1272 'RU' => __('Russia', 'notificationx'),
1273 'RW' => __('Rwanda', 'notificationx'),
1274 'SA' => __('Saudi Arabia', 'notificationx'),
1275 'SN' => __('Senegal', 'notificationx'),
1276 'RS' => __('Serbia', 'notificationx'),
1277 'SC' => __('Seychelles', 'notificationx'),
1278 'SL' => __('Sierra Leone', 'notificationx'),
1279 'SG' => __('Singapore', 'notificationx'),
1280 'SK' => __('Slovakia', 'notificationx'),
1281 'SI' => __('Slovenia', 'notificationx'),
1282 'SB' => __('Solomon Islands', 'notificationx'),
1283 'SO' => __('Somalia', 'notificationx'),
1284 'ZA' => __('South Africa', 'notificationx'),
1285 'ES' => __('Spain', 'notificationx'),
1286 'LK' => __('Sri Lanka', 'notificationx'),
1287 'SD' => __('Sudan', 'notificationx'),
1288 'SR' => __('Suriname', 'notificationx'),
1289 'SE' => __('Sweden', 'notificationx'),
1290 'CH' => __('Switzerland', 'notificationx'),
1291 'SY' => __('Syria', 'notificationx'),
1292 'TW' => __('Taiwan', 'notificationx'),
1293 'TJ' => __('Tajikistan', 'notificationx'),
1294 'TZ' => __('Tanzania', 'notificationx'),
1295 'TH' => __('Thailand', 'notificationx'),
1296 'TG' => __('Togo', 'notificationx'),
1297 'TO' => __('Tonga', 'notificationx'),
1298 'TT' => __('Trinidad and Tobago', 'notificationx'),
1299 'TN' => __('Tunisia', 'notificationx'),
1300 'TR' => __('Turkey', 'notificationx'),
1301 'TM' => __('Turkmenistan', 'notificationx'),
1302 'UG' => __('Uganda', 'notificationx'),
1303 'UA' => __('Ukraine', 'notificationx'),
1304 'AE' => __('United Arab Emirates', 'notificationx'),
1305 'GB' => __('United Kingdom', 'notificationx'),
1306 'US' => __('United States', 'notificationx'),
1307 'UY' => __('Uruguay', 'notificationx'),
1308 'UZ' => __('Uzbekistan', 'notificationx'),
1309 'VU' => __('Vanuatu', 'notificationx'),
1310 'VE' => __('Venezuela', 'notificationx'),
1311 'VN' => __('Vietnam', 'notificationx'),
1312 'YE' => __('Yemen', 'notificationx'),
1313 'ZM' => __('Zambia', 'notificationx'),
1314 'ZW' => __('Zimbabwe', 'notificationx'),
1315 ];
1316 if (!empty($search)) {
1317 $search = strtolower($search);
1318 $countries = array_filter($countries, function($name) use ($search) {
1319 return strpos(strtolower($name), $search) !== false;
1320 });
1321 }
1322 return $countries;
1323 }
1324
1325
1326 }
1327