PluginProbe
Post Grid Gutenberg Blocks – PostX / 5.0.33
Post Grid Gutenberg Blocks – PostX v5.0.33
5.1.1 5.1.0 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 All 240 releases
ultimate-post / includes / notice / class-notice.php

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

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