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