PluginProbe
Post Grid Gutenberg Blocks – PostX / 5.0.34
Post Grid Gutenberg Blocks – PostX v5.0.34
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 2.1.2 All 237 releases
ultimate-post / includes / notice / class-notice.php

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

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