PluginProbe ʕ •ᴥ•ʔ
Jetpack – WP Security, Backup, Speed, & Growth / 15.5.1
Jetpack – WP Security, Backup, Speed, & Growth v15.5.1
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 14.1.1 14.2.2 14.3.1 14.4.2 14.5.1 14.6.1 14.7.1 14.8.1 14.9.2 15.0.3 15.1.2 15.2.1 15.3.2 15.4.1 15.5.1 15.6.1 15.7.2 15.8.1 15.9.2 16.0.2 16.1.3 16.2-a.5 16.2-a.3 16.1.2 16.2-a.1 16.1.1 16.1 16.1-beta 16.1-beta.2 16.1-beta.3 16.1-a.5 16.1-a.3 16.0.1 16.1-a.1 16.0 16.0-beta 16.0-a.7 16.0-a.5 15.9.1 16.0-a.3 16.0-a.1 15.9 15.9-beta 15.9-a.7 15.9-a.5 15.9-a.3 15.9-a.1 15.8 15.8-beta 15.8-a.7 15.8-a.5 5.2.5 5.3.4 5.4.4 5.5.5 5.6.5 5.7.5 5.8.4 5.9.4 6.0.4 6.1 6.1.1 6.1.2 6.1.3 6.1.4 6.1.5 6.2 6.2.1 6.2.2 6.2.3 6.2.4 6.2.5 6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5 6.3.6 6.3.7 6.4 6.4.1 6.4.2 6.4.3 6.4.4 6.4.5 6.4.6 6.5 6.5.1 6.5.2 6.5.3 6.5.4 6.6 6.6.1 6.6.2 6.6.3 6.6.4 6.6.5 6.7 6.7.1 6.7.2 6.7.3 6.7.4 6.8 6.8.1 6.8.2 6.8.3 6.8.4 6.8.5 6.9 6.9.1 6.9.2 6.9.3 6.9.4 7.0 7.0.1 7.0.2 7.0.3 7.0.4 7.0.5 7.1 7.1.1 7.1.2 7.1.3 7.1.4 7.1.5 7.2 7.2.1 7.2.1.1 7.2.2 7.2.3 7.2.4 7.2.5 7.3 7.3.0.1 7.3.1 7.3.1.1 7.3.2 7.3.3 7.3.4 7.3.5 7.4 7.4.1 7.4.2 7.4.3 7.4.4 7.4.5 7.5 7.5.0.1 7.5.1 7.5.2 7.5.3 7.5.4 7.5.5 7.5.6 7.5.7 7.6 7.6.1 7.6.2 7.6.3 7.6.4 7.7 7.7.1 7.7.2 7.7.3 7.7.4 7.7.5 7.7.6 7.8 7.8.1 7.8.2 7.8.3 7.8.4 7.9 7.9.1 7.9.2 7.9.3 7.9.4 8.0 8.0.1 8.0.2 8.0.3 8.1 8.1.1 8.1.2 8.1.3 8.1.4 8.2 8.2.0.1 8.2.1 8.2.2 8.2.3 8.2.4 8.2.5 8.2.6 8.3 8.3.1 8.3.2 8.3.3 8.4 8.4.1 8.4.2 8.4.3 8.4.4 8.4.5 8.5 8.5.1 8.5.2 8.5.3 8.6 8.6.1 8.6.2 8.6.3 8.6.4 8.7 8.7.0.1 8.7.1 8.7.2 8.7.3 8.7.4 8.8 8.8.1 8.8.2 8.8.3 8.8.4 8.8.5 8.9 8.9.1 8.9.2 8.9.3 8.9.4 9.0 9.0.1 9.0.2 9.0.3 9.0.4 9.0.5 9.1 9.1.1 9.1.2 9.1.3 9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.3 9.3.1 9.3.2 9.3.3 9.3.4 9.3.5 9.4 9.4.1 9.4.2 9.4.3 9.4.4 9.5 9.5.1 9.5.2 9.5.3 9.5.4 9.5.5 9.6 9.6.1 9.6.2 9.6.3 9.6.4 9.7 9.7.1 9.7.2 15.7-beta.2 9.7.3 15.7.1 9.8 15.8-a.1 9.8.1 15.8-a.3 9.8.2 2.0.9 9.8.3 2.1.7 9.9 2.2.10 9.9.1 2.3.10 9.9.2 2.4.7 9.9.3 2.5.5 2.6.6 2.7.5 2.8.5 2.9.6 3.0.6 3.1.5 3.2.5 3.3.6 3.4.6 3.5.6 3.6.4 3.7.5 3.8.5 3.9.10 4.0.7 4.1.4 4.2.5 4.3.5 4.4.5 4.5.3 4.6.3 4.7.4 4.8.5 4.9.3 5.0.3 5.1.4 trunk 10.0 10.0.1 10.0.2 10.1 10.1.1 10.1.2 10.2 10.2.1 10.2.2 10.2.3 10.3 10.3.1 10.3.2 10.4 10.4.1 10.4.2 10.5 10.5.1 10.5.2 10.5.3 10.6 10.6.1 10.6.2 10.7 10.7.1 10.7.2 10.8 10.8.1 10.8.2 10.9 10.9.1 10.9.2 10.9.3 11.0 11.0.1 11.0.2 11.1 11.1.1 11.1.2 11.1.3 11.1.4 11.2 11.2.1 11.2.2 11.3 11.3.1 11.3.2 11.3.3 11.3.4 11.4 11.4.1 11.4.2 11.5 11.5.1 11.5.2 11.5.3 11.6 11.6.1 11.6.2 11.7 11.7.1 11.7.2 11.7.3 11.8 11.8.3 11.8.4 11.8.5 11.8.6 11.9 11.9.1 11.9.2 11.9.3 12.0 12.0.1 12.0.2 12.1 12.1.1 12.1.2 12.2 12.2.1 12.2.2 12.3 12.3.1 12.4 12.4.1 12.5 12.5.1 12.6 12.6.1 12.6.2 12.6.3 12.7 12.7.1 12.7.2 12.8 12.8.1 12.8.2 12.9 12.9.1 12.9.2 12.9.3 12.9.4 13.0 13.0.1 13.1 13.1.1 13.1.2 13.1.3 13.1.4 13.2 13.2.1 13.2.2 13.2.3 13.3 13.3.1 13.3.2 13.4 13.4.1 13.4.2 13.4.3 13.4.4 13.5 13.5.1 13.6 13.6.1 13.7 13.7.1 13.8 13.8.1 13.8.2 13.9 13.9.1 14.0 14.1 14.2 14.2.1 14.3 14.4 14.4.1 14.5 14.6 14.7 14.8 14.9 14.9.1 15.0 15.0.1 15.0.2 15.1 15.1.1 15.2 15.3 15.3.1 15.4 15.5 15.6 15.7 15.7-a.1 15.7-a.3 15.7-a.5 15.7-a.7 15.7-beta
jetpack / extensions / blocks / map / map.php
jetpack / extensions / blocks / map Last commit date
map.php 8 months ago
map.php
249 lines
1 <?php
2 /**
3 * Map block.
4 *
5 * @since 6.8.0
6 *
7 * @package automattic/jetpack
8 */
9
10 namespace Automattic\Jetpack\Extensions\Map;
11
12 use Automattic\Jetpack\Blocks;
13 use Automattic\Jetpack\Status\Host;
14 use Automattic\Jetpack\Tracking;
15 use Jetpack;
16 use Jetpack_Gutenberg;
17 use Jetpack_Mapbox_Helper;
18
19 if ( ! defined( 'ABSPATH' ) ) {
20 exit( 0 );
21 }
22
23 if ( ! class_exists( 'Jetpack_Mapbox_Helper' ) ) {
24 require_once JETPACK__PLUGIN_DIR . '_inc/lib/class-jetpack-mapbox-helper.php';
25 }
26
27 /**
28 * Registers the block for use in Gutenberg
29 * This is done via an action so that we can disable
30 * registration if we need to.
31 */
32 function register_block() {
33 Blocks::jetpack_register_block(
34 __DIR__,
35 array(
36 'render_callback' => __NAMESPACE__ . '\load_assets',
37 )
38 );
39 }
40 add_action( 'init', __NAMESPACE__ . '\register_block' );
41
42 /**
43 * Record a Tracks event every time the Map block is loaded on WordPress.com and Atomic.
44 *
45 * @param string $access_token_source The Mapbox API access token source.
46 */
47 function wpcom_load_event( $access_token_source ) {
48 if ( 'wpcom' !== $access_token_source ) {
49 return;
50 }
51
52 $event_name = 'map_block_mapbox_wpcom_key_load';
53 if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
54 require_lib( 'tracks/client' );
55 tracks_record_event( wp_get_current_user(), $event_name );
56 } elseif ( ( new Host() )->is_woa_site() && Jetpack::is_connection_ready() ) {
57 $tracking = new Tracking();
58 $tracking->record_user_event( $event_name );
59 }
60 }
61
62 /**
63 * Function to determine which map provider to choose
64 *
65 * @param string $html The block's HTML - needed for the class name.
66 *
67 * @return string The name of the map provider.
68 */
69 function get_map_provider( $html ) {
70 $mapbox_styles = array( 'is-style-terrain' );
71 // return mapbox if html contains one of the mapbox styles
72 foreach ( $mapbox_styles as $style ) {
73 if ( str_contains( $html, $style ) ) {
74 return 'mapbox';
75 }
76 }
77
78 // you can override the map provider with a cookie
79 if ( isset( $_COOKIE['map_provider'] ) ) {
80 return sanitize_text_field( wp_unslash( $_COOKIE['map_provider'] ) );
81 }
82
83 // if we don't apply the filters & default to mapbox
84 return apply_filters( 'wpcom_map_block_map_provider', 'mapbox' );
85 }
86
87 /**
88 * Map block registration/dependency declaration.
89 *
90 * @param array $attr Array containing the map block attributes.
91 * @param string $content String containing the map block content.
92 *
93 * @return string
94 */
95 function load_assets( $attr, $content ) {
96 $access_token = Jetpack_Mapbox_Helper::get_access_token();
97 wpcom_load_event( $access_token['source'] );
98
99 if ( Blocks::is_amp_request() ) {
100 static $map_block_counter = array();
101
102 $id = get_the_ID();
103 if ( ! isset( $map_block_counter[ $id ] ) ) {
104 $map_block_counter[ $id ] = 0;
105 }
106 ++$map_block_counter[ $id ];
107
108 $iframe_url = add_query_arg(
109 array(
110 'map-block-counter' => absint( $map_block_counter[ $id ] ),
111 'map-block-post-id' => $id,
112 ),
113 get_permalink()
114 );
115
116 $placeholder = preg_replace( '/(?<=<div\s)/', 'placeholder ', $content );
117
118 return sprintf(
119 '<amp-iframe src="%s" width="%d" height="%d" layout="responsive" allowfullscreen sandbox="allow-scripts">%s</amp-iframe>',
120 esc_url( $iframe_url ),
121 4,
122 3,
123 $placeholder
124 );
125 }
126
127 Jetpack_Gutenberg::load_assets_as_required( __DIR__ );
128
129 $map_provider = get_map_provider( $content );
130 if ( $map_provider === 'mapkit' ) {
131 return preg_replace( '/<div /', '<div data-map-provider="mapkit" data-api-key="' . esc_attr( $access_token['key'] ) . '" data-blog-id="' . \Jetpack_Options::get_option( 'id' ) . '" ', $content, 1 );
132 }
133
134 return preg_replace( '/<div /', '<div data-map-provider="mapbox" data-api-key="' . esc_attr( $access_token['key'] ) . '" ', $content, 1 );
135 }
136
137 /**
138 * Render a page containing only a single Map block.
139 */
140 function render_single_block_page() {
141 // phpcs:ignore WordPress.Security.NonceVerification
142 $map_block_counter = isset( $_GET['map-block-counter'] ) ? absint( $_GET['map-block-counter'] ) : null;
143 // phpcs:ignore WordPress.Security.NonceVerification
144 $map_block_post_id = isset( $_GET['map-block-post-id'] ) ? absint( $_GET['map-block-post-id'] ) : null;
145
146 if ( ! $map_block_counter || ! $map_block_post_id ) {
147 return;
148 }
149
150 /* Create an array of all root-level DIVs that are Map Blocks */
151 $post = get_post( $map_block_post_id );
152
153 if ( ! class_exists( 'DOMDocument' ) ) {
154 return;
155 }
156
157 $post_html = new \DOMDocument();
158 /** This filter is already documented in core/wp-includes/post-template.php */
159 $content = apply_filters( 'the_content', $post->post_content );
160
161 // Return early if empty to prevent DOMDocument::loadHTML fatal.
162 if ( empty( $content ) ) {
163 return;
164 }
165
166 /* Suppress warnings */
167 libxml_use_internal_errors( true );
168 @$post_html->loadHTML( $content ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
169 libxml_use_internal_errors( false );
170
171 $xpath = new \DOMXPath( $post_html );
172 $container = $xpath->query( '//div[ contains( @class, "wp-block-jetpack-map" ) ]' )->item( $map_block_counter - 1 );
173
174 /* Check that we have a block matching the counter position */
175 if ( ! $container ) {
176 return;
177 }
178
179 /* Compile scripts and styles */
180 ob_start();
181
182 add_filter( 'jetpack_is_amp_request', '__return_false' );
183
184 Jetpack_Gutenberg::load_assets_as_required( __DIR__ );
185 wp_scripts()->do_items();
186 wp_styles()->do_items();
187
188 add_filter( 'jetpack_is_amp_request', '__return_true' );
189
190 $head_content = ob_get_clean();
191
192 /* Put together a new complete document containing only the requested block markup and the scripts/styles needed to render it */
193 $block_markup = $post_html->saveHTML( $container );
194 $access_token = Jetpack_Mapbox_Helper::get_access_token();
195 $page_html = sprintf(
196 '<!DOCTYPE html><head><style>html, body { margin: 0; padding: 0; }</style>%s</head><body>%s</body>',
197 $head_content,
198 preg_replace( '/(?<=<div\s)/', 'data-api-key="' . esc_attr( $access_token['key'] ) . '" ', $block_markup, 1 )
199 );
200 echo $page_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
201 exit( 0 );
202 }
203 add_action( 'wp', __NAMESPACE__ . '\render_single_block_page' );
204
205 /**
206 * Helper function to generate the markup of the block in PHP.
207 *
208 * @param Array $points - Array containing geo location points.
209 *
210 * @return string Markup for the jetpack/map block.
211 */
212 function map_block_from_geo_points( $points ) {
213 $map_block_data = array(
214 'points' => $points,
215 'zoom' => 8,
216 'mapCenter' => array(
217 'lng' => $points[0]['coordinates']['longitude'],
218 'lat' => $points[0]['coordinates']['latitude'],
219 ),
220 );
221
222 $list_items = array_map(
223 function ( $point ) {
224 $link = add_query_arg(
225 array(
226 'api' => 1,
227 'query' => $point['coordinates']['latitude'] . ',' . $point['coordinates']['longitude'],
228 ),
229 'https://www.google.com/maps/search/'
230 );
231 return sprintf( '<li><a href="%s">%s</a></li>', esc_url( $link ), $point['title'] );
232 },
233 $points
234 );
235
236 $map_block = '<!-- wp:jetpack/map ' . wp_json_encode( $map_block_data, JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP ) . ' -->' . PHP_EOL;
237 $map_block .= sprintf(
238 '<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">',
239 esc_attr( wp_json_encode( $map_block_data['points'], JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) ),
240 $map_block_data['zoom'],
241 esc_attr( wp_json_encode( $map_block_data['mapCenter'], JSON_HEX_AMP | JSON_UNESCAPED_SLASHES ) )
242 );
243 $map_block .= '<ul>' . implode( "\n", $list_items ) . '</ul>';
244 $map_block .= '</div>' . PHP_EOL;
245 $map_block .= '<!-- /wp:jetpack/map -->';
246
247 return $map_block;
248 }
249