Completed
Push — add/publishing-tweetstorms ( 53ba9c...ada03e )
by Gary
08:38
created

eventbrite.php ➔ render_embed_block()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 55

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 2
nop 3
dl 0
loc 55
rs 8.9818
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Eventbrite Block.
4
 *
5
 * @since 8.2.0
6
 *
7
 * @package Jetpack
8
 */
9
10
namespace Automattic\Jetpack\Extensions\Eventbrite;
11
12
use Automattic\Jetpack\Blocks;
13
use Jetpack_Gutenberg;
14
15
const FEATURE_NAME = 'eventbrite';
16
const BLOCK_NAME   = 'jetpack/' . FEATURE_NAME;
17
18
/**
19
 * Registers the block for use in Gutenberg
20
 * This is done via an action so that we can disable
21
 * registration if we need to.
22
 */
23
function register_block() {
24
	jetpack_register_block(
25
		BLOCK_NAME,
26
		array( 'render_callback' => __NAMESPACE__ . '\render_block' )
27
	);
28
}
29
add_action( 'init', __NAMESPACE__ . '\register_block' );
30
31
/**
32
 * Get current URL.
33
 *
34
 * @return string Current URL.
35
 */
36
function get_current_url() {
37 View Code Duplication
	if ( isset( $_SERVER['HTTP_HOST'] ) ) {
38
		$host = wp_unslash( $_SERVER['HTTP_HOST'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
39
	} else {
40
		$host = wp_parse_url( home_url(), PHP_URL_HOST );
0 ignored issues
show
Unused Code introduced by
The call to wp_parse_url() has too many arguments starting with PHP_URL_HOST.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
41
	}
42 View Code Duplication
	if ( isset( $_SERVER['REQUEST_URI'] ) ) {
43
		$path = wp_unslash( $_SERVER['REQUEST_URI'] ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
44
	} else {
45
		$path = '/';
46
	}
47
	return esc_url_raw( ( is_ssl() ? 'https' : 'http' ) . '://' . $host . $path );
48
}
49
50
/**
51
 * Eventbrite block registration/dependency delclaration.
52
 *
53
 * @param array  $attr    Eventbrite block attributes.
54
 * @param string $content Rendered embed element (without scripts) from the block editor.
55
 *
56
 * @return string Rendered block.
57
 */
58
function render_block( $attr, $content ) {
59
	if ( is_admin() || empty( $attr['eventId'] ) || empty( $attr['url'] ) ) {
60
		return '';
61
	}
62
63
	$attr['url'] = Jetpack_Gutenberg::validate_block_embed_url(
64
		$attr['url'],
65
		array( '#^https?:\/\/(?:[0-9a-z]+\.)?eventbrite\.(?:com|co\.uk|com\.ar|com\.au|be|com\.br|ca|cl|co|dk|de|es|fi|fr|hk|ie|it|com\.mx|nl|co\.nz|at|com\.pe|pt|ch|sg|se)\/e\/[^\/]*?(?:\d+)\/?(?:\?[^\/]*)?$#' ),
66
		true
67
	);
68
69
	$widget_id = wp_unique_id( 'eventbrite-widget-' );
70
71
	// Show the embedded version.
72
	if ( empty( $attr['useModal'] ) && ( empty( $attr['style'] ) || 'modal' !== $attr['style'] ) ) {
73
		return render_embed_block( $widget_id, Blocks::is_amp_request(), $attr );
74
	} else {
75
		return render_modal_block( $widget_id, Blocks::is_amp_request(), $attr, $content );
76
	}
77
}
78
79
/**
80
 * Render block with embed style.
81
 *
82
 * @param string $widget_id Widget ID to use.
83
 * @param bool   $is_amp    Whether AMP page.
84
 * @param array  $attr      Eventbrite block attributes.
85
 * @return string Rendered block.
86
 */
87
function render_embed_block( $widget_id, $is_amp, $attr ) {
88
89
	// $content contains a fallback link to the event that's saved in the post_content.
90
	// Append a div that will hold the iframe embed created by the Eventbrite widget.js.
91
	$classes = Blocks::classes( FEATURE_NAME, $attr );
92
93
	$classes .= ' wp-block-jetpack-eventbrite--embed';
94
95
	$direct_link = sprintf(
96
		'<a href="%s" rel="noopener noreferrer" target="_blank" class="eventbrite__direct-link" %s>%s</a>',
97
		esc_url( $attr['url'] ),
98
		$is_amp ? 'placeholder fallback' : '',
99
		esc_html__( 'Register on Eventbrite', 'jetpack' )
100
	);
101
102
	if ( $is_amp ) {
103
		$embed = sprintf(
104
			'<amp-iframe src="%s" layout="responsive" resizable width="1" height="1" sandbox="allow-scripts allow-same-origin allow-forms"><button overflow>%s</button>%s</amp-iframe>',
105
			esc_url(
106
				add_query_arg(
107
					array(
108
						'eid'    => $attr['eventId'],
109
						'parent' => rawurlencode( get_current_url() ),
110
					),
111
					'https://www.eventbrite.com/checkout-external'
112
				)
113
			),
114
			esc_html__( 'Expand', 'jetpack' ),
115
			$direct_link
116
		);
117
	} else {
118
		$embed = $direct_link;
119
120
		wp_enqueue_script( 'eventbrite-widget', 'https://www.eventbrite.com/static/widgets/eb_widgets.js', array(), JETPACK__VERSION, true );
121
122
		// Add CSS to hide direct link.
123
		Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME );
124
125
		wp_add_inline_script(
126
			'eventbrite-widget',
127
			"window.EBWidgets.createWidget( {
128
				widgetType: 'checkout',
129
				eventId: " . absint( $attr['eventId'] ) . ",
130
				iframeContainerId: '" . esc_js( $widget_id ) . "',
131
			} );"
132
		);
133
	}
134
135
	return sprintf(
136
		'<div id="%1$s" class="%2$s">%3$s</div>',
137
		esc_attr( $widget_id ),
138
		esc_attr( $classes ),
139
		$embed
140
	);
141
}
142
143
/**
144
 * Render block with modal style.
145
 *
146
 * @param string $widget_id Widget ID to use.
147
 * @param bool   $is_amp    Whether AMP page.
148
 * @param array  $attr      Eventbrite block attributes.
149
 * @param string $content   Rendered embed element (without scripts) from the block editor.
150
 * @return string Rendered block.
151
 */
152
function render_modal_block( $widget_id, $is_amp, $attr, $content ) {
153
154
	if ( $is_amp ) {
155
		$lightbox_id = "{$widget_id}-lightbox";
156
157
		// Add CSS to for lightbox.
158
		Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME );
159
160
		$content = preg_replace(
161
			'/\shref="#" target="_blank/',
162
			sprintf( ' on="%s" ', esc_attr( "tap:{$lightbox_id}.open" ) ),
163
			$content
164
		);
165
166
		$iframe_src = add_query_arg(
167
			array(
168
				// Note that modal=1 is intentionally omitted here since we need to put the close button inside the amp-lightbox.
169
				'eid'    => $attr['eventId'],
170
				'parent' => rawurlencode( get_current_url() ),
171
			),
172
			'https://www.eventbrite.com/checkout-external'
173
		);
174
175
		$lightbox = sprintf(
176
			'<amp-lightbox id="%1$s" on="%2$s" class="eventbrite__lightbox" layout="nodisplay">%3$s</amp-lightbox>',
177
			esc_attr( $lightbox_id ),
178
			esc_attr( "tap:{$lightbox_id}.close" ),
179
			sprintf(
180
				'
181
					<div class="eventbrite__lighbox-inside">
182
						<div class="eventbrite__lighbox-iframe-wrapper">
183
							<amp-iframe class="eventbrite__lighbox-iframe" src="%s" layout="fill" sandbox="allow-scripts allow-same-origin allow-forms">
184
								<span placeholder=""></span>
185
							</amp-iframe>
186
							<span class="eventbrite__lighbox-close" on="%s" role="button" tabindex="0" aria-label="%s">
187
								<svg viewBox="0 0 24 24">
188
									<path d="M13.4 12l3.5-3.5-1.4-1.4-3.5 3.5-3.5-3.5-1.4 1.4 3.5 3.5-3.5 3.5 1.4 1.4 3.5-3.5 3.5 3.5 1.4-1.4z"></path>
189
								</svg>
190
							</span>
191
						</div>
192
					</div>
193
				',
194
				esc_url( $iframe_src ),
195
				esc_attr( "tap:{$lightbox_id}.close" ),
196
				esc_attr__( 'Close', 'jetpack' )
197
			)
198
		);
199
200
		$content = preg_replace(
201
			':(?=</div>\s*$):',
202
			$lightbox,
203
			$content
204
		);
205
206
		return $content;
207
	}
208
209
	wp_enqueue_script( 'eventbrite-widget', 'https://www.eventbrite.com/static/widgets/eb_widgets.js', array(), JETPACK__VERSION, true );
210
211
	// Show the modal version.
212
	wp_add_inline_script(
213
		'eventbrite-widget',
214
		"window.EBWidgets.createWidget( {
215
			widgetType: 'checkout',
216
			eventId: " . absint( $attr['eventId'] ) . ",
217
			modal: true,
218
			modalTriggerElementId: '" . esc_js( $widget_id ) . "',
219
		} );"
220
	);
221
222
	// Modal button is saved as an `<a>` element with `role="button"` because `<button>` is not allowed
223
	// by WordPress.com wp_kses. This javascript adds the necessary event handling for button-like behavior.
224
	// @link https://www.w3.org/TR/wai-aria-practices/examples/button/button.html.
225
	wp_add_inline_script(
226
		'eventbrite-widget',
227
		"( function() {
228
			var widget = document.getElementById( '" . esc_js( $widget_id ) . "' );
229
			if ( widget ) {
230
				widget.addEventListener( 'click', function( event ) {
231
					event.preventDefault();
232
				} );
233
234
				widget.addEventListener( 'keydown', function( event ) {
235
					// Enter and space keys.
236
					if ( event.keyCode === 13 || event.keyCode === 32 ) {
237
						event.preventDefault();
238
						event.target && event.target.click();
239
					}
240
				} );
241
			}
242
		} )();"
243
	);
244
245
	// Replace the placeholder id saved in the post_content with a unique id used by widget.js.
246
	$content = str_replace( 'eventbrite-widget-id', esc_attr( $widget_id ), $content );
247
248
	// Fallback for block version deprecated/v2.
249
	$content = preg_replace( '/eventbrite-widget-\d+/', esc_attr( $widget_id ), $content );
250
251
	// Inject URL to event in case the JS for the lightbox fails to load.
252
	$content = preg_replace(
253
		'/\shref="#"/',
254
		sprintf(
255
			' href="%s" rel="noopener noreferrer" target="_blank"',
256
			esc_url( $attr['url'] )
257
		),
258
		$content
259
	);
260
261
	return $content;
262
}
263