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 / FrontEnd / FrontEnd.php

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

993 lines 42.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * FrontEnd Class
5 *
6 * @package NotificationX\FrontEnd
7 */
8
9 namespace NotificationX\FrontEnd;
10
11 use NotificationX\Admin\Entries;
12 use NotificationX\Admin\Settings;
13 use NotificationX\Core\Analytics;
14 use NotificationX\Core\Database;
15 use NotificationX\Core\GetData;
16 use NotificationX\NotificationX;
17 use NotificationX\Core\Locations;
18 use NotificationX\Core\PostType;
19 use NotificationX\Core\REST;
20 use NotificationX\GetInstance;
21 use NotificationX\Extensions\PressBar\PressBar;
22 use NotificationX\Core\Helper;
23 use NotificationX\Extensions\ExtensionFactory;
24 use NotificationX\Types\GDPR;
25
26 /**
27 * This class is responsible for all Front-End actions.
28 * @method static FrontEnd get_instance($args = null)
29 */
30 class FrontEnd {
31 /**
32 * Instance of FrontEnd
33 *
34 * @var FrontEnd
35 */
36 use GetInstance;
37 /**
38 * Assets Path and URL
39 */
40 const ASSET_URL = NOTIFICATIONX_ASSETS . 'public/';
41 const ASSET_PATH = NOTIFICATIONX_ASSETS_PATH . 'public/';
42 protected $notificationXArr = [];
43
44 /**
45 * Initially Invoked
46 * when its initialized.
47 */
48 public function __construct() {
49 Analytics::get_instance();
50 if (!is_admin() || !empty($_GET['frontend'])) {
51 add_action('init', [$this, 'init'], 10);
52 }
53 add_filter('nx_frontend_localize_data', [$this, 'get_localize_data']);
54 Preview::get_instance();
55 }
56
57 /**
58 * This method is reponsible for Admin Menu of
59 * NotificationX
60 *
61 * @return void
62 */
63 public function init() {
64 add_action('wp_enqueue_scripts', [$this, 'enqueue_scripts'], 10);
65 add_filter('nx_fallback_data', [$this, 'fallback_data'], 10, 3);
66 add_filter('nx_filtered_data', [$this, 'filtered_data'], 9999, 3);
67 add_filter('nx_filtered_post', [$this, 'filtered_post'], 9999, 2);
68 add_action('wp_print_footer_scripts', [$this, 'footer_scripts']);
69 add_filter('body_class', [ $this, 'nx_add_body_class' ] );
70
71 }
72
73 /**
74 * This method is responsible for enqueueing scripts for public use.
75 *
76 * @return void
77 */
78 public function enqueue_scripts() {
79 $custom_css = $this->generate_custom_css();
80 wp_register_script('notificationx-public', Helper::file('public/js/frontend.js', true), [], apply_filters('nx_frontend_js_version', NOTIFICATIONX_VERSION ), true);
81 wp_register_style('notificationx-public', Helper::file('public/css/frontend.css', true), [], apply_filters('nx_frontend_css_version', NOTIFICATIONX_VERSION ), 'all');
82 // wp_register_style('notificationx-icon-pack', Helper::file('public/icon/style.css', true), [], NOTIFICATIONX_VERSION, 'all');
83 // Localize scripts for frontend
84 wp_localize_script(
85 'notificationx-public',
86 'notificationxPublic',
87 array(
88 'necessary_tab_info' => [
89 'title' => __('Necessary', 'notificationx'),
90 'desc' => __('Necessary cookies are needed to ensure the basic functions of this site, like allowing secure log-ins and managing your consent settings. These cookies do not collect any personal information.', 'notificationx'),
91 ],
92 'functional_tab_info' => [
93 'title' => __('Functional', 'notificationx'),
94 'desc' => __('Functional cookies assist in performing tasks like sharing website content on social media, collecting feedback, and enabling other third-party features.', 'notificationx'),
95 ],
96 'analytics_tab_info' => [
97 'title' => __('Analytics', 'notificationx'),
98 'desc' => __('Analytical cookies help us understand how visitors use the website. They provide data on metrics like the number of visitors, bounce rate, traffic sources etc.', 'notificationx'),
99 ],
100 'performance_tab_info' => [
101 'title' => __('Performance', 'notificationx'),
102 'desc' => __("Performance cookies help analyze the website's key performance indicators, which in turn helps improve the user experience for visitors.", 'notificationx'),
103 ],
104 'advertising_tab_info' => [
105 'title' => __('Advertisement', 'notificationx'),
106 'desc' => __("Advertisement cookies help analyze the website's key advertising indicators, which in turn helps improve the user experience for visitors.", 'notificationx'),
107 ],
108 'uncategorized_tab_info' => [
109 'title' => __('Uncategorized', 'notificationx'),
110 'desc' => __("Uncategorized cookies are those that don't fall into any specific category but may still be used for various purposes on the site. These cookies help us improve user experience by tracking interactions that don't fit into other cookie types.", 'notificationx'),
111 ],
112 'is_enabled_wp_consent_api' => is_plugin_active('wp-consent-api/wp-consent-api.php'),
113 )
114 );
115
116 $exit = false;
117 if(isset($_SERVER['HTTP_REFERER']) && strpos($_SERVER['HTTP_REFERER'], 'wp-admin/widgets.php') !== false){
118 $exit = ['total' => 0];
119 }
120
121 $exit = apply_filters('nx_before_enqueue_scripts', $exit);
122 if(!empty($exit)){
123 $this->notificationXArr = $exit;
124 return;
125 }
126
127 if (!$exit && empty($_GET['elementor-preview'])) {
128 $this->notificationXArr = $this->get_notifications_ids();
129 if ($this->notificationXArr['total'] > 0) {
130 $lang = get_locale();
131 $lang = str_replace('_', '-', $lang);
132 $lang = strtolower($lang);
133 $_lang = explode('-', $lang);
134 if ($lang !== "en" && $lang !== "en-us") {
135 $script = Helper::file("public/locale/$lang.js", false);
136 if (file_exists($script)) {
137 wp_enqueue_script('notificationx-moment-locale', Helper::file("public/locale/$lang.js", true), [], NOTIFICATIONX_VERSION, true);
138 } else if (!empty($_lang[1])) {
139 $lang = $_lang[0];
140 $script = Helper::file("public/locale/$lang.js", false);
141 if (file_exists($script)) {
142 wp_enqueue_script('notificationx-moment-locale', Helper::file("public/locale/$lang.js", true), [], NOTIFICATIONX_VERSION, true);
143 }
144 }
145 }
146
147 wp_enqueue_style('notificationx-public');
148 wp_enqueue_script('notificationx-public');
149 wp_enqueue_style('dashicons');
150 do_action('notificationx_scripts', $this->notificationXArr);
151 wp_add_inline_style( 'notificationx-public', $custom_css );
152 }
153 } else {
154 // @todo maybe elementor edit mode CSS. to move to top.
155 // LATER
156 }
157 }
158
159 public function nx_add_body_class($classes) {
160 $classes[] = 'has-notificationx';
161 return $classes;
162 }
163
164 private function separate_css($css) {
165 $media_css = '';
166 $normal_css = '';
167
168 // Match @media blocks
169 preg_match_all('/@media[^{]*{([^}]*{[^}]*})*[^}]*}/', $css, $media_matches);
170
171 // Extract normal CSS
172 $normal_css = preg_replace('/@media[^{]*{([^}]*{[^}]*})*[^}]*}/', '', $css);
173
174 // Extract @media CSS
175 if (!empty($media_matches[0])) {
176 $media_css = implode("\n", $media_matches[0]);
177 }
178
179 // Clean up normal CSS (remove extra whitespace)
180 $normal_css = trim($normal_css);
181
182 return [
183 'normal_css' => $normal_css,
184 'media_css' => $media_css
185 ];
186 }
187
188 public function generate_custom_css() {
189 $posts = Database::get_instance()->get_posts(Database::$table_posts, '*', ['enabled' => true] );
190 $combine_css = "";
191 foreach ($posts as $post) {
192 if( !empty( $post['data']['add_custom_css'] ) && !empty( $post['nx_id'] ) ) {
193 $separatedCss = $this->separate_css($post['data']['add_custom_css']);
194 if( !empty( $post['data']['source'] ) && $post['data']['source'] == 'press_bar' ) {
195 $combine_css .= "{$separatedCss['normal_css']} {$separatedCss['media_css']} ";
196 } else if( !empty( $post['data']['source'] ) && $post['data']['source'] == 'gdpr_notification' ) {
197 $combine_css .= "{$separatedCss['normal_css']} {$separatedCss['media_css']} ";
198 }
199 else {
200 $combine_css .= "{$separatedCss['normal_css']} {$separatedCss['media_css']} ";
201 }
202 }
203 }
204 return $combine_css;
205 }
206
207 public function footer_scripts() {
208 if (!empty($this->notificationXArr['total']) && $this->notificationXArr['total'] > 0) {
209 $this->notificationXArr = apply_filters('nx_frontend_localize_data', $this->notificationXArr);
210 ?>
211 <script data-no-optimize="1">
212 (function() {
213 window.notificationXArr = window.notificationXArr || [];
214 window.notificationXArr.push(<?php echo json_encode($this->notificationXArr); ?>);
215 })();
216 </script>
217 <?php
218 }
219 }
220
221 // @todo deprecated. use get_localize_data instead
222 public function localizeScripts() {
223 return [];
224 }
225
226 public function get_localize_data($data) {
227 $data['rest'] = REST::get_instance()->rest_data(false);
228 $data['assets'] = self::ASSET_URL;
229 $data['is_pro'] = false;
230 $data['gmt_offset'] = get_option('gmt_offset');
231 $data['lang'] = get_locale();
232 $data['common_assets'] = NOTIFICATIONX_COMMON_URL;
233 $data['extra'] = [
234 'is_singular' => is_singular(),
235 'query' => $GLOBALS['wp_query']->query,
236 'queried_id' => get_queried_object_id(),
237 'pid' => !empty($GLOBALS['post']->ID) ? $GLOBALS['post']->ID : 0,
238 ];
239 $data['localeData'] = load_script_textdomain('notificationx-public', 'notificationx');
240 return $data;
241 }
242
243 public function get_notifications_data($params) {
244 $_params = $params;
245 $result = [
246 'global' => [],
247 'active' => [],
248 'pressbar' => [],
249 'gdpr' => [],
250 'shortcode' => [],
251 'popup' => [],
252 'exit_intent' => [],
253 ];
254 if (!empty($_params['all_active'])) {
255 $params = $this->get_notifications_ids();
256 }
257 $params = wp_parse_args(
258 $params,
259 [
260 'global' => [],
261 'active' => [],
262 'pressbar' => [],
263 'gdpr' => [],
264 'popup' => [],
265 'exit_intent' => [],
266 'shortcode' => [],
267 'inline_shortcode' => false,
268 ]
269 );
270 $global = $params['global'];
271 $active = $params['active'];
272 $pressbar = $params['pressbar'];
273 $gdpr = $params['gdpr'];
274 $popup = $params['popup'];
275 $exit_intent = $params['exit_intent'];
276 $shortcode = $params['shortcode'];
277 $all = array_merge($global, $active, $shortcode);
278 $_defaults = array(
279 'none' => '',
280 'name' => __('Someone', 'notificationx'),
281 'first_name' => __('Someone', 'notificationx'),
282 'last_name' => __('Someone', 'notificationx'),
283 'anonymous_title' => __('Anonymous Title', 'notificationx'),
284 'sometime' => __('Some time ago', 'notificationx'),
285 );
286
287 // foreach (['global', 'active'] as $key => $type) {
288 // foreach ($params[$type] as $id) {
289 // $result[$type][$id] = [];
290 // }
291 // }
292
293 $device = isset($params['deviceType']) && !empty($params['deviceType']) ? $params['deviceType'] : '';
294 if (!empty($all)) {
295 $notifications = $this->get_notifications($all, $device);
296 $entries = $this->get_entries($all, $notifications, $params);
297
298 foreach ($entries as $entry) {
299 $nx_id = $entry['nx_id'];
300 $settings = $notifications[$nx_id];
301
302 // check if notification is enabled or not.
303 if (!$settings['enabled']) {
304 continue;
305 }
306
307 $type = $settings['type'];
308 $source = $settings['source'];
309
310 $should_continue = apply_filters("nx_entry_show_on_frontend_$source", false, $entry, $settings);
311 if ( $should_continue ) {
312 continue;
313 }
314
315 if (!empty($entry['timestamp'])) {
316 $timestamp = $entry['timestamp'];
317 $display_from = !empty($settings['display_from']) ? $settings['display_from'] : 2;
318 $display_from = Helper::generate_time_string($settings);
319 if (!is_numeric($timestamp)) {
320 $entry['timestamp'] = $timestamp = is_string($timestamp) ? strtotime($timestamp) : false;
321 }
322 if ($timestamp && $display_from > $timestamp) {
323 if (apply_filters("nx_entry_display_$source", true, $entry, $settings)) {
324 continue;
325 }
326 }
327 }
328
329 $defaults = apply_filters("nx_fallback_data_$source", $_defaults, $entry, $settings);
330 $defaults = apply_filters('nx_fallback_data', $defaults, $entry, $settings);
331
332 $entry = $this->apply_defaults($entry, $defaults);
333 $entry['image_data'] = $this->get_image_url($entry, $settings);
334 if (!empty($entry['title'])) {
335 $entry['title'] = strip_tags(html_entity_decode($entry['title']));
336 }
337
338 $entry = apply_filters("nx_filtered_entry_$type", $entry, $settings);
339 $entry = apply_filters("nx_filtered_entry_$source", $entry, $settings);
340 $entry = apply_filters('nx_filtered_entry', $entry, $settings);
341 $entry = $this->link_url($entry, $settings, $params);
342
343 // @todo shortcode
344 // @todo check if the current page have shortcode.
345 if (in_array($nx_id, $shortcode)) {
346 $position = $settings['position'];
347 $settings['position'] = "notificationx-shortcode-$nx_id";
348 if (empty($result['shortcode'][$nx_id]['post'])) {
349 $result['shortcode'][$nx_id]['post'] = $settings;
350 }
351 $result['shortcode'][$nx_id]['entries'][] = $entry;
352 $settings['position'] = $position;
353 if ($settings['show_on'] === 'only_shortcode' || 'inline' === $settings['type'] || 'woocommerce_sales_inline' == $settings['source']) {
354 continue;
355 }
356 if (empty($global) && empty($active)) {
357 continue;
358 }
359 }
360
361 if (!empty($settings['global_queue'])) {
362 if (empty($result['global'][$nx_id]['post'])) {
363 $result['global'][$nx_id]['post'] = $settings;
364 }
365 $result['global'][$nx_id]['entries'][] = $entry;
366 } else {
367 if (empty($result['active'][$nx_id]['post'])) {
368 $result['active'][$nx_id]['post'] = $settings;
369 }
370 $result['active'][$nx_id]['entries'][] = $entry;
371 }
372 }
373
374 foreach ($result as &$group) {
375 foreach ($group as &$value) {
376 $value['entries'] = apply_filters("nx_filtered_data_{$value['post']['type']}", $value['entries'], $value['post'], $params);
377 $value['entries'] = apply_filters("nx_filtered_data_{$value['post']['source']}", $value['entries'], $value['post'], $params);
378 $value['entries'] = apply_filters('nx_filtered_data', $value['entries'], $value['post'], $params);
379 $value['post'] = apply_filters('nx_filtered_post', $value['post'], $params);
380 }
381 }
382 $result = apply_filters('nx_filtered_notice', $result, $params);
383 }
384
385 if (!empty($pressbar)) {
386 $notifications = $this->get_notifications($pressbar, $device);
387 foreach ($notifications as $key => $settings) {
388 $_nx_id = $settings['nx_id'];
389 // check if position is bottom_left then modify it to top
390 if($settings['position'] == 'bottom_left'){
391 $settings['position'] = 'top';
392 }
393 $elementor_post_id = isset($settings['elementor_id']) ? $settings['elementor_id'] : '';
394 if ($elementor_post_id == '' || get_post_status($elementor_post_id) !== 'publish' | !class_exists('\Elementor\Plugin')) {
395 $settings['elementor_id'] = false;
396 }
397 if ( ( !empty( $_params['all_active']) && $elementor_post_id ) || !$settings['enabled'] ) {
398 continue;
399 }
400
401 // $settings['button_url'] = apply_filters("nx_notification_link_{$settings['source']}", $settings['button_url'], $settings);
402 $settings['button_url'] = apply_filters('nx_notification_link', $settings['button_url'], $settings);
403 if (!empty($settings['button_url']) && strpos($settings['button_url'], '//') === false && strpos($settings['button_url'], './') === false) {
404 $settings['button_url'] = "//{$settings['button_url']}";
405 }
406 $bar_content = $this->get_bar_content($settings, false, $params);
407 if ($bar_content !== '&nbsp;' || !empty($settings['enable_countdown'])) {
408 $settings = apply_filters('nx_filtered_post', $settings, $params);
409 $result['pressbar'][$_nx_id]['post'] = $settings;
410 $result['pressbar'][$_nx_id]['content'] = $bar_content;
411 }
412
413 unset($_nx_id);
414 }
415 }
416
417 if (!empty($gdpr)) {
418 $notifications = $this->get_notifications($gdpr);
419 foreach ($notifications as $key => $settings) {
420 $_nx_id = $settings['nx_id'];
421 if (!empty($_params['all_active'])) {
422 continue;
423 }
424
425 $settings = apply_filters('nx_filtered_post', $settings, $params);
426
427 $result['gdpr'][$_nx_id]['post'] = $settings;
428 $result['gdpr'][$_nx_id]['content'] = "";
429 unset($_nx_id);
430 }
431 }
432
433 // Popup Notification
434 if (!empty($popup)) {
435 $popup_notifications = $this->get_notifications($popup);
436 foreach ($popup_notifications as $key => $settings) {
437 $_nx_id = $settings['nx_id'];
438 if ( !$settings['enabled'] ) {
439 continue;
440 }
441
442 $settings = apply_filters('nx_filtered_post', $settings, $params);
443
444 $result['popup'][$_nx_id]['post'] = $settings;
445 $result['popup'][$_nx_id]['content'] = "";
446 unset($_nx_id);
447 }
448 }
449
450 // Exit Intent Notification
451 if (!empty($exit_intent)) {
452 $exit_intent_notifications = $this->get_notifications($exit_intent);
453 foreach ($exit_intent_notifications as $key => $settings) {
454 $_nx_id = $settings['nx_id'];
455 if ( !$settings['enabled'] ) {
456 continue;
457 }
458 $settings = apply_filters('nx_filtered_post', $settings, $params);
459 $result['exit_intent'][$_nx_id]['post'] = $settings;
460 $result['exit_intent'][$_nx_id]['content'] = "";
461 unset($_nx_id);
462 }
463 }
464
465 $result['settings'] = $this->get_settings();
466 return $result;
467 }
468
469 public function get_settings(){
470
471 $branding_url = apply_filters('nx_branding_url', NOTIFICATIONX_PLUGIN_URL . '?utm_source=' . esc_url(home_url()) . '&utm_medium=notificationx');
472 $settings = [
473 'disable_powered_by' => Settings::get_instance()->get('settings.disable_powered_by'),
474 'affiliate_link' => $branding_url,
475 'enable_analytics' => Settings::get_instance()->get('settings.enable_analytics', true),
476 'analytics_from' => Settings::get_instance()->get('settings.analytics_from'),
477 'delay_before' => Settings::get_instance()->get('settings.delay_before', 5),
478 'display_for' => Settings::get_instance()->get('settings.display_for', 5),
479 'delay_between' => Settings::get_instance()->get('settings.delay_between', 5),
480 'loop' => Settings::get_instance()->get('settings.loop', 5),
481 'random' => Settings::get_instance()->get('settings.random', 5),
482 'analytics_nonce' => wp_create_nonce('analytics_nonce'),
483 ];
484 return $settings;
485 }
486
487 public function get_notifications_ids($return_posts = false, $args = []) {
488 $args = wp_parse_args($args, [
489 'enabled' => true,
490 'updated_at' => ['<=', Helper::mysql_time()],
491 // 'global_queue' => true,
492 ]);
493 $notifications = PostType::get_instance()->get_posts($args);
494
495 $active_notifications = $global_notifications = $bar_notifications = $gdpr_notification = $popup_notifications = $exit_intent_notifications = array();
496
497 foreach ($notifications as $key => $settings) {
498 // $settings = NotificationX::get_instance()->normalize_post($post);
499
500 // IF PRESSBAR TIME RE_CONFIG THEN REMOVE COOKIE
501 // if( $settings['source'] == 'press_bar'){
502 // if( $_settings->enable_countdown && ( Helper::current_timestamp($_settings->countdown_start_date) < time() || Helper::current_timestamp($_settings->countdown_end_date) > time() ) ) {
503 // unset( $_COOKIE["notificationx_{$settings['nx_id']}"] );
504 // \setcookie("notificationx_{$settings['nx_id']}", null);
505 // }
506 // }
507
508 /**
509 * Check if it's a pro source and pro plugin is disabled.
510 */
511 if(!NotificationX::is_pro()){
512 $ext = ExtensionFactory::get_instance()->get($settings['source']);
513 if($ext && $ext->is_pro){
514 continue;
515 }
516 }
517
518 $countdown_rand = !empty($settings['countdown_rand']) ? "-{$settings['countdown_rand']}" : '';
519
520 if (!empty($_COOKIE["notificationx_{$settings['nx_id']}$countdown_rand"]) && $_COOKIE["notificationx_{$settings['nx_id']}$countdown_rand"] == true) {
521 unset($notifications[$key]);
522 continue;
523 }
524
525 if($this->is_logged_in($settings['show_on_display'])){
526 continue;
527 }
528
529 $locations = isset($settings['all_locations']) ? $settings['all_locations'] : [];
530 $custom_ids = isset($settings['custom_ids']) ? $settings['custom_ids'] : [];
531 $taxonomy_ids = isset($settings['taxonomy_ids']) ? $settings['taxonomy_ids'] : [];
532
533 if($this->check_show_on($locations, $custom_ids, $settings['show_on'], $taxonomy_ids)){
534 continue;
535 }
536
537 /**
538 * Check for hiding in mobile device
539 */
540 // if ($settings['hide_on_mobile'] && wp_is_mobile()) {
541 // continue;
542 // }
543
544 $show_on_exclude = apply_filters('nx_show_on_exclude', false, $settings);
545 if ($show_on_exclude) {
546 continue;
547 }
548
549 // excluding pressBar on rest request. PressBar is printed directly in head.
550 // if((empty($args['source']) || $args['source'] !== 'press_bar') && $settings['source'] == 'press_bar'){
551 // continue;
552 // }
553
554 $active_global_queue = boolval($settings['global_queue']);
555 if ($settings['source'] == 'press_bar') {
556 // if(
557 // !$_settings->elementor_id &&
558 // $_settings->enable_countdown &&
559 // !$_settings->evergreen_timer &&
560 // (
561 // strtotime($_settings->countdown_start_date) > time() ||
562 // strtotime($_settings->countdown_end_date) < time()
563 // )
564 // ){
565 // continue;
566 // }
567
568 $bar_notifications[] = $return_posts ? $settings : $settings['nx_id'];
569 if (!empty($settings['elementor_id']) && class_exists('\Elementor\Plugin')) {
570 // @todo Find a function to only load css instead of building content.
571 \Elementor\Plugin::$instance->frontend->get_builder_content($settings['elementor_id'], false);
572 }
573 } elseif($settings['source'] == 'gdpr_notification') {
574 $gdpr_notification[] = $return_posts ? $settings : $settings['nx_id'];
575 } elseif($settings['source'] == 'popup_notification') {
576 $popup_notifications[] = $settings['nx_id'];
577 } elseif($settings['source'] == 'exit_intent_custom') {
578 $exit_intent_notifications[] = $settings['nx_id'];
579 // Force Elementor's frontend runtime + per-widget assets onto the
580 // page (elementor-frontend.js, the document CSS, and each widget's
581 // get_style_depends()/get_script_depends() — e.g. nx-countdown).
582 // The popup HTML itself is rendered later via REST, where these
583 // enqueues would be discarded, so the countdown widget would lose
584 // its layout CSS and timer JS. Mirrors the press_bar branch above.
585 if (!empty($settings['elementor_id']) && class_exists('\Elementor\Plugin')) {
586 \Elementor\Plugin::$instance->frontend->get_builder_content($settings['elementor_id'], false);
587 }
588 } elseif ($active_global_queue && NotificationX::is_pro()) {
589 $global_notifications[] = $return_posts ? $settings : $settings['nx_id'];
590 } else {
591 $active_notifications[] = $return_posts ? $settings : $settings['nx_id'];
592 }
593
594 unset($notifications[$key]);
595 }
596 // do_action('nx_active_notificationx', $notifications);
597
598 // @todo maybe combine two hooks.
599
600 return apply_filters(
601 'get_notifications_ids',
602 [
603 'global' => $global_notifications,
604 'active' => $active_notifications,
605 'pressbar' => $bar_notifications,
606 'gdpr' => $gdpr_notification,
607 'popup' => $popup_notifications,
608 'exit_intent' => $exit_intent_notifications,
609 'total' => (count($global_notifications) + count($active_notifications) + count($bar_notifications) + count($gdpr_notification) + count($popup_notifications) + count($exit_intent_notifications)),
610 ],
611 $notifications
612 );
613 }
614
615 public function is_logged_in($show_on_display){
616 $logged_in = is_user_logged_in();
617
618 if (($logged_in && 'logged_out_user' == $show_on_display) || (!$logged_in && 'logged_in_user' == $show_on_display)) {
619 return true;
620 }
621 return false;
622 }
623
624 /**
625 * @todo filter is not extensive enough.
626 */
627 public function check_show_on($locations, $custom_ids, $show_on, $taxonomy_ids = ''){
628 $check_location = false;
629
630 if ($locations == 'is_custom' || is_array($locations) && in_array('is_custom', $locations)) {
631 $custom_ids = !empty($custom_ids) ? $custom_ids : [];
632 }
633 if (!empty($locations)) {
634 // @todo need to pass url.
635 $check_location = Locations::get_instance()->check_location($locations, $custom_ids, $taxonomy_ids);
636 }
637
638 $check_location = apply_filters('nx_check_location', $check_location, $custom_ids, $show_on);
639
640 if ($show_on == 'on_selected') {
641 // show if the page is on selected
642 if (!$check_location) {
643 return true;
644 }
645 } elseif ($show_on == 'hide_on_selected') {
646 // hide if the page is on selected
647 if ($check_location) {
648 return true;
649 }
650 } elseif ($show_on === 'only_shortcode') {
651 return true;
652 }
653 return false;
654 }
655
656 public function get_notifications($ids, $device = '') {
657 $results = [];
658 $notifications = PostType::get_instance()->get_posts_by_ids($ids);
659
660 foreach ($notifications as $key => $value) {
661 /**
662 * Check for hiding in mobile device
663 */
664 if (empty($value['hide_on_mobile']) && $device === 'mobile') {
665 continue;
666 }
667
668 /**
669 * Check for hiding in tablet device
670 */
671 if (empty($value['hide_on_tab']) && $device === 'tablet') {
672 continue;
673 }
674
675 /**
676 * Check for hiding in desktop device
677 */
678 if (empty($value['hide_on_desktop']) && $device === 'desktop') {
679 continue;
680 }
681
682 /**
683 * Check if it's a pro source and pro plugin is disabled.
684 */
685 if(!NotificationX::is_pro()){
686 $ext = ExtensionFactory::get_instance()->get($value['source']);
687 if($ext && $ext->is_pro){
688 continue;
689 }
690 }
691
692 $results[$value['nx_id']] = $value;
693 }
694 return $results;
695 }
696
697 public function get_entries($ids, $notifications,$params) {
698 $entries = [];
699 if (!empty($ids) && is_array($ids)) {
700 $query = [];
701 foreach ($ids as $id) {
702 if (!empty($notifications[$id])) {
703 $post = $notifications[$id];
704 $global_query = " nx_id = " . absint($id) . " AND source = '" . esc_sql($post['source']) . "'";
705 $_q = apply_filters("nx_get_entries_query_part_{$notifications[$id]['source']}",$global_query, $notifications[$id], $params );
706 $query[$id] = " (" . $_q . ")";
707 }
708 }
709 if (!empty($query)) {
710 $entries = Entries::get_instance()->get_entries('WHERE' . implode(' OR ', $query));
711 foreach ($entries as $key => $value) {
712 if (!empty($value['data'])) {
713 $entries[$key] = array_merge($value, $value['data']);
714 unset($entries[$key]['data']);
715 }
716 }
717 }
718 }
719 if (!is_array($entries)) {
720 $entries = [];
721 }
722 $entries = apply_filters('nx_frontend_get_entries', $entries, $ids, $notifications,$params);
723 return $entries;
724 }
725
726 /**
727 * This function is responsible for make ready the link for notifications.
728 *
729 * @param array $data
730 * @return void
731 */
732 public static function link_url($entry, $post, $params = []) {
733 if (empty($entry)) {
734 return false;
735 }
736 $link = isset($entry['link']) ? $entry['link'] : '';
737 // removing link if link type is none.
738 if (empty($post['link_type']) || $post['link_type'] === 'none') {
739 $link = '';
740 }
741
742 $link = apply_filters("nx_notification_link_{$post['source']}", $link, $post, $entry, $params);
743 $entry['link'] = apply_filters('nx_notification_link', $link, $post, $entry, $params);
744 return $entry;
745 }
746
747 /**
748 * This function is responsible for getting the image url
749 * using Product ID or from default image settings.
750 *
751 * @param array $data
752 * @param array $settings
753 * @return array of image data, contains url and title as alt text
754 */
755 public function get_image_url($data, $settings) {
756 $source = $settings['source'];
757 $alt_title = isset($data['name']) ? $data['name'] : '';
758 $image_type = isset($settings['show_notification_image']) ? $settings['show_notification_image'] : false;
759 if (empty($alt_title)) {
760 $alt_title = isset($data['title']) ? $data['title'] : '';
761 }
762 $image_data = [
763 'url' => '',
764 'alt' => $alt_title,
765 ];
766
767 if ($settings['show_default_image']) {
768 if (!empty($settings['image_url']['url'])) {
769 $image_size = (string) Settings::get_instance()->get('settings.notification_image_size', '100_100');
770 $image_size = explode('_', $image_size);
771 $width = 100;
772 $height = 100;
773 if( !empty( $image_size[0] ) && !empty( $image_size[1] ) ) {
774 $width = $image_size[0];
775 $height = $image_size[1];
776 }
777 $image = wp_get_attachment_image_src($settings['image_url']['id'], [$width, $height], true);
778 $image_data['url'] = $image[0];
779 } else {
780 $default_avatar = $settings['default_avatar'];
781 $image_data['url'] = NOTIFICATIONX_PUBLIC_URL . 'image/icons/' . $default_avatar;
782 }
783 } else {
784 if ($image_type === 'gravatar') {
785 $_data = array_change_key_case($data);
786 if (isset($_data['email'])) {
787 $image_data['url'] = get_avatar_url($_data['email'], ['size' => '100']);
788 }
789 }
790 }
791
792 $image_data['classes'] = $image_type;
793 $image_data = apply_filters("nx_notification_image_$source", $image_data, $data, $settings);
794 $image_data = apply_filters('nx_notification_image', $image_data, $data, $settings);
795
796 if (!empty($image_data['url'])) {
797 return $image_data;
798 }
799
800 return false;
801 }
802
803 public function apply_defaults($entry, $defaults) {
804
805 foreach ($defaults as $key => $value) {
806 // @todo mukul remove `|| empty(trim($entry[$key]))`
807 if (empty($entry[$key]) || (is_string($entry[$key]) && empty(trim($entry[$key])))) {
808 $entry[$key] = $value;
809 }
810 }
811
812 return $entry;
813 }
814
815 public function fallback_data($data, $saved_data, $settings) {
816 if ((empty($saved_data['name']) || $data['name'] == __('Someone', 'notificationx')) && isset($saved_data['first_name']) || isset($saved_data['last_name'])) {
817 $first_name = isset($saved_data['first_name']) ? $saved_data['first_name'] : '';
818 $last_name = isset($saved_data['last_name']) ? $saved_data['last_name'] : '';
819 $data['name'] = Helper::name($first_name, $last_name);
820 }
821 if (!empty($saved_data['name']) && empty($saved_data['first_name']) && empty($saved_data['last_name'])) {
822 $data['first_name'] = $saved_data['name'];
823 }
824 $data['title'] = isset($saved_data['post_title']) ? $saved_data['post_title'] : (isset($data['title']) ? $data['title'] : '');
825 return $data;
826 }
827
828 /**
829 * Add NotificationX in Footer
830 *
831 * @return void
832 */
833 public function filtered_data($entries, $post, $params) {
834 if (is_array($entries) && (!defined('NX_DEBUG') || !NX_DEBUG)) {
835 if (!empty($post['display_last']) && !in_array($post['source'], ['google', 'woo_inline', 'edd_inline', 'tutor_inline', 'learndash_inline', 'google_reviews', 'youtube','woocommerce_sales_inline','fluentcart_inline'])) {
836 $entries = array_slice($entries, 0, $post['display_last']);
837 }
838 foreach ($entries as $index => $entry) {
839 $_entry = apply_filters("nx_frontend_keep_entry_{$post['source']}", [
840 'nx_id' => $entry['nx_id'],
841 'timestamp' => isset($entry['timestamp']) ? $entry['timestamp'] : Helper::current_timestamp($entry['updated_at']),
842 'updated_at' => isset( $entry['updated_at'] ) ? $entry['updated_at'] : '',
843 'image_data' => $entry['image_data'],
844 'link' => $entry['link'],
845 // Location is rendered by themes (e.g. conv-theme-fifteen) via the
846 // hardcoded {{city_country}} tag, not through a notification-template
847 // param, so the template loop below never whitelists it. Keep the
848 // raw parts here so the frontend can compose "City, Country".
849 'city' => $entry['city'] ?? '',
850 'country' => $entry['country'] ?? '',
851 ], $entry, $post, $params);
852 if (!empty($params['inline_shortcode']) && isset($entry['product_id'])) {
853 $_entry['product_id'] = $entry['product_id'];
854 }
855
856 // `notification-template` can be absent for some posts (e.g. advanced-
857 // template notifications or imported/migrated posts), so guard against
858 // passing null to array_values() — that is a fatal TypeError on PHP 8.
859 $template_arr = ( ! empty( $post['notification-template'] ) && is_array( $post['notification-template'] ) )
860 ? array_values( $post['notification-template'] )
861 : [];
862 if ( ! empty( $post['template_adv'] ) ) {
863 $adv_template = isset( $post['advanced_template'] ) ? $post['advanced_template'] : '';
864 $pattern = "/{{(.+?)}}/i";
865 if (preg_match_all($pattern, $adv_template, $matches)) {
866 $template_arr = $matches[1];
867 }
868 }
869 if (is_array($template_arr)) {
870 foreach ($template_arr as $entry_key) {
871 $_entry_key = $entry_key;
872 if ($entry_key == 'tag_siteview' || $entry_key == 'tag_realtime_siteview') {
873 $entry_key = 'views';
874 } elseif ($entry_key == 'ga_title' || $entry_key == 'ga_page_title') {
875 $entry_key = 'title';
876 } elseif (strpos($entry_key, 'tag_product_') === 0) {
877 $entry_key = str_replace('tag_product_', '', $entry_key);
878 } elseif (strpos($entry_key, 'tag_') === 0) {
879 $entry_key = str_replace('tag_', '', $entry_key);
880 } elseif (strpos($entry_key, 'product_') === 0) {
881 $entry_key = str_replace('product_', '', $entry_key);
882 }
883
884 if (isset($entry[$entry_key])) {
885 $_entry[$entry_key] = $entry[$entry_key];
886 }
887 if (isset($entry[$_entry_key])) {
888 $_entry[$_entry_key] = $entry[$_entry_key];
889 }
890 }
891 $entries[$index] = $_entry;
892 }
893 }
894 }
895 return $entries;
896 }
897
898 /**
899 * Remove unnecessary props from post in frontend.
900 *
901 * @return void
902 */
903 public function filtered_post($post, $params = null) {
904 if (is_array($post) && empty($params['inline_shortcode']) && (!defined('NX_DEBUG') || !NX_DEBUG)) {
905 $ignore_props = [
906 'all_locations',
907 'category_list',
908 'combine_multiorder_text',
909 'content_trim_length',
910 'convertkit_form',
911 'currentTab',
912 'custom_contents',
913 'custom_ids',
914 'default_avatar',
915 'elementor_edit_link',
916 'enabled',
917 'exclude_categories',
918 'exclude_products',
919 'form_list',
920 'freemius_item_type',
921 'freemius_plugins',
922 'freemius_themes',
923 'give_form_list',
924 'give_forms_control',
925 'image_url',
926 'inline_location',
927 'is_confirmed',
928 'is_elementor',
929 'is_inline',
930 'ld_course_list',
931 'ld_product_control',
932 'mailchimp_list',
933 'max_stock',
934 'nx-bar_with_elementor',
935 'nx-bar_with_elementor-remove',
936 'nx-bar_with_elementor_install',
937 'order_status',
938 'press_content',
939 'preview',
940 'product_control',
941 'product_exclude_by',
942 'product_list',
943 'rest_route',
944 'show_default_image',
945 'show_notification_image',
946 'show_on',
947 'show_on_display',
948 'source_error',
949 'utm_campaign',
950 'utm_medium',
951 'utm_source',
952 'wp_reviews_product_type',
953 'wp_reviews_slug',
954 'wp_stats_product_type',
955 'wp_stats_slug',
956 '_locale',
957 '__product_list',
958 '__form_list',
959 '__ld_course_list',
960 '__give_form_list',
961 ];
962 foreach ($ignore_props as $prop) {
963 if (isset($post[$prop])) {
964 unset($post[$prop]);
965 }
966 }
967 }
968 if (isset($post['template_adv'], $post['advanced_template'])) {
969 $post['advanced_template'] = do_shortcode($post['advanced_template']);
970 }
971 if( !empty( $post['notification-template'] ) ) {
972 $post['notification-template'] = array_map( 'esc_html', $post['notification-template'] );
973 }
974 return $post;
975 }
976
977 public function get_bar_content($settings, $suppress_filters = false, $params = []){
978 $bar_content = PressBar::get_instance()->print_bar_notice($settings);
979 if(!$suppress_filters){
980 $bar_content = apply_filters("nx_filtered_data_{$settings['source']}", $bar_content, $settings, $params);
981 }
982
983 // checking if content is empty
984 $_bar_content = str_replace(array("\r\n", "\n", "\r"), '', $bar_content);
985 $_bar_content = trim(strip_tags($_bar_content));
986 if (empty($_bar_content) && !empty($settings['enable_countdown'])) {
987 $bar_content = '&nbsp;';
988 }
989 return $bar_content;
990 }
991
992 }
993