PluginProbe
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress / 9.1.3
WPVR – 360 Panorama viewer and Virtual Tour Builder for WordPress v9.1.3
9.1.3 9.1.2 9.1.1 9.1.0 9.0.3 9.0.2 9.0.1 9.0.0 8.5.79 8.5.78 8.5.77 8.5.76 8.5.75 8.5.74 8.5.73 8.5.72 8.5.71 8.5.70 8.5.69 8.5.68 8.5.35 8.5.36 8.5.37 8.5.38 8.5.39 All 222 releases
← All changes | src/Api/Transformers/TourTransformer.php +63 -14 9.0.29.1.3 View file →
@@ -53,8 +53,9 @@
53 53 'previewImage' => $raw['preview'] ?? '',
54 54 'sceneFadeDuration' => isset( $raw['scenefadeduration'] ) ? (int) $raw['scenefadeduration'] : 0,
55 55 'showSceneInfo' => ( $raw['scene-info-enabled'] ?? 'on' ) !== 'off',
56 56 'autoRotate' => $auto_rotate,
57 + 'socialShare' => ( $raw['wpvr_social_share'] ?? 'off' ) === 'on',
57 58 ],
58 59 'floorPlan' => $this->floor_plan_to_api( $raw ),
59 60 'backgroundTour' => [
60 61 'enabled' => ( $raw['bg_tour_enabler'] ?? 'off' ) === 'on',
@@ -62,10 +63,10 @@
62 63 'subtitle' => $raw['bg_tour_subtitle'] ?? '',
63 64 ],
64 65 'videoData' => [
65 66 'url' => $raw['vidurl'] ?? '',
66 - 'autoplay' => ( $raw['video-autoplay'] ?? 'off' ) === 'on',
67 - 'loop' => ( $raw['video-loop'] ?? 'off' ) === 'on',
67 + 'autoplay' => ( $raw['video-autoplay'] ?? $raw['autoplay'] ?? 'off' ) === 'on',
68 + 'loop' => ( $raw['video-loop'] ?? $raw['loop'] ?? 'off' ) === 'on',
68 69 ],
69 70 'streetViewData' => [
70 71 'embedUrl' => $raw['streetviewurl'] ?? '',
71 72 ],
@@ -161,8 +162,10 @@
161 162 'tour-type' => $tour_type,
162 163 'vidurl' => esc_url_raw( $video_data['url'] ?? '' ),
163 164 'video-autoplay' => ! empty( $video_data['autoplay'] ) ? 'on' : 'off',
164 165 'video-loop' => ! empty( $video_data['loop'] ) ? 'on' : 'off',
166 + 'autoplay' => ! empty( $video_data['autoplay'] ) ? 'on' : 'off',
167 + 'loop' => ! empty( $video_data['loop'] ) ? 'on' : 'off',
165 168 'streetviewurl' => esc_url_raw( $street_view_data['embedUrl'] ?? '' ),
166 169 'streetview' => ! empty( $street_view_data['embedUrl'] ) ? 'on' : 'off',
167 170 'panodata' => [
168 171 'scene-list' => $this->scenes_from_api(
@@ -170,10 +173,15 @@
170 173 $default_scene_id,
171 174 ( $settings['showSceneInfo'] ?? true ) !== false
172 175 ),
173 176 ],
177 + 'wpvr_social_share' => ! empty( $settings['socialShare'] ) ? 'on' : 'off',
174 178 ];
175 179
180 + if ( $tour_type === 'video' && ! empty( $video_data['url'] ) ) {
181 + $raw['vidid'] = 'vid' . ( $data['tourId'] ?? $data['id'] ?? wp_rand( 1000, 99999 ) );
182 + }
183 +
176 184 return $raw;
177 185 }
178 186
179 187 // -------------------------------------------------------------------------
@@ -266,9 +274,9 @@
266 274 }
267 275 if ( isset( $raw['streetviewdata'] ) || ! empty( $raw['streetviewurl'] ) ) {
268 276 return 'street-view';
269 277 }
270 - if ( isset( $raw['vidid'] ) || ! empty( $raw['vidurl'] ) ) {
278 + if ( ! empty( $raw['vidid'] ) || ! empty( $raw['vidurl'] ) ) {
271 279 return 'video';
272 280 }
273 281 return 'image';
274 282 }
@@ -562,8 +570,17 @@
562 570 : null;
563 571 $scene_yaw = isset( $hotspot['hotspot-scene-yaw'] ) && $hotspot['hotspot-scene-yaw'] !== ''
564 572 ? (float) $hotspot['hotspot-scene-yaw']
565 573 : null;
574 + $product_id = isset( $hotspot['hotspot-product-id'] ) ? (string) $hotspot['hotspot-product-id'] : '';
575 + $product_name = '';
576 + if ( ! empty( $product_id ) && function_exists( 'wc_get_product' ) ) {
577 + $product_obj = wc_get_product( $product_id );
578 + if ( is_object( $product_obj ) ) {
579 + $product_name = $product_obj->get_formatted_name();
580 + }
581 + }
582 +
566 583 $hotspots[] = [
567 584 'id' => $hotspot['hotspot-id'] ?? wp_generate_uuid4(),
568 585 'type' => $hotspot['hotspot-type'] ?? 'info',
569 586 'pitch' => isset( $hotspot['hotspot-pitch'] ) ? (float) $hotspot['hotspot-pitch'] : 0,
@@ -574,8 +591,11 @@
574 591 'urlOpen' => $hotspot['hotspot-url-open'] ?? 'off',
575 592 'hover' => $hotspot['hotspot-hover'] ?? '',
576 593 'targetSceneId' => $hotspot['hotspot-scene'] ?? '',
577 594 'customClass' => $hotspot['hotspot-customclass'] ?? '',
595 + 'fluentFormId' => isset( $hotspot['fluent-form-id'] ) ? (string) $hotspot['fluent-form-id'] : '',
596 + 'productId' => $product_id,
597 + 'productName' => $product_name,
578 598 // Pro styling fields
579 599 'iconClass' => ( ( $hotspot['hotspot-customclass-pro'] ?? '' ) === 'none' || ( $hotspot['hotspot-customclass-pro'] ?? '' ) === '' ) ? '' : $hotspot['hotspot-customclass-pro'],
580 600 'iconBgColor' => $hotspot['hotspot-customclass-color-icon-value'] ?? '#00b4ff',
581 601 'iconColor' => $hotspot['hotspot-custom-icon-color-value'] ?? '#ffffff',
@@ -596,23 +616,53 @@
596 616
597 617 protected function hotspots_from_api( array $hotspots ): array {
598 618 $hotspot_list = [];
599 619 foreach ( $hotspots as $hotspot ) {
620 + $hotspot_type = sanitize_key( $hotspot['type'] ?? 'info' );
621 + $is_fluent_form = $hotspot_type === 'fluent_form';
622 + $raw_content = (string) ( $hotspot['content'] ?? '' );
623 + $raw_hover = (string) ( $hotspot['hover'] ?? '' );
624 +
625 + // For fluent_form hotspots, content is dynamically rendered server-side from fluent-form-id.
626 + // User-supplied content is never used and must not be saved, completely eliminating stored XSS.
627 + if ( $is_fluent_form ) {
628 + $content = '';
629 + } else {
630 + $content = function_exists( 'sanitize_content_preserve_styles' )
631 + ? sanitize_content_preserve_styles( $raw_content, false )
632 + : wp_kses_post( $raw_content );
633 + }
634 + $hover = function_exists( 'sanitize_content_preserve_styles' )
635 + ? sanitize_content_preserve_styles( $raw_hover, false )
636 + : wp_kses_post( $raw_hover );
637 +
600 638 $hs = [
601 639 'hotspot-id' => $hotspot['id'] ?? wp_generate_uuid4(),
602 - 'hotspot-type' => $hotspot['type'] ?? 'info',
640 + 'hotspot-type' => $hotspot_type,
603 641 'hotspot-pitch' => (string) ( $hotspot['pitch'] ?? 0 ),
604 642 'hotspot-yaw' => (string) ( $hotspot['yaw'] ?? 0 ),
605 - 'hotspot-title' => $hotspot['text'] ?? '',
606 - 'hotspot-content' => $hotspot['content'] ?? '',
607 - 'hotspot-url' => $hotspot['url'] ?? '',
608 - 'hotspot-url-open' => $hotspot['urlOpen'] ?? 'off',
609 - 'hotspot-hover' => $hotspot['hover'] ?? '',
610 - 'hotspot-scene' => $hotspot['targetSceneId'] ?? '',
611 - 'hotspot-customclass' => $hotspot['customClass'] ?? '',
643 + 'hotspot-title' => sanitize_text_field( $hotspot['text'] ?? '' ),
644 + 'hotspot-content' => $content,
645 + 'hotspot-url' => sanitize_text_field( $hotspot['url'] ?? '' ),
646 + 'hotspot-url-open' => ( $hotspot['urlOpen'] ?? 'off' ) === 'on' ? 'on' : 'off',
647 + 'hotspot-hover' => $hover,
648 + 'hotspot-scene' => sanitize_text_field( $hotspot['targetSceneId'] ?? '' ),
649 + 'hotspot-customclass' => sanitize_text_field( $hotspot['customClass'] ?? '' ),
612 650 'hotspot-scene-list' => 'none',
613 651 ];
614 652
653 + if ( isset( $hotspot['fluentFormId'] ) ) {
654 + $hs['fluent-form-id'] = (string) absint( $hotspot['fluentFormId'] );
655 + } elseif ( isset( $hotspot['fluent-form-id'] ) ) {
656 + $hs['fluent-form-id'] = (string) absint( $hotspot['fluent-form-id'] );
657 + }
658 +
659 + if ( isset( $hotspot['productId'] ) ) {
660 + $hs['hotspot-product-id'] = sanitize_text_field( $hotspot['productId'] );
661 + } elseif ( isset( $hotspot['hotspot-product-id'] ) ) {
662 + $hs['hotspot-product-id'] = sanitize_text_field( $hotspot['hotspot-product-id'] );
663 + }
664 +
615 665 if ( $this->is_pro ) {
616 666 $hs = array_merge( $hs, [
617 667 // Pro styling fields
618 668 'hotspot-customclass-pro' => !empty( $hotspot['iconClass'] ) ? $hotspot['iconClass'] : 'none',
@@ -623,11 +673,10 @@
623 673 'hotspot-border' => $hotspot['border'] ?? 'off',
624 674 'hotspot-border-width' => $hotspot['borderWidth'] ?? '1',
625 675 'hotspot-border-style' => $hotspot['borderStyle'] ?? 'none',
626 676 'hotspot-border-color' => $hotspot['borderColor'] ?? '#00b4ff',
627 - // Pro navigation entry point fields
628 - 'hotspot-scene-pitch' => $hotspot['scenePitch'] !== null ? (string) $hotspot['scenePitch'] : '',
629 - 'hotspot-scene-yaw' => $hotspot['sceneYaw'] !== null ? (string) $hotspot['sceneYaw'] : '',
677 + 'hotspot-scene-pitch' => ( isset( $hotspot['scenePitch'] ) && $hotspot['scenePitch'] !== null ) ? (string) $hotspot['scenePitch'] : '',
678 + 'hotspot-scene-yaw' => ( isset( $hotspot['sceneYaw'] ) && $hotspot['sceneYaw'] !== null ) ? (string) $hotspot['sceneYaw'] : '',
630 679 'hotspot-scene-entry-point-mode' => in_array( $hotspot['sceneEntryPointMode'] ?? '', [ 'inherit', 'custom' ], true )
631 680 ? $hotspot['sceneEntryPointMode']
632 681 : 'inherit',
633 682 ] );