PluginProbe
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings / trunk
MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings vtrunk
7.2.2 7.2.1 7.2 7.1.2 7.1.1 7.1 7.0.4 7.0.6 7.0.7 6.3.8 6.3.7 6.3.6 6.3.5 6.3.4 6.3.3 6.3.1 trunk 5.7.3 5.7.5 5.8.1 5.8.2 5.8.3 5.8.4 5.8.6 6.0.4 All 37 releases
mlsimport / includes / standalone / class-mlsimport-property-section-assets.php

class-mlsimport-property-section-assets.php in MLSImport: IDX Plugin & MLS Plugin for Real Estate Listings trunk, at includes/standalone/class-mlsimport-property-section-assets.php

191 lines 8.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Standalone (theme_id 990) single-property section assets.
4 *
5 * Registers the front-end CSS/JS each section can use and enqueues them
6 * on demand: the dispatcher calls enqueue() with a section's declared asset
7 * handles only when that section actually renders, so Splide/Leaflet/etc. load
8 * only on pages that use them (decision 6/8). Handles are registered idempotently
9 * so enqueue works regardless of hook order. See docs/adr/0005.
10 *
11 * @package Mlsimport
12 */
13
14 if ( ! defined( 'ABSPATH' ) ) {
15 exit;
16 }
17
18 /**
19 * Registers and on-demand enqueues single-property section assets.
20 */
21 class Mlsimport_Property_Section_Assets {
22
23 /**
24 * The base stylesheet handle, enqueued whenever any section renders.
25 */
26 const BASE_STYLE = 'mlsimport-property-sections';
27
28 /**
29 * Register all section asset handles once. Idempotent.
30 *
31 * @return void
32 */
33 public static function ensure_registered(): void {
34 static $done = false;
35 if ( $done || ! function_exists( 'wp_register_style' ) ) {
36 return;
37 }
38 $done = true;
39
40 $url = defined( 'MLSIMPORT_PLUGIN_URL' ) ? MLSIMPORT_PLUGIN_URL : '';
41 $ver = defined( 'MLSIMPORT_VERSION' ) ? MLSIMPORT_VERSION : false;
42
43 wp_register_style( self::BASE_STYLE, $url . 'public/css/mlsimport-property-sections.css', array(), $ver );
44 // Re-theme the section tokens from the "Main Color" design setting on EVERY
45 // page that loads the base style — property pages, page blocks, the agent
46 // profile (enqueued directly in agent-sections.php) and the editor preview.
47 // Attached at REGISTRATION so all enqueue paths get it, not just enqueue().
48 if ( function_exists( 'mlsimport_standalone_attach_brand_color' ) ) {
49 mlsimport_standalone_attach_brand_color( self::BASE_STYLE );
50 }
51
52 // Single-agent profile styles — layered on the base tokens/section shell.
53 wp_register_style( 'mlsimport-agent', $url . 'public/css/mlsimport-agent.css', array( self::BASE_STYLE ), $ver );
54
55 // Vendored Splide (gallery/sliders) — registered, enqueued only on demand.
56 wp_register_style( 'mlsimport-splide', $url . 'public/vendor/splide/splide.min.css', array(), $ver );
57 wp_register_script( 'mlsimport-splide', $url . 'public/vendor/splide/splide.min.js', array(), $ver, true );
58 wp_register_script( 'mlsimport-property-slider', $url . 'public/js/mlsimport-property-slider.js', array( 'mlsimport-splide' ), $ver, true );
59
60 // Vendored GLightbox (gallery/slider click-to-zoom) — registered, enqueued on demand.
61 wp_register_style( 'mlsimport-glightbox', $url . 'public/vendor/glightbox/glightbox.min.css', array(), $ver );
62 wp_register_script( 'mlsimport-glightbox', $url . 'public/vendor/glightbox/glightbox.min.js', array(), $ver, true );
63 wp_register_script( 'mlsimport-property-lightbox', $url . 'public/js/mlsimport-property-lightbox.js', array( 'mlsimport-glightbox' ), $ver, true );
64
65 // Vendored Leaflet + map init (map section) — registered, enqueued on demand.
66 wp_register_style( 'mlsimport-leaflet', $url . 'public/vendor/leaflet/leaflet.css', array(), $ver );
67 wp_register_script( 'mlsimport-leaflet', $url . 'public/vendor/leaflet/leaflet.js', array(), $ver, true );
68 wp_register_script( 'mlsimport-property-map', $url . 'public/js/mlsimport-property-map.js', array(), $ver, true );
69
70 // Multi-marker map for the "Map with Listings" page block — reuses Leaflet.
71 wp_register_script( 'mlsimport-page-block-map', $url . 'public/js/mlsimport-page-block-map.js', array(), $ver, true );
72
73 // Half Map page block: split listings/map surface. The coordinator depends on
74 // the page-block map script (which exposes node.mlsimportMap on query maps).
75 wp_register_style( 'mlsimport-half-map', $url . 'public/css/mlsimport-half-map.css', array(), $ver );
76 wp_register_script( 'mlsimport-half-map', $url . 'public/js/mlsimport-half-map.js', array( 'mlsimport-page-block-map' ), $ver, true );
77
78 // The "I'm interested in" dropdown widget. Declared as a dependency of the lead
79 // script rather than as a section asset, so it loads exactly where lead forms
80 // load — including the booking rail's Ask a Question panel — with no section
81 // declaration to keep in sync.
82 wp_register_script( 'mlsimport-property-interest', $url . 'public/js/mlsimport-property-interest.js', array(), $ver, true );
83
84 // Lead forms — AJAX submit; localize the admin-ajax URL.
85 wp_register_script( 'mlsimport-property-lead', $url . 'public/js/mlsimport-property-lead.js', array( 'mlsimport-property-interest' ), $ver, true );
86 wp_localize_script(
87 'mlsimport-property-lead',
88 'MLSImportLead',
89 array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) )
90 );
91
92 // Mortgage calculator — browser-only.
93 wp_register_script( 'mlsimport-property-calculator', $url . 'public/js/mlsimport-property-calculator.js', array(), $ver, true );
94
95 // Share / print buttons — browser-only.
96 wp_register_script( 'mlsimport-property-share', $url . 'public/js/mlsimport-property-share.js', array(), $ver, true );
97
98 // Details-as-tabs toggling — browser-only.
99 wp_register_script( 'mlsimport-property-tabs', $url . 'public/js/mlsimport-property-tabs.js', array(), $ver, true );
100
101 // Sticky in-page sub-nav (scrollspy + smooth scroll) — browser-only.
102 wp_register_script( 'mlsimport-property-subnav', $url . 'public/js/mlsimport-property-subnav.js', array(), $ver, true );
103
104 // Booking sidebar tour/question tab toggle — browser-only.
105 wp_register_script( 'mlsimport-property-booking', $url . 'public/js/mlsimport-property-booking.js', array(), $ver, true );
106 }
107
108 /**
109 * Enqueue the base stylesheet plus a section's declared asset handles.
110 *
111 * @param string[] $handles Section asset handles from the manifest.
112 * @return void
113 */
114 public static function enqueue( array $handles = array() ): void {
115 if ( ! function_exists( 'wp_enqueue_style' ) ) {
116 return;
117 }
118 self::ensure_registered();
119
120 wp_enqueue_style( self::BASE_STYLE );
121
122 foreach ( $handles as $handle ) {
123 if ( wp_script_is( $handle, 'registered' ) ) {
124 wp_enqueue_script( $handle );
125 }
126 if ( wp_style_is( $handle, 'registered' ) ) {
127 wp_enqueue_style( $handle );
128 }
129 }
130 }
131
132 /**
133 * Pre-enqueue the single-property page's section assets into the <head>.
134 *
135 * The single templates print the header (firing wp_head) before any section
136 * renders, so the per-section on-demand enqueue in the render dispatcher lands
137 * too late for the head — WordPress prints those styles in the footer via
138 * print_late_styles(), and the page paints unstyled markup that snaps into
139 * place once the footer CSS/JS loads (issue #172, the gallery/section flash).
140 *
141 * Hooked on wp_enqueue_scripts, this resolves the exact sections the single
142 * template will render — the locked hero, the "Arrange Sections" content
143 * column and the booking sidebar — and enqueues their declared assets while
144 * the head is still open. It reuses the same per-section asset manifests as
145 * the on-demand path (which stays in place and no-ops for the already-queued
146 * handles), so a section never styles itself twice and conditional vendors
147 * (Leaflet, GLightbox) still load only when their section is active.
148 *
149 * @return void
150 */
151 public static function enqueue_for_single(): void {
152 if ( ! function_exists( 'is_singular' ) || ! function_exists( 'wp_enqueue_style' ) ) {
153 return;
154 }
155
156 // Both the stored single (is_singular) and the live virtual route render
157 // the same section stack, so cover both.
158 $is_live = function_exists( 'get_query_var' ) && '' !== (string) get_query_var( 'mlsimport_live_listing' );
159 if ( ! $is_live && ! is_singular( 'mlsimport_property' ) ) {
160 return;
161 }
162
163 if ( function_exists( 'mlsimport_register_builtin_property_sections' ) ) {
164 mlsimport_register_builtin_property_sections();
165 }
166 if ( ! function_exists( 'mlsimport_property_section_registry' ) ) {
167 return;
168 }
169
170 $id = $is_live ? 0 : (int) get_queried_object_id();
171 $active = function_exists( 'mlsimport_standalone_active_sections' )
172 ? mlsimport_standalone_active_sections()
173 : array();
174 /** This filter is documented in templates/single-mlsimport-property.php */
175 $active = (array) apply_filters( 'mlsimport_single_property_sections', $active, $id );
176
177 // The locked hero + content column + booking sidebar — the full set the
178 // single template renders.
179 $slugs = array_merge( array( 'breadcrumbs', 'property_gallery', 'title_bar', 'subnav' ), $active, array( 'booking' ) );
180 $registry = mlsimport_property_section_registry();
181 $handles = array();
182 foreach ( array_unique( $slugs ) as $slug ) {
183 if ( isset( $registry[ $slug ]['assets'] ) ) {
184 $handles = array_merge( $handles, (array) $registry[ $slug ]['assets'] );
185 }
186 }
187
188 self::enqueue( array_unique( $handles ) );
189 }
190 }
191