PluginProbe
Jetpack – WP Security, Backup, Speed, & Growth / 16.3-a.1
Jetpack – WP Security, Backup, Speed, & Growth v16.3-a.1
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 +102 -16 12.7.316.3-a.1 View file →
@@ -15,10 +15,11 @@
15 15 use Jetpack;
16 16 use Jetpack_Gutenberg;
17 17 use Jetpack_Mapbox_Helper;
18 18
19 -const FEATURE_NAME = 'map';
20 -const BLOCK_NAME = 'jetpack/' . FEATURE_NAME;
19 +if ( ! defined( 'ABSPATH' ) ) {
20 + exit( 0 );
21 +}
21 22
22 23 if ( ! class_exists( 'Jetpack_Mapbox_Helper' ) ) {
23 24 require_once JETPACK__PLUGIN_DIR . '_inc/lib/class-jetpack-mapbox-helper.php';
24 25 }
@@ -29,9 +30,9 @@
29 30 * registration if we need to.
30 31 */
31 32 function register_block() {
32 33 Blocks::jetpack_register_block(
33 - BLOCK_NAME,
34 + __DIR__,
34 35 array(
35 36 'render_callback' => __NAMESPACE__ . '\load_assets',
36 37 )
37 38 );
@@ -50,9 +51,10 @@
50 51
51 52 $event_name = 'map_block_mapbox_wpcom_key_load';
52 53 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
53 54 require_lib( 'tracks/client' );
54 - tracks_record_event( wp_get_current_user(), $event_name );
55 + // Tracking::record_user_event() prefixes the source itself; tracks_record_event() does not.
56 + tracks_record_event( wp_get_current_user(), 'jetpack_' . $event_name );
55 57 } elseif ( ( new Host() )->is_woa_site() && Jetpack::is_connection_ready() ) {
56 58 $tracking = new Tracking();
57 59 $tracking->record_user_event( $event_name );
58 60 }
@@ -60,9 +62,9 @@
60 62
61 63 /**
62 64 * Function to determine which map provider to choose
63 65 *
64 - * @param array $html The block's HTML - needed for the class name.
66 + * @param string $html The block's HTML - needed for the class name.
65 67 *
66 68 * @return string The name of the map provider.
67 69 */
68 70 function get_map_provider( $html ) {
@@ -68,9 +70,9 @@
68 70 function get_map_provider( $html ) {
69 71 $mapbox_styles = array( 'is-style-terrain' );
70 72 // return mapbox if html contains one of the mapbox styles
71 73 foreach ( $mapbox_styles as $style ) {
72 - if ( strpos( $html, $style ) !== false ) {
74 + if ( str_contains( $html, $style ) ) {
73 75 return 'mapbox';
74 76 }
75 77 }
76 78
@@ -122,16 +124,95 @@
122 124 $placeholder
123 125 );
124 126 }
125 127
126 - Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME );
128 + Jetpack_Gutenberg::load_assets_as_required( __DIR__ );
127 129
128 130 $map_provider = get_map_provider( $content );
129 - if ( $map_provider === 'mapkit' ) {
130 - return preg_replace( '/<div /', '<div data-map-provider="mapkit" data-blog-id="' . \Jetpack_Options::get_option( 'id' ) . '" ', $content, 1 );
131 +
132 + return rebuild_map_block_div( $attr, $content, $map_provider, $access_token );
133 +}
134 +
135 +/**
136 + * Rebuild the map block div to move large JSON data from HTML attributes
137 + * into an inline JS payload, keeping the DOM lightweight.
138 + *
139 + * @param array $attr Array containing the map block attributes.
140 + * @param string $content String containing the map block content.
141 + * @param string $map_provider The map provider (mapbox or mapkit).
142 + * @param array $access_token The Mapbox/MapKit access token data.
143 + *
144 + * @return string
145 + */
146 +function rebuild_map_block_div( $attr, $content, $map_provider, $access_token ) {
147 + static $did_inline = false;
148 +
149 + $block_id = wp_unique_id( 'jp-map-' );
150 +
151 + // Extract map-style from the saved HTML since it's no longer a block attribute
152 + // (was deprecated and converted to CSS class names like is-style-terrain).
153 + $map_style = 'default';
154 + if ( preg_match( '/data-map-style="([^"]*)"/', $content, $matches ) ) {
155 + $map_style = $matches[1];
131 156 }
132 157
133 - return preg_replace( '/<div /', '<div data-map-provider="mapbox" data-api-key="' . esc_attr( $access_token['key'] ) . '" ', $content, 1 );
158 + $classes = array( 'wp-block-jetpack-map' );
159 + if ( ! empty( $attr['align'] ) ) {
160 + $classes[] = 'align' . $attr['align'];
161 + }
162 + if ( ! empty( $attr['className'] ) ) {
163 + $classes[] = $attr['className'];
164 + }
165 +
166 + // Keep the tag small: no giant JSON in attributes.
167 + $data_attrs = array(
168 + 'class' => implode( ' ', $classes ),
169 + 'data-map-id' => $block_id,
170 + 'data-map-provider' => $map_provider,
171 + 'data-api-key' => $access_token['key'],
172 + 'data-map-style' => $map_style,
173 + );
174 +
175 + if ( 'mapkit' === $map_provider ) {
176 + $data_attrs['data-blog-id'] = \Jetpack_Options::get_option( 'id' );
177 + }
178 +
179 + // Put everything else in the JS payload (including points).
180 + $payload = array(
181 + 'points' => $attr['points'] ?? null,
182 + 'zoom' => $attr['zoom'] ?? null,
183 + 'mapCenter' => $attr['mapCenter'] ?? null,
184 + 'markerColor' => $attr['markerColor'] ?? null,
185 + 'scrollToZoom' => $attr['scrollToZoom'] ?? null,
186 + 'mapDetails' => $attr['mapDetails'] ?? null,
187 + 'mapHeight' => $attr['mapHeight'] ?? null,
188 + 'showFullscreenButton' => $attr['showFullscreenButton'] ?? null,
189 + 'mapStyle' => $map_style,
190 + );
191 +
192 + $handle = 'jetpack-block-map';
193 +
194 + // Seed global once.
195 + if ( ! $did_inline ) {
196 + wp_add_inline_script( $handle, 'window.JetpackMapBlockData = window.JetpackMapBlockData || {};', 'before' );
197 + $did_inline = true;
198 + }
199 +
200 + // Add this block's payload keyed by ID.
201 + wp_add_inline_script(
202 + $handle,
203 + 'window.JetpackMapBlockData[' . wp_json_encode( $block_id, JSON_HEX_TAG | JSON_HEX_AMP ) . '] = ' . wp_json_encode( $payload, JSON_HEX_TAG | JSON_HEX_AMP ) . ';',
204 + 'before'
205 + );
206 +
207 + $div_open = '<div';
208 + foreach ( $data_attrs as $key => $value ) {
209 + $div_open .= ' ' . $key . '="' . esc_attr( $value ) . '"';
210 + }
211 + $div_open .= '>';
212 +
213 + $result = preg_replace( '/<div[^>]*>/', $div_open, $content, 1 );
214 + return $result ?? $content;
134 215 }
135 216
136 217 /**
137 218 * Render a page containing only a single Map block.
@@ -156,8 +237,13 @@
156 237 $post_html = new \DOMDocument();
157 238 /** This filter is already documented in core/wp-includes/post-template.php */
158 239 $content = apply_filters( 'the_content', $post->post_content );
159 240
241 + // Return early if empty to prevent DOMDocument::loadHTML fatal.
242 + if ( empty( $content ) ) {
243 + return;
244 + }
245 +
160 246 /* Suppress warnings */
161 247 libxml_use_internal_errors( true );
162 248 @$post_html->loadHTML( $content ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
163 249 libxml_use_internal_errors( false );
@@ -174,9 +260,9 @@
174 260 ob_start();
175 261
176 262 add_filter( 'jetpack_is_amp_request', '__return_false' );
177 263
178 - Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME );
264 + Jetpack_Gutenberg::load_assets_as_required( __DIR__ );
179 265 wp_scripts()->do_items();
180 266 wp_styles()->do_items();
181 267
182 268 add_filter( 'jetpack_is_amp_request', '__return_true' );
@@ -191,9 +277,9 @@
191 277 $head_content,
192 278 preg_replace( '/(?<=<div\s)/', 'data-api-key="' . esc_attr( $access_token['key'] ) . '" ', $block_markup, 1 )
193 279 );
194 280 echo $page_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
195 - exit;
281 + exit( 0 );
196 282 }
197 283 add_action( 'wp', __NAMESPACE__ . '\render_single_block_page' );
198 284
199 285 /**
@@ -226,14 +312,14 @@
226 312 },
227 313 $points
228 314 );
229 315
230 - $map_block = '<!-- wp:jetpack/map ' . wp_json_encode( $map_block_data ) . ' -->' . PHP_EOL;
316 + $map_block = '<!-- wp:jetpack/map ' . wp_json_encode( $map_block_data, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ' -->' . PHP_EOL;
231 317 $map_block .= sprintf(
232 318 '<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">',
233 - esc_html( wp_json_encode( $map_block_data['points'] ) ),
234 - (int) $map_block_data['zoom'],
235 - esc_html( wp_json_encode( $map_block_data['mapCenter'] ) )
319 + esc_attr( wp_json_encode( $map_block_data['points'], JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) ),
320 + $map_block_data['zoom'],
321 + esc_attr( wp_json_encode( $map_block_data['mapCenter'], JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) )
236 322 );
237 323 $map_block .= '<ul>' . implode( "\n", $list_items ) . '</ul>';
238 324 $map_block .= '</div>' . PHP_EOL;
239 325 $map_block .= '<!-- /wp:jetpack/map -->';