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 +46 -9 9.0.39.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',
@@ -601,11 +621,17 @@
601 621 $is_fluent_form = $hotspot_type === 'fluent_form';
602 622 $raw_content = (string) ( $hotspot['content'] ?? '' );
603 623 $raw_hover = (string) ( $hotspot['hover'] ?? '' );
604 624
605 - $content = function_exists( 'sanitize_content_preserve_styles' )
606 - ? sanitize_content_preserve_styles( $raw_content, $is_fluent_form )
607 - : wp_kses_post( $raw_content );
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 + }
608 634 $hover = function_exists( 'sanitize_content_preserve_styles' )
609 635 ? sanitize_content_preserve_styles( $raw_hover, false )
610 636 : wp_kses_post( $raw_hover );
611 637
@@ -623,8 +649,20 @@
623 649 'hotspot-customclass' => sanitize_text_field( $hotspot['customClass'] ?? '' ),
624 650 'hotspot-scene-list' => 'none',
625 651 ];
626 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 +
627 665 if ( $this->is_pro ) {
628 666 $hs = array_merge( $hs, [
629 667 // Pro styling fields
630 668 'hotspot-customclass-pro' => !empty( $hotspot['iconClass'] ) ? $hotspot['iconClass'] : 'none',
@@ -635,11 +673,10 @@
635 673 'hotspot-border' => $hotspot['border'] ?? 'off',
636 674 'hotspot-border-width' => $hotspot['borderWidth'] ?? '1',
637 675 'hotspot-border-style' => $hotspot['borderStyle'] ?? 'none',
638 676 'hotspot-border-color' => $hotspot['borderColor'] ?? '#00b4ff',
639 - // Pro navigation entry point fields
640 - 'hotspot-scene-pitch' => $hotspot['scenePitch'] !== null ? (string) $hotspot['scenePitch'] : '',
641 - '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'] : '',
642 679 'hotspot-scene-entry-point-mode' => in_array( $hotspot['sceneEntryPointMode'] ?? '', [ 'inherit', 'custom' ], true )
643 680 ? $hotspot['sceneEntryPointMode']
644 681 : 'inherit',
645 682 ] );