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


Generated : Sat Nov 14 08:20:01 2026 Cross-referenced by PHPXref