Completed
Push — add/paid-mention-blocks ( 0a325f...25129a )
by
unknown
08:03
created

map.php ➔ jetpack_get_mapbox_api_key()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
nc 4
nop 0
dl 0
loc 20
rs 9.6
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
	if ( defined( 'IS_WPCOM' ) && IS_WPCOM ) {
24
		$endpoint = sprintf(
25
			'https://public-api.wordpress.com/wpcom/v2/sites/%d/service-api-keys/mapbox',
26
			get_current_blog_id()
27
		);
28
	} else {
29
		$endpoint = rest_url( 'wpcom/v2/service-api-keys/mapbox' );
30
	}
31
32
	$response      = wp_remote_get( esc_url_raw( $endpoint ) );
33
	$response_code = wp_remote_retrieve_response_code( $response );
34
35
	if ( 200 === $response_code ) {
36
		$response_body = json_decode( wp_remote_retrieve_body( $response ) );
37
		return $response_body->service_api_key;
38
	}
39
40
	return Jetpack_Options::get_option( 'mapbox_api_key' );
41
}
42
43
/**
44
 * Map block registration/dependency declaration.
45
 *
46
 * @param array  $attr    Array containing the map block attributes.
47
 * @param string $content String containing the map block content.
48
 *
49
 * @return string
50
 */
51
function jetpack_map_block_load_assets( $attr, $content ) {
52
	$api_key = jetpack_get_mapbox_api_key();
53
54
	if ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() ) {
55
		static $map_block_counter = array();
56
57
		$id = get_the_ID();
58
		if ( ! isset( $map_block_counter[ $id ] ) ) {
59
			$map_block_counter[ $id ] = 0;
60
		}
61
		$map_block_counter[ $id ]++;
62
63
		$iframe_url = add_query_arg(
64
			array(
65
				'map-block-counter' => absint( $map_block_counter[ $id ] ),
66
				'map-block-post-id' => $id,
67
			),
68
			get_permalink()
69
		);
70
71
		$placeholder = preg_replace( '/(?<=<div\s)/', 'placeholder ', $content );
72
73
		return sprintf(
74
			'<amp-iframe src="%s" width="%d" height="%d" layout="responsive" allowfullscreen sandbox="allow-scripts">%s</amp-iframe>',
75
			esc_url( $iframe_url ),
76
			4,
77
			3,
78
			$placeholder
79
		);
80
	}
81
82
	Jetpack_Gutenberg::load_assets_as_required( 'map' );
83
84
	return preg_replace( '/<div /', '<div data-api-key="' . esc_attr( $api_key ) . '" ', $content, 1 );
85
}
86
87
/**
88
 * Render a page containing only a single Map block.
89
 */
90
function jetpack_map_block_render_single_block_page() {
91
	// phpcs:ignore WordPress.Security.NonceVerification
92
	$map_block_counter = isset( $_GET, $_GET['map-block-counter'] ) ? absint( $_GET['map-block-counter'] ) : null;
93
	// phpcs:ignore WordPress.Security.NonceVerification
94
	$map_block_post_id = isset( $_GET, $_GET['map-block-post-id'] ) ? absint( $_GET['map-block-post-id'] ) : null;
95
96
	if ( ! $map_block_counter || ! $map_block_post_id ) {
97
		return;
98
	}
99
100
	/* Create an array of all root-level DIVs that are Map Blocks */
101
	$post = get_post( $map_block_post_id );
102
103
	if ( ! class_exists( 'DOMDocument' ) ) {
104
		return;
105
	}
106
107
	$post_html = new DOMDocument();
108
	/** This filter is already documented in core/wp-includes/post-template.php */
109
	$content = apply_filters( 'the_content', $post->post_content );
110
111
	/* Suppress warnings */
112
	libxml_use_internal_errors( true );
113
	@$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...
114
	libxml_use_internal_errors( false );
115
116
	$xpath     = new DOMXPath( $post_html );
117
	$container = $xpath->query( '//div[ contains( @class, "wp-block-jetpack-map" ) ]' )->item( $map_block_counter - 1 );
118
119
	/* Check that we have a block matching the counter position */
120
	if ( ! $container ) {
121
		return;
122
	}
123
124
	/* Compile scripts and styles */
125
	ob_start();
126
127
	add_filter( 'jetpack_is_amp_request', '__return_false' );
128
129
	Jetpack_Gutenberg::load_assets_as_required( 'map' );
130
	wp_scripts()->do_items();
131
	wp_styles()->do_items();
132
133
	add_filter( 'jetpack_is_amp_request', '__return_true' );
134
135
	$head_content = ob_get_clean();
136
137
	/* Put together a new complete document containing only the requested block markup and the scripts/styles needed to render it */
138
	$block_markup = $post_html->saveHTML( $container );
139
	$api_key      = jetpack_get_mapbox_api_key();
140
	$page_html    = sprintf(
141
		'<!DOCTYPE html><head><style>html, body { margin: 0; padding: 0; }</style>%s</head><body>%s</body>',
142
		$head_content,
143
		preg_replace( '/(?<=<div\s)/', 'data-api-key="' . esc_attr( $api_key ) . '" ', $block_markup, 1 )
144
	);
145
	echo $page_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
146
	exit;
147
}
148
149
add_action( 'wp', 'jetpack_map_block_render_single_block_page' );
150