PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.2
Jetpack – WP Security, Backup, Speed, & Growth v16.2
16.3-a.3 16.3-a.1 16.2 16.2-beta 12.0.3 12.1.3 12.2.3 12.3.2 12.4.2 12.5.2 12.6.4 12.7.3 12.8.3 12.9.5 13.0.2 13.1.5 13.2.4 13.3.3 13.4.5 13.5.2 13.6.2 13.7.2 13.8.3 13.9.2 14.0.1 All 504 releases
← All changes | extensions/blocks/map/map.php +97 -9 12.9.516.2 View file →
@@ -15,8 +15,12 @@
15 15 use Jetpack;
16 16 use Jetpack_Gutenberg;
17 17 use Jetpack_Mapbox_Helper;
18 18
19 +if ( ! defined( 'ABSPATH' ) ) {
20 + exit( 0 );
21 +}
22 +
19 23 if ( ! class_exists( 'Jetpack_Mapbox_Helper' ) ) {
20 24 require_once JETPACK__PLUGIN_DIR . '_inc/lib/class-jetpack-mapbox-helper.php';
21 25 }
22 26
@@ -57,9 +61,9 @@
57 61
58 62 /**
59 63 * Function to determine which map provider to choose
60 64 *
61 - * @param array $html The block's HTML - needed for the class name.
65 + * @param string $html The block's HTML - needed for the class name.
62 66 *
63 67 * @return string The name of the map provider.
64 68 */
65 69 function get_map_provider( $html ) {
@@ -122,13 +126,92 @@
122 126
123 127 Jetpack_Gutenberg::load_assets_as_required( __DIR__ );
124 128
125 129 $map_provider = get_map_provider( $content );
126 - if ( $map_provider === 'mapkit' ) {
127 - return preg_replace( '/<div /', '<div data-map-provider="mapkit" data-blog-id="' . \Jetpack_Options::get_option( 'id' ) . '" ', $content, 1 );
130 +
131 + return rebuild_map_block_div( $attr, $content, $map_provider, $access_token );
132 +}
133 +
134 +/**
135 + * Rebuild the map block div to move large JSON data from HTML attributes
136 + * into an inline JS payload, keeping the DOM lightweight.
137 + *
138 + * @param array $attr Array containing the map block attributes.
139 + * @param string $content String containing the map block content.
140 + * @param string $map_provider The map provider (mapbox or mapkit).
141 + * @param array $access_token The Mapbox/MapKit access token data.
142 + *
143 + * @return string
144 + */
145 +function rebuild_map_block_div( $attr, $content, $map_provider, $access_token ) {
146 + static $did_inline = false;
147 +
148 + $block_id = wp_unique_id( 'jp-map-' );
149 +
150 + // Extract map-style from the saved HTML since it's no longer a block attribute
151 + // (was deprecated and converted to CSS class names like is-style-terrain).
152 + $map_style = 'default';
153 + if ( preg_match( '/data-map-style="([^"]*)"/', $content, $matches ) ) {
154 + $map_style = $matches[1];
128 155 }
129 156
130 - return preg_replace( '/<div /', '<div data-map-provider="mapbox" data-api-key="' . esc_attr( $access_token['key'] ) . '" ', $content, 1 );
157 + $classes = array( 'wp-block-jetpack-map' );
158 + if ( ! empty( $attr['align'] ) ) {
159 + $classes[] = 'align' . $attr['align'];
160 + }
161 + if ( ! empty( $attr['className'] ) ) {
162 + $classes[] = $attr['className'];
163 + }
164 +
165 + // Keep the tag small: no giant JSON in attributes.
166 + $data_attrs = array(
167 + 'class' => implode( ' ', $classes ),
168 + 'data-map-id' => $block_id,
169 + 'data-map-provider' => $map_provider,
170 + 'data-api-key' => $access_token['key'],
171 + 'data-map-style' => $map_style,
172 + );
173 +
174 + if ( 'mapkit' === $map_provider ) {
175 + $data_attrs['data-blog-id'] = \Jetpack_Options::get_option( 'id' );
176 + }
177 +
178 + // Put everything else in the JS payload (including points).
179 + $payload = array(
180 + 'points' => $attr['points'] ?? null,
181 + 'zoom' => $attr['zoom'] ?? null,
182 + 'mapCenter' => $attr['mapCenter'] ?? null,
183 + 'markerColor' => $attr['markerColor'] ?? null,
184 + 'scrollToZoom' => $attr['scrollToZoom'] ?? null,
185 + 'mapDetails' => $attr['mapDetails'] ?? null,
186 + 'mapHeight' => $attr['mapHeight'] ?? null,
187 + 'showFullscreenButton' => $attr['showFullscreenButton'] ?? null,
188 + 'mapStyle' => $map_style,
189 + );
190 +
191 + $handle = 'jetpack-block-map';
192 +
193 + // Seed global once.
194 + if ( ! $did_inline ) {
195 + wp_add_inline_script( $handle, 'window.JetpackMapBlockData = window.JetpackMapBlockData || {};', 'before' );
196 + $did_inline = true;
197 + }
198 +
199 + // Add this block's payload keyed by ID.
200 + wp_add_inline_script(
201 + $handle,
202 + 'window.JetpackMapBlockData[' . wp_json_encode( $block_id, JSON_HEX_TAG | JSON_HEX_AMP ) . '] = ' . wp_json_encode( $payload, JSON_HEX_TAG | JSON_HEX_AMP ) . ';',
203 + 'before'
204 + );
205 +
206 + $div_open = '<div';
207 + foreach ( $data_attrs as $key => $value ) {
208 + $div_open .= ' ' . $key . '="' . esc_attr( $value ) . '"';
209 + }
210 + $div_open .= '>';
211 +
212 + $result = preg_replace( '/<div[^>]*>/', $div_open, $content, 1 );
213 + return $result ?? $content;
131 214 }
132 215
133 216 /**
134 217 * Render a page containing only a single Map block.
@@ -153,8 +236,13 @@
153 236 $post_html = new \DOMDocument();
154 237 /** This filter is already documented in core/wp-includes/post-template.php */
155 238 $content = apply_filters( 'the_content', $post->post_content );
156 239
240 + // Return early if empty to prevent DOMDocument::loadHTML fatal.
241 + if ( empty( $content ) ) {
242 + return;
243 + }
244 +
157 245 /* Suppress warnings */
158 246 libxml_use_internal_errors( true );
159 247 @$post_html->loadHTML( $content ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
160 248 libxml_use_internal_errors( false );
@@ -188,9 +276,9 @@
188 276 $head_content,
189 277 preg_replace( '/(?<=<div\s)/', 'data-api-key="' . esc_attr( $access_token['key'] ) . '" ', $block_markup, 1 )
190 278 );
191 279 echo $page_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
192 - exit;
280 + exit( 0 );
193 281 }
194 282 add_action( 'wp', __NAMESPACE__ . '\render_single_block_page' );
195 283
196 284 /**
@@ -223,14 +311,14 @@
223 311 },
224 312 $points
225 313 );
226 314
227 - $map_block = '<!-- wp:jetpack/map ' . wp_json_encode( $map_block_data ) . ' -->' . PHP_EOL;
315 + $map_block = '<!-- wp:jetpack/map ' . wp_json_encode( $map_block_data, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ' -->' . PHP_EOL;
228 316 $map_block .= sprintf(
229 317 '<div class="wp-block-jetpack-map" data-map-style="default" data-map-details="true" data-points="%1$s" data-zoom="%2$d" data-map-center="%3$s" data-marker-color="red" data-show-fullscreen-button="true">',
230 - esc_html( wp_json_encode( $map_block_data['points'] ) ),
231 - (int) $map_block_data['zoom'],
232 - esc_html( wp_json_encode( $map_block_data['mapCenter'] ) )
318 + esc_attr( wp_json_encode( $map_block_data['points'], JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) ),
319 + $map_block_data['zoom'],
320 + esc_attr( wp_json_encode( $map_block_data['mapCenter'], JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) )
233 321 );
234 322 $map_block .= '<ul>' . implode( "\n", $list_items ) . '</ul>';
235 323 $map_block .= '</div>' . PHP_EOL;
236 324 $map_block .= '<!-- /wp:jetpack/map -->';