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