PluginProbe
Gutenberg / 23.7.2
Gutenberg v23.7.2
23.9.1 23.9.0 23.8.0 23.7.2 23.7.1 23.7.0 23.6.1 23.6.2 23.6.0 23.5.3 23.5.2 23.5.1 23.5.0 23.4.0 23.3.2 23.3.1 23.3.0 23.2.0 23.2.1 23.2.2 23.1.1 23.1.0 23.0.1 12.6.0 7.4.0 All 402 releases
gutenberg / build / scripts / block-library / playlist.php

playlist.php in Gutenberg 23.7.2, at build/scripts/block-library/playlist.php

216 lines 6.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Server-side rendering of the `core/playlist` block.
4 *
5 * @package WordPress
6 */
7
8 /**
9 * Renders the `core/playlist` block on server.
10 *
11 * @since 7.1.0
12 *
13 * @param array $attributes The block attributes.
14 * @param string $content The block content.
15 * @param WP_Block $block The block instance.
16 *
17 * @return string Returns the Playlist.
18 */
19 function gutenberg_render_block_core_playlist( $attributes, $content, $block ) {
20 $playlist_id = wp_unique_id( 'playlist-' );
21 $playlist_tracks = array();
22 $tracks_data = array();
23 $show_play_button_artwork = ! empty( $attributes['showPlayButtonArtwork'] );
24
25 // Parse inner blocks to extract track data.
26 // This approach avoids duplicating track data in the HTML output.
27 if ( ! empty( $block->inner_blocks ) ) {
28 foreach ( $block->inner_blocks as $inner_block ) {
29 if ( 'core/playlist-track' === $inner_block->name ) {
30 $track_attributes = $inner_block->attributes;
31
32 if ( empty( $track_attributes['id'] ) ) {
33 continue;
34 }
35
36 $track_id = 'track-' . count( $playlist_tracks );
37 $playlist_tracks[] = $track_id;
38
39 // Extract track metadata from block attributes.
40 $track_title_attr = $track_attributes['title'] ?? null;
41 $track_artist = $track_attributes['artist'] ?? null;
42 $track_album = $track_attributes['album'] ?? null;
43 $track_image = $track_attributes['image'] ?? null;
44 $track_src = $track_attributes['src'] ?? null;
45 $title = ! empty( $track_title_attr ) && is_string( $track_title_attr ) ? $track_title_attr : __( 'Unknown title' );
46 $artist = is_string( $track_artist ) ? $track_artist : '';
47 $album = is_string( $track_album ) ? $track_album : '';
48 $image = is_string( $track_image ) ? $track_image : '';
49 $image_alt = $track_attributes['imageAlt'] ?? '';
50 $url = is_string( $track_src ) ? $track_src : '';
51 $aria_label = $title;
52
53 if ( $title && $artist && $album ) {
54 $aria_label = sprintf(
55 /* translators: %1$s: track title, %2$s: artist name, %3$s: album name. */
56 _x( '%1$s by %2$s from the album %3$s', 'track title, artist name, album name' ),
57 $title,
58 $artist,
59 $album
60 );
61 }
62
63 // Data is passed to wp_interactivity_state() which JSON-encodes it,
64 // so we use wp_strip_all_tags() instead of esc_html() to prevent
65 // HTML injection without double-encoding. URLs still use esc_url().
66 $tracks_data[ $track_id ] = array(
67 'url' => esc_url( $url ),
68 'title' => wp_strip_all_tags( $title ),
69 'artist' => wp_strip_all_tags( $artist ),
70 'album' => wp_strip_all_tags( $album ),
71 'image' => esc_url( $image ),
72 'imageAlt' => wp_strip_all_tags( $image_alt ),
73 'ariaLabel' => wp_strip_all_tags( $aria_label ),
74 );
75 }
76 }
77 }
78
79 if ( empty( $playlist_tracks ) ) {
80 return '';
81 }
82
83 wp_enqueue_script_module( '@wordpress/block-library/playlist/view' );
84
85 // Add the playlist tracks to the global state,
86 // but keep them isolated from other playlists with the help of playlistId.
87 wp_interactivity_state(
88 'core/playlist',
89 array(
90 'playlists' => array(
91 $playlist_id => array(
92 'tracks' => $tracks_data,
93 ),
94 ),
95 )
96 );
97
98 // Add waveform player container with translated button labels.
99 $label_play = esc_attr__( 'Play' );
100 $label_pause = esc_attr__( 'Pause' );
101 $label_seek = esc_attr__( 'Seek' );
102 /* translators: %1$s: current audio time, %2$s: total audio duration. */
103 $label_seek_value = esc_attr_x(
104 '%1$s of %2$s',
105 'audio current time of total duration'
106 );
107 $waveform_color_attribute = '';
108 $waveform_gradient_attribute = '';
109 $waveform_background_color_attribute = '';
110 $waveform_background_gradient_attribute = '';
111 if ( ! empty( $attributes['waveformColor'] ) ) {
112 $waveform_color_attribute = sprintf(
113 ' data-waveform-player-color="%s"',
114 esc_attr( $attributes['waveformColor'] )
115 );
116 }
117 if ( ! empty( $attributes['waveformGradient'] ) ) {
118 $waveform_gradient_attribute = sprintf(
119 ' data-waveform-player-gradient="%s"',
120 esc_attr( $attributes['waveformGradient'] )
121 );
122 }
123 if ( ! empty( $attributes['waveformBackgroundColor'] ) ) {
124 $waveform_background_color_attribute = sprintf(
125 ' data-waveform-player-background-color="%s"',
126 esc_attr( $attributes['waveformBackgroundColor'] )
127 );
128 }
129 if ( ! empty( $attributes['waveformBackgroundGradient'] ) ) {
130 $waveform_background_gradient_attribute = sprintf(
131 ' data-waveform-player-background-gradient="%s"',
132 esc_attr( $attributes['waveformBackgroundGradient'] )
133 );
134 }
135 $html = '<div class="wp-block-playlist__waveform-player"' .
136 $waveform_color_attribute .
137 $waveform_gradient_attribute .
138 $waveform_background_color_attribute .
139 $waveform_background_gradient_attribute . '
140 data-wp-watch="callbacks.initWaveformPlayer"
141 data-label-play="' . $label_play . '"
142 data-label-pause="' . $label_pause . '"
143 data-label-seek="' . $label_seek . '"
144 data-label-seek-value="' . $label_seek_value . '"
145 ></div>';
146
147 // Add the waveform player container inside the figure.
148 $figure = null;
149 preg_match( '/<figure[^>]*>/', $content, $figure );
150 if ( ! empty( $figure[0] ) ) {
151 $content = preg_replace( '/(<figure[^>]*>)/', '$1' . $html, $content, 1 );
152 }
153
154 $processor = new WP_HTML_Tag_Processor( $content );
155 $processor->next_tag( 'figure' );
156 $processor->set_attribute( 'data-wp-interactive', 'core/playlist' );
157
158 $waveform_style = $attributes['waveformStyle'] ?? 'bars';
159
160 $processor->set_attribute(
161 'data-wp-context',
162 wp_json_encode(
163 array(
164 'playlistId' => $playlist_id,
165 'currentId' => $playlist_tracks[0],
166 'isPlaying' => false,
167 'tracks' => $playlist_tracks,
168 'waveformStyle' => $waveform_style,
169 'showPlayButtonArtwork' => $show_play_button_artwork,
170 'labelPauseTrack' => __( 'Pause' ),
171 'labelSelectTrack' => __( 'Play' ),
172 )
173 )
174 );
175
176 // Track IDs are render-time only. Add them after inner blocks have rendered
177 // so track buttons can update the Interactivity API state without storing
178 // persistent unique IDs in post content.
179 $track_index = 0;
180 while ( $processor->next_tag( array( 'class_name' => 'wp-block-playlist-track__button' ) ) ) {
181 $track_id = $playlist_tracks[ $track_index ] ?? null;
182
183 if ( null === $track_id ) {
184 break;
185 }
186
187 $processor->set_attribute(
188 'data-wp-context',
189 wp_json_encode(
190 array(
191 'trackId' => $track_id,
192 )
193 )
194 );
195
196 ++$track_index;
197 }
198
199 return $processor->get_updated_html();
200 }
201
202 /**
203 * Registers the `core/playlist` block on server.
204 *
205 * @since 7.1.0
206 */
207 function gutenberg_register_block_core_playlist() {
208 register_block_type_from_metadata(
209 __DIR__ . '/playlist',
210 array(
211 'render_callback' => 'gutenberg_render_block_core_playlist',
212 )
213 );
214 }
215 add_action( 'init', 'gutenberg_register_block_core_playlist', 20 );
216