PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.0.0
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.0.0
9.1.3 9.1.2 9.1.1 9.1.0 9.0.3 9.0.2 9.0.1 9.0.0 8.5.79 8.5.78 8.5.77 8.5.76 8.5.75 8.5.74 8.5.73 8.5.72 8.5.71 8.5.70 8.5.69 8.5.68 8.5.35 8.5.36 8.5.37 8.5.38 8.5.39 All 222 releases
wpvr / legacy / admin / classes / class-wpvr-sells-notification-bar.php

class-wpvr-sells-notification-bar.php in WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress 9.0.0, at legacy/admin/classes/class-wpvr-sells-notification-bar.php

646 lines 22.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class WPVR_Notification_Bar {
4
5 private $occasion = '';
6 private $start_datetime = '';
7 private $end_datetime = '';
8
9 public function __construct( $occasion_slug, $start_datetime, $end_datetime ) {
10
11
12 $this->occasion = $occasion_slug;
13 $this->start_datetime = $start_datetime;
14 $this->end_datetime = $end_datetime;
15 $current_datetime = current_time('Y-m-d H:i:s');
16
17 if( $current_datetime >= $this->start_datetime && $current_datetime <= $this->end_datetime ) {
18 // Hook into the admin_notices action to display the banner
19 add_action('admin_notices', array($this, 'display_banner'));
20 // Add styles
21 add_action('admin_head', array($this, 'add_styles'));
22
23 add_action('wp_ajax_wpvr_sale_notification_notice', array($this, 'wpvr_sale_notification_notice'));
24 }
25 }
26
27
28 /**
29 * Displays the special occasion banner if the current date and time are within the specified range.
30 */
31 public function display_banner()
32 {
33
34 $screen = get_current_screen();
35 $promotional_notice_pages = ['dashboard', 'plugins', 'edit-wpvr_item', 'toplevel_page_wpvr', 'wp-vr_page_wpvr-setup-wizard', 'wpvr_item', 'wp-vr_page_wpvr-addons','wp-vr_page_wpvr-setting'];
36 if (!in_array($screen->id, $promotional_notice_pages)) {
37 return;
38 }
39
40 if ( $screen->base === 'plugins' || $screen->base === 'dashboard' ) {
41 if ( defined( 'WPVR_SPECIAL_OCCASION_BANNER_SHOWN_GLOBAL' ) ) {
42 return;
43 }
44 define( 'WPVR_SPECIAL_OCCASION_BANNER_SHOWN_GLOBAL', true );
45 }
46
47 // Check if banner was dismissed within last 5 days
48 $dismissed_option = 'wpvr_' . $this->occasion . '_dismissed';
49 $dismissed_time = get_option($dismissed_option, 0);
50 if ($dismissed_time && (time() - $dismissed_time) < 432000) {
51 return; // Don't show if dismissed within last 5 days
52 }
53
54 $base_url = 'https://rextheme.com/wpvr/wpvr-pricing/';
55
56 $utm_params = array(
57 'utm_source' => 'website',
58 'utm_medium' => 'plugin-ban-wpvr',
59 'utm_campaign' => 'eidoffer2026',
60 );
61
62 $btn_link = add_query_arg( $utm_params, $base_url );
63
64 $img_url = WPVR_PLUGIN_DIR_URL . 'admin/icon/banner-images/ramadan-kareem.webp';
65 $img_path = WPVR_PLUGIN_DIR_PATH . 'admin/icon/banner-images/ramadan-kareem.webp';
66 $img_size = getimagesize($img_path);
67 $img_width = $img_size[0];
68 $img_height = $img_size[1];
69
70 ?>
71
72 <section class="wpvr-promo-banner wpvr-promo-banner--regular" aria-labelledby="wpvr-promo-banner-title" id="wpvr-promo-banner">
73 <div class="wpvr-regular-promotional-banner" id="wpvr-regular-promotional-banner" role="region" aria-labelledby="banner-flash-title">
74
75 <div class="wpvr-regular-promotional-banner-container">
76
77 <div class="wpvr-regular-promotional-banner-content" id="banner-flash">
78
79 <!-- Close Button -->
80 <button class="wpvr-close-btn"
81 type="button"
82 aria-label="<?php esc_attr_e( 'Close banner', 'wpvr' ); ?>"
83 id="wpvr-promo-banner__cross-icon">
84 <svg xmlns="http://www.w3.org/2000/svg" width="9" height="9" viewBox="0 0 9 9" fill="none">
85 <path d="M7.77482 0.75L0.75 7.75" stroke="#7E7E7E" stroke-width="1.5" stroke-linecap="round"/>
86 <path d="M7.77482 7.75L0.75 0.75" stroke="#7E7E7E" stroke-width="1.5" stroke-linecap="round"/>
87 </svg>
88 </button>
89
90 <!-- Banner Title + Timer -->
91 <div class="wpvr-regular-promotional-banner-title">
92
93
94 <div class="wpvr-badge-content-img-area">
95 <div class="heart-icon">
96 <figure class="wpvr-banner-img black-friday">
97 <img src="<?php echo esc_url($img_url); ?>" alt="ramadan kareem" width="<?php echo esc_attr($img_width); ?>"
98 height="<?php echo esc_attr($img_height); ?>" />
99 </figure>
100 </div>
101
102 <div class="wpvr-badge-content">
103
104 <div class="wpvr-banner-title">
105
106
107 <h2 id="banner-flash-title">
108 <?php echo esc_html__('Eid Mubarak, Save Big', 'wpvr'); ?>
109 </h2>
110 </div>
111
112 <div class="wpvr-title wpvr-banner-offer">
113 <?php echo esc_html__('Up to 50% Off', 'wpvr'); ?>
114 </div>
115 </div>
116 </div>
117
118 <!-- Countdown Timer -->
119 <div class="wpvr-timer">
120 <div class="wpvr-timer-box">
121 <span class="wpvr-timer-number" id="wpvr_days">12</span>
122 <span class="wpvr-timer-label">DAY</span>
123 </div>
124 <div class="wpvr-timer-box">
125 <span class="wpvr-timer-number" id="wpvr_hours">10</span>
126 <span class="wpvr-timer-label">HR</span>
127 </div>
128 <div class="wpvr-timer-box">
129 <span class="wpvr-timer-number" id="wpvr_minutes">45</span>
130 <span class="wpvr-timer-label">MIN</span>
131 </div>
132 <div class="wpvr-timer-box">
133 <span class="wpvr-timer-number" id="wpvr_seconds">30</span>
134 <span class="wpvr-timer-label">SEC</span>
135 </div>
136 </div>
137
138 </div>
139
140 <!-- CTA Button -->
141 <a href="<?php echo esc_url( $btn_link ); ?>"
142 target="_blank"
143 class="wpvr-regular-promotional-banner-link"
144 role="button"
145 aria-label="<?php esc_attr_e('Claim Your Deal on Eid-Ul-Fitr', 'wpvr'); ?>">
146 <?php esc_html_e('Claim Your Deal', 'wpvr'); ?>
147 <span class="arrow-icon">
148 <svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10">
149 <path d="M10 0.78V9.22C10 9.65 9.65 10 9.22 10C8.79 10 8.44 9.65 8.44 9.22V2.66L1.33 9.77C1.19 9.92 0.99 10 0.78 10C0.35 10 0 9.65 0 9.22C0 9.01 0.08 8.81 0.23 8.67L7.33 1.56H0.78C0.35 1.56 0 1.21 0 0.78C0.35 1.56 0 1.21 0 0.78C0 0.35 0.35 0 0.78 0H9.22C9.65 0 10 0.35 10 0.78Z"
150 fill="#fff"/>
151 </svg>
152 </span>
153 </a>
154
155 </div>
156 </div>
157 </div>
158
159 </section>
160 <script>
161
162 (function () {
163 // Get timer elements
164 const daysEl = document.getElementById('wpvr_days');
165 const hoursEl = document.getElementById('wpvr_hours');
166 const minutesEl = document.getElementById('wpvr_minutes');
167 const secondsEl = document.getElementById('wpvr_seconds');
168 const banner = document.getElementById('wpvr-promo-banner');
169
170 // Get labels (next siblings of timer numbers)
171 const daysLabel = daysEl ? daysEl.nextElementSibling : null;
172 const hoursLabel = hoursEl ? hoursEl.nextElementSibling : null;
173 const minutesLabel = minutesEl ? minutesEl.nextElementSibling : null;
174 const secondsLabel = secondsEl ? secondsEl.nextElementSibling : null;
175
176 // Configure end time from PHP
177 const wpvr_end = new Date(<?php echo wp_json_encode( $this->end_datetime ); ?>);
178
179 let wpvr_timer;
180
181 // Update countdown timer
182 function wpvr_updateCountdown() {
183 const now = new Date();
184
185 // Check if deal expired
186 if (now > wpvr_end) {
187 if (daysEl) daysEl.textContent = '0';
188 if (hoursEl) hoursEl.textContent = '0';
189 if (minutesEl) minutesEl.textContent = '0';
190 if (secondsEl) secondsEl.textContent = '0';
191 clearInterval(wpvr_timer);
192 // Auto-hide banner after countdown expires
193 setTimeout(function() {
194 if (banner) banner.style.display = 'none';
195 }, 2000);
196 return;
197 }
198
199 // Calculate remaining time
200 const diff = wpvr_end - now;
201 const days = Math.floor(diff / (1000 * 60 * 60 * 24));
202 const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
203 const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
204 const seconds = Math.floor((diff % (1000 * 60)) / 1000);
205
206 // Update numbers (pad single digits with leading zero)
207 if (daysEl) daysEl.textContent = days < 10 ? '0' + days : days;
208 if (hoursEl) hoursEl.textContent = hours < 10 ? '0' + hours : hours;
209 if (minutesEl) minutesEl.textContent = minutes < 10 ? '0' + minutes : minutes;
210 if (secondsEl) secondsEl.textContent = seconds < 10 ? '0' + seconds : seconds;
211
212 // Update labels (singular/plural)
213 if (daysLabel) daysLabel.textContent = (days === 0 || days === 1) ? 'DAY' : 'DAYS';
214 if (hoursLabel) hoursLabel.textContent = (hours === 0 || hours === 1) ? 'HR' : 'HRS';
215 if (minutesLabel) minutesLabel.textContent = (minutes === 0 || minutes === 1) ? 'MIN' : 'MINS';
216 if (secondsLabel) secondsLabel.textContent = (seconds === 0 || seconds === 1) ? 'SEC' : 'SECS';
217 }
218
219 // Initialize countdown
220 wpvr_updateCountdown(); // Run immediately
221 wpvr_timer = setInterval(wpvr_updateCountdown, 1000); // Update every second
222 })();
223
224 (function ($) {
225 /**
226 * Dismiss sale notification notice
227 *
228 * @param e
229 */
230 function wpvr_sale_notification_notice(e) {
231 e.preventDefault();
232 $('#wpvr-promo-banner').hide(); // Ensure the correct element is selected
233 jQuery.ajax({
234 type: "POST",
235 url: ajaxurl,
236 data: {
237 action: "wpvr_sale_notification_notice",
238 nonce: wpvr_global_obj.ajax_nonce
239 },
240 success: function(response) {
241 $('#wpvr-promo-banner').hide(); // Ensure the correct element is selected
242 },
243 error: function(xhr, status, error) {
244 console.error('AJAX request failed:', status, error);
245 }
246 });
247 }
248
249 jQuery(document).ready(function($) {
250 $(document).on('click', '#wpvr-promo-banner__cross-icon', wpvr_sale_notification_notice);
251 });
252 })(jQuery);
253 </script>
254 <!-- .rex-feed-tb-notification end -->
255 <?php
256 }
257
258
259 /**
260 * Adds internal CSS styles for the special occasion banners.
261 */
262 public function add_styles()
263 {
264 ?>
265 <style id="wpvr-promotional-banner-style" type="text/css">
266 :root {
267 --wpvr-primary-color: #24EC2C;
268 }
269
270 @font-face {
271 font-family: 'Roboto';
272 src: url(<?php echo esc_url(WPVR_PLUGIN_DIR_URL . 'admin/fonts/Roboto-Regular.woff2'); ?>) format('woff2');
273 font-weight: 400;
274 font-style: normal;
275 font-display: swap;
276 }
277
278 @font-face {
279 font-family: 'Roboto';
280 src: url(<?php echo esc_url(WPVR_PLUGIN_DIR_URL . 'admin/fonts/Roboto-Bold.woff2'); ?>) format('woff2');
281 font-weight: 700;
282 font-style: normal;
283 font-display: swap;
284 }
285
286 .wpvr-promo-banner * {
287 box-sizing: border-box;
288 }
289
290 @font-face {
291 font-family: 'Inter';
292 src: url(<?php echo esc_url(WPVR_PLUGIN_DIR_URL . 'admin/fonts/campaign-font/Inter-Bold.woff2'); ?>) format('woff2');
293 font-weight: 700;
294 font-style: normal;
295 font-display: swap;
296 }
297
298 @font-face {
299 font-family: 'Inter';
300 src: url(<?php echo esc_url(WPVR_PLUGIN_DIR_URL . 'admin/fonts/campaign-font/Inter-SemiBold.woff2'); ?>) format('woff2');
301 font-weight: 600;
302 font-style: normal;
303 font-display: swap;
304 }
305
306 .wpvr-regular-promotional-banner {
307 background: radial-gradient(41.22% 84.27% at 50.55% 15.73%, #1d3a10 0, #0e1b09 100%);
308 padding: 10px 0;
309 position: relative;
310 z-index: 2;
311 margin-top: 40px;
312 width: calc(100% - 20px);
313 }
314
315 .wpvr-regular-promotional-banner-container {
316 max-width: 830px;
317 margin: 0 auto;
318 padding: 0 15px;
319 }
320
321 .wpvr-regular-promotional-banner-content {
322 display: flex;
323 align-items: center;
324 justify-content: space-between;
325 gap: 24px;
326 }
327
328
329 .wpvr-regular-promotional-banner-content .wpvr-badge-content-img-area {
330 display: flex;
331 align-items: center;
332 gap: 33px;
333 }
334
335 .wpvr-regular-promotional-banner-content .wpvr-banner-title {
336 display: flex;
337 align-items: center;
338 gap: 5px;
339 margin-bottom: 3px;
340 line-height: 1.1;
341 animation: slideInLeft 0.8s ease-out;
342 }
343
344 .wpvr-regular-promotional-banner-content .heart-icon img {
345 width: 100%;
346 height: auto;
347 max-width: 53px;
348 }
349
350 .wpvr-regular-promotional-banner-content .heart-icon figure {
351 margin: 0;
352 }
353
354 .wpvr-regular-promotional-banner-content .wpvr-banner-title h2 {
355 font-family: 'Inter', sans-serif;
356 font-size: 16px;
357 font-weight: 500;
358 line-height: 1.3;
359 letter-spacing: -0.32px;
360 color: #FFF;
361 margin: 0;
362 }
363
364 .wpvr-regular-promotional-banner-content .wpvr-regular-promotional-banner-title {
365 display: flex;
366 align-items: center;
367 gap: 65px;
368 }
369
370 .wpvr-regular-promotional-banner-content .linno-banner.closing {
371 animation: linno-slideUp 0.5s ease-in forwards;
372 }
373
374 /* CLOSE BUTTON */
375 .wpvr-regular-promotional-banner-content .wpvr-close-btn {
376 position: absolute;
377 top: 33px;
378 right: 40px;
379 border: none;
380 display: flex;
381 align-items: center;
382 justify-content: center;
383 cursor: pointer;
384 background-color: transparent;
385 transition: all 0.3s ease-in-out;
386 }
387
388 .wpvr-regular-promotional-banner-content .wpvr-close-btn:hover {
389 transform: rotate(90deg);
390 }
391
392 /* TITLE, SUBTITLE, BADGE */
393 .wpvr-regular-promotional-banner-content .wpvr-title {
394 font-family: "Inter", sans-serif;
395 font-size: 24px;
396 font-weight: 700;
397 line-height: 1;
398 letter-spacing: -0.084px;
399 color: #24ec2c;
400 margin: 0;
401 }
402
403 .wpvr-regular-promotional-banner-content span.arrow-icon {
404 margin-left: 10px;
405 }
406
407 .wpvr-regular-promotional-banner-content .wpvr-badge {
408 font-family: "Inter", sans-serif;
409 font-size: 16px;
410 font-weight: 600;
411 line-height: 12px;
412 letter-spacing: 2px;
413 text-transform: uppercase;
414 color: #24EC2C;
415 }
416
417 /* BUTTON */
418 .wpvr-regular-promotional-banner-content .wpvr-regular-promotional-banner-link {
419 padding: 12px 16px;
420 cursor: pointer;
421 transition: all 0.3s ease-in-out;
422 border-radius: 4px;
423 background: #211cfd;
424 color: #fff;
425 font-family: "Inter", sans-serif;
426 font-size: 15px;
427 font-weight: 600;
428 line-height: 1;
429 letter-spacing: -0.084px;
430 text-decoration: none;
431 }
432
433 .wpvr-regular-promotional-banner-content .wpvr-regular-promotional-banner-link:hover {
434 transform: translateY(-2px);
435 box-shadow: 0 6px 15px rgba(0,0,0,0.3);
436 }
437
438 /* TIMER */
439 .wpvr-regular-promotional-banner-content .wpvr-timer {
440 display: flex;
441 gap: 3px;
442 }
443
444 .wpvr-regular-promotional-banner-content .wpvr-timer-box {
445 display: flex;
446 flex-direction: column;
447 align-items: center;
448 justify-content: center;
449 padding: 6px 11px;
450 text-align: center;
451 color: #fff;
452 border: 1px solid #2d5d1a;
453 background: rgba(29, 58, 16, .4);
454 }
455
456 .wpvr-regular-promotional-banner-content .wpvr-timer-box:first-child {
457 border-radius: 4px 0 0 4px;
458 }
459
460 .wpvr-regular-promotional-banner-content .wpvr-timer-box:last-child {
461 border-radius: 0 4px 4px 0;
462 }
463
464 .wpvr-regular-promotional-banner-content .wpvr-timer-number {
465 font-family: "Inter", sans-serif;
466 font-size: 20px;
467 font-weight: 800;
468 line-height: 1.1;
469 margin-bottom: 6px;
470 color: #FFF;
471 }
472
473 .wpvr-regular-promotional-banner-content .wpvr-timer-label {
474 font-family: "Inter", sans-serif;
475 font-size: 12px;
476 font-weight: 400;
477 line-height: 1;
478 letter-spacing: 0.24px;
479 text-transform: uppercase;
480 opacity: 0.8;
481 }
482
483 /* ANIMATIONS */
484 @keyframes linno-slideDown {
485 from { transform: translateY(-100%); opacity: 0; }
486 to { transform: translateY(0); opacity: 1; }
487 }
488
489 @keyframes linno-slideUp {
490 from { transform: translateY(0); opacity: 1; }
491 to { transform: translateY(-100%); opacity: 0; }
492 }
493
494 @keyframes linno-pulse {
495 0%,100% { transform: scale(1); }
496 50% { transform: scale(1.05); }
497 }
498
499 @keyframes linno-float {
500 0%,100% { transform: translateY(0); }
501 50% { transform: translateY(-20px); }
502 }
503
504 @keyframes heartbeat {
505 0%,100% { transform: scale(1); }
506 25% { transform: scale(1.2); }
507 50% { transform: scale(1); }
508 }
509
510 /* REDUCED MOTION */
511 @media (prefers-reduced-motion: reduce) {
512 .wpvr-regular-promotional-banner {
513 transition: none;
514 }
515 }
516
517 /* RESPONSIVE */
518
519 @media only screen and (max-width: 1199px) {
520 .wpvr-regular-promotional-banner {
521 margin-top: 55px;
522 }
523
524 .wpvr-regular-promotional-banner-container {
525 max-width: 780px;
526 }
527
528 .wpvr-regular-promotional-banner-content .wpvr-regular-promotional-banner-title {
529 gap: 40px;
530 }
531
532 .wpvr-regular-promotional-banner-content .wpvr-close-btn {
533 top: 32px;
534 right: 14px;
535 }
536 }
537
538 @media only screen and (max-width: 991px) {
539
540 .wpvr-regular-promotional-banner-container {
541 max-width: 700px;
542 }
543
544 .wpvr-regular-promotional-banner-content .wpvr-banner-title h2 {
545 font-size: 13px;
546 }
547
548 .wpvr-regular-promotional-banner-content .wpvr-timer-box {
549 padding: 4px 9px;
550 }
551
552 .wpvr-regular-promotional-banner-content .wpvr-badge-content-img-area {
553 gap: 15px;
554 }
555
556 .wpvr-regular-promotional-banner-content .wpvr-title {
557 font-size: 20px;
558 }
559
560 .wpvr-regular-promotional-banner-content .wpvr-timer-number {
561 font-size: 18px;
562 line-height: 1.3;
563 }
564
565 .wpvr-regular-promotional-banner-content .wpvr-close-btn {
566 top: 32px;
567 right: 3px;
568 }
569
570 .wpvr-regular-promotional-banner-content .wpvr-badge {
571 font-size: 14px;
572 }
573
574 .wpvr-regular-promotional-banner-content .wpvr-regular-promotional-banner-title {
575 gap: 30px;
576 }
577 }
578
579 @media only screen and (max-width: 767px) {
580
581 .wpvr-regular-promotional-banner-content {
582 flex-direction: column;
583 text-align: center;
584 gap: 30px;
585 padding: 30px 0;
586 }
587
588 .wpvr-regular-promotional-banner-content .heart-icon {
589 margin-bottom: 0px;
590 }
591
592 .wpvr-regular-promotional-banner-content .wpvr-title {
593 font-size: 22px;
594 }
595
596 .wpvr-regular-promotional-banner-content .wpvr-regular-promotional-banner-title {
597 flex-direction: column;
598 }
599
600 .wpvr-regular-promotional-banner-content .wpvr-timer-number {
601 font-size: 20px;
602 }
603
604 .wpvr-regular-promotional-banner-content .wpvr-timer {
605 justify-content: center;
606 flex-wrap: wrap;
607 }
608
609 .wpvr-regular-promotional-banner-content .wpvr-close-btn {
610 top: 15px;
611 right: 20px;
612 }
613 }
614
615
616 </style>
617
618 <?php
619
620 }
621
622
623 public function wpvr_sale_notification_notice()
624 {
625 if (!current_user_can('manage_options')) {
626 $response = array(
627 'success' => false,
628 'data' => 'Permission denied.'
629 );
630 wp_send_json($response);
631 }
632
633 $nonce = isset($_POST['nonce']) ? sanitize_text_field(wp_unslash($_POST['nonce'])) : '';
634 if (!$nonce || !wp_verify_nonce($nonce, 'wpvr')) {
635 wp_die( esc_html__( 'Permission check failed', 'wpvr' ) );
636 }
637
638 // Store current timestamp for 24-hour dismissal
639 $dismissed_option = 'wpvr_' . $this->occasion . '_dismissed';
640 update_option($dismissed_option, time());
641
642 echo wp_json_encode(['success' => true]);
643 wp_die();
644 }
645
646 }