Completed
Push — fix/podcast-player-theme-compa... ( 9f16ef...aa0d46 )
by
unknown
12:57 queued 06:01
created

podcast-player.php ➔ get_css_vars()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
nc 3
nop 1
dl 0
loc 12
rs 9.8666
c 0
b 0
f 0
1
<?php
2
/**
3
 * Podcast Player Block.
4
 *
5
 * @since 8.4.0
6
 *
7
 * @package Jetpack
8
 */
9
10
namespace Automattic\Jetpack\Extensions\Podcast_Player;
11
12
use WP_Error;
13
use Jetpack_Gutenberg;
14
use Jetpack_Podcast_Helper;
15
use Jetpack_AMP_Support;
16
17
const FEATURE_NAME = 'podcast-player';
18
const BLOCK_NAME   = 'jetpack/' . FEATURE_NAME;
19
20
if ( ! class_exists( 'Jetpack_Podcast_Helper' ) ) {
21
	\jetpack_require_lib( 'class-jetpack-podcast-helper' );
22
}
23
24
/**
25
 * Registers the block for use in Gutenberg
26
 * This is done via an action so that we can disable
27
 * registration if we need to.
28
 */
29
function register_block() {
30
	jetpack_register_block(
31
		BLOCK_NAME,
32
		array(
33
			'attributes'      => array(
34
				'url'                    => array(
35
					'type' => 'url',
36
				),
37
				'itemsToShow'            => array(
38
					'type'    => 'integer',
39
					'default' => 5,
40
				),
41
				'showCoverArt'           => array(
42
					'type'    => 'boolean',
43
					'default' => true,
44
				),
45
				'showEpisodeDescription' => array(
46
					'type'    => 'boolean',
47
					'default' => true,
48
				),
49
			),
50
			'render_callback' => __NAMESPACE__ . '\render_block',
51
		)
52
	);
53
}
54
add_action( 'init', __NAMESPACE__ . '\register_block' );
55
56
/**
57
 * Podcast Player block registration/dependency declaration.
58
 *
59
 * @param array $attributes Array containing the Podcast Player block attributes.
60
 * @return string
61
 */
62
function render_block( $attributes ) {
63
64
	// Test for empty URLS.
65
	if ( empty( $attributes['url'] ) ) {
66
		return '<p>' . esc_html__( 'No Podcast URL provided. Please enter a valid Podcast RSS feed URL.', 'jetpack' ) . '</p>';
67
	}
68
69
	// Test for invalid URLs.
70
	if ( ! wp_http_validate_url( $attributes['url'] ) ) {
71
		return '<p>' . esc_html__( 'Your podcast URL is invalid and couldn\'t be embedded. Please double check your URL.', 'jetpack' ) . '</p>';
72
	}
73
74
	// Sanitize the URL.
75
	$attributes['url'] = esc_url_raw( $attributes['url'] );
76
77
	$player_data = Jetpack_Podcast_Helper::get_player_data( $attributes['url'] );
78
79
	if ( is_wp_error( $player_data ) ) {
80
		return '<p>' . esc_html( $player_data->get_error_message() ) . '</p>';
0 ignored issues
show
Bug introduced by
The method get_error_message() does not seem to exist on object<WP_Error>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
81
	}
82
83
	return render_player( $player_data, $attributes );
84
}
85
86
/**
87
 * Renders the HTML for the Podcast player and tracklist.
88
 *
89
 * @param array $player_data The player data details.
90
 * @param array $attributes Array containing the Podcast Player block attributes.
91
 * @return string The HTML for the podcast player.
92
 */
93
function render_player( $player_data, $attributes ) {
94
	// If there are no tracks (it is possible) then display appropriate user facing error message.
95
	if ( empty( $player_data['tracks'] ) ) {
96
		return '<p>' . esc_html__( 'No tracks available to play.', 'jetpack' ) . '</p>';
97
	}
98
99
	// Only use the amount of tracks requested.
100
	$player_data['tracks'] = array_slice(
101
		$player_data['tracks'],
102
		0,
103
		absint( $attributes['itemsToShow'] )
104
	);
105
106
	// Generate a unique id for the block instance.
107
	$instance_id             = wp_unique_id( 'jetpack-podcast-player-block-' );
108
	$player_data['playerId'] = $instance_id;
109
110
	// Generate object to be used as props for PodcastPlayer.
111
	$player_props = array_merge(
112
		// Add all attributes.
113
		array( 'attributes' => $attributes ),
114
		// Add all player data.
115
		$player_data
116
	);
117
118
	$primary_colors    = get_colors( 'primary', $attributes, 'color' );
119
	$secondary_colors  = get_colors( 'secondary', $attributes, 'color' );
120
	$background_colors = get_colors( 'background', $attributes, 'background-color' );
121
122
	$player_classes_name  = trim( "{$secondary_colors['class']} {$background_colors['class']}" );
123
	$player_inline_style  = trim( "{$secondary_colors['style']} ${background_colors['style']}" );
124
	$player_inline_style .= get_css_vars( $attributes );
125
126
	$block_classname = Jetpack_Gutenberg::block_classes( FEATURE_NAME, $attributes, array( 'is-default' ) );
127
	$is_amp          = ( class_exists( 'Jetpack_AMP_Support' ) && Jetpack_AMP_Support::is_amp_request() );
128
129
	ob_start();
130
	?>
131
	<div class="<?php echo esc_attr( $block_classname ); ?>" id="<?php echo esc_attr( $instance_id ); ?>">
132
		<section
133
			class="jetpack-podcast-player <?php echo esc_attr( $player_classes_name ); ?>"
134
			style="<?php echo esc_attr( $player_inline_style ); ?>"
135
		>
136
			<?php
137
			render(
138
				'podcast-header',
139
				array_merge(
140
					$player_props,
141
					array(
142
						'primary_colors' => $primary_colors,
143
						'player_id'      => $player_data['playerId'],
144
					)
145
				)
146
			);
147
			?>
148
			<ol class="jetpack-podcast-player__tracks">
149
				<?php foreach ( $player_data['tracks'] as $track_index => $attachment ) : ?>
150
					<?php
151
					render(
152
						'playlist-track',
153
						array(
154
							'is_active'        => 0 === $track_index,
155
							'attachment'       => $attachment,
156
							'primary_colors'   => $primary_colors,
157
							'secondary_colors' => $secondary_colors,
158
						)
159
					);
160
					?>
161
				<?php endforeach; ?>
162
			</ol>
163
		</section>
164
		<?php if ( ! $is_amp ) : ?>
165
		<script type="application/json"><?php echo wp_json_encode( $player_props ); ?></script>
166
		<?php endif; ?>
167
	</div>
168
	<?php if ( ! $is_amp ) : ?>
169
	<script>
170
		( function( instanceId ) {
171
			document.getElementById( instanceId ).classList.remove( 'is-default' );
172
			window.jetpackPodcastPlayers=(window.jetpackPodcastPlayers||[]);
173
			window.jetpackPodcastPlayers.push( instanceId );
174
		} )( <?php echo wp_json_encode( $instance_id ); ?> );
175
	</script>
176
	<?php endif; ?>
177
	<?php
178
	/**
179
	 * Enqueue necessary scripts and styles.
180
	 */
181
	if ( ! $is_amp ) {
182
		wp_enqueue_style( 'wp-mediaelement' );
183
	}
184
	Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME, array( 'mediaelement' ) );
185
186
	return ob_get_clean();
187
}
188
189
/**
190
 * Given the color name, block attributes and the CSS property,
191
 * the function will return an array with the `class` and `style`
192
 * HTML attributes to be used straight in the markup.
193
 *
194
 * @example
195
 * $color = get_colors( 'secondary', $attributes, 'border-color'
196
 *  => array( 'class' => 'has-secondary', 'style' => 'border-color: #333' )
197
 *
198
 * @param string $name     Color attribute name, for instance `primary`, `secondary`, ...
199
 * @param array  $attrs    Block attributes.
200
 * @param string $property Color CSS property, fo instance `color`, `background-color`, ...
201
 * @return array           Colors array.
202
 */
203
function get_colors( $name, $attrs, $property ) {
204
	$attr_color  = "{$name}Color";
205
	$attr_custom = 'custom' . ucfirst( $attr_color );
206
207
	$color        = isset( $attrs[ $attr_color ] ) ? $attrs[ $attr_color ] : null;
208
	$custom_color = isset( $attrs[ $attr_custom ] ) ? $attrs[ $attr_custom ] : null;
209
210
	$colors = array(
211
		'class' => '',
212
		'style' => '',
213
	);
214
215
	if ( $color || $custom_color ) {
216
		$colors['class'] .= "has-{$name}";
217
218
		if ( $color ) {
219
			$colors['class'] .= " has-{$color}-{$property}";
220
		} elseif ( $custom_color ) {
221
			$colors['style'] .= "{$property}: {$custom_color};";
222
		}
223
	}
224
225
	return $colors;
226
}
227
228
/**
229
 * It generates a string with CSS variables according to the
230
 * block colors, prefixing each one with `--jetpack-podcast-player'.
231
 *
232
 * @param array $attrs Podcast Block attributes object.
233
 * @return string      CSS variables depending on block colors.
234
 */
235
function get_css_vars( $attrs ) {
236
	$colors_name = array( 'primary', 'secondary', 'background' );
237
238
	$inline_style = '';
239
	foreach ( $colors_name as $color ) {
240
		$hex_color = 'hex' . ucfirst( $color ) . 'Color';
241
		if ( ! empty( $attrs[ $hex_color ] ) ) {
242
			$inline_style .= " --jetpack-podcast-player-{$color}: {$attrs[ $hex_color ]};";
243
		}
244
	}
245
	return $inline_style;
246
}
247
248
/**
249
 * Render the given template in server-side.
250
 * Important note:
251
 *    The $template_props array will be extracted.
252
 *    This means it will create a var for each array item.
253
 *    Keep it mind when using this param to pass
254
 *    properties to the template.
255
 *
256
 * @param string $name           Template name, available in `./templates` folder.
257
 * @param array  $template_props Template properties. Optional.
258
 * @param bool   $print          Render template. True as default.
259
 * @return false|string          HTML markup or false.
260
 */
261
function render( $name, $template_props = array(), $print = true ) {
262
	if ( ! strpos( $name, '.php' ) ) {
263
		$name = $name . '.php';
264
	}
265
266
	$template_path = dirname( __FILE__ ) . '/templates/' . $name;
267
268
	if ( ! file_exists( $template_path ) ) {
269
		return '';
270
	}
271
272
	// Optionally provided an assoc array of data to pass to template
273
	// IMPORTANT: It will be extracted into variables.
274
	if ( is_array( $template_props ) ) {
275
		// It ignores the `discouraging` sniffer rule for extract,
276
		// since it's needed to make the templating system works.
277
		extract( $template_props ); // phpcs:ignore WordPress.PHP.DontExtract.extract_extract
278
	}
279
280
	if ( $print ) {
281
		include $template_path;
282
	} else {
283
		ob_start();
284
		include $template_path;
285
		$markup = ob_get_contents();
286
		ob_end_clean();
287
288
		return $markup;
289
	}
290
}
291