PluginProbe
Post Grid Gutenberg Blocks – PostX / 5.0.41
Post Grid Gutenberg Blocks – PostX v5.0.41
5.0.41 5.0.39 5.0.38 5.0.37 5.0.36 5.0.35 5.0.34 5.0.33 5.0.32 5.0.31 5.0.30 5.0.29 5.0.28 5.0.27 5.0.26 5.0.25 5.0.23 5.0.24 5.0.22 5.0.21 5.0.20 5.0.19 5.0.18 5.0.17 2.1.1 All 238 releases
ultimate-post / includes / notice / class-notice.php

class-notice.php in Post Grid Gutenberg Blocks – PostX 5.0.41, at includes/notice/class-notice.php

1,077 lines 32.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php //phpcs:ignore
2 namespace ULTP\Includes\Notice;
3
4 defined( 'ABSPATH' ) || exit;
5
6 use ULTP\Includes\Durbin\Xpo;
7 use ULTP\Includes\Durbin\DurbinClient;
8
9 /**
10 * Plugin Notice
11 */
12 class Notice {
13
14
15 /**
16 * Notice version
17 *
18 * @var string
19 */
20 private $notice_version = 'v5132';
21
22 /**
23 * Notice JS/CSS applied
24 *
25 * @var boolean
26 */
27 private $notice_js_css_applied = false;
28
29 /**
30 * Notice Priority
31 *
32 * @var string $plugin_notice_priority
33 */
34 private $plugin_notice_priority = 1;
35
36 /**
37 * Notice Priority
38 *
39 * @var string $plugin_notice_priority
40 */
41 private $plugin_notice_priority_key = 'postx';
42
43 /**
44 * Notice Constructor
45 */
46 public function __construct() {
47 add_action( 'admin_notices', array( $this, 'admin_notices_callback' ) );
48 add_action( 'admin_init', array( $this, 'set_dismiss_notice_callback' ) );
49
50 // REST API routes.
51 add_action( 'rest_api_init', array( $this, 'register_rest_route' ) );
52
53 // Woocommerce Install Action
54 // add_action( 'wp_ajax_ultp_install', array( $this, 'install_activate_plugin' ) ); // this ajax not called anywhere in future need to removed, that is arise patchstack security issue
55 add_filter( 'xpo_active_notice_lists', array( $this, 'handle_xpo_active_notice_lists' ), 99, 1 );
56 }
57
58 /**
59 * Registers REST API endpoints.
60 *
61 * @return void
62 */
63 public function register_rest_route() {
64 $routes = array(
65 // Hello Bar.
66 array(
67 'endpoint' => 'hello_bar',
68 'methods' => 'POST',
69 'callback' => array( $this, 'hello_bar_callback' ),
70 'permission_callback' => function () {
71 return current_user_can( 'manage_options' );
72 },
73 ),
74 );
75
76 foreach ( $routes as $route ) {
77 register_rest_route(
78 'ultp',
79 $route['endpoint'],
80 array(
81 array(
82 'methods' => $route['methods'],
83 'callback' => $route['callback'],
84 'permission_callback' => $route['permission_callback'],
85 ),
86 )
87 );
88 }
89 }
90
91 /**
92 * Hellobar config
93 *
94 * @return array
95 */
96 public static function get_hellobar_config() {
97 return array(
98 // Final hours sale.
99 'ultp_helloBar_summer_sale_2026_v1' => Xpo::get_transient_without_cache( 'ultp_helloBar_summer_sale_2026_v1' ),
100 'ultp_helloBar_summer_sale_2026_v1_2' => Xpo::get_transient_without_cache( 'ultp_helloBar_summer_sale_2026_v1_2' ),
101 'ultp_helloBar_base_price_2026' => Xpo::get_transient_without_cache( 'ultp_helloBar_base_price_2026' ),
102 );
103 }
104
105 /**
106 * Handles Hello Bar dismissal action via REST API .
107 *
108 * @param \WP_REST_Request $request REST request object .
109 * @return \WP_REST_Response
110 */
111 public function hello_bar_callback( \WP_REST_Request $request ) {
112 $request_params = $request->get_params();
113 $type = isset( $request_params['type'] ) ? $request_params['type'] : '';
114 $id = isset( $request_params['id'] ) ? $request_params['id'] : '';
115
116 if ( 'hello_bar' === $type && ! empty( $id ) ) {
117 Xpo::set_transient_without_cache( $id, 'hide', 1296000 );
118 }
119
120 return new \WP_REST_Response(
121 array(
122 'success' => true,
123 'message' => __( 'Hello Bar Action performed', 'ultimate-post' ),
124 ),
125 200
126 );
127 }
128
129 /**
130 * Set Notice Dismiss Callback
131 *
132 * @return void
133 */
134 public function set_dismiss_notice_callback() {
135
136 if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['wpnonce'] ?? '' ) ), 'ultp-nonce' ) ) {
137 return;
138 }
139
140 $durbin_key = sanitize_text_field( wp_unslash( $_GET['ultp_durbin_key'] ?? '' ) );
141
142 // Durbin notice dismiss.
143 if ( ! empty( $durbin_key ) ) {
144 Xpo::set_transient_without_cache( 'ultp_durbin_notice_' . $durbin_key, 'off' );
145
146 if ( 'get' === sanitize_text_field( wp_unslash( $_GET['ultp_get_durbin'] ?? '' ) ) ) {
147 DurbinClient::send( DurbinClient::ACTIVATE_ACTION );
148 }
149 }
150
151 // Install notice dismiss.
152 $install_key = sanitize_text_field( wp_unslash( $_GET['ultp_install_key'] ?? '' ) );
153 if ( ! empty( $install_key ) ) {
154 Xpo::set_transient_without_cache( 'ultp_install_notice_' . $install_key, 'off' );
155 }
156 $notice_key = sanitize_text_field( wp_unslash( $_GET['ultp_notice'] ?? '' ) );
157 if ( ! empty( $notice_key ) ) {
158 $interval = (int) sanitize_text_field( wp_unslash( $_GET['ultp_interval'] ?? '' ) );
159 if ( ! empty( $interval ) ) {
160 Xpo::set_transient_without_cache( 'ultp_get_pro_notice_' . $notice_key, 'off', $interval );
161 } else {
162 Xpo::set_transient_without_cache( 'ultp_get_pro_notice_' . $notice_key, 'off' );
163 }
164 }
165 }
166
167 /**
168 * Admin Notices Callback
169 *
170 * @return void
171 */
172 public function admin_notices_callback() {
173 $this->ultp_dashboard_notice_callback();
174 $this->ultp_dashboard_durbin_notice_callback();
175 }
176
177 /**
178 * Admin Dashboard Notice Callback
179 *
180 * @return void
181 */
182 public function ultp_dashboard_notice_callback() {
183 if ( $this->is_available_for_notice() ) {
184 $this->ultp_dashboard_banner_notice();
185 $this->ultp_dashboard_content_notice();
186 $this->ultp_dashboard_image_banner_notice();
187
188 }
189 }
190
191 /**
192 * Dashboard Banner Notice
193 *
194 * @return void
195 */
196 public function ultp_dashboard_banner_notice( $return_bool = false ) {
197 $ultp_db_nonce = wp_create_nonce( 'ultp-nonce' );
198 $banner_notices = array(
199 // FLash sale.
200 array(
201 'key' => 'ultp_banner_flash_sale_2026_1',
202 'start' => '2026-05-18 00:00 Asia/Dhaka',
203 'end' => '2026-05-21 23:59 Asia/Dhaka', // format YY-MM-DD always set time 23:59 and zone Asia/Dhaka.
204
205 'brand_color' => '#0322ff',
206
207 'left_image' => ULTP_URL . 'assets/img/dashboard_banner/flash_sale/offer.png',
208 'right_image' => ULTP_URL . 'assets/img/dashboard_banner/flash_sale/btn.png',
209 'bg_image' => ULTP_URL . 'assets/img/dashboard_banner/flash_sale/bg.png',
210 'text' => 'Deal ending soon',
211 'countdown_duration' => 259200, // Duration in seconds.
212 // 'countdown_color' => '#0322ff',
213 'countdown_color' => '#3CF357',
214 'url' => Xpo::generate_utm_link(
215 array(
216 'utmKey' => 'flash_sale_content',
217 )
218 ),
219
220 'visibility' => ! Xpo::is_lc_active(),
221 ),
222 // surprise sale
223 array(
224 'key' => 'ultp_banner_surprise_sale_2026_1',
225 'start' => '2026-05-29 00:00 Asia/Dhaka',
226 'end' => '2026-06-01 23:59 Asia/Dhaka', // format YY-MM-DD always set time 23:59 and zone Asia/Dhaka.
227
228 'brand_color' => '#0322ff',
229
230 'left_image' => ULTP_URL . 'assets/img/dashboard_banner/surprise_sale/offer.png',
231 'right_image' => ULTP_URL . 'assets/img/dashboard_banner/surprise_sale/btn.png',
232 'bg_image' => ULTP_URL . 'assets/img/dashboard_banner/surprise_sale/bg.png',
233 'text' => 'Limited Time Offer',
234 'countdown_duration' => 259200, // Duration in seconds.
235 // 'countdown_color' => '#0322ff',
236 'countdown_color' => '#3CF357',
237 'url' => Xpo::generate_utm_link(
238 array(
239 'utmKey' => 'surprise_sale_content',
240 )
241 ),
242
243 'visibility' => ! Xpo::is_lc_active(),
244 ),
245 // massive sale
246 array(
247 'key' => 'ultp_banner_massive_sale_2026_1',
248 'start' => '2026-06-17 00:00 Asia/Dhaka',
249 'end' => '2026-06-20 23:59 Asia/Dhaka', // format YY-MM-DD always set time 23:59 and zone Asia/Dhaka.
250
251 'brand_color' => '#0322ff',
252
253 'left_image' => ULTP_URL . 'assets/img/dashboard_banner/massive_sale/offer.png',
254 'right_image' => ULTP_URL . 'assets/img/dashboard_banner/massive_sale/btn.png',
255 'bg_image' => ULTP_URL . 'assets/img/dashboard_banner/massive_sale/bg.png',
256 'text' => 'Deal ending soon',
257 'countdown_duration' => 259200, // Duration in seconds.
258 // 'countdown_color' => '#0322ff',
259 'countdown_color' => '#3CF357',
260 'url' => Xpo::generate_utm_link(
261 array(
262 'utmKey' => 'massive_sale_content',
263 )
264 ),
265
266 'visibility' => ! Xpo::is_lc_active(),
267 ),
268 // Final hours sale
269 array(
270 'key' => 'ultp_banner_final_hours_sale_2026_1',
271 'start' => '2026-06-28 00:00 Asia/Dhaka',
272 'end' => '2026-06-30 23:59 Asia/Dhaka', // format YY-MM-DD always set time 23:59 and zone Asia/Dhaka.
273
274 'brand_color' => '#0322ff',
275
276 'left_image' => ULTP_URL . 'assets/img/dashboard_banner/final_hours_sale/offer.png',
277 'right_image' => ULTP_URL . 'assets/img/dashboard_banner/final_hours_sale/btn.png',
278 'bg_image' => ULTP_URL . 'assets/img/dashboard_banner/final_hours_sale/bg.png',
279 'text' => 'Hurry Before It Ends!',
280 'countdown_duration' => 259200, // Duration in seconds.
281 // 'countdown_color' => '#0322ff',
282 'countdown_color' => '#3CF357',
283 'url' => Xpo::generate_utm_link(
284 array(
285 'utmKey' => 'final_hours_content',
286 )
287 ),
288 'visibility' => ! Xpo::is_lc_active(),
289 ),
290 );
291 foreach ( $banner_notices as $notice ) {
292 $notice_key = isset( $notice['key'] ) ? $notice['key'] : $this->notice_version;
293
294 if ( isset( $_GET['ultp_notice'] ) && $notice_key === sanitize_text_field(wp_unslash($_GET['ultp_notice'])) ) { // phpcs:ignore
295 continue;
296 }
297
298 $current_time = gmdate( 'U' );
299 $notice_start = gmdate( 'U', strtotime( $notice['start'] ) );
300 $notice_end = gmdate( 'U', strtotime( $notice['end'] ) );
301 if ( $current_time >= $notice_start && $current_time <= $notice_end && $notice['visibility'] ) {
302
303 $notice_transient = Xpo::get_transient_without_cache( 'ultp_get_pro_notice_' . $notice_key );
304
305 if ( 'off' === $notice_transient ) {
306 continue;
307 }
308 if ( $return_bool ) { // Early return for Other plugin notice.
309 return true;
310 }
311 if ( ! $this->notice_js_css_applied ) {
312 $this->ultp_banner_notice_js();
313 $this->notice_js_css_applied = true;
314 }
315 $query_args = array(
316 'ultp_notice' => $notice_key,
317 'wpnonce' => $ultp_db_nonce,
318 );
319 if ( isset( $notice['repeat_interval'] ) && $notice['repeat_interval'] ) {
320 $query_args['ultp_interval'] = $notice['repeat_interval'];
321 }
322 ?>
323 <style type="text/css">
324 .ultp-notice-wrapper.ultp-banner-notice {
325 height: auto !important;
326 padding: 0 !important;
327 position: relative;
328 box-sizing: border-box;
329 background-repeat: no-repeat;
330 background-size: cover;
331 background-position: center;
332 }
333 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-link {
334 width: 100%;
335 text-decoration: none;
336 display: block;
337 }
338 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-content {
339 display: flex;
340 justify-content: space-between;
341 align-items: center;
342 max-width: 700px;
343 margin: 0 auto;
344 padding: 10px 16px;
345 gap: 16px;
346 }
347 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-side-image {
348 display: block;
349 max-width: 100%;
350 height: auto;
351 max-height: 32px;
352 }
353 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-main .ultp-banner-main-text {
354 color: #ffffff;
355 }
356 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-main {
357 display: flex;
358 flex-direction: column;
359 gap: 4px;
360 align-items: center;
361 justify-content: center;
362 font-weight: 700;
363 font-size: 18px;
364 color: #333333;
365 line-height: 1.2;
366 text-align: center;
367 }
368
369 @media screen and (max-width: 1100px) {
370 /* .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-content {
371 flex-direction: column;
372 } */
373 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-content .ultp-banner-main-text {
374 display: none;
375 }
376 }
377 @media screen and (max-width: 490px) {
378 .ultp-notice-wrapper.ultp-banner-notice {
379 display: none;
380 }
381 }
382 @media screen and (max-width: 782px) {
383 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-content {
384 justify-content: center;
385 padding: 12px 32px 12px 12px;
386 }
387 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-main {
388 font-size: 22px;
389 line-height: 28px;
390 }
391 }
392 @media screen and (max-width: 480px) {
393 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-content {
394 padding: 10px 32px 10px 10px;
395 }
396 .ultp-notice-wrapper.ultp-banner-notice .ultp-banner-main {
397 font-size: 18px;
398 line-height: 24px;
399 }
400 }
401 </style>
402 <div
403 class="ultp-notice-wrapper ultp-banner-notice notice"
404 style="
405 border-left: 3px solid <?php echo esc_attr( $notice['brand_color'] ); ?>;
406 background-image: url('<?php echo esc_attr( $notice['bg_image'] ); ?>');
407 ">
408 <a
409 class="wc-dismiss-notice dashicons dashicons-no-alt"
410 style="
411 position: absolute;
412 top: 1px;
413 right: 1px;
414 border-radius: 50%;
415 background-color: black;
416 color: white;
417 font-size: 14px;
418 display: flex;
419 align-items: center;
420 justify-content: center;
421 "
422 aria-label="<?php esc_html_e( 'Close Banner', 'ultimate-post' ); ?>"
423 href="<?php echo esc_url( add_query_arg( $query_args ) ); ?>">
424 </a>
425
426 <a class="ultp-banner-link" target="_blank" href="<?php echo esc_url( $notice['url'] ); ?>">
427 <div class="ultp-banner-content">
428 <img class="ultp-banner-side-image" loading="lazy" src="<?php echo esc_url( $notice['left_image'] ); ?>" />
429 <div class="ultp-banner-main">
430 <span class="ultp-banner-main-text">
431 <?php echo esc_html( $notice['text'] ); ?>
432 </span>
433 <div
434 class="ultp-notice-countdown"
435 style="
436 color: <?php echo esc_attr( $notice['countdown_color'] ); ?>;
437 "
438 data-notice-key="<?php echo esc_attr( $notice_key . '-countdown' ); ?>"
439 data-duration="<?php echo esc_attr( $notice['countdown_duration'] ); ?>">
440 00:00:00:00
441 </div>
442 </div>
443 <img class="ultp-banner-side-image" loading="lazy" src="<?php echo esc_url( $notice['right_image'] ); ?>" />
444 </div>
445 </a>
446 </div>
447 <?php
448 }
449 }
450 }
451
452 /**
453 * Banner JS
454 *
455 * @return void
456 */
457 public function ultp_banner_notice_js() {
458 ?>
459 <script type="text/javascript">
460 jQuery(function($) {
461 'use strict';
462
463 const storagePrefix = 'ultp_notice_countdown_';
464
465 const formatCountdown = function(seconds) {
466 const days = Math.floor(seconds / 86400);
467 const hours = Math.floor((seconds % 86400) / 3600);
468 const minutes = Math.floor((seconds % 3600) / 60);
469 const secs = seconds % 60;
470
471 return String(days).padStart(2, '0') + ':' + String(hours).padStart(2, '0') + ':' + String(minutes).padStart(2, '0') + ':' + String(secs).padStart(2, '0');
472 };
473
474 const parseDurationToSeconds = function(duration) {
475 if (typeof duration === 'number' && Number.isFinite(duration) && duration > 0) {
476 return Math.floor(duration);
477 }
478
479 const durationString = String(duration || '').trim();
480 if (/^\d+$/.test(durationString)) {
481 return parseInt(durationString, 10);
482 }
483
484 return 0;
485 };
486
487 const nowInSeconds = function() {
488 return Math.floor(Date.now() / 1000);
489 };
490
491 $('.ultp-notice-countdown').each(function() {
492 const countdownElement = $(this);
493 const noticeKey = String(countdownElement.data('noticeKey') || '');
494 const duration = parseDurationToSeconds(countdownElement.data('duration'));
495
496 if (!noticeKey || duration <= 0) {
497 return;
498 }
499
500 const storageKey = storagePrefix + noticeKey;
501 let endAt = 0;
502
503 try {
504 const storedDataRaw = window.localStorage.getItem(storageKey);
505 if (storedDataRaw) {
506 const storedData = JSON.parse(storedDataRaw);
507 if (storedData && parseInt(storedData.duration, 10) === duration) {
508 endAt = parseInt(storedData.endAt, 10) || 0;
509 }
510 }
511 } catch (error) {
512 endAt = 0;
513 }
514
515 const saveTimerState = function(nextEndAt) {
516 try {
517 window.localStorage.setItem(
518 storageKey,
519 JSON.stringify({
520 endAt: nextEndAt,
521 duration: duration,
522 })
523 );
524 } catch (error) {
525 // No-op.
526 }
527 };
528
529 const resetTimer = function(currentTime) {
530 endAt = currentTime + duration;
531 saveTimerState(endAt);
532 };
533
534 const tick = function() {
535 const currentTime = nowInSeconds();
536
537 if (endAt <= currentTime) {
538 resetTimer(currentTime);
539 }
540
541 const remaining = Math.max(endAt - currentTime, 0);
542 countdownElement.text(formatCountdown(remaining));
543 };
544
545 if (endAt <= nowInSeconds()) {
546 resetTimer(nowInSeconds());
547 }
548
549 tick();
550 window.setInterval(tick, 1000);
551 });
552 });
553 </script>
554 <?php
555 }
556
557
558 /**
559 * The Durbin Html
560 *
561 * @return void
562 */
563 public function ultp_dashboard_durbin_notice_callback() {
564 $durbin_key = 'ultp_durbin_dc1';
565
566 if (
567 isset( $_GET['ultp_durbin_key'] ) || // phpcs:ignore
568 'off' === Xpo::get_transient_without_cache( 'ultp_durbin_notice_' . $durbin_key )
569 ) {
570 return;
571 }
572
573 if ( ! $this->notice_js_css_applied ) {
574 $this->notice_js_css_applied = true;
575 }
576
577 $ultp_db_nonce = wp_create_nonce( 'ultp-nonce' );
578
579 ?>
580 <style>
581 .ultp-consent-box {
582 width: 656px;
583 padding: 16px !important;
584 border: 1px solid #070707;
585 border-left-width: 4px;
586 border-radius: 4px;
587 background-color: #fff;
588 position: relative;
589 width: 100%;
590 box-sizing: border-box;
591 }
592 .ultp-consent-content {
593 display: flex;
594 justify-content: flex-start;
595 align-items: flex-end;
596 gap: 26px;
597 }
598
599 .ultp-consent-text-first {
600 font-size: 14px;
601 font-weight: 600;
602 color: #070707;
603 }
604 .ultp-consent-text-last {
605 margin: 4px 0 0;
606 font-size: 14px;
607 color: #070707;
608 }
609
610 .ultp-consent-accept {
611 background-color: #070707;
612 color: #fff !important;
613 border: none;
614 padding: 6px 10px;
615 border-radius: 4px;
616 cursor: pointer;
617 font-size: 12px;
618 font-weight: 600;
619 text-decoration: none;
620 }
621 .ultp-consent-accept:hover {
622 background-color:rgb(38, 38, 38);
623 color: #fff;
624 }
625 </style>
626 <div class="ultp-consent-box ultp-notice-wrapper notice data_collection_notice">
627 <div class="ultp-consent-content">
628 <div class="ultp-consent-text">
629 <div class="ultp-consent-text-first"><?php esc_html_e( 'Want to help make PostX even more awesome?', 'ultimate-post' ); ?></div>
630 <div class="ultp-consent-text-last">
631 <?php esc_html_e( 'Allow us to collect diagnostic data and usage information. see ', 'ultimate-post' ); ?>
632 <a href="https://www.wpxpo.com/data-collection-policy/" target="_blank" ><?php esc_html_e( 'what we collect.', 'ultimate-post' ); ?></a>
633 </div>
634 </div>
635 <a
636 class="ultp-consent-accept"
637 href=
638 <?php
639 echo esc_url(
640 add_query_arg(
641 array(
642 'ultp_durbin_key' => $durbin_key,
643 'ultp_get_durbin' => 'get',
644 'wpnonce' => $ultp_db_nonce,
645 )
646 )
647 );
648 ?>
649 class="ultp-notice-close"
650 ><?php esc_html_e( 'Accept & Close', 'ultimate-post' ); ?></a>
651 </div>
652 <a href=
653 <?php
654 echo esc_url(
655 add_query_arg(
656 array(
657 'ultp_durbin_key' => $durbin_key,
658 'wpnonce' => $ultp_db_nonce,
659 )
660 )
661 );
662 ?>
663 class="ultp-notice-close"
664 style="
665 position: absolute;
666 right: 2px;
667 top: 5px;
668 text-decoration: unset;
669 color: #b6b6b6;
670 font-family: dashicons;
671 font-size: 16px;
672 font-style: normal;
673 font-weight: 400;
674 line-height: 20px;
675 "
676 >
677 <span
678 style="font-size: 14px;"
679 class="ultp-notice-close-icon dashicons dashicons-dismiss"> </span></a>
680 </div>
681 <?php
682 }
683 /**
684 * Dashboard Content Notice
685 *
686 * @return void
687 */
688 public function ultp_dashboard_content_notice( $return_bool = false ) {
689 $content_notices = array(
690 array(
691 'key' => 'ultp_dashboard_content_notice_summer_sale_2026_vv1',
692 'start' => '2026-07-06 00:00 Asia/Dhaka',
693 'end' => '2026-07-12 23:59 Asia/Dhaka',
694 'url' => Xpo::generate_utm_link(
695 array(
696 'utmKey' => 'summer_db',
697 )
698 ),
699 'visibility' => ! Xpo::is_lc_active(),
700 'content_heading' => __( 'Summer Sale:', 'ultimate-post' ),
701 /* translators: %s: discount percentage */
702 'content_subheading' => __( 'Enjoy up to %s on PostX Pro.', 'ultimate-post' ),
703 'discount_content' => ' 50% OFF',
704 'border_color' => '#0322ff',
705 'icon' => ULTP_URL . 'assets/img/dashboard_banner/brand_logo.svg',
706 'button_text' => __( 'Upgrade Now!', 'ultimate-post' ),
707 'is_discount_logo' => true,
708 ),
709 array(
710 'key' => 'ultp_dashboard_content_notice_summer_sale_2026_vv3',
711 'start' => '2026-08-02 00:00 Asia/Dhaka',
712 'end' => '2026-08-08 23:59 Asia/Dhaka',
713 'url' => Xpo::generate_utm_link(
714 array(
715 'utmKey' => 'summer_db',
716 )
717 ),
718 'visibility' => ! Xpo::is_lc_active(),
719 'content_heading' => __( 'Summer Sale:', 'ultimate-post' ),
720 /* translators: %s: discount percentage */
721 'content_subheading' => __( 'Enjoy up to %s on PostX Pro.', 'ultimate-post' ),
722 'discount_content' => ' 50% OFF',
723 'border_color' => '#0322ff',
724 'icon' => ULTP_URL . 'assets/img/dashboard_banner/flash_sale_50_discount_logo.png',
725 'button_text' => __( 'Upgrade Now!', 'ultimate-post' ),
726 'is_discount_logo' => true,
727 ),
728
729 );
730
731 $ultp_db_nonce = wp_create_nonce( 'ultp-nonce' );
732
733 foreach ( $content_notices as $key => $notice ) {
734 $notice_key = isset( $notice['key'] ) ? $notice['key'] : $this->notice_version;
735 if ( isset( $_GET['ultp_notice'] ) && $notice_key === $_GET['ultp_notice'] ) {
736 continue;
737 } else {
738 $border_color = $notice['border_color'];
739
740 $current_time = gmdate( 'U' );
741 $notice_start = gmdate( 'U', strtotime( $notice['start'] ) );
742 $notice_end = gmdate( 'U', strtotime( $notice['end'] ) );
743 if ( $current_time >= $notice_start && $current_time <= $notice_end && $notice['visibility'] ) {
744 $notice_transient = Xpo::get_transient_without_cache( 'ultp_get_pro_notice_' . $notice_key );
745
746 if ( 'off' !== $notice_transient ) {
747 if ( $return_bool ) { // Early return for Other plugin notice.
748 return true;
749 }
750 $query_args = array(
751 'ultp_notice' => $notice_key,
752 'wpnonce' => $ultp_db_nonce,
753 );
754 if ( isset( $notice['repeat_interval'] ) && $notice['repeat_interval'] ) {
755 $query_args['ultp_interval'] = $notice['repeat_interval'];
756 }
757
758 $url = isset( $notice['url'] ) ? $notice['url'] : Xpo::generate_utm_link(
759 array(
760 'utmKey' => 'content_notice',
761 )
762 );
763
764 ?>
765
766 <style id="ultp-notice-css" type="text/css">
767 .ultp-content-notice-wrapper {
768 border: 1px solid #c3c4c7;
769 border-left: 3px solid #037fff;
770 margin: 15px 0 !important;
771 display: flex;
772 align-items: center;
773 background-color: #eef0f4;
774 width: 100%;
775 padding: 10px 0;
776 position: relative;
777 box-sizing: border-box;
778 }
779
780 .ultp-content-notice-wrapper.notice {
781 margin: 10px 0;
782 width: calc(100% - 20px);
783 }
784
785 .wrap .ultp-content-notice-wrapper.notice {
786 width: 100%;
787 }
788
789 .ultp-content-notice-icon {
790 margin-left: 15px;
791 }
792
793 .ultp-content-notice-discout-icon {
794 margin-left: 10px;
795 }
796
797 .ultp-content-notice-icon img {
798 max-width: 42px;
799 height: 70px;
800 }
801
802 .ultp-content-notice-discout-icon img {
803 height: 70px;
804 width: 70px;
805 object-fit: contain;
806 }
807
808 .ultp-notice-content-wrapper {
809 display: flex;
810 flex-direction: column;
811 gap: 8px;
812 font-size: 14px;
813 line-height: 20px;
814 margin-left: 15px;
815 }
816
817 .ultp-content-notice-buttons {
818 display: flex;
819 align-items: center;
820 gap: 15px;
821 }
822
823 .ultp-content-notice-btn {
824 font-weight: 600;
825 text-transform: uppercase !important;
826 padding: 2px 10px !important;
827 background-color: #0322ff;
828 border: none !important;
829 }
830
831 .ultp-content-discount_btn {
832 background-color: #ffffff;
833 text-decoration: none;
834 border: 1px solid #0322ff;
835 padding: 5px 10px;
836 border-radius: 5px;
837 font-weight: 500;
838 text-transform: uppercase;
839 color: #0322ff !important;
840 }
841
842 .ultp-content-notice-close {
843 position: absolute;
844 right: 2px;
845 top: 5px;
846 text-decoration: none;
847 color: #b6b6b6;
848 font-family: dashicons;
849 font-size: 16px;
850 line-height: 20px;
851 }
852
853 .ultp-content-notice-close-icon {
854 font-size: 14px;
855 }
856 </style>
857 <div class="ultp-content-notice-wrapper notice data_collection_notice"
858 style="border-left: 3px solid <?php echo esc_attr( $border_color ); ?>;"
859 >
860 <?php
861 if ( $notice['is_discount_logo'] ) {
862 ?>
863 <div class="ultp-content-notice-discout-icon"> <img src="<?php echo esc_url( $notice['icon'] ); ?>"/> </div>
864 <?php
865 } else {
866 ?>
867 <div class="ultp-content-notice-icon"> <img src="<?php echo esc_url( $notice['icon'] ); ?>"/> </div>
868 <?php
869 }
870 ?>
871
872 <div class="ultp-notice-content-wrapper">
873 <div class="">
874 <strong><?php printf( esc_html( $notice['content_heading'] ) ); ?> </strong>
875 <?php
876 printf(
877 wp_kses_post( $notice['content_subheading'] ),
878 '<strong>' . esc_html( $notice['discount_content'] ) . '</strong>'
879 );
880 ?>
881 </div>
882 <div class="ultp-content-notice-buttons">
883 <?php if ( isset( $notice['is_discount_logo'] ) && $notice['is_discount_logo'] ) : ?>
884 <a class="ultp-content-discount_btn" href="<?php echo esc_url( $url ); ?>" target="_blank">
885 <?php echo esc_html( $notice['button_text'] ); ?>
886 </a>
887 <?php else : ?>
888 <a class="ultp-content-notice-btn button button-primary" href="<?php echo esc_url( $url ); ?>" target="_blank" style="background-color: <?php echo ! empty( $notice['background_color'] ) ? esc_attr( $notice['background_color'] ) : '#86a62c'; ?>;">
889 <?php echo esc_html( $notice['button_text'] ); ?>
890
891 </a>
892 <?php endif; ?>
893 </div>
894 </div>
895 <a href=
896 <?php
897 echo esc_url(
898 add_query_arg(
899 $query_args
900 )
901 );
902 ?>
903 class="ultp-content-notice-close"><span class="ultp-content-notice-close-icon dashicons dashicons-dismiss"> </span></a>
904 </div>
905 <?php
906 }
907 }
908 }
909 }
910 }
911
912 /**
913 * Handle Plugin Notice for all plugins
914 *
915 * @param array $active_lists Lists of all active plugin notice.
916 * @return array
917 */
918 public function handle_xpo_active_notice_lists( $active_lists ) {
919 if ( $this->ultp_dashboard_banner_notice( true ) || $this->ultp_dashboard_content_notice( true ) || $this->ultp_dashboard_image_banner_notice( true ) ) {
920 $active_lists[ $this->plugin_notice_priority_key ] = $this->plugin_notice_priority;
921 }
922 return $active_lists;
923 }
924
925 /**
926 * Handle Plugin Notice for all plugins
927 *
928 * @return bool
929 */
930 public function is_available_for_notice() {
931 $active_notices = apply_filters( 'xpo_active_notice_lists', array() );
932 if ( empty( $active_notices ) ) {
933 return true;
934 }
935 asort( $active_notices );
936 return array_key_first( $active_notices ) === $this->plugin_notice_priority_key;
937 }
938
939 public function ultp_dashboard_image_banner_notice( $return_bool = false ) {
940 $ultp_db_nonce = wp_create_nonce( 'ultp-nonce' );
941 $banner_notices = array(
942 array(
943 'key' => 'ultp_summer_sale_2612',
944 'start' => '2026-07-20 00:00 Asia/Dhaka', // format YY-MM-DD always set time 00:00 and zone Asia/Dhaka
945 'end' => '2026-08-01 23:59 Asia/Dhaka', // format YY-MM-DD always set time 23:59 and zone Asia/Dhaka
946 'banner_src' => ULTP_URL . 'assets/img/dashboard_banner/dashboard_banner_summer_sale.png',
947 'url' => Xpo::generate_utm_link(
948 array(
949 'utmKey' => 'sub_menu_offer',
950 )
951 ),
952 'close_color' => '#000000',
953 'visibility' => ! Xpo::is_lc_active(),
954 ),
955 array(
956 'key' => 'ultp_summer_sale_2613',
957 'start' => '2026-08-09 00:00 Asia/Dhaka', // format YY-MM-DD always set time 00:00 and zone Asia/Dhaka
958 'end' => '2026-08-16 23:59 Asia/Dhaka', // format YY-MM-DD always set time 23:59 and zone Asia/Dhaka
959 'banner_src' => ULTP_URL . 'assets/img/dashboard_banner/dashboard_banner_summer_sale.png',
960 'url' => Xpo::generate_utm_link(
961 array(
962 'utmKey' => 'sub_menu_offer',
963 )
964 ),
965 'close_color' => '#000000',
966 'visibility' => ! Xpo::is_lc_active(),
967 ),
968 array(
969 'key' => 'ultp_preco_sale_campaign_262_1',
970 'start' => '2026-08-23 00:00 Asia/Dhaka', // format YY-MM-DD always set time 00:00 and zone Asia/Dhaka
971 'end' => '2026-08-29 23:59 Asia/Dhaka', // format YY-MM-DD always set time 23:59 and zone Asia/Dhaka
972 'banner_src' => ULTP_URL . 'assets/img/dashboard_banner/preco_banner_insider_deal.png',
973 'url' => 'https://www.wpxpo.com/product/wowrecommend/?utm_source=db-postx-notice&utm_medium=insider-deal&utm_campaign=postx-dashboard/#pricing',
974 'close_color' => '#ffffff',
975 'visibility' => ! Xpo::is_lc_active(),
976 ),
977 array(
978 'key' => 'ultp_preco_sale_campaign_262_2',
979 'start' => '2026-08-30 00:00 Asia/Dhaka', // format YY-MM-DD always set time 00:00 and zone Asia/Dhaka.
980 'end' => '2026-09-19 23:59 Asia/Dhaka', // format YY-MM-DD always set time 23:59 and zone Asia/Dhaka.
981 'banner_src' => ULTP_URL . 'assets/img/dashboard_banner/preco_banner_early_bird.png',
982 'url' => 'https://www.wpxpo.com/product/wowrecommend/?utm_source=db-postx-notice&utm_medium=early-bird&utm_campaign=postx-dashboard/#pricing',
983 'close_color' => '#ffffff',
984 'visibility' => ! Xpo::is_lc_active(),
985 ),
986 );
987
988 foreach ( $banner_notices as $notice ) {
989 $notice_key = isset( $notice['key'] ) ? $notice['key'] : $this->notice_version;
990 if ( isset( $_GET['ultp_notice'] ) && $notice_key === sanitize_text_field(wp_unslash($_GET['ultp_notice'])) ) { // phpcs:ignore
991 continue;
992 }
993
994 $current_time = gmdate( 'U' );
995 $notice_start = gmdate( 'U', strtotime( $notice['start'] ) );
996 $notice_end = gmdate( 'U', strtotime( $notice['end'] ) );
997 if ( $current_time >= $notice_start && $current_time <= $notice_end && $notice['visibility'] ) {
998
999 $notice_transient = Xpo::get_transient_without_cache( 'ultp_get_pro_notice_' . $notice_key );
1000
1001 if ( 'off' === $notice_transient ) {
1002 continue;
1003 }
1004
1005 if ( $return_bool ) { // Early return for Other plugin notice.
1006 return true;
1007 }
1008
1009 if ( ! $this->notice_js_css_applied ) {
1010 $this->ultp_banner_notice_js();
1011 $this->notice_js_css_applied = true;
1012 }
1013 $query_args = array(
1014 'ultp_notice' => $notice_key,
1015 'wpnonce' => $ultp_db_nonce,
1016 );
1017 if ( isset( $notice['repeat_interval'] ) && $notice['repeat_interval'] ) {
1018 $query_args['ultp_interval'] = $notice['repeat_interval'];
1019 }
1020 ?>
1021 <style type="text/css">
1022 .ultp-notice-wrapper.ultp-image-notice-wrapper {
1023 padding: 0 !important;
1024 position: relative;
1025 box-sizing: border-box;
1026 overflow: hidden;
1027 border-radius: 0px;
1028 border: none !important;
1029 }
1030 .ultp-notice-wrapper.ultp-image-notice-wrapper .ultp-image-banner {
1031 position: relative;
1032 line-height: 0;
1033 }
1034 .ultp-notice-wrapper.ultp-image-notice-wrapper .ultp-btn-image {
1035 display: block;
1036 }
1037 .ultp-notice-wrapper.ultp-image-notice-wrapper .ultp-btn-image img {
1038 display: block;
1039 width: 100%;
1040 height: auto;
1041 border-radius: 0;
1042 }
1043 .ultp-notice-wrapper.ultp-image-notice-wrapper .ultp-content-notice-close {
1044 top: 4px;
1045 right: 4px;
1046 position: absolute;
1047 z-index: 999;
1048 }
1049 @media screen and (max-width: 650px) {
1050 .ultp-image-notice-wrapper {
1051 display: none;
1052 }
1053 }
1054 </style>
1055 <div class="ultp-notice-wrapper ultp-image-notice-wrapper notice wc-install ultp-free-notice">
1056 <div class="wc-install-body ultp-image-banner">
1057 <a class="wc-dismiss-notice ultp-content-notice-close" href="
1058 <?php
1059 echo esc_url(
1060 add_query_arg(
1061 $query_args
1062 )
1063 );
1064 ?>
1065 "><span class="ultp-content-notice-close-icon dashicons dashicons-dismiss" style="color: <?php echo esc_attr( $notice['close_color'] ); ?>;"> </span></a>
1066 <a class="ultp-btn-image" target="_blank" href="<?php echo esc_url( $notice['url'] ); ?>">
1067 <img loading="lazy" src="<?php echo esc_url( $notice['banner_src'] ); ?>" alt="Discount Banner"/>
1068 </a>
1069 </div>
1070 </div>
1071
1072 <?php
1073 }
1074 }
1075 }
1076 }
1077