PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.0.1
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.0.1
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 / wpvr.php

wpvr.php in WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress 9.0.1, at legacy/wpvr.php

4,353 lines 200.8 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 // Legacy bootstrap for WP VR plugin
3 // This file is a direct copy of the original wpvr.php before architecture migration.
4 // Do not edit legacy logic here; only update if the legacy code itself changes.
5
6 if (!defined('WPINC')) {
7 die;
8 }
9
10 require WPVR_PLUGIN_LEGACY_DIR_PATH . 'elementor/elementor.php';
11 if ( file_exists( dirname( WPVR_PLUGIN_LEGACY_DIR_PATH ) . '/vendor/autoload.php' ) ) {
12 require_once dirname( WPVR_PLUGIN_LEGACY_DIR_PATH ) . '/vendor/autoload.php';
13 } elseif ( file_exists( WPVR_PLUGIN_LEGACY_DIR_PATH . 'vendor/autoload.php' ) ) {
14 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'vendor/autoload.php';
15 }
16
17 if ( wp_get_theme('bricks')->exists() && 'bricks' === get_template()) {
18 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'bricks/bricks.php';
19 }
20
21
22 /**
23 * Currently plugin version.
24 * Start at version 1.0.0 and use SemVer - https://semver.org
25 * Rename this for your plugin and update it as you release new versions.
26 */
27 define( 'WPVR_WEBHOOK_URL', sanitize_url( 'https://rextheme.com/?mailmint=1&route=webhook&topic=contact&hash=bbd19901-6d42-4ae5-a7a8-01eb1013c553' ) );
28 if ( ! defined( 'WPVR_TELEMETRY_API_KEY' ) ) {
29 define( 'WPVR_TELEMETRY_API_KEY', 'phc_amk3VQz1P5ZqZOMRRoWM1B41QMFpf3hu8pg7yRfzSXW' );
30 }
31 if ( ! defined( 'WPVR_TELEMETRY_API_SECRET' ) ) {
32 define( 'WPVR_TELEMETRY_API_SECRET', 'sec_dfb2ab8e84391ae7a0f9' );
33 }
34 if ( ! defined( 'WPVR_TELEMETRY_HOST' ) ) {
35 define( 'WPVR_TELEMETRY_HOST', 'https://eu.i.posthog.com' );
36 }
37
38
39 if ( ! function_exists( 'activate_wpvr' ) ) {
40 /**
41 * The code that runs during plugin activation.
42 * This action is documented in includes/class-wpvr-activator.php
43 */
44 function activate_wpvr()
45 {
46 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'includes/class-wpvr-activator.php';
47 Wpvr_Activator::activate();
48
49 // Trigger plugin activation tracking
50 do_action( 'wpvr_plugin_activated' );
51 }
52 }
53
54 if ( ! function_exists( 'deactivate_wpvr' ) ) {
55 /**
56 * The code that runs during plugin deactivation.
57 * This action is documented in includes/class-wpvr-deactivator.php
58 */
59 function deactivate_wpvr()
60 {
61 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'includes/class-wpvr-deactivator.php';
62 Wpvr_Deactivator::deactivate();
63
64 // Trigger plugin deactivation tracking
65 do_action( 'wpvr_plugin_deactivated' );
66 }
67 }
68
69 register_activation_hook( WPVR_FILE, 'activate_wpvr' );
70 register_deactivation_hook( WPVR_FILE, 'deactivate_wpvr' );
71
72 /**
73 * The core plugin class that is used to define internationalization,
74 * admin-specific hooks, and public-facing site hooks.
75 */
76 require WPVR_PLUGIN_LEGACY_DIR_PATH . 'includes/class-wpvr.php';
77
78 // Include banner classes
79 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-occasion-banner.php';
80 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-sells-notification-bar.php';
81 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-first-tour-banner.php';
82 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-onboarding-notice.php';
83 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'admin/classes/class-wpvr-new-user-tour.php';
84
85 if ( defined( 'WPB_VC_VERSION' ) ) {
86 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'builders/wpbakery/wpvr-loader.php';
87 if ( class_exists( 'Vc_Manager' ) ) {
88 require_once WPVR_PLUGIN_LEGACY_DIR_PATH . 'builders/wpbakery/wpvr-element.php';
89 }
90 }
91
92
93 /**
94 * Begins execution of the plugin.
95 *
96 * Since everything within the plugin is registered via hooks,
97 * then kicking off the plugin from this point in the file does
98 * not affect the page life cycle.
99 *
100 * @since 7.3.6
101 */
102 function run_wpvr()
103 {
104
105 $plugin = new Wpvr();
106 $plugin->run();
107 // new Tracker();
108
109 // black friday banner class initialization
110 // new WPVR_Special_Occasion_Banner(
111 // 'halloween_deal_2025',
112 // '2025-10-01 00:00:01',
113 // '2025-11-05 23:59:59'
114 // );
115
116 if (!defined('WPVR_PRO_VERSION') && 'no' === get_option('wpvr_sell_eid_ul_fitr_2026_notification_bar', 'no')) {
117 new WPVR_Notification_Bar(
118 'Eid_Ul_Fitr_2026',
119 '2026-03-16 00:00:00',
120 '2026-03-24 23:59:59'
121 );
122 }
123
124 // Initialize first tour banner
125 new WPVR_First_Tour_Banner();
126
127 // Initialize listing-page onboarding notice ("Remind me later" flow)
128 new WPVR_Onboarding_Notice();
129
130 // Auto-launch guided tour for truly-new users on the Add New Tour page.
131 new WPVR_New_User_Tour();
132
133 // Pro preview banner (shown via JS when free user toggles Advanced Controls)
134 if (!defined('WPVR_PRO_VERSION')) {
135 add_action('admin_notices', 'wpvr_render_pro_preview_banner', 11);
136 }
137
138 }
139 run_wpvr();
140
141 /**
142 * Render Pro preview banner as admin notice.
143 * Hidden by default; shown via JS when free user toggles Advanced Controls.
144 *
145 * @since 8.5.44
146 */
147 function wpvr_render_pro_preview_banner() {
148 $screen = get_current_screen();
149 if (!$screen || $screen->id !== 'wpvr_item') {
150 return;
151 }
152 ?>
153 <div class="wpvr-pro-preview-banner" id="wpvr-pro-preview-banner" style="display:none;">
154 <div class="wpvr-pro-preview-banner__left">
155 <span class="wpvr-pro-preview-banner__icon">
156 <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M12 4.5C7 4.5 2.73 7.61 1 12c1.73 4.39 6 7.5 11 7.5s9.27-3.11 11-7.5c-1.73-4.39-6-7.5-11-7.5zm0 12.5c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5zm0-8c-1.66 0-3 1.34-3 3s1.34 3 3 3 3-1.34 3-3-1.34-3-3-3z"/></svg>
157 </span>
158 <span class="wpvr-pro-preview-banner__text"><?php esc_html_e('You are previewing Pro features in action.', 'wpvr'); ?></span>
159 </div>
160 <div class="wpvr-pro-preview-banner__pricing">
161 <div class="wpvr-pro-preview-banner__pricing-top">
162 <span class="wpvr-pro-preview-banner__old-price"><?php esc_html_e('Normally $99.99/year', 'wpvr'); ?></span>
163 <span class="wpvr-pro-preview-banner__badge"><?php esc_html_e('SAVE 20%', 'wpvr'); ?></span>
164 </div>
165 <span class="wpvr-pro-preview-banner__new-price"><?php esc_html_e('Starting at $79.99/year', 'wpvr'); ?></span>
166 </div>
167 <a href="<?php echo esc_url('https://rextheme.com/wpvr/wpvr-pricing/?utm_source=plugin&utm_medium=pro-preview-banner&utm_campaign=advanced-controls'); ?>" class="wpvr-pro-preview-banner__btn" target="_blank" rel="noopener noreferrer">
168 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M5 16L3 5l5.5 5L12 4l3.5 6L21 5l-2 11H5zm0 2h14v1c0 .55-.45 1-1 1H6c-.55 0-1-.45-1-1v-1z"/></svg>
169 <?php esc_html_e('Upgrade to save changes', 'wpvr'); ?>
170 </a>
171 </div>
172 <?php
173 }
174
175
176 /**
177 * Array information checker
178 *
179 * @param mixed $needle
180 * @param mixed $haystack
181 * @param bool $strict
182 *
183 * @return bool
184 * @since 7.3.6
185 */
186 function wpvr_in_array_r($needle, $haystack, $strict = false)
187 {
188 foreach ($haystack as $item) {
189 if ((($strict ? $item === $needle : $item == $needle)) || is_array($item) && wpvr_in_array_r($needle, $item, $strict)) {
190 return true;
191 }
192 }
193 return false;
194 }
195
196 if ( ! function_exists( 'wpvr_parse_custom_control' ) ) {
197 /**
198 * Normalize custom control data into an array.
199 *
200 * @param mixed $custom_control Raw custom control value from meta.
201 *
202 * @return array
203 * @since 8.5.63
204 */
205 function wpvr_parse_custom_control( $custom_control ) {
206 if ( is_array( $custom_control ) ) {
207 return $custom_control;
208 }
209
210 if ( is_object( $custom_control ) ) {
211 return (array) $custom_control;
212 }
213
214 if ( ! is_string( $custom_control ) || '' === trim( $custom_control ) ) {
215 return array();
216 }
217
218 $unserialized = maybe_unserialize( $custom_control );
219 if ( is_array( $unserialized ) ) {
220 return $unserialized;
221 }
222
223 $decoded = json_decode( wp_unslash( $custom_control ), true );
224 if ( is_array( $decoded ) ) {
225 return $decoded;
226 }
227
228 return array();
229 }
230 }
231
232 if ( ! function_exists( 'wpvr_restore_modern_layout_default_controls' ) ) {
233 /**
234 * Restore Pannellum's default controls after WP VR Pro adds Modern layout CSS.
235 *
236 * The Modern layout stylesheet is added by WP VR Pro at filter priority 10.
237 * Running at priority 20 keeps this compatibility rule in the Free plugin while
238 * ensuring it is output after the Pro stylesheet, regardless of plugin load order.
239 *
240 * @param string $html Generated tour HTML.
241 * @param array $postdata Saved tour settings.
242 * @param int $id Tour post ID.
243 *
244 * @return string
245 * @since 9.0.0
246 */
247 function wpvr_restore_modern_layout_default_controls( $html, $postdata, $id ) {
248 $tour_layout = is_array( $postdata['tourLayout'] ?? null )
249 ? ( $postdata['tourLayout']['layout'] ?? 'default' )
250 : ( $postdata['tourLayout'] ?? 'default' );
251
252 if (
253 ! defined( 'WPVR_PRO_VERSION' )
254 || 'layout1' !== $tour_layout
255 || empty( $postdata['showControls'] )
256 ) {
257 return $html;
258 }
259
260 $custom_control = wp_parse_args(
261 wpvr_parse_custom_control( $postdata['customcontrol'] ?? array() ),
262 array(
263 'panupSwitch' => 'off',
264 'panDownSwitch' => 'off',
265 'panLeftSwitch' => 'off',
266 'panRightSwitch' => 'off',
267 'panZoomInSwitch' => 'off',
268 'panZoomOutSwitch' => 'off',
269 'panFullscreenSwitch' => 'off',
270 'gyroscopeSwitch' => 'off',
271 'backToHomeSwitch' => 'off',
272 )
273 );
274
275 $gyro_enabled = isset( $postdata['gyro'] )
276 && in_array( $postdata['gyro'], array( true, 1, '1', 'on' ), true );
277 $gyro_button_enabled = function_exists( 'wpvr_isMobileDevice' )
278 && wpvr_isMobileDevice()
279 && $gyro_enabled
280 && 'on' === $custom_control['gyroscopeSwitch'];
281
282 $custom_navigation_enabled = $gyro_button_enabled;
283 foreach (
284 array(
285 'panupSwitch',
286 'panDownSwitch',
287 'panLeftSwitch',
288 'panRightSwitch',
289 'panZoomInSwitch',
290 'panZoomOutSwitch',
291 'panFullscreenSwitch',
292 'backToHomeSwitch',
293 ) as $switch
294 ) {
295 if ( 'on' === $custom_control[ $switch ] ) {
296 $custom_navigation_enabled = true;
297 break;
298 }
299 }
300
301 if ( $custom_navigation_enabled ) {
302 return $html;
303 }
304
305 $pano_id = 'pano' . absint( $id );
306 $sprites_url = esc_url( WPVR_PLUGIN_PUBLIC_DIR_URL . 'lib/pannellum/src/css/img/sprites.svg' );
307
308 $html .= '<style id="wpvr-modern-default-controls-' . esc_attr( $id ) . '">
309 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-zoom-controls.pnlm-controls {
310 display: block !important;
311 width: 28px !important;
312 height: 52px !important;
313 right: auto !important;
314 bottom: auto !important;
315 margin-top: 4px !important;
316 border: 1px solid rgba(0, 0, 0, 0.4) !important;
317 border-radius: 3px !important;
318 background-color: #fff !important;
319 background-image: none !important;
320 background-position: 0 0 !important;
321 background-repeat: repeat !important;
322 background-size: auto !important;
323 }
324
325 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-fullscreen-toggle-button {
326 display: block !important;
327 width: 28px !important;
328 height: 26px !important;
329 right: auto !important;
330 bottom: auto !important;
331 margin-top: 4px !important;
332 border: 1px solid rgba(0, 0, 0, 0.4) !important;
333 border-radius: 3px !important;
334 background-color: #fff !important;
335 background-image: url("' . $sprites_url . '") !important;
336 background-repeat: repeat !important;
337 background-size: auto !important;
338 }
339
340 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-fullscreen-toggle-button-inactive {
341 background-position: 1px -52px !important;
342 }
343
344 #et-boc .et-l #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-fullscreen-toggle-button-inactive {
345 background-position: -1px -53px !important;
346 }
347
348 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-fullscreen-toggle-button-active {
349 background-position: 0 -78px !important;
350 }
351
352 #' . esc_attr( $pano_id ) . ' .pnlm-controls-container .pnlm-control:hover {
353 background-color: #f8f8f8 !important;
354 }
355 </style>';
356
357 return $html;
358 }
359 }
360
361 add_filter( 'wpvr_generate_tour_layout_html', 'wpvr_restore_modern_layout_default_controls', 20, 3 );
362
363 if ( ! function_exists( 'wpvr_render_scene_info_row' ) ) {
364 /**
365 * Keep scene title and author metadata aligned for every tour layout.
366 *
367 * WP VR Pro can replace the Pannellum asset registered by the Free plugin and
368 * adds Modern layout CSS at priority 10. This late, tour-scoped layer keeps
369 * both Pannellum copies and both layouts consistent without modifying Pro.
370 *
371 * @param string $html Generated tour HTML.
372 * @param array $postdata Saved tour settings.
373 * @param int $id Tour post ID.
374 *
375 * @return string
376 * @since 9.0.0
377 */
378 function wpvr_render_scene_info_row( $html, $postdata, $id ) {
379 $pano_id = 'pano' . absint( $id );
380 $pano_id_json = wp_json_encode( $pano_id );
381 $by_label = wp_json_encode( __( 'By', 'wpvr' ) );
382 $tour_layout = is_array( $postdata['tourLayout'] ?? null )
383 ? ( $postdata['tourLayout']['layout'] ?? 'default' )
384 : ( $postdata['tourLayout'] ?? 'default' );
385 $is_classic_layout = wp_json_encode( 'layout1' !== $tour_layout );
386
387 $html .= '<style id="wpvr-scene-info-' . esc_attr( $id ) . '">
388 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row {
389 display: flex !important;
390 align-items: center !important;
391 justify-content: center !important;
392 gap: 10px !important;
393 box-sizing: border-box !important;
394 min-width: 0 !important;
395 overflow: hidden !important;
396 text-align: center !important;
397 z-index: 2147483647 !important;
398 -webkit-transform: translateZ(10000px) !important;
399 transform: translateZ(10000px) !important;
400 }
401
402 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row .pnlm-title-box {
403 flex: 0 1 auto !important;
404 min-width: 0 !important;
405 max-width: calc(70% - 5px) !important;
406 width: auto !important;
407 margin: 0 !important;
408 padding: 0 !important;
409 display: block !important;
410 overflow: hidden !important;
411 text-overflow: ellipsis !important;
412 white-space: nowrap !important;
413 }
414
415 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row .pnlm-author-box {
416 flex: 0 1 auto !important;
417 min-width: 0 !important;
418 max-width: calc(30% - 5px) !important;
419 margin: 0 !important;
420 border-left: 1px solid rgba(255, 255, 255, 0.45) !important;
421 padding: 0 0 0 10px !important;
422 display: block !important;
423 overflow: hidden !important;
424 line-height: 1.2 !important;
425 text-overflow: ellipsis !important;
426 white-space: nowrap !important;
427 }
428
429 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info .wpvr-author-label {
430 flex: none !important;
431 margin-right: 4px !important;
432 font-size: 10px !important;
433 font-weight: 700 !important;
434 letter-spacing: 0.06em !important;
435 opacity: 0.8 !important;
436 text-transform: uppercase !important;
437 }
438
439 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info .pnlm-author-box a {
440 color: inherit !important;
441 text-decoration: underline !important;
442 text-underline-offset: 2px !important;
443 }
444
445 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-has-title:not(.wpvr-has-author) .pnlm-title-box,
446 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-has-author:not(.wpvr-has-title) .pnlm-author-box {
447 max-width: 100% !important;
448 border-left: 0 !important;
449 padding-left: 0 !important;
450 }
451
452 #' . esc_attr( $pano_id ) . '.wpvr-layout-classic.wpvr-has-scene-info .scene-gallery.wpvr-gallery--classic {
453 bottom: calc(var(--wpvr-scene-info-height, 34px) + 8px) !important;
454 }
455
456 #' . esc_attr( $pano_id ) . '.wpvr-layout-classic.wpvr-has-scene-info .vrgcontrols {
457 bottom: calc(var(--wpvr-scene-info-height, 34px) + 4px) !important;
458 }
459
460 #' . esc_attr( $pano_id ) . '.wpvr-layout-classic.wpvr-has-scene-info .wpvr_slider_nav {
461 bottom: calc(var(--wpvr-scene-info-height, 34px) + 15px) !important;
462 }
463
464 #' . esc_attr( $pano_id ) . '.wpvr-layout-classic.wpvr-has-scene-info .controls {
465 bottom: calc(var(--wpvr-scene-info-height, 34px) + 6px) !important;
466 }
467
468 @media (max-width: 767px) {
469 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row {
470 gap: 7px !important;
471 padding-right: 10px !important;
472 padding-left: 10px !important;
473 }
474
475 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row .pnlm-title-box {
476 max-width: calc(65% - 4px) !important;
477 }
478
479 #' . esc_attr( $pano_id ) . ' .pnlm-panorama-info.wpvr-scene-info-row .pnlm-author-box {
480 max-width: calc(35% - 4px) !important;
481 padding-left: 7px !important;
482 }
483 }
484 </style>
485 <script id="wpvr-scene-info-script-' . esc_attr( $id ) . '">
486 (function () {
487 var pano = document.getElementById(' . $pano_id_json . ');
488 var byLabel = ' . $by_label . ';
489
490 if (!pano || !window.MutationObserver) {
491 return;
492 }
493
494 function addAuthorLabel(author) {
495 if (!author || !author.textContent.trim() || author.querySelector(".wpvr-author-label")) {
496 return;
497 }
498
499 var firstNode = author.firstChild;
500 if (firstNode && firstNode.nodeType === 3) {
501 var prefix = byLabel + " ";
502 if (firstNode.nodeValue.indexOf(prefix) === 0) {
503 firstNode.nodeValue = firstNode.nodeValue.slice(prefix.length);
504 }
505 }
506
507 var label = document.createElement("span");
508 label.className = "wpvr-author-label";
509 label.textContent = byLabel;
510 author.insertBefore(label, author.firstChild);
511 }
512
513 function syncSceneInfo() {
514 var info = pano.querySelector(".pnlm-panorama-info");
515 if (!info) {
516 return;
517 }
518
519 // Keep the Pannellum full-screen drag layer in its original
520 // stacking order so hotspots remain clickable. Promote only
521 // the compact metadata bar to the tour root instead.
522 if (info.parentNode !== pano) {
523 pano.appendChild(info);
524 }
525
526 var title = info.querySelector(".pnlm-title-box");
527 var author = info.querySelector(".pnlm-author-box");
528 var hasTitle = !!(title && title.textContent.trim());
529 var hasAuthor = !!(author && author.textContent.trim());
530
531 if (hasTitle) {
532 title.setAttribute("title", title.textContent.trim());
533 } else if (title) {
534 title.removeAttribute("title");
535 }
536
537 if (hasAuthor) {
538 addAuthorLabel(author);
539 var authorName = author.textContent.replace(byLabel, "").trim();
540 author.setAttribute("aria-label", byLabel + " " + authorName);
541 author.setAttribute("title", authorName);
542 } else if (author) {
543 author.removeAttribute("aria-label");
544 author.removeAttribute("title");
545 }
546
547 info.classList.toggle("wpvr-scene-info-row", hasTitle || hasAuthor);
548 info.classList.toggle("wpvr-has-title", hasTitle);
549 info.classList.toggle("wpvr-has-author", hasAuthor);
550 info.style.display = hasTitle || hasAuthor ? "flex" : "none";
551
552 var hasSceneInfo = hasTitle || hasAuthor;
553 var isClassicLayout = ' . $is_classic_layout . ';
554 pano.classList.toggle("wpvr-has-scene-info", hasSceneInfo);
555 pano.classList.toggle("wpvr-layout-classic", isClassicLayout);
556
557 if (hasSceneInfo) {
558 pano.style.setProperty("--wpvr-scene-info-height", info.offsetHeight + "px");
559 } else {
560 pano.style.removeProperty("--wpvr-scene-info-height");
561 }
562 }
563
564 var observer = new MutationObserver(syncSceneInfo);
565 observer.observe(pano, { childList: true, subtree: true, characterData: true });
566 syncSceneInfo();
567 }());
568 </script>';
569
570 return $html;
571 }
572 }
573
574 add_filter( 'wpvr_generate_tour_layout_html', 'wpvr_render_scene_info_row', 30, 3 );
575
576 if ( ! function_exists( 'wpvr_render_explainer_button' ) ) {
577 /**
578 * Render the WPVR explainer button independently.
579 *
580 * @param array|null $custom_control
581 * @param array $postdata
582 * @param bool $is_pro
583 * @param bool $autoload
584 * @param string $explainer_right
585 * @param int|string $id
586 *
587 * @return string
588 * @since 8.5.63
589 */
590 function wpvr_render_explainer_button( $custom_control, $postdata, $is_pro, $autoload, $explainer_right, $id ) {
591 $html = '';
592 $explainer_enabled = isset( $postdata['explainerSwitch'] )
593 && in_array( $postdata['explainerSwitch'], array( true, 1, '1', 'on' ), true );
594 $explainer_icon = 'fa fa-video';
595 $explainer_color = '#f7fffb';
596
597 if ( isset( $custom_control ) ) {
598 $explainer_icon = isset( $custom_control['explainerIcon'] ) ? $custom_control['explainerIcon'] : $explainer_icon;
599 $explainer_color = isset( $custom_control['explainerColor'] ) ? $custom_control['explainerColor'] : $explainer_color;
600 } elseif ( isset( $postdata['customcontrol'] ) ) {
601 $raw_control = wpvr_parse_custom_control( $postdata['customcontrol'] );
602 $explainer_icon = isset( $raw_control['explainerIcon'] ) ? $raw_control['explainerIcon'] : $explainer_icon;
603 $explainer_color = isset( $raw_control['explainerColor'] ) ? $raw_control['explainerColor'] : $explainer_color;
604 }
605
606 $pro_license_status = get_option( 'wpvr_edd_license_status' );
607 if ( $explainer_enabled && $pro_license_status === 'valid' && $is_pro ) {
608 $explainer_style = empty( $postdata['explainerContent'] )
609 ? 'pointer-events: none; opacity: 0.5;'
610 : '';
611
612 // Initial display:none to prevent flash for non-autoload tours.
613 $initial_display = ! $autoload ? 'display:none; ' : '';
614
615 $html .= '<div class="explainer_button" id="explainer_button_' . esc_attr( $id ) . '" style="' . $initial_display . 'right:' . esc_attr( $explainer_right ) . '; ' . esc_attr( $explainer_style ) . '">';
616 $html .= '<div class="ctrl" id="explainer_target_' . esc_attr( $id ) . '"><i class="' . esc_attr( $explainer_icon ) . '" style="color:' . esc_attr( $explainer_color ) . ';"></i></div>';
617 $html .= '</div>';
618 }
619
620 return $html;
621 }
622 }
623
624 // Linno telemetry integration
625 function wpvr_block()
626 {
627 wp_register_script(
628 'wpvr-block',
629 plugins_url('build/index.build.js', __FILE__),
630 array('wp-blocks', 'wp-element', 'wp-components', 'wp-editor')
631 );
632
633 if (is_admin()) {
634 wp_enqueue_style(
635 'gutyblocks/guty-block',
636 plugins_url('src/view.css', __FILE__),
637 array()
638 );
639 }
640
641
642 if (function_exists('register_block_type')) {
643 register_block_type('wpvr/wpvr-block', array(
644 'attributes' => array(
645 'id' => array(
646 'type' => 'string',
647 'default' => '0',
648 ),
649 'width' => array(
650 'type' => 'string',
651 'default' => '600',
652 ),
653 'width_unit' => array(
654 'type' => 'string',
655 'default' => 'px',
656 ),
657 'height' => array(
658 'type' => 'string',
659 'default' => '400',
660 ),
661 'height_unit' => array(
662 'type' => 'string',
663 'default' => 'px',
664 ),
665 'mobile_height' => array(
666 'type' => 'string',
667 'default' => '300',
668 ),
669 'mobile_height_unit' => array(
670 'type' => 'string',
671 'default' => 'px',
672 ),
673 'radius' => array(
674 'type' => 'string',
675 'default' => '0',
676 ),
677 'border_width' => array(
678 'type' => 'string',
679 'default' => '0px',
680 ),
681 'border_style' => array(
682 'type' => 'string',
683 'default' => 'none',
684 ),
685 'border_color' => array(
686 'type' => 'string',
687 'default' => 'none',
688 ),
689 'radius_unit' => array(
690 'type' => 'string',
691 'default' => 'px',
692 ),
693 'content' => array(
694 'type' => 'string',
695 'source' => 'html',
696 'default' => '<script> </script>'
697 ),
698 ),
699 'editor_script' => 'wpvr-block',
700 'render_callback' => 'wpvr_block_render',
701 ));
702 }
703 }
704
705 add_action('init', 'wpvr_block');
706
707 function wpvr_block_render($attributes)
708 {
709 if (isset($attributes['id'])) {
710 $id = $attributes['id'];
711 } else {
712 $id = 0;
713 }
714
715 do_action('rex_wpvr_embadded_tour', $id);
716
717 $memberpress_active = defined('MEPR_VERSION');
718 $rcp_active = is_plugin_active( 'restrict-content-pro/restrict-content-pro.php' );
719
720 if (($memberpress_active || $rcp_active ) && apply_filters('is_wpvr_pro_active', false)) {
721
722 if (!is_user_logged_in()) {
723 return esc_html__('You need to log in to access this content.', 'wpvr');
724 }
725
726 $user_id = get_current_user_id();
727 $allowed_access = false;
728
729 // Get saved membership levels from post meta
730 $allowed_membership_levels = get_post_meta($id, '_wpvr_allowed_roles_levels', true);
731 if ( isset($allowed_membership_levels) && 'none' !== $allowed_membership_levels ) {
732 if (!is_array($allowed_membership_levels)) {
733 $allowed_membership_levels = array($allowed_membership_levels);
734 }
735
736 // Check MemberPress Access
737 if ($memberpress_active) {
738 $user = new MeprUser($user_id);
739 $active_memberships = $user->active_product_subscriptions();
740 if (array_intersect($allowed_membership_levels, $active_memberships) ) {
741 $allowed_access = true;
742 }
743 }
744
745 // Check Restrict Content Pro Access
746 if ($rcp_active) {
747 $user_rcp_memberships = rcp_get_customer_memberships($user_id);
748 foreach ($user_rcp_memberships as $membership) {
749 $rcp_access_level = array(
750 $membership->get_object_id()
751 );
752 if (array_intersect($allowed_membership_levels, $rcp_access_level) ) {
753 $allowed_access = true;
754 break;
755 }
756 }
757 }
758 } else {
759 // If no membership restriction is set, allow access by default
760 $allowed_access = true;
761 }
762
763 if (!$allowed_access) {
764 return esc_html__('You do not have access to this content.', 'wpvr');
765 }
766 }
767
768
769 if (isset($attributes['width'])) {
770 $width = $attributes['width'];
771 }
772 if (isset($attributes['width_unit'])) {
773 $width_unit = $attributes['width_unit'];
774 }
775 if (isset($attributes['height'])) {
776 $height = $attributes['height'];
777 }
778 if (isset($attributes['height_unit'])) {
779 $height_unit = $attributes['height_unit'];
780 }
781 if (isset($attributes['mobile_height'])) {
782 $mobile_height = $attributes['mobile_height'];
783 }
784 if (isset($attributes['mobile_height_unit'])) {
785 $mobile_height_unit = $attributes['mobile_height_unit'];
786 }
787 if (isset($attributes['radius']) && isset($attributes['radius_unit'])) {
788 $radius = $attributes['radius'] . $attributes['radius_unit'];
789 }
790 $border_style = '';
791 if (isset($attributes['border_width'], $attributes['border_style'], $attributes['border_color'])) {
792 $border_style = $attributes['border_width'] . 'px ' . $attributes['border_style'] . ' ' . $attributes['border_color'];
793 }
794
795 if (isset($attributes['className'])) {
796 $className = $attributes['className'];
797 } else {
798 $className = '';
799 }
800 $get_post = get_post_status($id);
801 if ($get_post !== 'publish') {
802 return esc_html__('Oops! It seems like this post isn\'t published yet. Stay tuned for updates!', 'wpvr');
803 }
804 if (post_password_required($id)) {
805 return get_the_password_form();
806 }
807 $postdata = get_post_meta($id, 'panodata', true);
808 $postdata = is_array( $postdata ) ? wpvr_get_effective_panodata( $postdata ) : [];
809 $panoid = 'pano' . $id;
810 $panoid2 = 'pano2' . $id;
811 if (!isset($postdata) || empty($postdata)) {
812 return wp_kses(
813 __('Oops! It seems that you have not selected any tour yet. Please select a tour from the dropdown of WPVR block.<br>', 'wpvr'),
814 ['br' => []]
815 );
816 }
817 if (isset($postdata['streetviewdata'])) {
818 if (empty($width)) {
819 $width = '600px';
820 }
821 if (empty($height)) {
822 $height = '400px';
823 }
824 $streetviewurl = $postdata['streetviewurl'];
825 $html = '';
826 $html .= '<div class="vr-streetview ' . esc_attr( $className ) . '" style="text-align: center; max-width:100%; width:' . esc_attr( $width ) . esc_attr( $width_unit ) . '; height:' . esc_attr( $height ) . esc_attr( $height_unit ) . '; margin: 0 auto;">';
827 $html .= '<iframe src="' . esc_url( $streetviewurl ) . '" frameborder="0" style="border:0; width:100px; height:100%;" allowfullscreen=""></iframe>';
828 $html .= '</div>';
829
830 return $html;
831 }
832 $is_pro = apply_filters('is_wpvr_pro_active', false);
833
834 if (isset($postdata['vidid'])) {
835 if (empty($width)) {
836 $width = '600';
837 }
838 if (empty($height)) {
839 $height = '400';
840 }
841 $videourl = $postdata['vidurl'];
842
843 $videourl = $postdata['vidurl'];
844 $autoplay = 'off';
845 if (isset($postdata['autoplay'])) {
846 $autoplay = $postdata['autoplay'];
847 }
848 $loop = 'off';
849 if (isset($postdata['loop'])) {
850 $loop = $postdata['loop'];
851 }
852
853 if (strpos($videourl, 'youtube') > 0 || strpos($videourl, 'youtu') > 0) {
854 $explodeid = '';
855 $explodeid = explode("=", $videourl);
856 $foundid = '';
857 $muted = '&mute=1';
858
859 if ($autoplay == 'on') {
860 $autoplay = '&autoplay=1';
861 } else {
862 $autoplay = '';
863 }
864
865 if ($loop == 'on') {
866 $loop = '&loop=1';
867 } else {
868 $loop = '';
869 }
870
871 if (strpos($videourl, 'youtu') > 0) {
872 $explodeid = explode("/", $videourl);
873 $foundid = $explodeid[3] . '?' . $autoplay . $loop;
874 $expdata = $explodeid[3];
875 } else {
876 $foundid = $explodeid[1] . '?' . $autoplay . $loop;
877 $expdata = $explodeid[1];
878 }
879
880 $playlist = '&playlist=' . $expdata;
881 $playlist = str_replace("?feature=shared", "", $playlist);
882
883
884 $html = '';
885 $html .= '<div class="' . esc_attr($className) . '" style="text-align:center; max-width:100%; width:' . esc_attr($width) . esc_attr($width_unit) . '; height:' . esc_attr($height) . esc_attr($height_unit) . '; border-radius: ' . esc_attr($radius) . '; margin: 0 auto;">';
886
887 // Compatibility check script
888 $html .= '<script>
889 function wpvr_check_360_support() {
890 var support = {
891 supported: false,
892 fullySupported: false,
893 webgl: false,
894 orientation: false,
895 gyroscope: false,
896 touch: false,
897 browser: "unknown",
898 isMobile: false,
899 isIPhone: false,
900 details: []
901 };
902
903 support.isMobile = /iPhone|iPad|iPod|Android/i.test(navigator.userAgent);
904 support.isIPhone = /iPhone/i.test(navigator.userAgent);
905 if (support.isMobile) support.details.push("Mobile device detected");
906 if (support.isIPhone) support.details.push("iPhone detected");
907
908 var ua = navigator.userAgent;
909 if (/^((?!chrome|android).)*safari/i.test(ua)) {
910 support.browser = "safari";
911 support.details.push("Safari browser detected");
912 } else if (ua.indexOf("Chrome") > -1) {
913 support.browser = "chrome";
914 support.details.push("Chrome browser detected");
915 } else if (ua.indexOf("Firefox") > -1) {
916 support.browser = "firefox";
917 support.details.push("Firefox browser detected");
918 } else if (ua.indexOf("MSIE") > -1 || ua.indexOf("Trident") > -1) {
919 support.browser = "ie";
920 support.details.push("Internet Explorer detected");
921 } else if (ua.indexOf("Edge") > -1 || ua.indexOf("Edg") > -1) {
922 support.browser = "edge";
923 support.details.push("Edge browser detected");
924 } else if (ua.indexOf("Opera") > -1 || ua.indexOf("OPR") > -1) {
925 support.browser = "opera";
926 support.details.push("Opera browser detected");
927 }
928
929 try {
930 var canvas = document.createElement("canvas");
931 support.webgl = !!(window.WebGLRenderingContext &&
932 (canvas.getContext("webgl") || canvas.getContext("experimental-webgl")));
933 support.details.push(support.webgl ? "WebGL supported" : "WebGL not supported");
934 } catch (e) {
935 support.webgl = false;
936 support.details.push("WebGL detection error: " + e.message);
937 }
938
939 support.orientation = !!(window.DeviceOrientationEvent);
940 support.details.push(support.orientation ? "Device Orientation API supported" : "Device Orientation API not supported");
941
942 support.gyroscope = !!window.Gyroscope;
943 support.details.push(support.gyroscope ? "Gyroscope supported" : "Gyroscope not supported");
944
945 support.touch = "ontouchstart" in window || navigator.maxTouchPoints > 0;
946 support.details.push(support.touch ? "Touch supported" : "Touch not supported");
947
948 support.supported = support.webgl;
949 support.fullySupported = support.webgl && ((support.isMobile && support.orientation) || !support.isMobile);
950
951 if (support.browser === "safari" && support.isIPhone) {
952 support.browserWarning = "iPhone has limited support for 360 videos in browser. The experience may not be optimal.";
953 support.fullySupported = false;
954 } else if (support.browser === "ie") {
955 support.browserWarning = "Internet Explorer has limited support for 360 videos.";
956 support.fullySupported = false;
957 } else if (!support.supported) {
958 support.browserWarning = "Your browser does not support 360° videos. Use Chrome or Firefox with WebGL.";
959 }
960
961 return support;
962 }
963 </script>';
964
965 $random_id = 'video-container-' . rand(10000, 99999);
966 $html .= '<div id="' . $random_id . '-container" style="position:relative; width:100%; height:100%;">';
967
968 // Compatibility check screen (initially hidden for all, will show only for iPhone)
969 $html .= '<div id="' . $random_id . '-compatibility-check" style="position:absolute; top:0; left:0; width:100%; height:100%; display:none; flex-direction:column; justify-content:center; align-items:center; background-color:#f9f9f9; border-radius:' . esc_attr( $radius ) . ';">
970 <div style="margin-bottom:20px; text-align:center;">
971 <div class="wpvr-loading-spinner" style="border:5px solid #f3f3f3; border-top:5px solid #3498db; border-radius:50%; width:50px; height:50px; margin:0 auto 15px; animation:wpvr-spin 1s linear infinite;"></div>
972 <p style="margin:0;">Checking browser compatibility...</p>
973 </div>
974 </div>';
975
976 // Spinner animation
977 $html .= '<style>@keyframes wpvr-spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }</style>';
978
979 // Iframe (initial display set to block)
980 $html .= '<div id="' . $random_id . '-frame" class="' . esc_attr($className) . '" style="display:block; max-width:100%; width:' . esc_attr($width) . esc_attr($width_unit) . '; height:' . esc_attr($height) . esc_attr($height_unit) . '; border-radius: ' . esc_attr($radius) . '; margin: 0 auto;">';
981 $html .= '<iframe id="' . $random_id . '-iframe" src="https://www.youtube.com/embed/' . rawurlencode(sanitize_text_field($expdata)) . '?rel=0&modestbranding=1' . esc_attr($loop) . '&autohide=1' . esc_attr($muted) . '&showinfo=0&controls=1' . esc_attr($autoplay) . esc_attr($playlist) . '&enablejsapi=1" width="100%" height="100%" style="border-radius: ' . esc_attr($radius) . ';" frameborder="0" allowfullscreen allow="accelerometer; gyroscope; picture-in-picture"></iframe>';
982 $html .= '</div>';
983
984 // Permission request (mobile only)
985 $html .= '<div id="' . $random_id . '-permission-request" style="position:absolute; top:0; left:0; width:100%; height:100%; display:none; flex-direction:column; justify-content:center; align-items:center; background-color:rgba(0,0,0,0.7); color:white; text-align:center; border-radius:' . esc_attr( $radius ) . ';">';
986 $html .= '<p style="font-size:16px; margin:0 20px 15px;">For the best 360° video experience on mobile</p>';
987 $html .= '<button id="' . $random_id . '-permission-button" style="padding:10px 15px; background-color:#0085ba; color:#fff; border:none; border-radius:4px; cursor:pointer;">Allow motion and orientation access</button>';
988 $html .= '</div>';
989
990 // Browser warning
991 $html .= '<div id="' . $random_id . '-browser-warning" style="position:absolute; top:0; left:0; width:100%; height:100%; display:none; flex-direction:column; justify-content:center; align-items:center; background-color:rgba(0,0,0,0.7); color:white; text-align:center; border-radius:' . esc_attr( $radius ) . ';">';
992 $html .= '<p id="' . $random_id . '-warning-text" style="font-size:16px; margin:0 20px 5px;"></p>';
993 $html .= '<p style="font-size:14px; margin:5px 20px 15px;">For the best experience, use Chrome or Firefox.</p>';
994 $html .= '<button id="' . $random_id . '-browser-continue" style="padding:10px 15px; background-color:#0085ba; color:#fff; border:none; border-radius:4px; cursor:pointer;">Continue Anyway</button>';
995 $html .= '</div>';
996
997 // Main script
998 $html .= '<script>
999 document.addEventListener("DOMContentLoaded", function() {
1000 var supportInfo = wpvr_check_360_support();
1001 var compatibilityCheck = document.getElementById("' . $random_id . '-compatibility-check");
1002 var frameContainer = document.getElementById("' . $random_id . '-frame");
1003 var warning = document.getElementById("' . $random_id . '-browser-warning");
1004 var warningText = document.getElementById("' . $random_id . '-warning-text");
1005 var continueBtn = document.getElementById("' . $random_id . '-browser-continue");
1006
1007 // Only show compatibility check and warning for iPhone
1008 if (supportInfo.isIPhone) {
1009 // Hide the iframe initially for iPhone
1010 frameContainer.style.display = "none";
1011
1012 // Show compatibility check for iPhone
1013 compatibilityCheck.style.display = "flex";
1014
1015 // After delay, hide compatibility check and show warning
1016 setTimeout(function() {
1017 compatibilityCheck.style.display = "none";
1018 warningText.textContent = supportInfo.browserWarning || "Your browser may not fully support 360° videos.";
1019 warning.style.display = "flex";
1020
1021 continueBtn.addEventListener("click", function() {
1022 warning.style.display = "none";
1023
1024 if (supportInfo.fullySupported && supportInfo.isMobile) {
1025 document.getElementById("' . $random_id . '-permission-request").style.display = "flex";
1026 document.getElementById("' . $random_id . '-permission-button").addEventListener("click", function() {
1027 requestDevicePermissions();
1028 });
1029 } else {
1030 showVideo();
1031 }
1032 });
1033 }, 1000);
1034 } else {
1035 // For non-iPhone devices, directly initialize the player
1036 initializeYouTubePlayer();
1037 }
1038
1039 function requestDevicePermissions() {
1040 try {
1041 if (typeof DeviceOrientationEvent !== "undefined" &&
1042 typeof DeviceOrientationEvent.requestPermission === "function") {
1043 DeviceOrientationEvent.requestPermission().then(function(response) {
1044 if (response === "granted") {
1045 if (typeof DeviceMotionEvent !== "undefined" &&
1046 typeof DeviceMotionEvent.requestPermission === "function") {
1047 DeviceMotionEvent.requestPermission().then(showVideo).catch(showVideo);
1048 } else {
1049 showVideo();
1050 }
1051 } else {
1052 showVideo();
1053 }
1054 }).catch(showVideo);
1055 } else {
1056 showVideo();
1057 }
1058 } catch (e) {
1059 showVideo();
1060 }
1061 }
1062
1063 function showVideo() {
1064 document.getElementById("' . $random_id . '-permission-request").style.display = "none";
1065 frameContainer.style.display = "block";
1066 initializeYouTubePlayer();
1067 }
1068
1069 function initializeYouTubePlayer() {
1070 if (window.YT) {
1071 initPlayer();
1072 } else {
1073 var tag = document.createElement("script");
1074 tag.src = "https://www.youtube.com/iframe_api";
1075 var firstScriptTag = document.getElementsByTagName("script")[0];
1076 firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
1077 window.onYouTubeIframeAPIReady = initPlayer;
1078 }
1079
1080 function initPlayer() {
1081 new YT.Player("' . $random_id . '-iframe", {
1082 events: {
1083 "onReady": function(event) {}
1084 }
1085 });
1086 }
1087 }
1088 });
1089 </script>';
1090
1091 $html .= '</div>'; // Close container
1092 $html .= '</div>'; // Close outer wrapper
1093 } else {
1094 $html = '';
1095 $html .= '<div id="pano' . esc_attr($id) . '" class="pano-wrap ' . esc_attr($className) . '" style="max-width:100%; width:' . esc_attr($width) . esc_attr($width_unit) . '; height: ' . esc_attr($height) . esc_attr($height_unit) . '; border-radius:' . esc_attr($radius) . '; margin: 0 auto;">';
1096 $html .= '<div style="width:100%; height:100%; border-radius: ' . esc_attr($radius) . ';">' . wp_kses(
1097 $postdata['panoviddata'],
1098 array(
1099 'video' => array(
1100 'id' => array(),
1101 'class' => array(),
1102 'src' => array(),
1103 'controls' => array(),
1104 'autoplay' => array(),
1105 'loop' => array(),
1106 'muted' => array(),
1107 'poster' => array(),
1108 'preload' => array(),
1109 'width' => array(),
1110 'height' => array(),
1111 'style' => array(),
1112 'playsinline' => array(),
1113 'crossorigin' => array(),
1114 'data-*' => true,
1115 ),
1116 'source' => array(
1117 'src' => array(),
1118 'type' => array(),
1119 ),
1120 'track' => array(
1121 'kind' => array(),
1122 'src' => array(),
1123 'srclang' => array(),
1124 'label' => array(),
1125 'default' => array(),
1126 ),
1127 'div' => array(
1128 'id' => array(),
1129 'class' => array(),
1130 'style' => array(),
1131 'data-*' => true,
1132 ),
1133 'span' => array(
1134 'id' => array(),
1135 'class' => array(),
1136 'style' => array(),
1137 ),
1138 'button' => array(
1139 'id' => array(),
1140 'class' => array(),
1141 'style' => array(),
1142 'type' => array(),
1143 'title' => array(),
1144 ),
1145 )
1146 ) . '</div>';
1147
1148 $html .= '
1149 <style>
1150 .video-js {
1151 border-radius:' . esc_attr($radius) . ';
1152 }
1153 .video-js canvas{
1154 border-radius:' . esc_attr($radius) . ';
1155 }
1156 #pano' . esc_attr($id) . ' .vjs-poster {
1157 border-radius: ' . esc_attr($radius) . ';
1158 }
1159 </style>
1160
1161 ';
1162
1163 // $html .= '<script>';
1164 // $html .= 'videojs(' . $postdata['vidid'] . ', {';
1165 // $html .= 'plugins: {';
1166 // $html .= 'pannellum: {}';
1167 // $html .= '}';
1168 // $html .= '});';
1169 // $html .= '</script>';
1170 $html .= '</div>';
1171
1172 //video js vr setup //
1173 $html .= '<script>';
1174 $html .= '
1175 (function (window, videojs) {
1176 var player = window.player = videojs("' . $postdata['vidid'] . '");
1177 player.mediainfo = player.mediainfo || {};
1178 player.mediainfo.projection = "equirectangular";
1179
1180 // AUTO is the default and looks at mediainfo
1181 var vr = window.vr = player.vr({ projection: "AUTO", debug: true, forceCardboard: false, antialias: false });
1182 }(window, window.videojs));
1183
1184 ';
1185 $html .= '</script>';
1186 //video js vr end //
1187 }
1188 return $html;
1189 }
1190
1191 $control = false;
1192 if (isset($postdata['showControls'])) {
1193 $control = $postdata['showControls'];
1194 }
1195
1196 if ($control) {
1197 if (isset($postdata['customcontrol'])) {
1198 $custom_control = wpvr_parse_custom_control($postdata['customcontrol']);
1199 $custom_control = wp_parse_args($custom_control, array(
1200 'panupSwitch' => 'off',
1201 'panDownSwitch' => 'off',
1202 'panLeftSwitch' => 'off',
1203 'panRightSwitch' => 'off',
1204 'panZoomInSwitch' => 'off',
1205 'panZoomOutSwitch' => 'off',
1206 'panFullscreenSwitch' => 'off',
1207 'gyroscopeSwitch' => 'off',
1208 'backToHomeSwitch' => 'off',
1209 'explainerSwitch' => 'off',
1210 ));
1211 $gyro_enabled = isset($postdata['gyro']) && in_array($postdata['gyro'], array(true, 1, '1', 'on'), true);
1212 $custom_control['gyroSwitch'] = $gyro_enabled ? 'on' : 'off';
1213 $gyro_button_enabled = wpvr_isMobileDevice() && $custom_control['gyroSwitch'] == "on" && $custom_control['gyroscopeSwitch'] == "on";
1214 if ($custom_control['panupSwitch'] == "on" || $custom_control['panDownSwitch'] == "on" || $custom_control['panLeftSwitch'] == "on" || $custom_control['panRightSwitch'] == "on" || $custom_control['panZoomInSwitch'] == "on" || $custom_control['panZoomOutSwitch'] == "on" || $custom_control['panFullscreenSwitch'] == "on" || $gyro_button_enabled || $custom_control['backToHomeSwitch'] == "on") {
1215 $control = false;
1216 }
1217 }
1218 }
1219
1220 $floor_plan_enable = 'off';
1221 $floor_plan_image = '';
1222 if (isset($postdata['floor_plan_tour_enabler']) && $postdata['floor_plan_tour_enabler'] == 'on') {
1223 $floor_plan_enable = $postdata['floor_plan_tour_enabler'];
1224 if (isset($postdata['floor_plan_attachment_url']) && !empty($postdata['floor_plan_attachment_url'])) {
1225 $floor_plan_image = $postdata['floor_plan_attachment_url'];
1226 }
1227 }
1228
1229 $vrgallery = false;
1230 if (isset($postdata['vrgallery'])) {
1231 $vrgallery = $postdata['vrgallery'];
1232 }
1233
1234 $vrgallery_title = false;
1235 if (isset($postdata['vrgallery_title'])) {
1236 $vrgallery_title = $postdata['vrgallery_title'];
1237 }
1238
1239 $vrgallery_display = false;
1240 if (isset($postdata['vrgallery_display'])) {
1241 $vrgallery_display = $postdata['vrgallery_display'];
1242 }
1243 $vrgallery_icon_size = false;
1244 if (isset($postdata['vrgallery_icon_size'])) {
1245 $vrgallery_icon_size = $postdata['vrgallery_icon_size'];
1246 }
1247
1248 $gyro = false;
1249 $gyro_orientation = false;
1250 if (isset($postdata['gyro'])) {
1251 $gyro = in_array($postdata['gyro'], array(true, 1, '1', 'on'), true);
1252 if ($gyro && isset($postdata['deviceorientationcontrol'])) {
1253 $gyro_orientation = in_array($postdata['deviceorientationcontrol'], array(true, 1, '1', 'on'), true);
1254 }
1255 }
1256
1257 $compass = false;
1258 $audio_right = "5px";
1259 if (isset($postdata['compass'])) {
1260 $compass = $postdata['compass'] == 'on' || $postdata['compass'] != null ? true : false;
1261 if ($compass) {
1262 $audio_right = "60px";
1263 }
1264 }
1265 $floor_map_right = "25px";
1266 if ((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')) {
1267 $floor_map_right = "85px";
1268 } elseif (isset($postdata['compass']) && $postdata['compass'] == 'on') {
1269 $floor_map_right = "55px";
1270 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
1271 $floor_map_right = "25px";
1272 }
1273
1274 //===explainer handle===//
1275
1276 //===explainer handle===//
1277 $explainer_right = "10px";
1278 if ((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on') && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1279 $explainer_right = "130px";
1280 } elseif (isset($postdata['compass']) && $postdata['compass'] == 'on' && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1281 $explainer_right = "100px";
1282 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on" && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1283 $explainer_right = "55px";
1284 } elseif ((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')) {
1285 $explainer_right = "80px";
1286 } elseif (isset($postdata['compass']) && $postdata['compass'] == 'on') {
1287 $explainer_right = "55px";
1288 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
1289 $explainer_right = "30px";
1290 } elseif ($floor_plan_enable == 'on' && !empty($floor_plan_image)) {
1291 $explainer_right = "70px";
1292 }
1293 $enable_cardboard = '';
1294 $is_cardboard = get_option('wpvr_cardboard_disable');
1295 if (wpvr_isMobileDevice() && $is_cardboard == 'true') {
1296 $enable_cardboard = 'enable-cardboard';
1297 $audio_right = "73px";
1298 if (isset($postdata['compass'])) {
1299 $compass = $postdata['compass'] == 'on' || $postdata['compass'] != null ? true : false;
1300 if ($compass) {
1301 $audio_right = "130px";
1302 }
1303 }
1304
1305 $floor_map_right = "60px";
1306 if ((isset($postdata['compass']) && $postdata['compass'] == 'on') && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')) {
1307 $floor_map_right = "150px";
1308 } elseif (isset($postdata['compass']) && $postdata['compass'] == 'on') {
1309 $floor_map_right = "120px";
1310 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
1311 $floor_map_right = "90px";
1312 }
1313
1314 //===explainer handle===//
1315
1316 $explainer_right = "65px";
1317
1318 if ((isset($postdata['compass']) && $postdata['compass'] == true) && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on')) {
1319 $explainer_right = "150px";
1320 } elseif ((isset($postdata['compass']) && $postdata['compass'] == true) && (isset($postdata['bg_music']) && $postdata['bg_music'] == 'on') && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1321 $explainer_right = "180px";
1322 } elseif (isset($postdata['compass']) && $postdata['compass'] == true && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1323 $explainer_right = "150px";
1324 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on" && ($floor_plan_enable == 'on' && !empty($floor_plan_image))) {
1325 $explainer_right = "120px";
1326 } elseif (isset($postdata['compass']) && $postdata['compass'] == true) {
1327 $explainer_right = "130px";
1328 } elseif (isset($postdata['bg_music']) && $postdata['bg_music'] == "on") {
1329 $explainer_right = "90px";
1330 } elseif ($floor_plan_enable == 'on' && !empty($floor_plan_image)) {
1331 $explainer_right = "90px";
1332 }
1333 }
1334
1335 //===explainer handle===//
1336
1337 $mouseZoom = true;
1338 if (isset($postdata['mouseZoom'])) {
1339 if ($postdata['mouseZoom'] == "off") {
1340 $mouseZoom = false;
1341 } else {
1342 $mouseZoom = true;
1343 }
1344 }
1345
1346 $draggable = true;
1347 if (isset($postdata['draggable'])) {
1348 $draggable = ! in_array( $postdata['draggable'], array( 'off', 'false', false ), true );
1349 }
1350 $diskeyboard = false;
1351 if (isset($postdata['diskeyboard'])) {
1352 $diskeyboard = ! in_array( $postdata['diskeyboard'], array( 'off', 'false', false ), true );
1353 }
1354
1355 $keyboardzoom = true;
1356 if (isset($postdata['keyboardzoom'])) {
1357 $keyboardzoom = ! in_array( $postdata['keyboardzoom'], array( 'off', 'false', false ), true );
1358 }
1359
1360 $autoload = false;
1361
1362 if (isset($postdata['autoLoad'])) {
1363 $autoload = in_array( $postdata['autoLoad'], array( true, 1, '1', 'on', 'true' ), true );
1364 }
1365
1366 $default_scene = '';
1367 if (isset($postdata['defaultscene'])) {
1368 $default_scene = $postdata['defaultscene'];
1369 }
1370
1371 $preview = '';
1372 if (isset($postdata['preview'])) {
1373 $preview = $postdata['preview'];
1374 }
1375
1376 $autorotation = '';
1377 if (isset($postdata["autoRotate"])) {
1378 $autorotation = $postdata["autoRotate"];
1379 }
1380 $autorotationinactivedelay = '';
1381 if (isset($postdata["autoRotateInactivityDelay"])) {
1382 $autorotationinactivedelay = $postdata["autoRotateInactivityDelay"];
1383 }
1384 $autorotationstopdelay = '';
1385 if (isset($postdata["autoRotateStopDelay"])) {
1386 $autorotationstopdelay = $postdata["autoRotateStopDelay"];
1387 }
1388
1389 $scene_fade_duration = '';
1390 if (isset($postdata['scenefadeduration'])) {
1391 $scene_fade_duration = $postdata['scenefadeduration'];
1392 }
1393
1394 $panodata = array();
1395 if (isset($postdata['panodata'])) {
1396 $panodata = $postdata['panodata'];
1397 }
1398
1399 $show_scene_info = ( $postdata['scene-info-enabled'] ?? 'on' ) !== 'off';
1400 $tour_layout = is_array( $postdata['tourLayout'] ?? null )
1401 ? ( $postdata['tourLayout']['layout'] ?? 'default' )
1402 : ( $postdata['tourLayout'] ?? 'default' );
1403 $is_classic_layout = 'layout1' !== $tour_layout;
1404
1405 $default_zoom_global = 100;
1406 if (isset($postdata['hfov']) && $postdata['hfov'] != '') {
1407 $default_zoom_global = $postdata['hfov'];
1408 }
1409
1410 $min_zoom_global = 50;
1411 if (isset($postdata['minHfov']) && $postdata['minHfov'] != '') {
1412 $min_zoom_global = $postdata['minHfov'];
1413 }
1414
1415 $max_zoom_global = 120;
1416 if (isset($postdata['maxHfov']) && $postdata['maxHfov'] != '') {
1417 $max_zoom_global = $postdata['maxHfov'];
1418 }
1419
1420 $hotspoticoncolor = '#00b4ff';
1421 $hotspotblink = 'on';
1422 $default_data = array();
1423 $default_data = array('firstScene' => $default_scene, 'sceneFadeDuration' => $scene_fade_duration, 'hfov' => $default_zoom_global, 'maxHfov' => $max_zoom_global, 'minHfov' => $min_zoom_global);
1424 $scene_data = array();
1425 if (is_array($panodata) && isset($panodata['scene-list'])) {
1426 if (!empty($panodata['scene-list'])) {
1427 foreach ($panodata['scene-list'] as $panoscenes) {
1428 $scene_ititle = '';
1429 if (isset($panoscenes["scene-ititle"])) {
1430 $scene_ititle = esc_html($panoscenes["scene-ititle"]);
1431 }
1432
1433 $scene_author = '';
1434 if (isset($panoscenes["scene-author"])) {
1435 $scene_author = esc_html($panoscenes["scene-author"]);
1436 }
1437
1438 $scene_author_url = '';
1439 if (isset($panoscenes["scene-author-url"])) {
1440 $scene_author_url = sanitize_text_field($panoscenes["scene-author-url"]);
1441 }
1442
1443 $scene_vaov = 180;
1444 if (isset($panoscenes["scene-vaov"])) {
1445 $scene_vaov = (float)$panoscenes["scene-vaov"];
1446 }
1447
1448 $scene_haov = 360;
1449 if (isset($panoscenes["scene-haov"])) {
1450 $scene_haov = (float)$panoscenes["scene-haov"];
1451 }
1452
1453 $scene_vertical_offset = 0;
1454 if (isset($panoscenes["scene-vertical-offset"])) {
1455 $scene_vertical_offset = (float)$panoscenes["scene-vertical-offset"];
1456 }
1457
1458 $default_scene_pitch = null;
1459 if (isset($panoscenes["scene-pitch"])) {
1460 $default_scene_pitch = (float)$panoscenes["scene-pitch"];
1461 }
1462
1463 $default_scene_yaw = null;
1464 if (isset($panoscenes["scene-yaw"])) {
1465 $default_scene_yaw = (float)$panoscenes["scene-yaw"];
1466 }
1467
1468 $scene_max_pitch = '';
1469 if (isset($panoscenes["scene-maxpitch"])) {
1470 $scene_max_pitch = (float)$panoscenes["scene-maxpitch"];
1471 }
1472
1473
1474 $scene_min_pitch = '';
1475 if (isset($panoscenes["scene-minpitch"])) {
1476 $scene_min_pitch = (float)$panoscenes["scene-minpitch"];
1477 }
1478
1479
1480 $scene_max_yaw = '';
1481 if (isset($panoscenes["scene-maxyaw"])) {
1482 $scene_max_yaw = (float)$panoscenes["scene-maxyaw"];
1483 }
1484
1485
1486 $scene_min_yaw = '';
1487 if (isset($panoscenes["scene-minyaw"])) {
1488 $scene_min_yaw = (float)$panoscenes["scene-minyaw"];
1489 }
1490
1491 $default_zoom = 100;
1492 if (isset($panoscenes["scene-zoom"]) && $panoscenes["scene-zoom"] != '') {
1493 $default_zoom = (int)$panoscenes["scene-zoom"];
1494 } else {
1495 if ($default_zoom_global != '') {
1496 $default_zoom = (int)$default_zoom_global;
1497 }
1498 }
1499
1500
1501 $max_zoom = 120;
1502 if (isset($panoscenes["scene-maxzoom"]) && $panoscenes["scene-maxzoom"] != '') {
1503 $max_zoom = (int)$panoscenes["scene-maxzoom"];
1504 } else {
1505 if ($max_zoom_global != '') {
1506 $max_zoom = (int)$max_zoom_global;
1507 }
1508 }
1509
1510 $min_zoom = 120;
1511 if (isset($panoscenes["scene-minzoom"]) && $panoscenes["scene-minzoom"] != '') {
1512 $min_zoom = (int)$panoscenes["scene-minzoom"];
1513 } else {
1514 if ($min_zoom_global != '') {
1515 $min_zoom = (int)$min_zoom_global;
1516 }
1517 }
1518
1519 $hotspot_datas = array();
1520 if (isset($panoscenes['hotspot-list'])) {
1521 $hotspot_datas = $panoscenes['hotspot-list'];
1522 }
1523
1524 $hotspots = array();
1525
1526 foreach ($hotspot_datas as $hotspot_data) {
1527 $status = get_option('wpvr_edd_license_status');
1528 if ($status !== false && $status == 'valid') {
1529
1530 if (isset($hotspot_data["hotspot-customclass-pro"]) && $hotspot_data["hotspot-customclass-pro"] != 'none') {
1531 $hotspot_data['hotspot-customclass'] = $hotspot_data["hotspot-customclass-pro"] . ' custom-' . $id . '-' . $panoscenes['scene-id'] . '-' . $hotspot_data['hotspot-title'];
1532 }
1533 if (isset($hotspot_data['hotspot-blink'])) {
1534 $hotspotblink = $hotspot_data['hotspot-blink'];
1535 }
1536 }
1537 $hotspot_scene_pitch = '';
1538 if (isset($hotspot_data["hotspot-scene-pitch"])) {
1539 $hotspot_scene_pitch = $hotspot_data["hotspot-scene-pitch"];
1540 }
1541 $hotspot_scene_yaw = '';
1542 if (isset($hotspot_data["hotspot-scene-yaw"])) {
1543 $hotspot_scene_yaw = $hotspot_data["hotspot-scene-yaw"];
1544 }
1545
1546 $hotspot_type = $hotspot_data["hotspot-type"] !== 'scene' ? 'info' : $hotspot_data["hotspot-type"];
1547 $hotspot_content = '';
1548
1549 ob_start();
1550 do_action('wpvr_hotspot_content', $hotspot_data);
1551 $hotspot_content = ob_get_clean();
1552
1553 if (!$hotspot_content) {
1554 $hotspot_content = $hotspot_data["hotspot-content"];
1555 }
1556
1557 if (isset($hotspot_data["wpvr_url_open"][0])) {
1558 $wpvr_url_open = $hotspot_data["wpvr_url_open"][0];
1559 } else {
1560 $wpvr_url_open = "off";
1561 }
1562 $on_hover_content = preg_replace_callback(
1563 '/<p>\s*(<img[^>]*>)\s*<br>\s*<\/p>/i',
1564 function ($matches) {
1565 return $matches[1];
1566 },
1567 $hotspot_data['hotspot-hover'] ?? ''
1568 );
1569
1570 if('fluent_form' !== $hotspot_data["hotspot-type"]){
1571 $on_hover_content = sanitize_content_preserve_styles($on_hover_content ?? '');
1572 $on_click_content = preg_replace_callback('/<img[^>]*>/', "replace_callback", $hotspot_content ?? '');
1573 $on_click_content = sanitize_content_preserve_styles($on_click_content ?? '');
1574 }else{
1575 $on_hover_content = $on_hover_content ?? '';
1576 $on_click_content = $hotspot_content ?? '';
1577 }
1578
1579
1580 // Shape is independent of the optional custom icon in the
1581 // new editor, so it must always be included in the public
1582 // hotspot configuration.
1583 $hotspot_shape = isset( $hotspot_data['hotspot-shape'] )
1584 && in_array( $hotspot_data['hotspot-shape'], [ 'round', 'square', 'hexagon' ], true )
1585 ? $hotspot_data['hotspot-shape']
1586 : 'round';
1587
1588 $hotspot_data_for_on_click=[];
1589 if( ('info' === $hotspot_type || 'fluent_form' === $hotspot_data["hotspot-type"] ) && !empty($on_click_content)){
1590 $hotspot_data_for_on_click = [
1591 'on_click_content' => $on_click_content,
1592 'tour_id' => $id,
1593 'scene_id' => $panoscenes['scene-id'],
1594 'hotspot_id' => sanitize_html_class($hotspot_data['hotspot-title']),
1595 ];
1596 } elseif('info' === $hotspot_type && !empty($hotspot_data["hotspot-url"])){
1597 $hotspot_data_for_on_click = [
1598 'on_click_content' => '',
1599 'tour_id' => $id,
1600 'scene_id' => $panoscenes['scene-id'],
1601 'hotspot_id' => sanitize_html_class($hotspot_data['hotspot-title']),
1602 ];
1603 }
1604
1605 $hotspot_info = array(
1606 'text' => esc_html(sanitize_text_field($hotspot_data['hotspot-title'])),
1607 'pitch' => $hotspot_data['hotspot-pitch'],
1608 'yaw' => $hotspot_data['hotspot-yaw'],
1609 'type' => $hotspot_type,
1610 'cssClass' => $hotspot_data['hotspot-customclass'],
1611 'URL' => $hotspot_data['hotspot-url'],
1612 "wpvr_url_open" => $wpvr_url_open,
1613 "clickHandlerArgs" => $hotspot_data_for_on_click,
1614 'createTooltipArgs' => !empty(trim($on_hover_content)) ? trim($on_hover_content) : '',
1615 "sceneId" => $hotspot_data["hotspot-scene"],
1616 "targetPitch" => (float)$hotspot_scene_pitch,
1617 "targetYaw" => (float)$hotspot_scene_yaw,
1618 'hotspot_type' => $hotspot_data['hotspot-type'],
1619 'hotspot_shape' => $hotspot_shape,
1620 );
1621
1622 $hotspot_info['URL'] = ($hotspot_data['hotspot-type'] === 'fluent_form' || $hotspot_data['hotspot-type'] === 'wc_product') ? '' : $hotspot_info['URL'];
1623
1624 if ($hotspot_data["hotspot-customclass"] == 'none' || $hotspot_data["hotspot-customclass"] == '') {
1625 unset($hotspot_info["cssClass"]);
1626 }
1627 if (empty($hotspot_data["hotspot-scene"])) {
1628 unset($hotspot_info['targetPitch']);
1629 unset($hotspot_info['targetYaw']);
1630 }
1631 array_push($hotspots, $hotspot_info);
1632 }
1633
1634 $device_scene = $panoscenes['scene-attachment-url'];
1635 $mobile_media_resize = get_option('mobile_media_resize');
1636 $file_accessible = ini_get('allow_url_fopen');
1637 if ($mobile_media_resize == "true" && $device_scene) {
1638 if ($file_accessible == "1") {
1639 $image_info = getimagesize($device_scene);
1640 if ($image_info && $image_info[0] > 4096) {
1641 $src_to_id_for_mobile = '';
1642 $src_to_id_for_desktop = '';
1643 if (wpvr_isMobileDevice()) {
1644 $src_to_id_for_mobile = attachment_url_to_postid($panoscenes['scene-attachment-url']);
1645 if ($src_to_id_for_mobile) {
1646 $mobile_scene = wp_get_attachment_image_src($src_to_id_for_mobile, 'wpvr_mobile');
1647 if ($mobile_scene[3]) {
1648 $device_scene = $mobile_scene[0];
1649 }
1650 }
1651 } else {
1652 $src_to_id_for_desktop = attachment_url_to_postid($panoscenes['scene-attachment-url']);
1653 if ($src_to_id_for_desktop) {
1654 $desktop_scene = wp_get_attachment_image_src($src_to_id_for_mobile, 'full');
1655 if ($desktop_scene && $desktop_scene[0]) {
1656 $device_scene = $desktop_scene[0];
1657 }
1658 }
1659 }
1660 }
1661 }
1662 }
1663
1664 $scene_info = array();
1665
1666 if ($panoscenes["scene-type"] == 'cubemap') {
1667 $pano_type = 'cubemap';
1668 $pano_attachment = array(
1669 $panoscenes["scene-attachment-url-face0"],
1670 $panoscenes["scene-attachment-url-face1"],
1671 $panoscenes["scene-attachment-url-face2"],
1672 $panoscenes["scene-attachment-url-face3"],
1673 $panoscenes["scene-attachment-url-face4"],
1674 $panoscenes["scene-attachment-url-face5"]
1675 );
1676
1677 $scene_info = array('type' => $panoscenes['scene-type'], 'cubeMap' => $pano_attachment, "pitch" => $default_scene_pitch, "maxPitch" => $scene_max_pitch, "minPitch" => $scene_min_pitch, "maxYaw" => $scene_max_yaw, "minYaw" => $scene_min_yaw, "yaw" => $default_scene_yaw, "hfov" => $default_zoom, "maxHfov" => $max_zoom, "minHfov" => $min_zoom, "title" => $scene_ititle, "author" => $scene_author, "authorURL" => $scene_author_url, "vaov" => $scene_vaov, "haov" => $scene_haov, "vOffset" => $scene_vertical_offset, 'hotSpots' => $hotspots);
1678 } else {
1679 $scene_info = array('type' => $panoscenes['scene-type'], 'panorama' => $device_scene, "pitch" => $default_scene_pitch, "maxPitch" => $scene_max_pitch, "minPitch" => $scene_min_pitch, "maxYaw" => $scene_max_yaw, "minYaw" => $scene_min_yaw, "yaw" => $default_scene_yaw, "hfov" => $default_zoom, "maxHfov" => $max_zoom, "minHfov" => $min_zoom, "title" => $scene_ititle, "author" => $scene_author, "authorURL" => $scene_author_url, "vaov" => $scene_vaov, "haov" => $scene_haov, "vOffset" => $scene_vertical_offset, 'hotSpots' => $hotspots);
1680 }
1681
1682
1683
1684 if (isset($panoscenes["ptyscene"])) {
1685 if ($panoscenes["ptyscene"] == "off") {
1686 unset($scene_info['pitch']);
1687 unset($scene_info['yaw']);
1688 }
1689 }
1690
1691 if (!$show_scene_info || empty($panoscenes["scene-ititle"])) {
1692 unset($scene_info['title']);
1693 }
1694 if (!$show_scene_info || empty($panoscenes["scene-author"])) {
1695 unset($scene_info['author']);
1696 }
1697 if (!$show_scene_info || empty($panoscenes["scene-author-url"])) {
1698 unset($scene_info['authorURL']);
1699 }
1700
1701 if (empty($scene_vaov)) {
1702 unset($scene_info['vaov']);
1703 }
1704
1705 if (empty($scene_haov)) {
1706 unset($scene_info['haov']);
1707 }
1708
1709 if (empty($scene_vertical_offset)) {
1710 unset($scene_info['vOffset']);
1711 }
1712
1713 if (isset($panoscenes["cvgscene"])) {
1714 if ($panoscenes["cvgscene"] == "off") {
1715 unset($scene_info['maxPitch']);
1716 unset($scene_info['minPitch']);
1717 }
1718 }
1719 if (empty($panoscenes["scene-maxpitch"])) {
1720 unset($scene_info['maxPitch']);
1721 }
1722
1723 if (empty($panoscenes["scene-minpitch"])) {
1724 unset($scene_info['minPitch']);
1725 }
1726
1727 if (isset($panoscenes["chgscene"])) {
1728 if ($panoscenes["chgscene"] == "off") {
1729 unset($scene_info['maxYaw']);
1730 unset($scene_info['minYaw']);
1731 }
1732 }
1733 if (empty($panoscenes["scene-maxyaw"])) {
1734 unset($scene_info['maxYaw']);
1735 }
1736
1737 if (empty($panoscenes["scene-minyaw"])) {
1738 unset($scene_info['minYaw']);
1739 }
1740
1741 // if (isset($panoscenes["czscene"])) {
1742 // if ($panoscenes["czscene"] == "off") {
1743 // unset($scene_info['hfov']);
1744 // unset($scene_info['maxHfov']);
1745 // unset($scene_info['minHfov']);
1746 // }
1747 // }
1748
1749 $scene_array = array();
1750 $scene_array = array(
1751 $panoscenes['scene-id'] => $scene_info
1752 );
1753
1754 $scene_data[$panoscenes['scene-id']] = $scene_info;
1755 }
1756 }
1757 }
1758 $pano_id_array = array();
1759 $pano_id_array = array('panoid' => $panoid);
1760 $pano_response = array();
1761 $pano_response = array('autoLoad' => $autoload, 'showControls' => $control, 'compass' => $compass, 'orientationOnByDefault' => $gyro_orientation, 'mouseZoom' => $mouseZoom, 'draggable' => $draggable, 'disableKeyboardCtrl' => $diskeyboard, 'keyboardZoom' => $keyboardzoom, "preview" => $preview, "autoRotate" => $autorotation, "autoRotateInactivityDelay" => $autorotationinactivedelay, "autoRotateStopDelay" => $autorotationstopdelay, 'default' => $default_data, 'scenes' => $scene_data);
1762 if (empty($autorotation)) {
1763 unset($pano_response['autoRotate']);
1764 unset($pano_response['autoRotateInactivityDelay']);
1765 unset($pano_response['autoRotateStopDelay']);
1766 }
1767 if (empty($autorotationinactivedelay)) {
1768 unset($pano_response['autoRotateInactivityDelay']);
1769 }
1770 if (empty($autorotationstopdelay)) {
1771 unset($pano_response['autoRotateStopDelay']);
1772 }
1773
1774 $response = array();
1775 $response = array($pano_id_array, $pano_response);
1776 if (!empty($response)) {
1777 $response = json_encode($response);
1778 }
1779 if (empty($width)) {
1780 $width = '600';
1781 }
1782 if (empty($height)) {
1783 $height = '400';
1784 }
1785 if ('fullwidth' == $width) {
1786 $width = "100%";
1787 }
1788
1789 $foreground_color = '#fff';
1790 $pulse_color = wpvr_hex2rgb($hotspoticoncolor);
1791 $rgb = wpvr_HTMLToRGB($hotspoticoncolor);
1792 $hsl = wpvr_RGBToHSL($rgb);
1793 if ($hsl->lightness > 200) {
1794 $foreground_color = '#000000';
1795 } else {
1796 $foreground_color = '#fff';
1797 }
1798
1799 $class = 'myclass';
1800 $html = 'test';
1801 $html = '';
1802 $html .= '<style>';
1803 if ($width == 'embed') {
1804 $html .= 'body{
1805 overflow: hidden;
1806 }';
1807 }
1808 $status = get_option('wpvr_edd_license_status');
1809 if ($status !== false && $status == 'valid') {
1810 if (isset($postdata['customcss_enable']) && $postdata['customcss_enable'] == 'on') {
1811 $html .= isset($postdata['customcss']) ? $postdata['customcss'] : '';
1812 }
1813 }
1814 if ($status !== false && $status == 'valid') {
1815 if (is_array($panodata) && isset($panodata['scene-list'])) {
1816 foreach ($panodata['scene-list'] as $panoscenes) {
1817
1818 foreach ($panoscenes['hotspot-list'] as $hotspot) {
1819 if (isset($hotspot['hotspot-customclass-color-icon-value']) && !empty($hotspot['hotspot-customclass-color-icon-value'])) {
1820 $hotspoticoncolor = $hotspot['hotspot-customclass-color-icon-value'];
1821 } else {
1822 $hotspoticoncolor = "#00b4ff";
1823 }
1824 $hotspot_border = '';
1825 if(isset($hotspot['hotspot-border']) && $hotspot['hotspot-border'] == 'on'){
1826 $border_width = $hotspot['hotspot-border-width'];
1827 $border_color = $hotspot['hotspot-border-color'];
1828 $border_style = $hotspot['hotspot-border-style'];
1829
1830 $hotspot_border = 'border: '.$border_width.'px '.$border_style.' '.$border_color.';';
1831 }
1832 $hotspot_background_color = 'background-color: ' . $hotspoticoncolor . ';';
1833 $hotspot_animation = ' animation: icon-pulse' . $panoid . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' 1.5s infinite cubic-bezier(.25, 0, 0, 1);
1834 '. $hotspot_border.'';
1835
1836
1837 $pulse_color = wpvr_hex2rgb($hotspoticoncolor);
1838 if (isset($hotspot["hotspot-customclass-pro"]) && $hotspot["hotspot-customclass-pro"] != 'none') {
1839 $border_radius = ' border-radius: 100%;';
1840 $hotspot_shape = isset($hotspot["hotspot-shape"]) ? $hotspot["hotspot-shape"] : 'round';
1841 if($hotspot_shape === 'square'){
1842 $border_radius = '';
1843 }
1844 if ($hotspot_shape === 'hexagon') {
1845 $border_radius = '';
1846 $hotspot_background_color = 'background-color: transparent;';
1847 $hotspot_animation = '';
1848 }
1849
1850 if(isset($hotspot['hotspot-custom-icon-color-value']) && !empty($hotspot['hotspot-custom-icon-color-value'])){
1851 $foreground_color = $hotspot['hotspot-custom-icon-color-value'];
1852 }
1853 $html .= '#' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.fas.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1854 #' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.fab.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1855 #' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.fa.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1856 #' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.fa-solid.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1857 #' . esc_attr( $panoid ). ' div.pnlm-hotspot-base.far.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' {
1858 display: block !important;
1859 '.$hotspot_background_color.'
1860 color: ' . $foreground_color . ';
1861 '.$border_radius.'
1862 width: 30px;
1863 height: 30px;
1864 font-size: 16px;
1865 line-height: 30px;
1866 '.$hotspot_animation.'
1867 }';
1868 if($hotspot_shape === 'hexagon'){
1869
1870 $html .= '#' . esc_attr( $panoid ) . ' .custom-' . esc_attr( $id ) . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' .hexagon-wrapper svg path {
1871 fill: ' . $hotspoticoncolor . ';
1872 }';
1873
1874 $html .= '#' . esc_attr( $panoid ) . ' .custom-' . esc_attr( $id ) . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . '.pnlm-tooltip:after{
1875 content: "";
1876 position: absolute;
1877 left: 50%;
1878 top: 50%;
1879 transform: translate(-50%, -50%);
1880 width: 85%;
1881 height: 85%;
1882 animation: icon-pulse' . esc_attr( $panoid ) . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' 1.5s infinite cubic-bezier(.25, 0, 0, 1);
1883 border-radius: 100%;
1884 z-index: -2;
1885 }';
1886
1887 }
1888 $html .= '#' . esc_attr( $panoid2 ). ' div.pnlm-hotspot-base.fas.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1889 #' . esc_attr( $panoid2 ). ' div.pnlm-hotspot-base.fab.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1890 #' . esc_attr( $panoid2 ). ' div.pnlm-hotspot-base.fa-solid.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1891 #' . esc_attr( $panoid2) . ' div.pnlm-hotspot-base.fa.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ',
1892 #' . esc_attr( $panoid2 ). ' div.pnlm-hotspot-base.far.custom-' . esc_attr( $id ). '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' {
1893 display: block !important;
1894 '.esc_attr( $hotspot_background_color).'
1895 color: ' . esc_attr( $foreground_color) . ';
1896 '.esc_attr( $border_radius).'
1897 width: 30px;
1898 height: 30px;
1899 font-size: 16px;
1900 line-height: 30px;
1901 '.esc_attr( $hotspot_animation).'
1902 }';
1903 }
1904 if (isset($hotspot['hotspot-blink'])) {
1905 $hotspotblink = $hotspot['hotspot-blink'];
1906 if ($hotspotblink == 'on') {
1907 $html .= '@-webkit-keyframes icon-pulse' . esc_attr( $panoid) . '-' . $panoscenes['scene-id'] . '-' . sanitize_html_class($hotspot['hotspot-title']) . ' {
1908 0% {
1909 box-shadow: 0 0 0 0px rgba(' . esc_attr( $pulse_color[0]) . ', 1);
1910 }
1911 100% {
1912 box-shadow: 0 0 0 10px rgba(' . esc_attr( $pulse_color[0]) . ', 0);
1913 }
1914 }
1915 @keyframes icon-pulse' . esc_attr( $panoid) . ' {
1916 0% {
1917 box-shadow: 0 0 0 0px rgba(' . esc_attr( $pulse_color[0]) . ', 1);)
1918 }
1919 100% {
1920 box-shadow: 0 0 0 10px rgba(' . esc_attr( $pulse_color[0] ). ', 0);
1921 }
1922 }';
1923 }
1924 }
1925 }
1926 }
1927 }
1928 }
1929
1930 $status = get_option('wpvr_edd_license_status');
1931 if ($status !== false && $status == 'valid') {
1932 if (!$gyro) {
1933 $html .= '#' . esc_attr( $panoid ). ' div.pnlm-orientation-button {
1934 display: none;
1935 }';
1936 }
1937 } else {
1938 $html .= '#' . esc_attr( $panoid ). ' div.pnlm-orientation-button {
1939 display: none;
1940 }';
1941 }
1942 $floor_plan_custom_color = isset($postdata['floor_plan_custom_color']) ? $postdata['floor_plan_custom_color'] : '#cca92c';
1943 $foreground_color_pointer = '#fff';
1944 if ($floor_plan_custom_color != '') {
1945 $pointer_pulse = wpvr_hex2rgb($floor_plan_custom_color);
1946 $floor_rgb = wpvr_HTMLToRGB($floor_plan_custom_color);
1947 $floor_hsl = wpvr_RGBToHSL($floor_rgb);
1948 if ($floor_hsl->lightness > 200) {
1949 $foreground_color_pointer = '#000000';
1950 }
1951 $html .= '
1952 .wpvr-floor-map .floor-plan-pointer.add-pulse:before {
1953 border: 17px solid ' . esc_attr( $floor_plan_custom_color ) . ';
1954 }
1955 @-webkit-keyframes pulse {
1956 0% {
1957 -webkit-box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0.7);
1958 }
1959 70% {
1960 -webkit-box-shadow: 0 0 0 10px rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1961 }
1962 100% {
1963 -webkit-box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1964 }
1965 }
1966 @keyframes pulse {
1967 0% {
1968 -moz-box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0.7);
1969 box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0.7);
1970 }
1971 70% {
1972 -moz-box-shadow: 0 0 0 10px rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1973 box-shadow: 0 0 0 10px rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1974 }
1975 100% {
1976 -moz-box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1977 box-shadow: 0 0 0 0 rgba(' . esc_attr( $pointer_pulse[0] ) . ', 0);
1978 }
1979 }';
1980 }
1981 $html .= '</style>';
1982
1983 $scene_animation = isset($postdata['sceneAnimation']) ? $postdata['sceneAnimation'] : 'off';
1984 $scene_animation_enabled = in_array( $scene_animation, array( 'on', '1', 1, true ), true );
1985
1986 if( $scene_animation_enabled && is_plugin_active( 'wpvr-pro/wpvr-pro.php' ) ) {
1987 $animation_type = isset($postdata['sceneAnimationName']) ? $postdata['sceneAnimationName'] : 'none';
1988 $animation_type = $animation_type === 'fade' ? 'fade_in' : $animation_type;
1989 $animationDuration = isset($postdata['sceneAnimationTransitionDuration']) ? $postdata['sceneAnimationTransitionDuration'] : '500ms';
1990 $animationDelay = isset($postdata['sceneAnimationTransitionDelay']) ? $postdata['sceneAnimationTransitionDelay'] : '0ms';
1991 $animation_css = apply_filters('wpvr_tour_scene_animation',$animation_type,$animationDuration, $animationDelay, $postdata,$id);
1992 $html .= $animation_css;
1993 }
1994
1995 if (wpvr_isMobileDevice()) {
1996 $html .= '<div id="master-container" class="wpvr-cardboard ' . esc_attr( $className ) . ' ' . esc_attr( $enable_cardboard ) . ' " style="max-width:' . esc_attr( $width ) . esc_attr( $width_unit ) . '; width: 100%; height: ' . esc_attr( $mobile_height ) . esc_attr( $mobile_height_unit ) . '; border-radius:' . esc_attr( $radius ) . '; direction:ltr; border : ' . esc_attr( $border_style ) . ' ">';
1997 } else {
1998 $html .= '<div id="master-container" class="wpvr-cardboard ' . esc_attr( $className ) . ' ' . esc_attr( $enable_cardboard ) . '" style="max-width:' . esc_attr( $width ) . esc_attr( $width_unit ) . '; width: 100%; height: ' . esc_attr( $height ) . esc_attr( $height_unit ) . '; border-radius:' . esc_attr( $radius ) . '; direction:ltr; border : ' . esc_attr( $border_style ) . '">';
1999 }
2000 $status = get_option('wpvr_edd_license_status');
2001 $is_cardboard = get_option('wpvr_cardboard_disable');
2002 if ($status !== false && 'valid' == $status && $is_pro && wpvr_isMobileDevice() && $is_cardboard == 'true') {
2003 $html .= '<button class="fullscreen-button">';
2004 $html .= '<span class="expand">';
2005 $html .= '<i class="fas fa-expand" aria-hidden="true"></i>';
2006 $html .= '</span>';
2007
2008 $html .= '<span class="compress">';
2009 $html .= '<i class="fas fa-minimize" aria-hidden="true"></i>';
2010 $html .= '</span>';
2011 $html .= '</button>';
2012 $html .= '<label class="wpvr-cardboard-switcher">
2013 <input type="checkbox" class="vr_mode_change' . $id . '" name="vr_mode_change" value="off">
2014 <span class="switcher-box">
2015 <span class="normal-mode-tooltip">Normal VR Mode</span>
2016 <svg width="78" height="60" viewBox="0 0 78 60" fill="none" xmlns="http://www.w3.org/2000/svg">
2017 <path d="M42.25 21.4286C42.25 22.2811 41.9076 23.0986 41.2981 23.7014C40.6886 24.3042 39.862 24.6429 39 24.6429C38.138 24.6429 37.3114 24.3042 36.7019 23.7014C36.0924 23.0986 35.75 22.2811 35.75 21.4286C35.75 20.5761 36.0924 19.7585 36.7019 19.1557C37.3114 18.5529 38.138 18.2143 39 18.2143C39.862 18.2143 40.6886 18.5529 41.2981 19.1557C41.9076 19.7585 42.25 20.5761 42.25 21.4286ZM19.5 30C18.9254 30 18.3743 30.2258 17.9679 30.6276C17.5616 31.0295 17.3333 31.5745 17.3333 32.1429C17.3333 32.7112 17.5616 33.2562 17.9679 33.6581C18.3743 34.06 18.9254 34.2857 19.5 34.2857H28.1667C28.7413 34.2857 29.2924 34.06 29.6987 33.6581C30.1051 33.2562 30.3333 32.7112 30.3333 32.1429C30.3333 31.5745 30.1051 31.0295 29.6987 30.6276C29.2924 30.2258 28.7413 30 28.1667 30H19.5ZM47.6667 32.1429C47.6667 31.5745 47.8949 31.0295 48.3013 30.6276C48.7076 30.2258 49.2587 30 49.8333 30H58.5C59.0746 30 59.6257 30.2258 60.0321 30.6276C60.4384 31.0295 60.6667 31.5745 60.6667 32.1429C60.6667 32.7112 60.4384 33.2562 60.0321 33.6581C59.6257 34.06 59.0746 34.2857 58.5 34.2857H49.8333C49.2587 34.2857 48.7076 34.06 48.3013 33.6581C47.8949 33.2562 47.6667 32.7112 47.6667 32.1429ZM32.5 0C31.9254 0 31.3743 0.225765 30.9679 0.627629C30.5616 1.02949 30.3333 1.57454 30.3333 2.14286V8.57143H18.4167C14.8693 8.57183 11.4528 9.89617 8.84994 12.2798C6.24706 14.6634 4.64954 17.9306 4.37667 21.4286H2.16667C1.59203 21.4286 1.04093 21.6543 0.634602 22.0562C0.228273 22.4581 0 23.0031 0 23.5714V36.4286C0 36.9969 0.228273 37.5419 0.634602 37.9438C1.04093 38.3457 1.59203 38.5714 2.16667 38.5714H4.33333V46.0714C4.33333 49.7655 5.81711 53.3083 8.45825 55.9204C11.0994 58.5325 14.6815 60 18.4167 60H25.3933C29.1269 59.9986 32.7071 58.5311 35.347 55.92L37.921 53.3786C38.0618 53.2393 38.229 53.1288 38.4131 53.0534C38.5971 52.978 38.7943 52.9392 38.9935 52.9392C39.1927 52.9392 39.3899 52.978 39.5739 53.0534C39.758 53.1288 39.9252 53.2393 40.066 53.3786L42.6357 55.92C45.2766 58.5322 48.8586 59.9998 52.5937 60H59.5833C63.3185 60 66.9006 58.5325 69.5418 55.9204C72.1829 53.3083 73.6667 49.7655 73.6667 46.0714V38.5714H75.8333C76.408 38.5714 76.9591 38.3457 77.3654 37.9438C77.7717 37.5419 78 36.9969 78 36.4286V23.5714C78 23.0031 77.7717 22.4581 77.3654 22.0562C76.9591 21.6543 76.408 21.4286 75.8333 21.4286H73.6233C73.3505 17.9306 71.753 14.6634 69.1501 12.2798C66.5472 9.89617 63.1307 8.57183 59.5833 8.57143H47.6667V2.14286C47.6667 1.57454 47.4384 1.02949 47.0321 0.627629C46.6257 0.225765 46.0746 0 45.5 0H32.5ZM69.3333 22.5V46.0714C69.3333 48.6289 68.3061 51.0816 66.4776 52.89C64.6491 54.6983 62.1692 55.7143 59.5833 55.7143H52.5937C50.0093 55.7132 47.5311 54.6973 45.7037 52.89L43.1297 50.3486C42.5864 49.8108 41.9413 49.3842 41.2312 49.0931C40.5211 48.8021 39.76 48.6522 38.9913 48.6522C38.2227 48.6522 37.4616 48.8021 36.7515 49.0931C36.0414 49.3842 35.3963 49.8108 34.853 50.3486L32.2833 52.89C30.4559 54.6973 27.9777 55.7132 25.3933 55.7143H18.4167C15.8308 55.7143 13.3509 54.6983 11.5224 52.89C9.6939 51.0816 8.66667 48.6289 8.66667 46.0714V22.5C8.66667 19.9426 9.6939 17.4899 11.5224 15.6815C13.3509 13.8731 15.8308 12.8571 18.4167 12.8571H59.5833C62.1692 12.8571 64.6491 13.8731 66.4776 15.6815C68.3061 17.4899 69.3333 19.9426 69.3333 22.5Z" fill="#216DF0"/>
2018 </svg>
2019 </span>
2020 </label>';
2021 }
2022
2023 if ($width == 'fullwidth') {
2024 if (wpvr_isMobileDevice()) {
2025 $html .= '<div class="cardboard-vrfullwidth vrfullwidth">';
2026 $html .= '<div id="pano2' . esc_attr( $id ) . '" class="pano-wrap pano-left cardboard-half" style="width: 49%!important; border-radius:' . esc_attr( $radius ). ' ;text-align:center; direction:ltr;" ><div id="center-pointer2' . esc_attr( $id ). '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
2027 $html .= '<div id="pano' . esc_attr( $id ) . '" class="pano-wrap pano-right" style="width: 100%; text-align:center; direction:ltr; border-radius:' . esc_attr( $radius ) . '" >';
2028 } else {
2029 $html .= '<div id="pano2' . esc_attr( $id ) . '" class="pano-wrap pano-left" style="width: 49%; border-radius:' . esc_attr( $radius ) . ';"><div id="center-pointer2' . esc_attr( $id ). '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
2030 $html .= '<div id="pano' . esc_attr( $id ) . '" class="pano-wrap vrfullwidth" style=" text-align:center; height: ' . esc_attr( $height ) . esc_attr( $height_unit ) . '; border-radius:' . esc_attr( $radius ) . '; direction:ltr;" >';
2031 }
2032 } else {
2033 if (wpvr_isMobileDevice()) {
2034 $html .= '<div id="pano2' . esc_attr( $id ) . '" class="pano-wrap pano-left cardboard-half" style="width: 49%; border-radius:' . esc_attr( $radius ) . ';">
2035 <div id="center-pointer2' . esc_attr( $id ) . '" class="vr-pointer-container">
2036 <span class="center-pointer"></span>
2037 </div>
2038 </div>';
2039 $html .= '<div id="pano' . esc_attr( $id ) . '" class="pano-wrap pano-right" style=" width: 100%; border-radius:' . esc_attr( $radius ) . ';">';
2040 } else {
2041
2042 $html .= '<div id="pano2' . esc_attr( $id ) . '" class="pano-wrap pano-left" style="width: 49%; border-radius:' . esc_attr( $radius ) . ';"><div id="center-pointer2' . esc_attr( $id ) . '" class="vr-pointer-container"><span class="center-pointer"></span></div></div>';
2043
2044 $html .= '<div id="pano' . esc_attr( $id ) . '" class="pano-wrap pano-right" style="width: 100%; border-radius:' . esc_attr( $radius ) . ';">';
2045 }
2046 }
2047 // Vr mode transction scene to scene
2048 if ($status !== false && 'valid' == $status && $is_pro && wpvr_isMobileDevice() && $is_cardboard == 'true') {
2049 $html .= '<div id="center-pointer' . esc_attr( $id ) . '" class="vr-pointer-container" style="display:none"><span class="center-pointer"></span></div>';
2050 }
2051
2052
2053 //===company logo===//
2054 if (isset($postdata['cpLogoSwitch'])) {
2055 $cpLogoImg = $postdata['cpLogoImg'] ?? '';
2056 $cpLogoContent = $postdata['cpLogoContent'] ?? '';
2057 if ($postdata['cpLogoSwitch'] == 'on' && 'valid' == $status && $is_pro) {
2058 $html .= '<div id="cp-logo-controls">';
2059 $html .= '<div class="cp-logo-ctrl" id="cp-logo">';
2060 if ($cpLogoImg) {
2061 $html .= '<img loading="lazy" src="' . esc_attr( $cpLogoImg ) . '" alt="Company Logo">';
2062 }
2063
2064 if ($cpLogoContent) {
2065 $html .= '<div class="cp-info">' . esc_html( $cpLogoContent ) . '</div>';
2066 }
2067 $html .= '</div>';
2068 $html .= '</div>';
2069 }
2070 }
2071 //===company logo ends===//
2072
2073 //===Background Tour===//
2074 if (isset($postdata['bg_tour_enabler'])) {
2075
2076 $bg_tour_enabler = $postdata['bg_tour_enabler'];
2077 if ($bg_tour_enabler == 'on') {
2078 $bg_tour_navmenu = $postdata['bg_tour_navmenu'] ?? 'off';
2079 $bg_tour_title = $postdata['bg_tour_title'] ?? '';
2080 $bg_tour_subtitle = $postdata['bg_tour_subtitle'] ?? '';
2081
2082 if ($bg_tour_navmenu == 'on') {
2083 $menuLocations = get_nav_menu_locations();
2084 $menuID = $menuLocations['primary'];
2085 $primaryNav = wp_get_nav_menu_items($menuID);
2086
2087 if ($primaryNav) {
2088 $html .= '<div class="wpvr-navbar-container">';
2089 foreach ($primaryNav as $primaryNav_key => $primaryNav_value) {
2090 if ($primaryNav_value->menu_item_parent == "0") {
2091 $html .= '<li>';
2092 $html .= '<a href="' . esc_url( $primaryNav_value->url ) . '">' . esc_attr( $primaryNav_value->title ) . '</a>';
2093 $html .= '<ul class="wpvr-navbar-dropdown">';
2094 foreach ($primaryNav as $pm_key => $pm_value) {
2095 if ($pm_value->menu_item_parent == $primaryNav_value->ID) {
2096 $html .= '<li>';
2097 $html .= '<a href="' . esc_url( $pm_value->url ) . '">' . esc_attr( $pm_value->title ) . '</a>';
2098 $html .= '</li>';
2099 }
2100 }
2101 $html .= '</ul>';
2102 $html .= '</li>';
2103 }
2104 }
2105 $html .= '</div>';
2106 }
2107 }
2108
2109 if($is_pro && 'valid' == $status ){
2110 $html .= '<div class="wpvr-home-content">';
2111 $html .= '<div class="wpvr-home-title">' . $bg_tour_title . '</div>';
2112 $html .= '<div class="wpvr-home-subtitle">' . $bg_tour_subtitle . '</div>';
2113 $html .= '</div>';
2114 }
2115 }
2116 }
2117 //===Background Tour End===//
2118
2119 //===Custom Control===//
2120 if (isset($custom_control)) {
2121 $gyro_button_enabled = wpvr_isMobileDevice() && $custom_control['gyroSwitch'] == "on" && $custom_control['gyroscopeSwitch'] == "on";
2122 if ($custom_control['panZoomInSwitch'] == "on" || $custom_control['panZoomOutSwitch'] == "on" || $gyro_button_enabled || $custom_control['backToHomeSwitch'] == "on") {
2123 $html .= '<div id="zoom-in-out-controls' . esc_attr( $id ) . '" class="zoom-in-out-controls">';
2124
2125 if ($custom_control['backToHomeSwitch'] == "on" && 'valid' == $status && $is_pro) {
2126 $html .= '<div class="ctrl" id="backToHome' . esc_attr( $id ) . '"><i class="' . $custom_control['backToHomeIcon'] . '" style="color:' . esc_attr( $custom_control['backToHomeColor'] ) . ';"></i></div>';
2127 }
2128
2129 if ($custom_control['panZoomInSwitch'] == "on" && 'valid' == $status && $is_pro) {
2130 $html .= '<div class="ctrl" id="zoom-in' . esc_attr( $id ) . '"><i class="' . $custom_control['panZoomInIcon'] . '" style="color:' . esc_attr( $custom_control['panZoomInColor'] ) . ';"></i></div>';
2131 }
2132
2133 if ($custom_control['panZoomOutSwitch'] == "on" && 'valid' == $status && $is_pro) {
2134 $html .= '<div class="ctrl" id="zoom-out' . esc_attr( $id ) . '"><i class="' . $custom_control['panZoomOutIcon'] . '" style="color:' . esc_attr( $custom_control['panZoomOutColor'] ) . ';"></i></div>';
2135 }
2136
2137 if ($gyro_button_enabled && 'valid' == $status && $is_pro) {
2138 $html .= '<div class="ctrl" id="gyroscope' . esc_attr( $id ) . '"><i class="' . $custom_control['gyroscopeIcon'] . '" style="color:' . esc_attr( $custom_control['gyroscopeColor'] ) . ';"></i></div>';
2139 }
2140
2141 $html .= '</div>';
2142 }
2143 //===zoom in out Control===//
2144
2145 if ( ($custom_control['panupSwitch'] == "on" || $custom_control['panDownSwitch'] == "on" || $custom_control['panLeftSwitch'] == "on" || $custom_control['panRightSwitch'] == "on" || $custom_control['panFullscreenSwitch'] == "on" ) && 'valid' == $status && $is_pro) {
2146
2147 //===Custom Control===//
2148 $html .= '<div class="controls" id="controls' . esc_attr( $id ) . '">';
2149
2150 if ($custom_control['panupSwitch'] == "on") {
2151 $html .= '<div class="ctrl pan-up" id="pan-up' . esc_attr( $id ) . '"><i class="' . $custom_control['panupIcon'] . '" style="color:' . esc_attr( $custom_control['panupColor'] ) . ';"></i></div>';
2152 }
2153
2154 if ($custom_control['panDownSwitch'] == "on") {
2155 $html .= '<div class="ctrl pan-down" id="pan-down' . esc_attr( $id ) . '"><i class="' . $custom_control['panDownIcon'] . '" style="color:' . esc_attr( $custom_control['panDownColor'] ) . ';"></i></div>';
2156 }
2157
2158 if ($custom_control['panLeftSwitch'] == "on") {
2159 $html .= '<div class="ctrl pan-left" id="pan-left' . esc_attr( $id ) . '"><i class="' . $custom_control['panLeftIcon'] . '" style="color:' . esc_attr( $custom_control['panLeftColor'] ) . ';"></i></div>';
2160 }
2161
2162 if ($custom_control['panRightSwitch'] == "on") {
2163 $html .= '<div class="ctrl pan-right" id="pan-right' . esc_attr( $id ) . '"><i class="' . $custom_control['panRightIcon'] . '" style="color:' . esc_attr( $custom_control['panRightColor'] ) . ';"></i></div>';
2164 }
2165
2166 if ($custom_control['panFullscreenSwitch'] == "on") {
2167 $html .= '<div class="ctrl fullscreen" id="fullscreen' . esc_attr( $id ) . '"><i class="' . $custom_control['panFullscreenIcon'] . '" style="color:' . esc_attr( $custom_control['panFullscreenColor'] ) . ';"></i></div>';
2168 }
2169 $html .= '</div>';
2170 }
2171 }
2172
2173 //===explainer button===//
2174 $html .= wpvr_render_explainer_button(
2175 isset( $custom_control ) ? $custom_control : null,
2176 $postdata,
2177 $is_pro,
2178 $autoload,
2179 $explainer_right,
2180 $id
2181 );
2182 //===explainer button end===//
2183
2184 //===Scene navigation Control===//
2185 if (isset($postdata['scene_navigation']) && $postdata['scene_navigation'] === 'on' && 'valid' == $status && $is_pro) {
2186 $scene_navigation_nav_class = 'custom-scene-navigation-nav' . ( $is_classic_layout ? ' wpvr-scene-navigation-nav--classic' : '' );
2187 $html .= '<style>
2188 #et-boc .et-l .pnlm-controls-container,
2189 .pnlm-controls-container{
2190 top: 33px;
2191 }
2192
2193 #et-boc .et-l .zoom-in-out-controls,
2194 .zoom-in-out-controls {
2195 top: 37px;
2196 }
2197 </style>';
2198 $html .= '<div id="custom-scene-navigation' . esc_attr( $id ) . '" class="custom-scene-navigation">
2199 <span class="hamburger-menu"><svg width="16" height="10" fill="none" viewBox="0 0 22 15" xmlns="http://www.w3.org/2000/svg"><rect width="21.177" height="2.647" fill="#f7fffb" rx="1.324"/><rect width="21.177" height="2.647" y="6.177" fill="#f7fffb" rx="1.324"/><rect width="21.177" height="2.647" y="12.352" fill="#f7fffb" rx="1.324"/></svg></span>
2200 </div>
2201
2202 <div id="custom-scene-navigation-nav' . esc_attr( $id ) . '" class="' . esc_attr( $scene_navigation_nav_class ) . '">
2203 <ul></ul>
2204 </div>
2205 ';
2206 }
2207
2208 //===Scene navigation Control===//
2209
2210 /**
2211 * Generic Form Handler
2212 * Renders a generic form with modal functionality if enabled in post data
2213 *
2214 * @param array $postdata Array containing form configuration data
2215 * @param string $id Unique identifier for the form instance
2216 * @return string $html Generated HTML content
2217 */
2218
2219 // Check if generic form is enabled and validate the setting
2220 if (isset($postdata["genericform"]) && $postdata["genericform"] === 'on' && 'valid' == $status && $is_pro) {
2221
2222 // Process shortcode with fallback handling
2223 $shortcode_content = '';
2224 if (isset($postdata["genericformshortcode"]) && !empty(trim($postdata["genericformshortcode"]))) {
2225 $shortcode_content = do_shortcode( $postdata["genericformshortcode"] );
2226 } else {
2227 $shortcode_content = '<p class="error-message">No shortcode found.</p>';
2228 }
2229
2230 // Generate the form trigger button
2231 $generic_form_icon = isset($postdata['genericformicon']) ? (string) $postdata['genericformicon'] : 'fab fa-wpforms';
2232 $generic_form_icon = implode(' ', array_filter(array_map('sanitize_html_class', preg_split('/\s+/', $generic_form_icon))));
2233 $generic_form_icon = $generic_form_icon ?: 'fab fa-wpforms';
2234 $generic_form_icon_color = sanitize_hex_color($postdata['genericformiconcolor'] ?? '') ?: '#f7fffb';
2235 $html .= '<div class="generic_form_button" id="generic_form_button_' . esc_attr( $id ) . '">';
2236 $html .= '<div class="generic-form-icon" title ="Generic Form" id="generic_form_target_' . esc_attr( $id ) . '"><i class="' . esc_attr( $generic_form_icon ) . '" style="color:' . esc_attr( $generic_form_icon_color ) . ';"></i></div>';
2237 $html .= '</div>';
2238
2239 // Generate the modal form container
2240 $html .= '<div class="wpvr-generic-form" id="wpvr-generic-form' . esc_attr( $id ) . '" style="display: none">';
2241 $html .= '<span class="close-generic-form"><i class="fa fa-times"></i></span>';
2242 $html .= '<div class="generic-form-container">' . $shortcode_content . '</div>';
2243 $html .= '</div>';
2244 }
2245 //=====custom generic form=====//
2246
2247 //===Floor map button===//
2248 $status = get_option('wpvr_edd_license_status');
2249 if ($status !== false && 'valid' == $status && $is_pro) {
2250 if ($floor_plan_enable == "on" && !empty($floor_plan_image)) {
2251 $html .= '<div class="floor_map_button" id="floor_map_button_' . esc_attr( $id ) . '" style="right:' . esc_attr( $floor_map_right ) . '">';
2252 $html .= '<div class="ctrl" id="floor_map_target_' . esc_attr( $id ) . '"><i class="fas fa-map" style="color:#f7fffb;"></i></div>';
2253 $html .= '</div>';
2254 }
2255 }
2256
2257 //===floor map button===//
2258 if ($vrgallery && 'valid' == $status && $is_pro ) {
2259 //===Carousal setup===//
2260 $size = '';
2261 if ($vrgallery_icon_size) {
2262 $size = 'vrg-icon-size-large';
2263 }
2264 $html .= '<div id="vrgcontrols' . esc_attr( $id ) . '" class="vrgcontrols">';
2265
2266 $html .= '<div class="vrgctrl' . esc_attr( $id ) . ' vrbounce ' . esc_attr( $size ) . '">';
2267 $html .= '</div>';
2268 $html .= '</div>';
2269
2270 $tour_layout = is_array( $postdata['tourLayout'] ?? null )
2271 ? ( $postdata['tourLayout']['layout'] ?? 'default' )
2272 : ( $postdata['tourLayout'] ?? 'default' );
2273 $gallery_layout_class = 'layout1' === $tour_layout
2274 ? 'wpvr-gallery--modern'
2275 : 'wpvr-gallery--classic';
2276
2277 $html .= '<div id="sccontrols' . esc_attr( $id ) . '" class="scene-gallery vrowl-carousel owl-theme ' . esc_attr( $gallery_layout_class ) . '">';
2278 if (isset($panodata["scene-list"])) {
2279 foreach ($panodata["scene-list"] as $panoscenes) {
2280 $scene_key = $panoscenes['scene-id'];
2281 if ($vrgallery_title == 'on') {
2282 $scene_key_title = isset($panoscenes['scene-ititle']) ? esc_html($panoscenes['scene-ititle']) : '';
2283 } else {
2284 $scene_key_title = "";
2285 }
2286
2287 if ($panoscenes['scene-type'] == 'cubemap') {
2288 $img_src_url = $panoscenes['scene-attachment-url-face0'];
2289 } else {
2290 $img_src_url = $panoscenes['scene-attachment-url'];
2291 }
2292
2293
2294 $src_to_id = attachment_url_to_postid($img_src_url);
2295 $thumbnail_array = wp_get_attachment_image_src($src_to_id, 'thumbnail');
2296 if ($thumbnail_array) {
2297 $thumbnail = $thumbnail_array[0];
2298 } else {
2299 $thumbnail = $img_src_url;
2300 }
2301 if ( 'layout1' !== $tour_layout ) {
2302 $html .= '<ul><li title="Double click to view scene"><span class="scene-title" title="' . esc_attr($scene_key_title) . '"> ' . $scene_key_title . '</span><img loading="lazy" class="scctrl" id="' . $scene_key . '_gallery_' . $id . '" src="' . $thumbnail . '"></li></ul>';
2303 }else {
2304 $html .= '<ul><li title="Double click to view scene"><img loading="lazy" class="scctrl" id="' . $scene_key . '_gallery_' . $id . '" src="' . $thumbnail . '"><span class="scene-title" title="' . esc_attr($scene_key_title) . '">' . $scene_key_title . '</span></li></ul>';
2305 }
2306 }
2307 }
2308 $html .= '</div>';
2309 $html .= '
2310 <div class="owl-nav wpvr_slider_nav">
2311 <button type="button" role="presentation" class="owl-prev wpvr_owl_prev">
2312 <div class="nav-btn prev-slide"><i class="fa fa-angle-left"></i></div>
2313 </button>
2314 <button type="button" role="presentation" class="owl-next wpvr_owl_next">
2315 <div class="nav-btn next-slide"><i class="fa fa-angle-right"></i></div>
2316 </button>
2317 </div>
2318 ';
2319 //===Carousal setup end===//
2320 }
2321
2322 $bg_music = isset($postdata['bg_music']) ? $postdata['bg_music'] : 'off';
2323 $bg_music_url = isset($postdata['bg_music_url']) ? $postdata['bg_music_url'] : '';
2324 $autoplay_bg_music = isset($postdata['autoplay_bg_music']) ? $postdata['autoplay_bg_music'] : 'off';
2325 $loop_bg_music = isset($postdata['loop_bg_music']) ? $postdata['loop_bg_music'] : 'off';
2326
2327 $bg_loop = ($loop_bg_music === 'on') ? 'loop' : '';
2328 $autoplay_attr = ($autoplay_bg_music === 'on') ? 'autoplay' : '';
2329 $audio_muted_attr = ($autoplay_bg_music === 'on') ? 'muted' : '';
2330 $audio_icon_class = 'fa-volume-mute'; // Always start with mute icon
2331
2332 if ($bg_music === 'on' && 'valid' == $status && $is_pro) {
2333 $html .= '<div id="adcontrol' . esc_attr( $id ) . '" class="adcontrol" style="right:' . esc_attr( $audio_right ) . '">';
2334 $html .= '<audio id="vrAudio' . esc_attr($id) . '" class="vrAudioDefault" data-autoplay="' . esc_attr($autoplay_bg_music) . '" onended="audionEnd' . esc_attr($id) . '()" ' . $autoplay_attr . ' ' . $audio_muted_attr . ' ' . $bg_loop . '>
2335 <source src="' . esc_url($bg_music_url) . '" type="audio/mpeg">
2336 Your browser does not support the audio element.
2337 </audio>';
2338 $html .= '<button onclick="playPause' . esc_attr($id) . '()" class="ctrl audio_control" id="audio_control' . esc_attr($id) . '">
2339 <i id="vr-volume' . esc_attr($id) . '" class="wpvrvolumeicon' . esc_attr($id) . ' fas ' . esc_attr($audio_icon_class) . '" style="color:#fff;"></i>
2340 </button>';
2341 $html .= '</div>';
2342 }
2343
2344 //===Explainer video section===//
2345 $explainerContent = "";
2346 if (isset($postdata['explainerContent'])) {
2347 $explainerContent = wpvr_sanitize_iframe_only($postdata['explainerContent']);
2348 }
2349 $html .= '<div class="explainer" id="explainer' . esc_attr( $id ) . '" style="display: none">';
2350 $html .= '<span class="close-explainer-video"><i class="fa fa-times"></i></span>';
2351 $html .= '' . $explainerContent . '';
2352 $html .= '</div>';
2353 //===Explainer video section End===//
2354
2355 //===Floor plan section===//
2356 $floor_map_image = "";
2357 $floor_map_pointer = array();
2358 $floor_map_scene_id = '';
2359 $floor_plan_custom_color = '#cca92c';
2360 $floor_plan_direction_indicator = isset($postdata['floor_plan_direction_indicator']) ? $postdata['floor_plan_direction_indicator'] : 'on';
2361
2362 if (isset($postdata['floor_plan_attachment_url'])) {
2363 $floor_map_image = $postdata['floor_plan_attachment_url'];
2364 $floor_map_pointer = $postdata['floor_plan_pointer_position'];
2365 $floor_map_scene_id = $postdata['floor_plan_data_list'];
2366 $floor_plan_custom_color = $postdata['floor_plan_custom_color'];
2367 }
2368 $html .= '<div class="wpvr-floor-map" id="wpvr-floor-map' . $id . '" style="display: none">';
2369 $html .= '<span class="close-floor-map-plan"><i class="fa fa-times"></i></span>';
2370 $html .= '<img loading="lazy" src="' . $floor_map_image . '">';
2371
2372 foreach ($floor_map_pointer as $key => $pointer_position) {
2373 $html .= '<div class="floor-plan-pointer ui-draggable ui-draggable-handle" scene_id = "' . esc_attr( $floor_map_scene_id[$key]->value ) . '" id="' . esc_attr( $pointer_position->id ) . '" data-top="' . esc_attr( $pointer_position->data_top ) . '" data-left="' . esc_attr( $pointer_position->data_left ) . '" style="' . esc_attr( $pointer_position->style ) . '">
2374
2375 <svg class="floor-pointer-circle" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2376 <circle cx="12" cy="12" r="11.5" stroke="' . esc_attr( $floor_plan_custom_color ) . '"/>
2377 <circle cx="12" cy="12" r="5" fill="' . esc_attr( $foreground_color_pointer ) . '"/>
2378 </svg>';
2379
2380 // Only add the floor pointer flash SVG if floor_plan_direction_indicator is "on"
2381 if ($floor_plan_direction_indicator === "on") {
2382 $html .= '<svg class="floor-pointer-flash" width="54" height="35" viewBox="0 0 54 35" fill="none" xmlns="http://www.w3.org/2000/svg">
2383 <path d="M0.454054 1.32433L11.7683 34.3243C11.9069 34.7285 12.287 35 12.7143 35H41.2857C41.713 35 42.0931 34.7285 42.2317 34.3243L53.5459 1.32432C53.7685 0.675257 53.2862 0 52.6 0H1.4C0.713843 0 0.231517 0.675258 0.454054 1.32433Z" fill="url(#paint0_linear_1_10)"/>
2384 <defs>
2385 <linearGradient id="paint0_linear_1_10" x1="27" y1="4.59807e-08" x2="26.5" y2="28" gradientUnits="userSpaceOnUse">
2386 <stop stop-color="' . esc_attr( $floor_plan_custom_color ) . '" stop-opacity="0"/>
2387 <stop offset="1" stop-color="' . esc_attr( $floor_plan_custom_color ) . '"/>
2388 </linearGradient>
2389 </defs>
2390 </svg>';
2391 }
2392 $html .= '</div>';
2393 }
2394 $html .= '</div>';
2395 //===Floor plan section===//
2396
2397 $html .= '<div class="wpvr-hotspot-tweak-contents-wrapper" style="display: none">';
2398 $html .= '<i class="fa fa-times cross" data-id="' . esc_attr( $id ) . '"></i>';
2399 $html .= '<div class="wpvr-hotspot-tweak-contents-flex">';
2400 $html .= '<div class="wpvr-hotspot-tweak-contents">';
2401 ob_start();
2402 do_action('wpvr_hotspot_tweak_contents', $scene_data);
2403 $hotspot_content = ob_get_clean();
2404 $html .= $hotspot_content;
2405 $html .= '</div>';
2406 $html .= '</div>';
2407 $html .= '</div>';
2408
2409 $html .= '<div class="custom-ifram-wrapper" style="display: none;">';
2410 $html .= '<i class="fa fa-times cross" data-id="' . esc_attr( $id ) . '"></i>';
2411 $html .= '<div class="custom-ifram-flex">';
2412 $html .= '<div class="custom-ifram">';
2413 $html .= '</div>';
2414 $html .= '</div>';
2415 $html .= '</div>';
2416 $html .= '</div>';
2417 $html .= '</div>';
2418
2419
2420 if ("fullwidth" == $width) {
2421 $html .= '</div>';
2422 }
2423 if ($status !== false && 'valid' == $status && $is_pro) {
2424 $call_to_action = isset($postdata['calltoaction']) ? $postdata['calltoaction'] : 'off';
2425 if ('on' == $call_to_action) {
2426 $buttontext = isset($postdata['buttontext']) ? $postdata['buttontext'] : '';
2427 $buttonurl = isset($postdata['buttonurl']) ? $postdata['buttonurl'] : '';
2428 $cta_btn_style = isset($postdata['button_configuration']) ? $postdata['button_configuration'] : array();
2429
2430 $button_open_new_tab = isset($cta_btn_style['button_open_new_tab']) ? $cta_btn_style['button_open_new_tab'] : "off";
2431 $target = '_self';
2432 $button_position = isset($cta_btn_style['button_position']) ? $cta_btn_style['button_position'] : "";
2433 $background_color = isset($cta_btn_style['button_background_color']) ? $cta_btn_style['button_background_color'] : "";
2434 $color = isset($cta_btn_style['button_font_color']) ? $cta_btn_style['button_font_color'] : "";
2435 $font_size = isset($cta_btn_style['button_font_size']) ? $cta_btn_style['button_font_size'] : "";
2436 $font_weight = isset($cta_btn_style['button_font_weight']) ? $cta_btn_style['button_font_weight'] : "";
2437 $text_align = isset($cta_btn_style['button_alignment']) ? $cta_btn_style['button_alignment'] : "";
2438 $text_transform = isset($cta_btn_style['button_transform']) ? $cta_btn_style['button_transform'] : "";
2439 $font_style = isset($cta_btn_style['button_text_style']) ? $cta_btn_style['button_text_style'] : "";
2440 $text_decoration = isset($cta_btn_style['button_text_decoration']) ? $cta_btn_style['button_text_decoration'] : "";
2441 $line_height = isset($cta_btn_style['button_line_height']) ? $cta_btn_style['button_line_height'] : "";
2442 $letter_spacing = isset($cta_btn_style['button_letter_spacing']) ? $cta_btn_style['button_letter_spacing'] : "";
2443 $word_spacing = isset($cta_btn_style['button_word_spacing']) ? $cta_btn_style['button_word_spacing'] : "";
2444
2445 $border_width = isset($cta_btn_style['button_border_width']) ? $cta_btn_style['button_border_width'] : "";
2446 $border_style = isset($cta_btn_style['button_border_style']) ? $cta_btn_style['button_border_style'] : "";
2447 $border_color = isset($cta_btn_style['button_border_color']) ? $cta_btn_style['button_border_color'] : "";
2448 $border_radius = isset($cta_btn_style['button_border_radius']) ? $cta_btn_style['button_border_radius'] : "";
2449
2450 $button_pt = isset($cta_btn_style['button_pt']) ? $cta_btn_style['button_pt'] : "";
2451 $button_pr = isset($cta_btn_style['button_pr']) ? $cta_btn_style['button_pr'] : "";
2452 $button_pb = isset($cta_btn_style['button_pb']) ? $cta_btn_style['button_pb'] : "";
2453 $button_pl = isset($cta_btn_style['button_pl']) ? $cta_btn_style['button_pl'] : "";
2454
2455 if ($button_open_new_tab == 'on') {
2456 $target = '_blank';
2457 }
2458 $style = 'background-color: ' . esc_attr( $background_color ) . ';
2459 color: ' . esc_attr( $color ) . ';
2460 font-size: ' . esc_attr( $font_size ) . 'px;
2461 font-weight: ' . esc_attr( $font_weight ) . ';
2462 text-align: center;
2463 display: inline-block;
2464 text-transform: ' . esc_attr( $text_transform ) . ';
2465 font-style: ' . esc_attr( $font_style ) . ';
2466 text-decoration: ' . esc_attr( $text_decoration ) . ';
2467 line-height: ' . esc_attr( $line_height ) . ';
2468 letter-spacing: ' . esc_attr( $letter_spacing ) . 'px;
2469 word-spacing: ' . esc_attr( $word_spacing ) . 'px;
2470 border: ' . esc_attr( $border_width ) . 'px ' . esc_attr( $border_style ) . ' ' . esc_attr( $border_color ) . ';
2471 border-radius: ' . esc_attr( $border_radius ). 'px;
2472 padding: ' . esc_attr( $button_pt ) . 'px ' . esc_attr( $button_pr ) . 'px ' . esc_attr( $button_pb ) . 'px ' . esc_attr( $button_pl ) . 'px;
2473 ';
2474 $html .= '<div class="wpvr-call-to-action-button position-' . esc_attr( $text_align ) . '" style="max-width:' . esc_attr( $width ) . esc_attr( $width_unit ) . '">
2475 <a href="' . esc_url( $buttonurl ) . '" style="' . esc_attr( $style ) . '" target="' . esc_attr( $target ) . '">' . esc_attr( $buttontext ) . '</a>
2476 </div>';
2477 }
2478 }
2479
2480 //script started
2481
2482 $html .= '<script>';
2483 if (isset($postdata['bg_music']) && $bg_music == 'on' && 'valid' == $status && $is_pro) {
2484 $html .= '
2485 var x' . $id . ' = document.getElementById("vrAudio' . $id . '");
2486
2487 var playing' . $id . ' = false;
2488 var autoplaySupported' . $id . ' = false;
2489 var alertShown' . $id . ' = false;
2490 var autoplayChecked' . $id . ' = false;
2491
2492 function playPause' . $id . '() {
2493 if (playing' . $id . ') {
2494 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2495 x' . $id . '.pause();
2496 jQuery("#audio_control' . $id . '").attr("data-play", "off");
2497 playing' . $id . ' = false;
2498 } else {
2499 x' . $id . '.muted = false;
2500 x' . $id . '.play().then(function() {
2501 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2502 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2503 playing' . $id . ' = true;
2504 }).catch(function(e) {
2505 console.log("Play failed:", e);
2506 });
2507 }
2508 }
2509
2510 function audionEnd' . $id . '() {
2511 playing' . $id . ' = false;
2512 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2513 jQuery("#audio_control' . $id . '").attr("data-play", "off");
2514 }
2515
2516 x' . $id . '.addEventListener("ended", audionEnd' . $id . ');';
2517
2518 if ($autoplay_bg_music == 'on') {
2519 $html .= '
2520
2521 x' . $id . '.addEventListener("loadeddata", function() {
2522 if (!autoplayChecked' . $id . ') {
2523 checkAutoplayStatus' . $id . '();
2524 }
2525 });
2526
2527 x' . $id . '.addEventListener("canplay", function() {
2528 if (!autoplayChecked' . $id . ') {
2529 checkAutoplayStatus' . $id . '();
2530 }
2531 });
2532
2533 x' . $id . '.addEventListener("canplaythrough", function() {
2534 if (!autoplayChecked' . $id . ') {
2535 checkAutoplayStatus' . $id . '();
2536 }
2537 });
2538
2539 setTimeout(function() {
2540 if (!autoplayChecked' . $id . ') {
2541 checkAutoplayStatus' . $id . '();
2542 }
2543 }, 1000);
2544
2545 x' . $id . '.addEventListener("play", function() {
2546 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2547 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2548 playing' . $id . ' = true;
2549 });
2550
2551 x' . $id . '.addEventListener("pause", function() {
2552 if (!playing' . $id . ') {
2553 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2554 jQuery("#audio_control' . $id . '").attr("data-play", "off");
2555 }
2556 });
2557
2558 function checkAutoplayStatus' . $id . '() {
2559 autoplayChecked' . $id . ' = true;
2560
2561 x' . $id . '.muted = true;
2562 var playPromise = x' . $id . '.play();
2563
2564 if (playPromise !== undefined) {
2565 playPromise.then(function () {
2566 if (x' . $id . '.muted || x' . $id . '.volume === 0) {
2567 handleAutoplayBlocked' . $id . '();
2568 } else {
2569 autoplaySupported' . $id . ' = true;
2570 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2571 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2572 playing' . $id . ' = true;
2573 }
2574 }).catch(function () {
2575 handleAutoplayBlocked' . $id . '();
2576 });
2577 } else {
2578 setTimeout(function () {
2579 if (x' . $id . '.paused || x' . $id . '.currentTime === 0) {
2580 handleAutoplayBlocked' . $id . '();
2581 } else {
2582 autoplaySupported' . $id . ' = true;
2583 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2584 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2585 playing' . $id . ' = true;
2586 }
2587 }, 300);
2588 }
2589 }
2590
2591 function handleAutoplayBlocked' . $id . '() {
2592 autoplaySupported' . $id . ' = false;
2593 if (!alertShown' . $id . ') {
2594 alert("Autoplay is not supported in your browser. Please click the audio button to play music.");
2595 alertShown' . $id . ' = true;
2596 }
2597
2598 x' . $id . '.pause();
2599 x' . $id . '.currentTime = 0;
2600 x' . $id . '.muted = true;
2601
2602 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-up").addClass("fas fa-volume-mute");
2603 jQuery("#audio_control' . $id . '").attr("data-play", "off");
2604
2605 document.getElementById("pano' . $id . '").addEventListener("click", musicPlay' . $id . ');
2606 document.addEventListener("touchstart", musicPlay' . $id . ', { once: true });
2607 document.addEventListener("click", musicPlay' . $id . ', { once: true });
2608 }
2609
2610 function musicPlay' . $id . '() {
2611 x' . $id . '.muted = false;
2612 var playPromise = x' . $id . '.play();
2613
2614 if (playPromise !== undefined) {
2615 playPromise.then(function () {
2616 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2617 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2618 playing' . $id . ' = true;
2619 }).catch(function(e) {
2620 console.log("Play failed:", e);
2621 });
2622 } else {
2623 setTimeout(function () {
2624 if (!x' . $id . '.paused) {
2625 jQuery("#vr-volume' . $id . '").removeClass("fas fa-volume-mute").addClass("fas fa-volume-up");
2626 jQuery("#audio_control' . $id . '").attr("data-play", "on");
2627 playing' . $id . ' = true;
2628 }
2629 }, 100);
2630 }
2631
2632 document.getElementById("pano' . $id . '").removeEventListener("click", musicPlay' . $id . ');
2633 document.removeEventListener("touchstart", musicPlay' . $id . ');
2634 document.removeEventListener("click", musicPlay' . $id . ');
2635 }
2636 ';
2637 }
2638 }
2639 $html .= 'jQuery(document).ready(function() {';
2640 $html .= 'var response = ' . $response . ';';
2641 $html .= 'var scenes = response[1];';
2642 $html .= 'if(scenes) {';
2643 $html .= 'var scenedata = scenes.scenes;';
2644 $html .= 'for(var i in scenedata) {';
2645 $html .= 'var scenehotspot = scenedata[i].hotSpots;';
2646 $html .= 'for(var i = 0; i < scenehotspot.length; i++) {';
2647 $html .= 'if(scenehotspot[i].type === "info") {';
2648 $html .= ' scenehotspot[i]["clickHandlerFunc"] = wpvrhotspot;';
2649 $html .= '} else if(scenehotspot[i].type === "scene") {';
2650 $html .= ' scenehotspot[i]["clickHandlerArgs"] = scenehotspot[i]["text"];';
2651 $status = get_option('wpvr_edd_license_status');
2652 if ($status !== false && $status == 'valid') {
2653 $html .='if(wpvr_public.is_pro_active) {';
2654 $html .= ' scenehotspot[i]["clickHandlerFunc"] = wpvrhotspotscene;';
2655 $html .='}';
2656 }
2657 $html .= '}';
2658 if (wpvr_isMobileDevice() && get_option('dis_on_hover') == "true") {
2659 } else {
2660 $html .= 'if(scenehotspot[i]["createTooltipArgs"] != "") {';
2661 $html .= 'scenehotspot[i]["createTooltipFunc"] = wpvrtooltip;';
2662 $html .= '}';
2663 }
2664 $html .= '}';
2665 $html .= '}';
2666 $html .= '}';
2667 $html .= 'var panoshow' . $id . ' = pannellum.viewer(response[0]["panoid"], scenes);';
2668 $html .= '
2669 window.wpvrViewers = window.wpvrViewers || {};
2670 window.wpvrViewers[response[0]["panoid"]] = panoshow' . $id . ';
2671 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
2672 detail: { containerId: response[0]["panoid"], viewer: panoshow' . $id . ' }
2673 }));
2674 ';
2675 if ( (float) $scene_fade_duration > 0 ) {
2676 $html .= '
2677 panoshow' . $id . '.on("scenechange", function() {
2678 var fadeImage = document.querySelector("#pano' . $id . ' .pnlm-render-container > .pnlm-fade-img");
2679 if (fadeImage) {
2680 fadeImage.style.opacity = "1";
2681 void fadeImage.offsetWidth;
2682 }
2683 });';
2684 }
2685 $html .= '
2686 if(!wpvr_public.is_pro_active || !wpvr_public.is_license_active) {
2687 panoshow' . $id . '.on("load", function() {
2688 jQuery(".pnlm-panorama-info").hide();
2689 jQuery(".pnlm-compass").hide();
2690 });
2691
2692 panoshow' . $id . '.on("scenechange", function() {
2693 jQuery(".pnlm-panorama-info").hide();
2694 jQuery(".pnlm-compass").hide();
2695 });
2696 }';
2697
2698 //===Dplicate mode only for vr mode===//
2699 $response2 = json_decode($response);
2700 $response2[1]->compass = false;
2701 $response2[1]->autoRotate = false;
2702 $response = json_encode($response2);
2703 $html .= 'var response_duplicate = ' . $response . ';';
2704 $html .= 'var scenes_duplicate = response_duplicate[1];';
2705
2706 $html .= 'if(scenes_duplicate) {';
2707 $html .= 'var scenedata = scenes_duplicate.scenes;';
2708 $html .= 'for(var i in scenedata) {';
2709 $html .= 'var scenehotspot = scenedata[i].hotSpots;';
2710 $html .= 'for(var i = 0; i < scenehotspot.length; i++) {';
2711 $html .= 'if(scenehotspot[i]["clickHandlerArgs"] != "") {';
2712 $html .= 'scenehotspot[i]["clickHandlerFunc"] = wpvrhotspot;';
2713 $html .= '}';
2714 if (wpvr_isMobileDevice() && get_option('dis_on_hover') == "true") {
2715 } else {
2716 $html .= 'if(scenehotspot[i]["createTooltipArgs"] != "") {';
2717 $html .= 'scenehotspot[i]["createTooltipFunc"] = wpvrtooltip;';
2718 $html .= '}';
2719 }
2720 $html .= '}';
2721 $html .= '}';
2722 $html .= '}';
2723 $html .= 'var vr_mode = "off";';
2724 $status = get_option('wpvr_edd_license_status');
2725 if ($status !== false && 'valid' == $status && $is_pro) {
2726 $html .= 'var panoshow2' . $id . ' = pannellum.viewer("pano2' . $id . '", scenes_duplicate);';
2727 $html .= '
2728 window.wpvrViewers = window.wpvrViewers || {};
2729 window.wpvrViewers["pano2' . $id . '"] = panoshow2' . $id . ';
2730 document.dispatchEvent(new CustomEvent("wpvr:viewer-ready", {
2731 detail: { containerId: "pano2' . $id . '", viewer: panoshow2' . $id . ' }
2732 }));
2733 ';
2734
2735 // Show Cardboard Mode in Tour
2736 $html .= '
2737 var tim;
2738 var im = 0;
2739 var active_scene = "' . $default_scene . '";
2740 var c_time;
2741 c_time = new Date();
2742 var timer = c_time.getTime() + 2000;
2743 function panoShowCardBoardOnTrigger(data){
2744 if(scenes_duplicate) {
2745 var scenedata = scenes_duplicate.scenes;
2746 for(var i in scenedata) {
2747 if(active_scene === i) {
2748 var scenehotspot = scenedata[i].hotSpots;
2749 for(var j in scenehotspot) {
2750 var plusFiveYaw = Math.round(scenehotspot[j].yaw) + 5;
2751 var minusFiveYaw = Math.round(scenehotspot[j].yaw) - 5;
2752 var plusFivePitch = Math.round(scenehotspot[j].pitch) + 5;
2753 var minusFivePitch = Math.round(scenehotspot[j].pitch) - 5;
2754 var firstCondition = ( Math.round(data.pitch) > minusFivePitch) && (Math.round(data.pitch) < plusFivePitch) ;
2755 var secCondition = (Math.round(data.yaw) > minusFiveYaw) && (Math.round(data.yaw) < plusFiveYaw);
2756 if(( Math.round(data.pitch) > minusFivePitch) && (Math.round(data.pitch) < plusFivePitch) ){
2757 if((Math.round(data.yaw) > minusFiveYaw) && (Math.round(data.yaw) < plusFiveYaw)){
2758 jQuery(".center-pointer").addClass("wpvr-pluse-effect")
2759 var getScene = scenehotspot[j].sceneId;
2760 if(scenehotspot[j].type == "scene"){
2761 panoshow' . $id . '.loadScene(getScene);
2762 panoshow2' . $id . '.loadScene(getScene);
2763 // var inside_current_time_object = new Date();
2764 // var inside_timer = inside_current_time_object.getTime();
2765 // if(inside_timer > timer) {
2766 // panoshow' . $id . '.loadScene(getScene);
2767 // panoshow2' . $id . '.loadScene(getScene);
2768 // jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2769 // }
2770 }else{
2771 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2772 }
2773 }
2774 else {
2775 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2776 c_time = new Date();
2777 timer = c_time.getTime() + 2000;
2778 }
2779 }
2780 else {
2781 c_time = new Date();
2782 timer = c_time.getTime() + 2000;
2783 }
2784 }
2785 }
2786 }
2787 }
2788 };
2789
2790 function vrDeviseOrientation(){
2791 var data = {
2792 pitch: panoshow' . $id . '.getPitch(),
2793 yaw: panoshow' . $id . '.getYaw(),
2794 };
2795 panoShowCardBoardOnTrigger(data);
2796 }
2797 ';
2798 $html .= '
2799
2800 function requestFullScreen(){
2801 var elem = document.getElementById("master-container");
2802 if (elem.requestFullscreen) {
2803 elem.requestFullscreen();
2804 } else if (elem.webkitRequestFullscreen) { /* Safari */
2805 elem.webkitRequestFullscreen();
2806 } else if (elem.msRequestFullscreen) { /* IE11 */
2807 elem.msRequestFullscreen();
2808 }
2809 }
2810 function requestExitFullscreen(){
2811 var elem = document.getElementById("master-container");
2812 if (document.exitFullscreen) {
2813 document.exitFullscreen();
2814 } else if (document.webkitExitFullscreen) { /* Safari */
2815 document.webkitExitFullscreen();
2816 } else if (document.msExitFullscreen) { /* IE11 */
2817 document.msExitFullscreen();
2818 }
2819 }
2820 jQuery(document).on("click",".fullscreen-button .expand",function() {
2821 jQuery(this).hide()
2822 jQuery(this).parent().find(".compress").show()
2823 requestFullScreen()
2824 screen.orientation.lock("landscape-primary")
2825 .then(function() {
2826 })
2827 .catch(function(error) {
2828 alert("Not Supported for this devise");
2829 });
2830
2831 });
2832 jQuery(document).on("click",".fullscreen-button .compress",function() {
2833 jQuery(this).hide()
2834 jQuery(this).parent().find(".expand").show()
2835 requestExitFullscreen()
2836 screen.orientation.unlock();
2837
2838 });
2839
2840 let onLoadAnalytics = false;
2841 let sceneLoadAnalytics = false;
2842 function storeAnalyticsData(data) {
2843 if(wpvr_public.is_pro_active) {
2844 jQuery.ajax({
2845 url: wpvrAnalyticsObj.ajaxUrl,
2846 type: "POST",
2847 data: {
2848 action: "store_scene_hotspot_data",
2849 scene_id: data.scene_id,
2850 tour_id: data.tour_id,
2851 type: data.type,
2852 hotspot_id: data.hotspot_id || "",
2853 user_agent: navigator.userAgent,
2854 device_type: getDeviceType() || "desktop",
2855 nonce: wpvrAnalyticsObj.nonce,
2856 },
2857 success: function (response) {
2858 console.log("Data stored successfully");
2859 },
2860 error: function (error) {
2861 console.log("Error in storing data");
2862 }
2863 });
2864 }
2865 }
2866
2867 function getDeviceType() {
2868 const userAgent = navigator.userAgent.toLowerCase();
2869
2870 if (/mobile|android|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(userAgent)) {
2871 return "mobile";
2872 } else if (/tablet|ipad/i.test(userAgent)) {
2873 return "tablet";
2874 } else {
2875 return "desktop";
2876 }
2877 }
2878
2879 panoshow' . $id . '.on("scenechange", function(scene) {
2880 onLoadAnalytics = true;
2881 sceneLoadAnalytics = true;
2882 let scene_id = scene;
2883 let tour_id = ' . $id . ';
2884 let type = "scene";
2885 let hotspot_id = "";
2886 let user_agent = navigator.userAgent;
2887 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2888 storeAnalyticsData({
2889 scene_id: scene_id,
2890 tour_id: tour_id,
2891 type: type,
2892 hotspot_id: hotspot_id,
2893 user_agent: user_agent,
2894 device_type: device_type,
2895 });
2896 if(!wpvr_public.is_pro_active) {
2897 jQuery(".pnlm-panorama-info").hide();
2898 setTimeout(function() {
2899 jQuery(".pnlm-panorama-info").each(function() {
2900 jQuery(this).hide();
2901 });
2902 }, 500);
2903 }
2904 });
2905
2906 panoshow' . $id . '.on("load", function() {
2907 let scene_id = panoshow' . $id . '.getScene();
2908 let tour_id = ' . $id . ';
2909 let type = "scene";
2910 let hotspot_id = "";
2911 let user_agent = navigator.userAgent;
2912 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2913 if(!onLoadAnalytics && !sceneLoadAnalytics){
2914 storeAnalyticsData({
2915 scene_id: scene_id,
2916 tour_id: tour_id,
2917 type: type,
2918 hotspot_id: hotspot_id,
2919 user_agent: user_agent,
2920 device_type: device_type,
2921 });
2922 }
2923 if(!wpvr_public.is_pro_active) {
2924 jQuery(".pnlm-panorama-info").hide();
2925 setTimeout(function() {
2926 jQuery(".pnlm-panorama-info").each(function() {
2927 jQuery(this).hide();
2928 });
2929 }, 500);
2930 }
2931 })
2932
2933 function wpvrhotspotscene(hotSpotDiv, args) {
2934 onLoadAnalytics = true;
2935 let scene_id = panoshow' . $id . '.getScene();
2936 let tour_id = ' . $id . ';
2937 let type = "hotspot";
2938 let hotspot_id = args;
2939 let user_agent = navigator.userAgent;
2940 let device_type = getDeviceType() ? getDeviceType() : "desktop";
2941 storeAnalyticsData({
2942 scene_id: scene_id,
2943 tour_id: tour_id,
2944 type: type,
2945 hotspot_id: hotspot_id,
2946 user_agent: user_agent,
2947 device_type: device_type
2948 });
2949 }';
2950
2951 $html .= '
2952 panoshow' . $id . '.on("scenechange", function (scene){
2953 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
2954 active_scene = scene;
2955 });
2956 var compassBlock = "";
2957 var infoBlock = "";
2958 var getValue = "";
2959 jQuery(document).on("click",".vr_mode_change' . $id . '",function (){
2960
2961 jQuery("#pano2' . $id . ' .pnlm-load-button").trigger("click");
2962 jQuery("#pano' . $id . ' .pnlm-load-button").trigger("click");
2963
2964 getValue = jQuery(this).val();
2965 var getParent = jQuery(this).parent().parent();
2966 var fullWidthParent = getParent.parent();
2967 var compass = getParent.find("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display");
2968 var panoInfo = getParent.find("#pano' . $id . ' .pnlm-panorama-info").css("display");
2969 if(compass == "block"){
2970 compassBlock = "block";
2971 }
2972 if(panoInfo == "block"){
2973 infoBlock = "block";
2974 }
2975 if (getValue == "off") {
2976 requestFullScreen()
2977 screen.orientation.lock("landscape-primary")
2978 .then(function() {
2979 })
2980 .catch(function(error) {
2981 alert("VR Glass Mode not supported in this device");
2982 });
2983 getParent.find(".pano-wrap").addClass("wpvr-cardboard-disable-event");
2984 // localStorage.setItem("vr_mode", "on");
2985 vr_mode = "on";
2986 jQuery(".vr-mode-title").show();
2987 jQuery(this).val("on");
2988 getParent.find("#pano2' . $id . '").css({
2989 "opacity": "1",
2990 "visibility": "visible",
2991 "position": "relative",
2992 });
2993 gyroSwitch = true;
2994 panoshow' . $id . '.startOrientation();
2995 panoshow2' . $id . '.startOrientation();
2996 panoshow2' . $id . '.setPitch(panoshow' . $id . '.getPitch(), 0);
2997 panoshow2' . $id . '.setYaw(panoshow' . $id . '.getYaw(), 0);
2998 getParent.find("#pano' . $id . ' #zoom-in-out-controls' . $id . '").hide();
2999 getParent.find("#pano' . $id . ' #controls' . $id . '").hide();
3000 getParent.find("#pano' . $id . ' #explainer_button_' . $id . '").hide();
3001 getParent.find("#pano' . $id . ' #generic_form_button_' . $id . '").hide();
3002 getParent.find("#pano' . $id . ' #floor_map_button_' . $id . '").hide();
3003 getParent.find("#pano' . $id . ' #vrgcontrols' . $id . '").hide();
3004 getParent.find("#pano' . $id . ' #sccontrols' . $id . '").hide();
3005 getParent.find("#pano' . $id . ' #adcontrol' . $id . '").hide();
3006 getParent.find("#pano' . $id . ' .owl-nav.wpvr_slider_nav").hide();
3007 getParent.find("#pano' . $id . ' #cp-logo-controls").hide();
3008
3009 getParent.find("#pano' . $id . ' #custom-scene-navigation' . $id . '").hide();
3010
3011 getParent.find("#pano2' . $id . ' .pnlm-controls-container").hide();
3012 getParent.find("#pano' . $id . ' .pnlm-controls-container").hide();
3013
3014 getParent.find("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").hide();
3015 getParent.find("#pano' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").hide();
3016
3017 getParent.find("#pano2' . $id . ' .pnlm-panorama-info").hide();
3018 getParent.find("#pano' . $id . ' .pnlm-panorama-info").hide();
3019 getParent.find("#pano' . $id . '").addClass("cardboard-half");
3020
3021 getParent.find("#center-pointer' . $id . '").show();
3022 getParent.find(".fullscreen-button").hide();
3023
3024
3025 if (window.DeviceOrientationEvent) {
3026 window.addEventListener("deviceorientation", vrDeviseOrientation);
3027 }
3028
3029 panoshow' . $id . '.on("mousemove", function (data){
3030 panoshow2' . $id . '.setPitch(data.pitch, 0);
3031 panoshow2' . $id . '.setYaw(data.yaw, 0);
3032 panoShowCardBoardOnTrigger(data);
3033
3034 });
3035 panoshow2' . $id . '.on("mousemove", function (data){
3036 panoshow2' . $id . '.setPitch(data.pitch, 0);
3037 panoshow' . $id . '.setYaw(data.yaw, 0);
3038 panoShowCardBoardOnTrigger(data);
3039
3040 });
3041
3042 panoshow' . $id . '.on("zoomchange", function (data){
3043 panoshow2' . $id . '.setHfov(data, 0);
3044 });
3045
3046 panoshow2' . $id . '.on("zoomchange", function (data){
3047 panoshow' . $id . '.setHfov(data, 0);
3048 });
3049
3050 panoshow' . $id . '.on("touchmove", function (data){
3051 panoshow' . $id . '.stopOrientation();
3052 panoshow2' . $id . '.stopOrientation();
3053 panoshow2' . $id . '.setPitch(data.pitch, 0);
3054 panoshow2' . $id . '.setYaw(data.yaw, 0);
3055 panoShowCardBoardOnTrigger(data);
3056
3057 });
3058
3059 panoshow2' . $id . '.on("touchmove", function (data){
3060 panoshow' . $id . '.stopOrientation();
3061 panoshow2' . $id . '.stopOrientation();
3062 panoshow' . $id . '.setPitch(data.pitch, 0);
3063 panoshow' . $id . '.setYaw(data.yaw, 0);
3064 panoShowCardBoardOnTrigger(data);
3065
3066 });
3067
3068 }
3069 else if(getValue == "on") {
3070 screen.orientation.unlock();
3071 requestExitFullscreen();
3072 // localStorage.setItem("vr_mode", "off");
3073 vr_mode = "off";
3074 jQuery(".vr-mode-title").hide();
3075 jQuery(this).val("off");
3076 getParent.find("#pano2' . $id . '").css({
3077 "opacity": "0",
3078 "visibility": "hidden",
3079 "position": "absolute",
3080 });
3081 panoshow' . $id . '.stopOrientation();
3082 panoshow2' . $id . '.stopOrientation();
3083 getParent.find(".pano-wrap").removeClass("wpvr-cardboard-disable-event");
3084 getParent.find("#pano' . $id . ' #zoom-in-out-controls' . $id . '").show();
3085 getParent.find("#pano' . $id . ' #controls' . $id . '").show();
3086 getParent.find("#pano' . $id . ' #explainer_button_' . $id . '").show();
3087 getParent.find("#pano' . $id . ' #generic_form_button_' . $id . '").show();
3088 getParent.find("#pano' . $id . ' #floor_map_button_' . $id . '").show();
3089
3090 getParent.find("#pano2' . $id . ' .pnlm-controls-container").show();
3091 getParent.find("#pano' . $id . ' .pnlm-controls-container").show();
3092 getParent.find("#pano' . $id . ' #vrgcontrols' . $id . '").show();
3093 getParent.find("#pano' . $id . ' #sccontrols' . $id . '").hide();
3094 getParent.find("#pano' . $id . ' #adcontrol' . $id . '").show();
3095 getParent.find("#pano' . $id . ' .owl-nav.wpvr_slider_nav").hide();
3096 getParent.find("#pano' . $id . ' #cp-logo-controls").show();
3097 getParent.find("#pano' . $id . ' #custom-scene-navigation' . $id . '").show();
3098
3099 if(compassBlock == "block"){
3100 getParent.find("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").show();
3101 getParent.find("#pano' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").show();
3102 }
3103 if(infoBlock == "block"){
3104 getParent.find("#pano2' . $id . ' .pnlm-panorama-info").show();
3105 getParent.find("#pano' . $id . ' .pnlm-panorama-info").show();
3106 }
3107
3108 getParent.find("#pano' . $id . '").removeClass("cardboard-half");
3109 getParent.find("#center-pointer' . $id . '").hide();
3110 getParent.find(".fullscreen-button").hide();
3111 panoshow' . $id . '.off("mousemove");
3112 panoshow' . $id . '.off("touchmove");
3113 panoshow2' . $id . '.off("mousemove");
3114 panoshow2' . $id . '.off("touchmove");
3115 if (window.DeviceOrientationEvent) {
3116 window.removeEventListener("deviceorientation", vrDeviseOrientation);
3117 }
3118 }
3119 });';
3120
3121 $html .= 'panoshow2' . $id . '.on("load", function (){
3122 // if(localStorage.getItem("vr_mode") == "off") {
3123 if( vr_mode == "off") {
3124 jQuery(".vr-mode-title").hide();
3125 }
3126 else {
3127 jQuery("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3128 jQuery("#pano' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3129 jQuery("#pano2' . $id . ' .pnlm-panorama-info").hide();
3130 jQuery("#pano' . $id . ' .pnlm-panorama-info").hide();
3131 jQuery(".vr-mode-title").show();
3132 }
3133 });';
3134 }
3135
3136 $html .= 'jQuery("#pano' . $id . ' .wpvr-floor-map .floor-plan-pointer").on("click",function(){
3137 var scene_id = jQuery(this).attr("scene_id");
3138 panoshow' . $id . '.loadScene(scene_id)
3139 jQuery(".floor-plan-pointer").removeClass("add-pulse")
3140 jQuery(this).addClass("add-pulse")
3141 });';
3142
3143 if ($scene_animation_enabled && is_plugin_active('wpvr-pro/wpvr-pro.php') ) {
3144 $animation_js = apply_filters('wpvr_scene_animation_js', $id, $animation_type, $animationDuration, $animationDelay);
3145 if (!empty($animation_js)) {
3146 $html .= $animation_js;
3147 $html .= 'panoshow' . $id . '.on("load", function (scene){
3148 if (typeof changeScene === "function") {
3149 changeScene();
3150 } else {
3151 console.warn("changeScene function is not defined.");
3152 }
3153 });';
3154 }
3155 }
3156
3157
3158 $html .= '
3159 panoshow' . $id . '.on("mousemove", function (data){
3160 jQuery(".add-pulse").css({"transform":"rotate("+data.yaw+"deg)"});
3161 });
3162 ';
3163
3164
3165
3166 $status = get_option('wpvr_edd_license_status');
3167 if ($status !== false && 'valid' == $status && $is_pro) {
3168 $html .= 'panoshow' . $id . '.on("scenechange", function (scene){
3169 jQuery(".center-pointer").removeClass("wpvr-pluse-effect")
3170 jQuery(".floor-plan-pointer").each(function(index ,element){
3171 var scene_id = jQuery(this).attr("scene_id");
3172 if( active_scene == scene_id ){
3173 jQuery(".floor-plan-pointer").removeClass("add-pulse")
3174 jQuery(this).addClass("add-pulse")
3175 }
3176 });
3177
3178 });';
3179 $html .= 'panoshow' . $id . '.on("load", function (){
3180 if(jQuery(".floor-plan-pointer").length > 0){
3181 jQuery(".floor-plan-pointer").each(function(index ,element){
3182 var scene_id = jQuery(this).attr("scene_id");
3183 if( active_scene == scene_id ){
3184 jQuery(".floor-plan-pointer").removeClass("add-pulse")
3185 jQuery(this).addClass("add-pulse")
3186 }
3187 });
3188 }
3189 });';
3190 }
3191
3192 if ($status !== false && 'valid' == $status && $is_pro) {
3193 $scene_navigation_content_type = isset($postdata['scene_navigation_content_type']) ? $postdata['scene_navigation_content_type'] : 'scene_id';
3194 $html .= '
3195 jQuery("#pano' . $id . ' .custom-scene-navigation").on("click",function(){
3196 jQuery("#custom-scene-navigation-nav' . $id . ' ul").empty()
3197 if(scenes){
3198 var scene_navigation_content_type = ' . "'" . $scene_navigation_content_type . "'" . ';
3199 var sceneList = scenes.scenes;
3200 var getScene = panoshow' . $id . '.getScene();
3201 for (const key in sceneList) {
3202 let title;
3203 if (scene_navigation_content_type === "scene_title") {
3204 if (sceneList[key].title) {
3205 title = sceneList[key].title;
3206
3207 }else{
3208 if(title == "" || title == undefined){
3209 if (sceneList[key].panorama) {
3210 title = getImageNameWithoutExtension(sceneList[key].panorama);
3211 }
3212 }
3213 }
3214 } else if (scene_navigation_content_type === "scene_image_name") {
3215 if (sceneList[key].panorama) {
3216 title = getImageNameWithoutExtension(sceneList[key].panorama);
3217 }
3218 } else {
3219 title = key;
3220 }
3221 if (sceneList.hasOwnProperty(key)) {
3222 if( key === getScene){
3223 jQuery("#custom-scene-navigation-nav' . $id . ' ul").append("<li class=\"scene-navigation-list active\" scene_id= " + key + " >" + title + "</li>");
3224 }else{
3225 jQuery("#custom-scene-navigation-nav' . $id . ' ul").append("<li class=\"scene-navigation-list\" scene_id= " + key + " >" + title + "</li>");
3226 }
3227 }
3228 }
3229 }
3230 jQuery("#custom-scene-navigation-nav' . $id . '").toggleClass("visible");
3231 });
3232 ';
3233
3234 $html .= 'function getImageNameWithoutExtension(imageUrl) {
3235 // Split the URL by "/"
3236 var parts = imageUrl.split("/");
3237
3238 // Get the last part which contains the image name
3239 var imageNameWithExtension = parts[parts.length - 1];
3240
3241 // Split the image name by period (.)
3242 var imageNameParts = imageNameWithExtension.split(".");
3243
3244 // Remove the last part (which is the extension) and join the remaining parts
3245 var imageNameWithoutExtension = imageNameParts.slice(0, -1).join(".");
3246
3247 // Return the image name without extension
3248 return imageNameWithoutExtension;
3249 }';
3250
3251
3252 $html .= '
3253 jQuery("#pano' . $id . ' #custom-scene-navigation-nav' . $id . ' ul").on("click", "li.scene-navigation-list", function() {
3254 if (scenes) {
3255 jQuery(this).siblings("li").removeClass("active");
3256 jQuery(this).addClass("active");
3257
3258 var scene_key = jQuery(this).attr("scene_id");
3259 panoshow' . $id . '.loadScene(scene_key);
3260 }
3261 });
3262 ';
3263 }
3264
3265 //Duplicate mode only for vr mode end===//
3266 $html .= 'panoshow' . $id . '.on("load", function (){
3267
3268 // if(localStorage.getItem("vr_mode") == "off") {
3269 if( vr_mode == "off") {
3270 jQuery(".vr-mode-title").hide();
3271 }
3272 else {
3273 jQuery("#pano2' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3274 jQuery("#pano' . $id . ' .pnlm-compass.pnlm-controls.pnlm-control").css("display","none");
3275 jQuery("#pano2' . $id . ' .pnlm-panorama-info").hide();
3276 jQuery("#pano' . $id . ' .pnlm-panorama-info").hide();
3277 jQuery(".vr-mode-title").show();
3278 }
3279
3280
3281 if (jQuery("#pano' . $id . '").children().children(".pnlm-panorama-info:visible").length > 0) {
3282 jQuery("#controls' . $id . '").css("bottom", "80px");
3283 }
3284 else {
3285 jQuery("#controls' . $id . '").css("bottom", "5px");
3286 }
3287 });';
3288
3289
3290 $html .= '
3291 if (scenes.autoRotate) {
3292 var wpvrAutoRotateTimer' . $id . ' = null;
3293 var wpvrAutoRotateStopDelay' . $id . ' = parseInt(scenes.autoRotateStopDelay, 10) || 0;
3294 var wpvrScheduleAutoRotate' . $id . ' = function () {
3295 clearTimeout(wpvrAutoRotateTimer' . $id . ');
3296 if (wpvrAutoRotateStopDelay' . $id . ' > 0) {
3297 wpvrAutoRotateTimer' . $id . ' = setTimeout(function () {
3298 panoshow' . $id . '.stopAutoRotate();
3299 }, wpvrAutoRotateStopDelay' . $id . ');
3300 } else {
3301 wpvrAutoRotateTimer' . $id . ' = setTimeout(function () {
3302 panoshow' . $id . '.startAutoRotate(scenes.autoRotate, 0);
3303 }, 3000);
3304 }
3305 };
3306 panoshow' . $id . '.on("load", wpvrScheduleAutoRotate' . $id . ');
3307 panoshow' . $id . '.on("scenechange", wpvrScheduleAutoRotate' . $id . ');
3308 }
3309 ';
3310 $html .= 'var touchtime = 0;';
3311 if ($vrgallery) {
3312 if (isset($panodata["scene-list"])) {
3313 foreach ($panodata["scene-list"] as $panoscenes) {
3314 $scene_key = $panoscenes['scene-id'];
3315 $scene_key_gallery = $panoscenes['scene-id'] . '_gallery_' . $id;
3316 $img_src_url = $panoscenes['scene-attachment-url'];
3317 // $html .= 'document.getElementById("' . $scene_key_gallery . '").addEventListener("click", function(e) { ';
3318 // $html .= 'if (touchtime == 0) {';
3319 // $html .= 'touchtime = new Date().getTime();';
3320 // $html .= '} else {';
3321 // $html .= 'if (((new Date().getTime()) - touchtime) < 800) {';
3322 // $html .= 'panoshow' . $id . '.loadScene("' . $scene_key . '");';
3323 // $html .= 'touchtime = 0;';
3324 // $html .= '} else {';
3325 // $html .= 'touchtime = new Date().getTime();';
3326 // $html .= '}';
3327 // $html .= '}';
3328 // $html .= '});';
3329 $html .= '
3330 jQuery(document).on("click","#' . $scene_key_gallery . '",function() {
3331 panoshow' . $id . '.loadScene("' . $scene_key . '");
3332 });
3333 ';
3334 }
3335 }
3336
3337 $html .= '
3338 var owlGallery' . $id . ' = jQuery("#sccontrols' . $id . '").owlCarousel({
3339 items: 1,
3340 loop: true,
3341 nav: false,
3342 dots: false,
3343 margin: 5,
3344 stagePadding: 30
3345 });
3346 jQuery("#pano' . $id . '").on("click", ".wpvr_owl_prev", function() {
3347 owlGallery' . $id . '.trigger("prev.owl.carousel");
3348 });
3349 jQuery("#pano' . $id . '").on("click", ".wpvr_owl_next", function() {
3350 owlGallery' . $id . '.trigger("next.owl.carousel");
3351 });
3352 ';
3353 }
3354
3355
3356
3357 //===Custom Control===//
3358 if (isset($custom_control)) {
3359 if ($custom_control['panupSwitch'] == "on" && $status == 'valid' && $is_pro) {
3360 $html .= 'document.getElementById("pan-up' . $id . '").addEventListener("click", function(e) {';
3361 $html .= 'panoshow' . $id . '.setPitch(panoshow' . $id . '.getPitch() + 10);';
3362 $html .= '});';
3363 }
3364
3365 if ($custom_control['panDownSwitch'] == "on" && $status == 'valid' && $is_pro) {
3366 $html .= 'document.getElementById("pan-down' . $id . '").addEventListener("click", function(e) {';
3367 $html .= 'panoshow' . $id . '.setPitch(panoshow' . $id . '.getPitch() - 10);';
3368 $html .= '});';
3369 }
3370
3371 if ($custom_control['panLeftSwitch'] == "on" && $status == 'valid' && $is_pro) {
3372 $html .= 'document.getElementById("pan-left' . $id . '").addEventListener("click", function(e) {';
3373 $html .= 'panoshow' . $id . '.setYaw(panoshow' . $id . '.getYaw() - 10);';
3374 $html .= '});';
3375 }
3376
3377 if ($custom_control['panRightSwitch'] == "on" && $status == 'valid' && $is_pro) {
3378 $html .= 'document.getElementById("pan-right' . $id . '").addEventListener("click", function(e) {';
3379 $html .= 'panoshow' . $id . '.setYaw(panoshow' . $id . '.getYaw() + 10);';
3380 $html .= '});';
3381 }
3382
3383 if ($custom_control['panZoomInSwitch'] == "on") {
3384 $html .= 'document.getElementById("zoom-in' . $id . '").addEventListener("click", function(e) {';
3385 $html .= 'panoshow' . $id . '.setHfov(panoshow' . $id . '.getHfov() - 10);';
3386 $html .= '});';
3387 }
3388
3389 if ($custom_control['panZoomOutSwitch'] == "on") {
3390 $html .= 'document.getElementById("zoom-out' . $id . '").addEventListener("click", function(e) {';
3391 $html .= 'panoshow' . $id . '.setHfov(panoshow' . $id . '.getHfov() + 10);';
3392 $html .= '});';
3393 }
3394
3395 if ($custom_control['panFullscreenSwitch'] == "on" && $status == 'valid' && $is_pro) {
3396 $html .= 'document.getElementById("fullscreen' . $id . '").addEventListener("click", function(e) {';
3397 $html .= 'panoshow' . $id . '.toggleFullscreen();';
3398 $html .= '});';
3399 $html .= '(function() {';
3400 $html .= 'function wpvrFsChange' . $id . '() {';
3401 $html .= 'var fsIcon = document.querySelector("#fullscreen' . $id . ' i");';
3402 $html .= 'if (!fsIcon) return;';
3403 $html .= 'if (document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement) {';
3404 $html .= 'fsIcon.classList.remove("fa-expand"); fsIcon.classList.add("fa-minimize");';
3405 $html .= '} else {';
3406 $html .= 'fsIcon.classList.remove("fa-minimize"); fsIcon.classList.add("fa-expand");';
3407 $html .= '}';
3408 $html .= '}';
3409 $html .= 'document.addEventListener("fullscreenchange", wpvrFsChange' . $id . ');';
3410 $html .= 'document.addEventListener("webkitfullscreenchange", wpvrFsChange' . $id . ');';
3411 $html .= 'document.addEventListener("mozfullscreenchange", wpvrFsChange' . $id . ');';
3412 $html .= 'document.addEventListener("MSFullscreenChange", wpvrFsChange' . $id . ');';
3413 $html .= '})();';
3414 }
3415
3416 if ($custom_control['backToHomeSwitch'] == "on" && $status == 'valid' && $is_pro) {
3417 $html .= 'document.getElementById("backToHome' . $id . '").addEventListener("click", function(e) {';
3418 $html .= 'panoshow' . $id . '.loadScene("' . $default_scene . '");';
3419 $html .= '});';
3420 }
3421
3422 if ($gyro_button_enabled && 'valid' == $status && $is_pro) {
3423 $html .= '
3424 (function() {
3425 var gyroButton = document.getElementById("gyroscope' . $id . '");
3426 var gyroIcon = gyroButton ? gyroButton.querySelector("i") : null;
3427 var activeColor = ' . wp_json_encode($custom_control['gyroscopeColor']) . ';
3428 var permissionGranted = false;
3429
3430 if (!gyroButton || !gyroIcon) {
3431 return;
3432 }
3433
3434 function updateGyroscopeState() {
3435 gyroIcon.style.color = panoshow' . $id . '.isOrientationActive()
3436 ? activeColor
3437 : "red";
3438 }
3439
3440 function startGyroscope() {
3441 if (!panoshow' . $id . '.isOrientationSupported()) {
3442 updateGyroscopeState();
3443 return;
3444 }
3445
3446 panoshow' . $id . '.startOrientation();
3447 window.setTimeout(updateGyroscopeState, 0);
3448 }
3449
3450 function requestGyroscopePermission() {
3451 var orientationEvent = window.DeviceOrientationEvent;
3452 if (orientationEvent) {
3453 if (typeof orientationEvent.requestPermission === "function") {
3454 if (!permissionGranted) {
3455 orientationEvent.requestPermission()
3456 .then(function(state) {
3457 permissionGranted = state === "granted";
3458 if (permissionGranted) {
3459 startGyroscope();
3460 } else {
3461 updateGyroscopeState();
3462 }
3463 })
3464 .catch(updateGyroscopeState);
3465 return;
3466 }
3467 }
3468 }
3469
3470 startGyroscope();
3471 }
3472
3473 panoshow' . $id . '.on("load", updateGyroscopeState);
3474 panoshow' . $id . '.on("scenechange", updateGyroscopeState);
3475
3476 gyroButton.addEventListener("click", function() {
3477 if (panoshow' . $id . '.isOrientationActive()) {
3478 panoshow' . $id . '.stopOrientation();
3479 updateGyroscopeState();
3480 return;
3481 }
3482
3483 requestGyroscopePermission();
3484 });
3485 })();';
3486 }
3487 }
3488
3489 $angle_up = '<i class="fa fa-angle-up"></i>';
3490 $angle_down = '<i class="fa fa-angle-down"></i>';
3491 $sin_qout = "'";
3492
3493 //===Explainer Script===//
3494 $html .= '
3495 jQuery(document).on("click","#explainer_button_' . $id . '",function() {
3496 jQuery("#explainer' . $id . '").slideToggle(function(){
3497 var $explainerVideoId = jQuery("#explainer' . $id . '");
3498 var $explainerVideoIframe = $explainerVideoId.find("iframe");
3499 var explainerVideoIframSrc = $explainerVideoIframe.attr("src");
3500 $explainerVideoIframe.attr("src", "");
3501 $explainerVideoIframe.attr("src", explainerVideoIframSrc);
3502 });
3503 });
3504
3505 jQuery(document).on("click", ".close-explainer-video", function() {
3506 var $explainer = jQuery(this).parent(".explainer");
3507 var $iframe = $explainer.find("iframe");
3508 var src = $iframe.attr("src");
3509 $iframe.attr("src", "");
3510 $explainer.hide();
3511 $iframe.attr("src", src);
3512 });
3513
3514 jQuery(document).on("click","#pano' . $id . '",function(event) {
3515 var isActiveModal = event.target.closest(".custom-ifram-wrapper");
3516 var isForm = event.target.closest(".wpvr-hotspot-tweak-contents");
3517 var isHotspot = event.target.closest(".pnlm-hotspot-base");
3518 if( isActiveModal == null && isForm == null && isHotspot == null){
3519 jQuery(".custom-ifram-wrapper .custom-ifram").empty();
3520 jQuery(".custom-ifram-wrapper").hide();
3521 jQuery(this).removeClass("show-modal");
3522 jQuery(".wpvr-hotspot-tweak-contents-wrapper").hide("show-modal");
3523 }else if(isForm != null){
3524 jQuery(this).addClass("show-modal");
3525 }
3526 });
3527
3528 ';
3529 //===Explainer Script End===//
3530
3531 //===generic form script===//
3532 if (isset($postdata["genericform"]) && $postdata["genericform"] === 'on') {
3533 $html .= '
3534 jQuery(document).on("click","#generic_form_button_' . $id . '",function() {
3535 jQuery("#wpvr-generic-form' . $id . '").fadeToggle();
3536 });
3537
3538 jQuery(document).on("click",".close-generic-form",function() {
3539 jQuery(this).parent(".wpvr-generic-form").fadeOut()
3540 });
3541 ';
3542 }
3543
3544 //===generic from script===//
3545
3546 //===Floor map Script===//
3547 $html .= '
3548 jQuery(document).on("click","#floor_map_button_' . $id . '",function() {
3549 jQuery("#wpvr-floor-map' . $id . '").toggle().removeClass("fullwindow");
3550 });
3551
3552 jQuery(document).on("dblclick","#wpvr-floor-map' . $id . '",function(){
3553 jQuery(this).addClass("fullwindow");
3554 jQuery(this).parents(".pano-wrap").addClass("show-modal");
3555 });
3556
3557 jQuery(document).on("click",".close-floor-map-plan",function() {
3558 jQuery(this).parent(".wpvr-floor-map").hide();
3559 jQuery(this).parent(".wpvr-floor-map").removeClass("fullwindow");
3560 jQuery(this).parents(".pano-wrap").removeClass("show-modal");
3561 });
3562
3563 ';
3564 //===Floor map Script End===//
3565
3566 if ($vrgallery_display) {
3567 if (!$autoload) {
3568 $html .= '
3569 jQuery(document).ready(function($){
3570 jQuery("#sccontrols' . $id . '").hide();
3571 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3572 jQuery("#sccontrols' . $id . '").hide();
3573 jQuery("#pano' . $id . ' .wpvr_slider_nav").hide();
3574 });
3575 ';
3576
3577 $html .= '
3578 var slide' . $id . ' = "down";
3579 jQuery(document).on("click","#vrgcontrols' . $id . '",function() {
3580
3581 if (slide' . $id . ' == "up") {
3582 jQuery(".vrgctrl' . $id . '").empty();
3583 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3584 slide' . $id . ' = "down";
3585 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3586 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3587 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3588 if (jQuery(this).is(":visible")) {
3589 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3590 "display": "flex",
3591 "justify-content": "center",
3592 "align-items": "center",
3593 "gap": "15px"
3594 });
3595 }
3596 }
3597 if (jQuery(".bricks-is-frontend").length) {
3598 if (jQuery(this).is(":visible")) {
3599 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3600 "display": "flex",
3601 "justify-content": "center",
3602 "align-items": "center"
3603 });
3604 }
3605 }
3606 });
3607 }
3608 else {
3609 jQuery(".vrgctrl' . $id . '").empty();
3610 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3611 slide' . $id . ' = "up";
3612 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3613 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3614 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3615 if (jQuery(this).is(":visible")) {
3616 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3617 "display": "flex",
3618 "justify-content": "center",
3619 "align-items": "center",
3620 "gap": "15px"
3621 });
3622 }
3623 }
3624 if (jQuery(".bricks-is-frontend").length) {
3625 if (jQuery(this).is(":visible")) {
3626 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3627 "display": "flex",
3628 "justify-content": "center",
3629 "align-items": "center"
3630 });
3631 }
3632 }
3633 });
3634 }
3635 });
3636 ';
3637 } else {
3638 $html .= '
3639 jQuery(document).ready(function($){
3640 jQuery("#sccontrols' . $id . '").show();
3641 jQuery("#pano' . $id . ' .wpvr_slider_nav").show();
3642 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3643 });
3644 ';
3645
3646 $html .= '
3647 var slide' . $id . ' = "down";
3648 jQuery(document).on("click","#vrgcontrols' . $id . '",function() {
3649
3650 if (slide' . $id . ' == "up") {
3651 jQuery(".vrgctrl' . $id . '").empty();
3652 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3653 slide' . $id . ' = "down";
3654 }
3655 else {
3656 jQuery(".vrgctrl' . $id . '").empty();
3657 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3658 slide' . $id . ' = "up";
3659 }
3660 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3661 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3662 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3663 if (jQuery(this).is(":visible")) {
3664 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3665 "display": "flex",
3666 "justify-content": "center",
3667 "align-items": "center",
3668 "gap": "15px"
3669 });
3670 }
3671 }
3672 if (jQuery(".bricks-is-frontend").length) {
3673 if (jQuery(this).is(":visible")) {
3674 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3675 "display": "flex",
3676 "justify-content": "center",
3677 "align-items": "center"
3678 });
3679 }
3680 }
3681 });
3682 });
3683 ';
3684 }
3685 } else {
3686 $html .= '
3687 jQuery(document).ready(function($){
3688 jQuery("#sccontrols' . $id . '").hide();
3689 jQuery("#pano' . $id . ' .wpvr_slider_nav").hide();
3690 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3691 });
3692 ';
3693
3694 $html .= '
3695 var slide' . $id . ' = "down";
3696 jQuery(document).on("click","#vrgcontrols' . $id . '",function() {
3697
3698 if (slide' . $id . ' == "up") {
3699 jQuery(".vrgctrl' . $id . '").empty();
3700 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_up . $sin_qout . ');
3701 slide' . $id . ' = "down";
3702 }
3703 else {
3704 jQuery(".vrgctrl' . $id . '").empty();
3705 jQuery(".vrgctrl' . $id . '").html(' . $sin_qout . $angle_down . $sin_qout . ');
3706 slide' . $id . ' = "up";
3707 }
3708 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3709 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3710 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3711 if (jQuery(this).is(":visible")) {
3712 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3713 "display": "flex",
3714 "justify-content": "center",
3715 "align-items": "center",
3716 "gap": "15px"
3717 });
3718 }
3719 }
3720 if (jQuery(".bricks-is-frontend").length) {
3721 if (jQuery(this).is(":visible")) {
3722 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3723 "display": "flex",
3724 "justify-content": "center",
3725 "align-items": "center"
3726 });
3727 }
3728 }
3729 });
3730 });
3731 ';
3732 }
3733
3734 if (!$autoload) {
3735 $html .= '
3736
3737 jQuery(document).ready(function(){
3738 jQuery("#controls' . $id . '").hide();
3739 jQuery("#zoom-in-out-controls' . $id . '").hide();
3740 jQuery("#adcontrol' . $id . '").hide();
3741 jQuery("#explainer_button_' . $id . '").hide();
3742 jQuery("#generic_form_button_' . $id . '").hide();
3743 jQuery("#floor_map_button_' . $id . '").hide();
3744 jQuery("#vrgcontrols' . $id . '").hide();
3745 jQuery("#cp-logo-controls").hide();
3746 jQuery(".custom-scene-navigation").hide();
3747 jQuery("#pano' . $id . '").find(".pnlm-panorama-info").hide();
3748 });
3749
3750 ';
3751
3752 if ($vrgallery_display) {
3753 $html .= 'var load_once = "true";';
3754 $html .= 'panoshow' . $id . '.on("load", function (){
3755 if (load_once == "true") {
3756 load_once = "false";
3757 jQuery("#sccontrols' . $id . '").slideToggle(function(){
3758 if (jQuery(".elementor-edit-mode .elementor-widget-container").length) {
3759 if (jQuery(this).is(":visible")) {
3760 jQuery(".elementor-edit-mode .elementor-widget-container .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css("display", "flex");
3761 }
3762 }
3763 if (jQuery(".bricks-is-frontend").length) {
3764 if (jQuery(this).is(":visible")) {
3765 jQuery(".bricks-is-frontend .wpvr-cardboard .pnlm-container #sccontrols' . $id . '").css({
3766 "display": "flex",
3767 "justify-content": "center",
3768 "align-items": "center"
3769 });
3770 }
3771 }
3772 });
3773 jQuery("#pano' . $id . ' .wpvr_slider_nav").slideToggle();
3774 }
3775 });';
3776 }
3777
3778 $html .= 'panoshow' . $id . '.on("load", function (){
3779 jQuery("#controls' . $id . '").show();
3780 jQuery("#zoom-in-out-controls' . $id . '").show();
3781 jQuery("#adcontrol' . $id . '").show();
3782 jQuery("#explainer_button_' . $id . '").show();
3783 jQuery("#generic_form_button_' . $id . '").show();
3784 jQuery("#floor_map_button_' . $id . '").show();
3785 jQuery("#vrgcontrols' . $id . '").show();
3786 jQuery("#cp-logo-controls").show();
3787 jQuery(".custom-scene-navigation").show();
3788 jQuery("#pano' . $id . '").find(".pnlm-panorama-info").show();
3789 });';
3790 }
3791
3792 $previewText = $postdata['previewtext'] ?? 'Click To Load Panorama';
3793 if ($previewText) {
3794 $html .= '
3795 jQuery("#pano' . $id . '").children(".pnlm-ui").find(".pnlm-load-button p").text("' . $previewText. '")
3796 ';
3797 } else {
3798 $html .= '
3799 jQuery("#pano' . $id . '").children(".pnlm-ui").find(".pnlm-load-button p").text("Click To Load Panorama")
3800 ';
3801 }
3802
3803 $html .= 'jQuery("#pano' . $id . ' .pnlm-title-box").on("mouseenter", function(){
3804 jQuery(this).attr("title", jQuery(this).text());
3805 });
3806 jQuery("#pano' . $id . ' .pnlm-title-box").on("mouseleave", function(){
3807 jQuery(this).removeAttr("title");
3808 });';
3809 $html .= '});';
3810 $html .= '</script>';
3811
3812 $tour_data = [];
3813 if(defined("WPVR_PRO_VERSION")){
3814 $tour_data = array(
3815 'explainerControlSwitch' => (
3816 isset( $postdata['explainerSwitch'] )
3817 && in_array( $postdata['explainerSwitch'], array( true, 1, '1', 'on' ), true )
3818 ) ? 'on' : 'off',
3819 'floor_plan_enable' => $floor_plan_enable ?? false,
3820 'floor_plan_image' => $floor_plan_image ?? '',
3821 'custom_control' => $custom_control ?? [],
3822 );
3823 }
3824 return apply_filters('wpvr_generate_tour_layout_html', $html ,$postdata ,$id, $tour_data);
3825 }
3826
3827 function sanitize_content_preserve_styles($content) {
3828 // Decode HTML entities first (in case content was encoded in database)
3829 $content = html_entity_decode($content, ENT_QUOTES | ENT_HTML5, 'UTF-8');
3830
3831 // Escape <script> blocks to display as text instead of removing them
3832 $content = preg_replace_callback('/<script\b[^>]*>(.*?)<\/script>/si', function($matches) {
3833 return esc_html($matches[0]); // Convert to plain text
3834 }, $content);
3835
3836 // Strip dangerous URL-based attributes
3837 $content = preg_replace('/(href|action|formaction)\s*=\s*["\']?\s*(javascript|vbscript|data|about):/i', '$1=""', $content);
3838
3839 // Escape inline event handlers (onclick, onhover, etc.) to display as text
3840 $content = preg_replace_callback('/\s*(on\w+)\s*=\s*(["\'])([^"\']*)\2/i', function($matches) {
3841 // Escape the attribute value but keep the attribute name visible as text
3842 return ' ' . esc_html($matches[1]) . '=' . $matches[2] . esc_html($matches[3]) . $matches[2];
3843 }, $content);
3844 $content = preg_replace_callback('/\s*(on\w+)\s*=\s*([^>\s]+)/i', function($matches) {
3845 // Handle unquoted event handlers
3846 return ' ' . esc_html($matches[1]) . '=' . esc_html($matches[2]);
3847 }, $content);
3848
3849 // Remove all unsafe embedded/interactive elements except iframe
3850 $content = preg_replace('/<(object|embed|applet|frame|frameset|meta|link|base|form|input|button|textarea|select|option)\b[^>]*>/i', '', $content);
3851 $content = preg_replace('/<\/(object|embed|applet|frame|frameset|meta|link|base|form|input|button|textarea|select|option)>/i', '', $content);
3852
3853 // Clean style attributes safely
3854 $content = preg_replace_callback('/style\s*=\s*["\']([^"\']*)["\']/', function($matches) {
3855 $style = $matches[1];
3856 $style = preg_replace('/expression\s*\(/i', '', $style);
3857 $style = preg_replace('/(javascript|vbscript|data|about)\s*:/i', '', $style);
3858 $style = preg_replace('/url\s*\(\s*["\']?\s*(javascript|vbscript|data):/i', '', $style);
3859 $style = preg_replace('/behavior\s*:/i', '', $style);
3860 $style = preg_replace('/-moz-binding\s*:/i', '', $style);
3861 return 'style="' . esc_attr($style) . '"';
3862 }, $content);
3863
3864 // Sanitize <style> blocks
3865 $content = preg_replace_callback('/<style\b[^>]*>(.*?)<\/style>/si', function($matches) {
3866 $css = $matches[1];
3867 $css = preg_replace('/(expression|javascript|vbscript|data|about)\s*:/i', '', $css);
3868 $css = preg_replace('/url\s*\(\s*["\']?\s*(javascript|vbscript|data):/i', '', $css);
3869 $css = preg_replace('/behavior\s*:/i', '', $css);
3870 $css = preg_replace('/-moz-binding\s*:/i', '', $css);
3871 return '<style>' . esc_html($css) . '</style>';
3872 }, $content);
3873
3874 // Allow iframes from safe sources only (e.g., YouTube, Vimeo)
3875 $allowed_tags = wp_kses_allowed_html('post');
3876 $allowed_tags['iframe'] = [
3877 'src' => true,
3878 'width' => true,
3879 'height' => true,
3880 'frameborder' => true,
3881 'allowfullscreen' => true,
3882 'class' => true,
3883 'style' => true,
3884 'title' => true,
3885 'allow' => true,
3886 'name' => true,
3887 'referrerpolicy' => true,
3888 'loading' => true,
3889 'sandbox' => true,
3890 ];
3891 $allowed_tags['img'] = [
3892 'src' => true,
3893 'alt' => true,
3894 'title' => true,
3895 'width' => true,
3896 'height' => true,
3897 'class' => true,
3898 'id' => true,
3899 'style' => true,
3900 'loading' => true,
3901 'srcset' => true,
3902 'sizes' => true,
3903 ];
3904
3905 // Apply wp_kses() to keep only allowed tags/attributes
3906 $content = wp_kses($content, $allowed_tags);
3907
3908 // Finally, validate iframe src for security (allow https only, block javascript: etc.)
3909 $content = preg_replace_callback('/<iframe[^>]+src=["\']([^"\']+)["\'][^>]*>(?:<\/iframe>)?/i', function($matches) {
3910 $src = $matches[1];
3911 // Allow any https:// or http:// URL, but block javascript:, data:, vbscript:, etc.
3912 if (preg_match('/^(https?:)?\/\//i', $src) && !preg_match('/^(javascript|data|vbscript|about):/i', $src)) {
3913 return $matches[0]; // keep safe iframe
3914 }
3915 // Strip unsafe iframe
3916 return '';
3917 }, $content);
3918
3919 return $content;
3920 }
3921 function wpvr_hex2rgb($colour)
3922 {
3923 if (isset($colour[0]) && $colour[0] == '#') {
3924 $colour = substr($colour, 1);
3925 }
3926 if (strlen($colour) == 6) {
3927 list($r, $g, $b) = array($colour[0] . $colour[1], $colour[2] . $colour[3], $colour[4] . $colour[5]);
3928 } elseif (strlen($colour) == 3) {
3929 list($r, $g, $b) = array($colour[0] . $colour[0], $colour[1] . $colour[1], $colour[2] . $colour[2]);
3930 } else {
3931 return false;
3932 }
3933 $r = hexdec($r);
3934 $g = hexdec($g);
3935 $b = hexdec($b);
3936 return array($r . ', ' . $g . ', ' . $b);
3937 }
3938
3939 function wpvr_HTMLToRGB($htmlCode)
3940 {
3941 $r = 0;
3942 $g = 0;
3943 $b = 0;
3944 if (isset($htmlCode[0]) && $htmlCode[0] == '#') {
3945 $htmlCode = substr($htmlCode, 1);
3946 }
3947
3948 if (strlen($htmlCode) == 3) {
3949 $htmlCode = $htmlCode[0] . $htmlCode[0] . $htmlCode[1] . $htmlCode[1] . $htmlCode[2] . $htmlCode[2];
3950 }
3951
3952 if (isset($htmlCode[0]) && isset($htmlCode[1])) {
3953 $r = hexdec($htmlCode[0] . $htmlCode[1]);
3954 }
3955 if (isset($htmlCode[2]) && isset($htmlCode[3])) {
3956 $g = hexdec($htmlCode[2] . $htmlCode[3]);
3957 }
3958 if (isset($htmlCode[4]) && isset($htmlCode[5])) {
3959 $b = hexdec($htmlCode[4] . $htmlCode[5]);
3960 }
3961
3962 return $b + ($g << 0x8) + ($r << 0x10);
3963 }
3964
3965 function wpvr_RGBToHSL($RGB)
3966 {
3967 $r = 0xFF & ($RGB >> 0x10);
3968 $g = 0xFF & ($RGB >> 0x8);
3969 $b = 0xFF & $RGB;
3970
3971 $r = ((float)$r) / 255.0;
3972 $g = ((float)$g) / 255.0;
3973 $b = ((float)$b) / 255.0;
3974
3975 $maxC = max($r, $g, $b);
3976 $minC = min($r, $g, $b);
3977
3978 $l = ($maxC + $minC) / 2.0;
3979
3980 if ($maxC == $minC) {
3981 $s = 0;
3982 $h = 0;
3983 } else {
3984 if ($l < .5) {
3985 $s = ($maxC - $minC) / ($maxC + $minC);
3986 } else {
3987 $s = ($maxC - $minC) / (2.0 - $maxC - $minC);
3988 }
3989 if ($r == $maxC) {
3990 $h = ($g - $b) / ($maxC - $minC);
3991 }
3992 if ($g == $maxC) {
3993 $h = 2.0 + ($b - $r) / ($maxC - $minC);
3994 }
3995 if ($b == $maxC) {
3996 $h = 4.0 + ($r - $g) / ($maxC - $minC);
3997 }
3998
3999 $h = $h / 6.0;
4000 }
4001
4002 $h = (int)round(255.0 * $h);
4003 $s = (int)round(255.0 * $s);
4004 $l = (int)round(255.0 * $l);
4005
4006 return (object) array('hue' => $h, 'saturation' => $s, 'lightness' => $l);
4007 }
4008
4009 add_action('rest_api_init', 'wpvr_rest_data_route');
4010 function wpvr_rest_data_route()
4011 {
4012 register_rest_route('wpvr/v1', '/panodata/', array(
4013 'methods' => 'GET',
4014 'callback' => 'wpvr_rest_data_set',
4015 'permission_callback' => 'wpvr_rest_route_permission'
4016 ));
4017 }
4018
4019 function wpvr_rest_route_permission()
4020 {
4021 return true;
4022 }
4023
4024 function wpvr_rest_data_set()
4025 {
4026 $query = new WP_Query(array(
4027 'post_type' => 'wpvr_item',
4028 'posts_per_page' => -1,
4029 ));
4030
4031 $wpvr_list = array();
4032 $list_none = array('value' => 0, 'label' => 'None');
4033 array_push($wpvr_list, $list_none);
4034 while ($query->have_posts()) {
4035 $query->the_post();
4036 $title = mb_convert_encoding(get_the_title(), 'UTF-8', 'HTML-ENTITIES');
4037 $post_id = get_the_ID();
4038 $title = $post_id . ' : ' . $title;
4039 $list_ob = array('value' => $post_id, 'label' => $title);
4040 array_push($wpvr_list, $list_ob);
4041 }
4042
4043 return $wpvr_list;
4044 }
4045
4046 function wpvr_isMobileDevice()
4047 {
4048 return preg_match("/(android|avantgo|blackberry|bolt|boost|cricket|docomo|fone|hiptop|mini|mobi|palm|phone|pie|tablet|up\.browser|up\.link|webos|wos)/i", $_SERVER["HTTP_USER_AGENT"]);
4049 }
4050
4051 function wpvr_directory()
4052 {
4053 $upload = wp_upload_dir();
4054 $upload_dir = $upload['basedir'];
4055 $upload_dir_temp = $upload_dir . '/wpvr/temp/';
4056 if (!is_dir($upload_dir_temp)) {
4057 wp_mkdir_p($upload_dir_temp, 0700);
4058 }
4059 }
4060
4061 add_action('admin_init', 'wpvr_directory');
4062
4063
4064 function wpvr_add_role_cap()
4065 {
4066 $editor_active = get_option('wpvr_editor_active');
4067
4068 $author_active = get_option('wpvr_author_active');
4069
4070 $admin = get_role('administrator');
4071 $admin->add_cap('publish_wpvr_tour');
4072 $admin->add_cap('edit_wpvr_tours');
4073 $admin->add_cap('read_wpvr_tour');
4074 $admin->add_cap('edit_wpvr_tour');
4075 $admin->add_cap('edit_wpvr_tours');
4076 $admin->add_cap('publish_wpvr_tours');
4077 $admin->add_cap('publish_wpvr_tour');
4078 $admin->add_cap('delete_wpvr_tour');
4079 $admin->add_cap('edit_other_wpvr_tours');
4080 $admin->add_cap('delete_other_wpvr_tours');
4081
4082 if ($editor_active == "true") {
4083 $editor = get_role('editor');
4084 if ($editor) {
4085 $editor->add_cap('publish_wpvr_tour');
4086 $editor->add_cap('edit_wpvr_tours');
4087 $editor->add_cap('read_wpvr_tour');
4088 $editor->add_cap('edit_wpvr_tour');
4089 $editor->add_cap('edit_wpvr_tours');
4090 $editor->add_cap('publish_wpvr_tours');
4091 $editor->add_cap('publish_wpvr_tour');
4092 $editor->add_cap('delete_wpvr_tour');
4093 $editor->add_cap('edit_other_wpvr_tours');
4094 $editor->add_cap('delete_other_wpvr_tours');
4095 }
4096 } else {
4097 $editor = get_role('editor');
4098 if ($editor) {
4099 $editor->remove_cap('publish_wpvr_tour');
4100 $editor->remove_cap('edit_wpvr_tours');
4101 $editor->remove_cap('read_wpvr_tour');
4102 $editor->remove_cap('edit_wpvr_tour');
4103 $editor->remove_cap('edit_wpvr_tours');
4104 $editor->remove_cap('publish_wpvr_tours');
4105 $editor->remove_cap('publish_wpvr_tour');
4106 $editor->remove_cap('delete_wpvr_tour');
4107 $editor->remove_cap('edit_other_wpvr_tours');
4108 $editor->remove_cap('delete_other_wpvr_tours');
4109 }
4110 }
4111
4112 if ($author_active == "true") {
4113 $author = get_role('author');
4114 if ($author) {
4115 $author->add_cap('read_wpvr_tour');
4116 $author->add_cap('edit_wpvr_tour');
4117 $author->add_cap('edit_wpvr_tours');
4118 $author->add_cap('publish_wpvr_tours');
4119 $author->add_cap('publish_wpvr_tour');
4120 $author->add_cap('delete_wpvr_tour');
4121 }
4122 } else {
4123 $author = get_role('author');
4124 if ($author) {
4125 $author->remove_cap('read_wpvr_tour');
4126 $author->remove_cap('edit_wpvr_tour');
4127 $author->remove_cap('edit_wpvr_tours');
4128 $author->remove_cap('publish_wpvr_tours');
4129 $author->remove_cap('publish_wpvr_tour');
4130 $author->remove_cap('delete_wpvr_tour');
4131 }
4132 }
4133
4134 if(is_plugin_active( 'dokan-lite/dokan.php' ) || is_plugin_active( 'dokan-pro/dokan.php' )){
4135 $dokan_vendor_active = get_option('dokan_vendor_active');
4136
4137 if( 'true' === $dokan_vendor_active){
4138 $seller = get_role('seller');
4139 if ($seller) {
4140 $seller->add_cap('read_wpvr_tour');
4141 $seller->add_cap('edit_wpvr_tour');
4142 $seller->add_cap('edit_wpvr_tours');
4143 $seller->add_cap('publish_wpvr_tours');
4144 $seller->add_cap('publish_wpvr_tour');
4145 $seller->add_cap('delete_wpvr_tour');
4146 }
4147 } else{
4148 $seller = get_role('seller');
4149 if ($seller) {
4150 $seller->remove_cap('read_wpvr_tour');
4151 $seller->remove_cap('edit_wpvr_tour');
4152 $seller->remove_cap('edit_wpvr_tours');
4153 $seller->remove_cap('publish_wpvr_tours');
4154 $seller->remove_cap('publish_wpvr_tour');
4155 $seller->remove_cap('delete_wpvr_tour');
4156 }
4157 }
4158 }
4159
4160
4161 }
4162
4163 add_action('admin_init', 'wpvr_add_role_cap', 999);
4164
4165 function wpvr_role_management_from_post_type($args, $post_type)
4166 {
4167 if ('wpvr_item' !== $post_type) {
4168 return $args;
4169 }
4170
4171 $editor_active = get_option('wpvr_editor_active');
4172 $author_active = get_option('wpvr_author_active');
4173 $user = wp_get_current_user();
4174
4175 if ($editor_active == "true") {
4176 if (in_array('editor', (array) $user->roles)) {
4177 $args['show_in_menu'] = true;
4178 }
4179 }
4180
4181 if ($author_active == "true") {
4182 if (in_array('author', (array) $user->roles)) {
4183 $args['show_in_menu'] = true;
4184 }
4185 }
4186
4187 if(is_plugin_active( 'dokan-lite/dokan.php' ) || is_plugin_active( 'dokan-pro/dokan.php' )){
4188 $dokan_vendor_active = get_option('dokan_vendor_active');
4189 if( 'true' === $dokan_vendor_active){
4190 if (in_array('seller', (array) $user->roles)) {
4191 $args['show_in_menu'] = true;
4192 }
4193 }
4194
4195 }
4196
4197 return $args;
4198 }
4199 add_filter('register_post_type_args', 'wpvr_role_management_from_post_type', 10, 2);
4200
4201 function wpvr_cache_admin_notice()
4202 {
4203 $option = get_option('wpvr_warning');
4204 if (!$option) {
4205 ?>
4206 <div class="notice notice-warning" id="wpvr-warning" style="position: relative;">
4207 <p><?php _e('Since you have updated the plugin, please clear the browser cache for smooth functioning. Follow these steps if you are using <a href="https://support.google.com/accounts/answer/32050?co=GENIE.Platform%3DDesktop&hl=en" target="_blank">Google Chrome</a>, <a href="https://support.mozilla.org/en-US/kb/how-clear-firefox-cache" target="_blank">Mozilla Firefox</a>, <a href="https://clear-my-cache.com/en/apple-mac-os/safari.html" target="_blank">Safai</a> or <a href="https://support.microsoft.com/en-us/help/10607/microsoft-edge-view-delete-browser-history" target="_blank">Microsoft Edge</a>', 'wpvr'); ?></p>
4208 <button type="button" id="wpvr-dismissible" class="notice-dismiss"><span class="screen-reader-text">Dismiss this notice.</span></button>
4209 </div>
4210 <?php
4211 }
4212 }
4213 // add_action('admin_notices', 'wpvr_cache_admin_notice');
4214
4215 //===Oxygen widget===//
4216 add_action('plugins_loaded', function () {
4217 if (!class_exists('OxyEl')) {
4218 return;
4219 }
4220 require_once __DIR__ . '/oxygen/oxy-manager.php';
4221 });
4222
4223 add_action('init', 'wpvr_mobile_media_handle');
4224 function wpvr_mobile_media_handle()
4225 {
4226 add_image_size('wpvr_mobile', 4096, 2048); //mobile
4227 }
4228
4229
4230 add_action(
4231 /**
4232 * @param $api \VisualComposer\Modules\Api\Factory
4233 */
4234 'vcv:api',
4235 function ($api) {
4236 $elementsToRegister = [
4237 'wpvrelement',
4238 ];
4239 $pluginBaseUrl = rtrim(plugins_url(basename(__DIR__)), '\\/');
4240 /** @var \VisualComposer\Modules\Elements\ApiController $elementsApi */
4241 $elementsApi = $api->elements;
4242 foreach ($elementsToRegister as $tag) {
4243 $manifestPath = __DIR__ . '/vc/' . $tag . '/manifest.json';
4244 $elementBaseUrl = $pluginBaseUrl . '/vc/' . $tag;
4245 $elementsApi->add($manifestPath, $elementBaseUrl);
4246 }
4247 }
4248 );
4249
4250 function wpvr_redirect_after_activation($plugin)
4251 {
4252 if ($plugin == plugin_basename(__FILE__)) {
4253 $url = admin_url('admin.php?page=rex-wpvr-setup-wizard');
4254 $url = esc_url($url, FILTER_SANITIZE_URL);
4255 exit(wp_safe_redirect($url));
4256 }
4257 }
4258 //add_action('activated_plugin', 'wpvr_redirect_after_activation');
4259
4260 function replace_callback($matches)
4261 {
4262 foreach ($matches as $match) {
4263 return str_replace('<img', '<img decoding="async" ', $match);
4264 }
4265 }
4266
4267
4268 function wpvr_get_explainer_embed_url( $input ) {
4269 $url = esc_url_raw( trim( (string) $input ), array( 'http', 'https' ) );
4270
4271 if ( empty( $url ) || ! preg_match( '#^https?://#i', $url ) ) {
4272 return '';
4273 }
4274
4275 $host = strtolower( (string) wp_parse_url( $url, PHP_URL_HOST ) );
4276 $host = preg_replace( '/^www\./', '', $host );
4277 $path = trim( (string) wp_parse_url( $url, PHP_URL_PATH ), '/' );
4278
4279 if ( 'youtu.be' === $host ) {
4280 $segments = explode( '/', $path );
4281 $video_id = isset( $segments[0] ) ? preg_replace( '/[^A-Za-z0-9_-]/', '', $segments[0] ) : '';
4282
4283 return $video_id ? 'https://www.youtube.com/embed/' . $video_id : '';
4284 }
4285
4286 if ( in_array( $host, array( 'youtube.com', 'm.youtube.com', 'music.youtube.com', 'youtube-nocookie.com' ), true ) ) {
4287 $video_id = '';
4288 $segments = explode( '/', $path );
4289
4290 if ( 'watch' === $path ) {
4291 $query = array();
4292 wp_parse_str( (string) wp_parse_url( $url, PHP_URL_QUERY ), $query );
4293 $video_id = isset( $query['v'] ) ? $query['v'] : '';
4294 } elseif ( isset( $segments[0], $segments[1] ) && in_array( $segments[0], array( 'embed', 'shorts', 'live' ), true ) ) {
4295 $video_id = $segments[1];
4296 }
4297
4298 $video_id = preg_replace( '/[^A-Za-z0-9_-]/', '', (string) $video_id );
4299
4300 return $video_id ? 'https://www.youtube.com/embed/' . $video_id : '';
4301 }
4302
4303 if ( 'vimeo.com' === $host || 'player.vimeo.com' === $host ) {
4304 $segments = array_reverse( array_filter( explode( '/', $path ) ) );
4305
4306 foreach ( $segments as $segment ) {
4307 if ( ctype_digit( $segment ) ) {
4308 return 'https://player.vimeo.com/video/' . $segment;
4309 }
4310 }
4311
4312 return '';
4313 }
4314
4315 return $url;
4316 }
4317
4318 function wpvr_sanitize_iframe_only( $input ) {
4319 // Start with standard allowed post HTML (p, a, strong, etc.)
4320 $allowed_tags = wp_kses_allowed_html( 'post' );
4321
4322 // Explicitly allow <iframe> with specific safe attributes
4323 $allowed_tags['iframe'] = array(
4324 'src' => true,
4325 'width' => true,
4326 'height' => true,
4327 'title' => true,
4328 'frameborder' => true,
4329 'allow' => true,
4330 'allowfullscreen' => true,
4331 'referrerpolicy' => true,
4332 );
4333
4334 $content = trim( (string) $input );
4335
4336 if ( '' === $content ) {
4337 return '';
4338 }
4339
4340 if ( false === stripos( $content, '<iframe' ) ) {
4341 $embed_url = wpvr_get_explainer_embed_url( $content );
4342
4343 if ( $embed_url ) {
4344 $content = sprintf(
4345 '<iframe src="%s" width="100%%" height="100%%" title="Explainer video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen referrerpolicy="strict-origin-when-cross-origin"></iframe>',
4346 esc_url( $embed_url )
4347 );
4348 }
4349 }
4350
4351 return wp_kses( $content, $allowed_tags );
4352 }
4353