| [ 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 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 register_block_core_playlist() { 208 register_block_type_from_metadata( 209 __DIR__ . '/playlist', 210 array( 211 'render_callback' => 'render_block_core_playlist', 212 ) 213 ); 214 } 215 add_action( 'init', 'register_block_core_playlist' );
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated : Tue Sep 15 08:20:32 2026 | Cross-referenced by PHPXref |