[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/blocks/ -> playlist.php (source)

   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' );


Generated : Wed Jul 15 08:20:16 2026 Cross-referenced by PHPXref