Completed
Push — fix/14475-mapbox-api-private-s... ( 9fd069...dd1eea )
by
unknown
11:49 queued 03:53
created

map.php ➔ jetpack_get_mapbox_api_key()   A

Complexity

Conditions 6
Paths 4

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 4
nop 0
dl 0
loc 19
rs 9.0111
c 0
b 0
f 0
1
<?php
2
/**
3
 * Map block.
4
 *
5
 * @since 6.8.0
6
 *
7
 * @package Jetpack
8
 */
9
10
jetpack_register_block(
11
	'jetpack/map',
12
	array(
13
		'render_callback' => 'jetpack_map_block_load_assets',
14
	)
15
);
16
17
/**
18
 * Return the site's own Mapbox API key if set, or the WordPress.com's one otherwise.
19
 *
20
 * @return string
21
 */
22
function jetpack_get_mapbox_api_key() {
23
	$service_api_key = Jetpack_Options::get_option( 'mapbox_api_key' );
24
	if ( $service_api_key ) {
25
		return $service_api_key;
26
	}
27
28
	if ( defined( 'IS_WPCOM' ) && IS_WPCOM && defined( 'WPCOM_MAPBOX_ACCESS_TOKEN' ) ) {
29
		return WPCOM_MAPBOX_ACCESS_TOKEN;
30
	}
31
32
	$request_url = rest_url( 'wpcom/v2/service-api-keys/mapbox' );
33
	$response    = wp_remote_get( esc_url_raw( $request_url ) );
34
	if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
35
		return '';
36
	}
37
38
	$response_body = json_decode( wp_remote_retrieve_body( $response ) );
39
	return $response_body->service_api_key;
40
}
41
42
/**
43
 * Map block registration/dependency declaration.
44
 *
45
 * @param array  $attr    Array containing the map block attributes.
46
 * @param string $content String containing the map block content.
47
 *
48
 * @return string
49
 */
50
function jetpack_map_block_load_assets( $attr, $content ) {
51
	$api_key = jetpack_get_mapbox_api_key();
52
53
	if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
54
		static $map_block_counter = array();
55
56
		$id = get_the_ID();
57
		if ( ! isset( $map_block_counter[ $id ] ) ) {
58
			$map_block_counter[ $id ] = 0;
59
		}
60
		$map_block_counter[ $id ]++;
61
62
		$iframe_url = add_query_arg(
63
			array(
64
				'map-block-counter' => absint( $map_block_counter[ $id ] ),
65
				'map-block-post-id' => $id,
66
			),
67
			get_permalink()
68
		);
69
70
		$placeholder = preg_replace( '/(?<=<div\s)/', 'placeholder ', $content );
71
72
		return sprintf(
73
			'<amp-iframe src="%s" width="%d" height="%d" layout="responsive" allowfullscreen sandbox="allow-scripts">%s</amp-iframe>',
74
			esc_url( $iframe_url ),
75
			4,
76
			3,
77
			$placeholder
78
		);
79
	}
80
81
	Jetpack_Gutenberg::load_assets_as_required( 'map' );
82
83
	return preg_replace( '/<div /', '<div data-api-key="' . esc_attr( $api_key ) . '" ', $content, 1 );
84
}
85
86
/**
87
 * Render a page containing only a single Map block.
88
 */
89
function jetpack_map_block_render_single_block_page() {
90
	// phpcs:ignore WordPress.Security.NonceVerification
91
	$map_block_counter = isset( $_GET, $_GET['map-block-counter'] ) ? absint( $_GET['map-block-counter'] ) : null;
92
	// phpcs:ignore WordPress.Security.NonceVerification
93
	$map_block_post_id = isset( $_GET, $_GET['map-block-post-id'] ) ? absint( $_GET['map-block-post-id'] ) : null;
94
95
	if ( ! $map_block_counter || ! $map_block_post_id ) {
96
		return;
97
	}
98
99
	/* Create an array of all root-level DIVs that are Map Blocks */
100
	$post = get_post( $map_block_post_id );
101
102
	if ( ! class_exists( 'DOMDocument' ) ) {
103
		return;
104
	}
105
106
	$post_html = new DOMDocument();
107
	/** This filter is already documented in core/wp-includes/post-template.php */
108
	$content = apply_filters( 'the_content', $post->post_content );
109
110
	/* Suppress warnings */
111
	libxml_use_internal_errors( true );
112
	@$post_html->loadHTML( $content ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
113
	libxml_use_internal_errors( false );
114
115
	$xpath     = new DOMXPath( $post_html );
116
	$container = $xpath->query( '//div[ contains( @class, "wp-block-jetpack-map" ) ]' )->item( $map_block_counter - 1 );
117
118
	/* Check that we have a block matching the counter position */
119
	if ( ! $container ) {
120
		return;
121
	}
122
123
	/* Compile scripts and styles */
124
	ob_start();
125
126
	add_filter( 'jetpack_is_amp_request', '__return_false' );
127
128
	Jetpack_Gutenberg::load_assets_as_required( 'map' );
129
	wp_scripts()->do_items();
130
	wp_styles()->do_items();
131
132
	add_filter( 'jetpack_is_amp_request', '__return_true' );
133
134
	$head_content = ob_get_clean();
135
136
	/* Put together a new complete document containing only the requested block markup and the scripts/styles needed to render it */
137
	$block_markup = $post_html->saveHTML( $container );
138
	$api_key      = jetpack_get_mapbox_api_key();
139
	$page_html    = sprintf(
140
		'<!DOCTYPE html><head><style>html, body { margin: 0; padding: 0; }</style>%s</head><body>%s</body>',
141
		$head_content,
142
		preg_replace( '/(?<=<div\s)/', 'data-api-key="' . esc_attr( $api_key ) . '" ', $block_markup, 1 )
143
	);
144
	echo $page_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
145
	exit;
146
}
147
148
add_action( 'wp', 'jetpack_map_block_render_single_block_page' );
149