| [ Index ] |
PHP Cross Reference of WordPress Trunk (Updated Daily) |
[Summary view] [Print] [Text view]
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 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 // A track needs a source URL to be playable. 33 if ( empty( $track_attributes['src'] ) ) { 34 continue; 35 } 36 37 $track_id = 'track-' . count( $playlist_tracks ); 38 $playlist_tracks[] = $track_id; 39 40 // Extract track metadata from block attributes. 41 $track_title_attr = $track_attributes['title'] ?? null; 42 $track_artist = $track_attributes['artist'] ?? null; 43 $track_album = $track_attributes['album'] ?? null; 44 $track_image = $track_attributes['image'] ?? null; 45 $track_src = $track_attributes['src'] ?? null; 46 $title = ! empty( $track_title_attr ) && is_string( $track_title_attr ) ? $track_title_attr : __( 'Unknown title' ); 47 $artist = is_string( $track_artist ) ? $track_artist : ''; 48 $album = is_string( $track_album ) ? $track_album : ''; 49 $image = is_string( $track_image ) ? $track_image : ''; 50 $image_alt = $track_attributes['imageAlt'] ?? ''; 51 $url = is_string( $track_src ) ? $track_src : ''; 52 $aria_label = $title; 53 54 if ( $title && $artist && $album ) { 55 $aria_label = sprintf( 56 /* translators: %1$s: track title, %2$s: artist name, %3$s: album name. */ 57 _x( '%1$s by %2$s from the album %3$s', 'track title, artist name, album name' ), 58 $title, 59 $artist, 60 $album 61 ); 62 } 63 64 // Data is passed to wp_interactivity_state() which JSON-encodes it, 65 // so we use wp_strip_all_tags() instead of esc_html() to prevent 66 // HTML injection without double-encoding. URLs still use esc_url(). 67 $tracks_data[ $track_id ] = array( 68 'url' => esc_url( $url ), 69 'title' => wp_strip_all_tags( $title ), 70 'artist' => wp_strip_all_tags( $artist ), 71 'album' => wp_strip_all_tags( $album ), 72 'image' => esc_url( $image ), 73 'imageAlt' => wp_strip_all_tags( $image_alt ), 74 'ariaLabel' => wp_strip_all_tags( $aria_label ), 75 ); 76 } 77 } 78 } 79 80 if ( empty( $playlist_tracks ) ) { 81 return ''; 82 } 83 84 wp_enqueue_script_module( '@wordpress/block-library/playlist/view' ); 85 86 // Add the playlist tracks to the global state, 87 // but keep them isolated from other playlists with the help of playlistId. 88 wp_interactivity_state( 89 'core/playlist', 90 array( 91 'playlists' => array( 92 $playlist_id => array( 93 'tracks' => $tracks_data, 94 ), 95 ), 96 ) 97 ); 98 99 // Add waveform player container with translated button labels. 100 $label_play = esc_attr__( 'Play' ); 101 $label_pause = esc_attr__( 'Pause' ); 102 $label_seek = esc_attr__( 'Seek' ); 103 /* translators: %1$s: current audio time, %2$s: total audio duration. */ 104 $label_seek_value = esc_attr_x( 105 '%1$s of %2$s', 106 'audio current time of total duration' 107 ); 108 $waveform_color_attribute = ''; 109 $waveform_gradient_attribute = ''; 110 $waveform_background_color_attribute = ''; 111 $waveform_background_gradient_attribute = ''; 112 if ( ! empty( $attributes['waveformColor'] ) ) { 113 $waveform_color_attribute = sprintf( 114 ' data-waveform-player-color="%s"', 115 esc_attr( $attributes['waveformColor'] ) 116 ); 117 } 118 if ( ! empty( $attributes['waveformGradient'] ) ) { 119 $waveform_gradient_attribute = sprintf( 120 ' data-waveform-player-gradient="%s"', 121 esc_attr( $attributes['waveformGradient'] ) 122 ); 123 } 124 if ( ! empty( $attributes['waveformBackgroundColor'] ) ) { 125 $waveform_background_color_attribute = sprintf( 126 ' data-waveform-player-background-color="%s"', 127 esc_attr( $attributes['waveformBackgroundColor'] ) 128 ); 129 } 130 if ( ! empty( $attributes['waveformBackgroundGradient'] ) ) { 131 $waveform_background_gradient_attribute = sprintf( 132 ' data-waveform-player-background-gradient="%s"', 133 esc_attr( $attributes['waveformBackgroundGradient'] ) 134 ); 135 } 136 $html = '<div class="wp-block-playlist__waveform-player"' . 137 $waveform_color_attribute . 138 $waveform_gradient_attribute . 139 $waveform_background_color_attribute . 140 $waveform_background_gradient_attribute . ' 141 data-wp-watch="callbacks.initWaveformPlayer" 142 data-label-play="' . $label_play . '" 143 data-label-pause="' . $label_pause . '" 144 data-label-seek="' . $label_seek . '" 145 data-label-seek-value="' . $label_seek_value . '" 146 ></div>'; 147 148 // Add the waveform player container inside the figure. 149 $processor = new class( $content ) extends WP_HTML_Tag_Processor { 150 /** 151 * Inserts HTML immediately after the current token. 152 * 153 * @since 7.1.4 154 * 155 * @param string $html HTML to insert. 156 */ 157 public function block_core_playlist_insert_after( string $html ) { 158 $this->set_bookmark( 'here' ); 159 $span = $this->bookmarks['here']; 160 161 $this->lexical_updates[] = new WP_HTML_Text_Replacement( $span->start + $span->length, 0, $html ); 162 } 163 }; 164 165 $waveform_style = $attributes['waveformStyle'] ?? 'bars'; 166 167 if ( $processor->next_tag( 'figure' ) ) { 168 $processor->block_core_playlist_insert_after( $html ); 169 $processor->set_attribute( 'data-wp-interactive', 'core/playlist' ); 170 $processor->set_attribute( 171 'data-wp-context', 172 wp_json_encode( 173 array( 174 'playlistId' => $playlist_id, 175 'currentId' => $playlist_tracks[0], 176 'isPlaying' => false, 177 'tracks' => $playlist_tracks, 178 'waveformStyle' => $waveform_style, 179 'showPlayButtonArtwork' => $show_play_button_artwork, 180 'labelPauseTrack' => __( 'Pause' ), 181 'labelSelectTrack' => __( 'Play' ), 182 ) 183 ) 184 ); 185 } 186 187 // Track IDs are render-time only. Add them after inner blocks have rendered 188 // so track buttons can update the Interactivity API state without storing 189 // persistent unique IDs in post content. 190 $track_index = 0; 191 while ( $processor->next_tag( array( 'class_name' => 'wp-block-playlist-track__button' ) ) ) { 192 $track_id = $playlist_tracks[ $track_index ] ?? null; 193 194 if ( null === $track_id ) { 195 break; 196 } 197 198 $processor->set_attribute( 199 'data-wp-context', 200 wp_json_encode( 201 array( 202 'trackId' => $track_id, 203 ) 204 ) 205 ); 206 207 ++$track_index; 208 } 209 210 return $processor->get_updated_html(); 211 } 212 213 /** 214 * Registers the `core/playlist` block on server. 215 * 216 * @since 7.1.0 217 */ 218 function register_block_core_playlist() { 219 register_block_type_from_metadata( 220 __DIR__ . '/playlist', 221 array( 222 'render_callback' => 'render_block_core_playlist', 223 ) 224 ); 225 } 226 add_action( 'init', 'register_block_core_playlist' );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Sat Nov 14 08:20:01 2026 | Cross-referenced by PHPXref |