[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

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

   1  <?php
   2  /**
   3   * Tabs Block
   4   *
   5   * @package WordPress
   6   */
   7  
   8  /**
   9   * Extract tabs list from tab-panel innerblocks.
  10   *
  11   * @since 7.1.0
  12   *
  13   * @param array  $innerblocks Parsed inner blocks of tabs block.
  14   * @param string $tabs_id     Unique ID for the tabs instance, used to generate tab IDs.
  15   *
  16   * @return array List of tab IDs.
  17   */
  18  function block_core_tabs_generate_tabs_list( array $innerblocks = array(), string $tabs_id = '' ): array {
  19      $tabs_list = array();
  20  
  21      // Find tab-panel block
  22      foreach ( $innerblocks as $inner_block ) {
  23          if ( 'core/tab-panels' === ( $inner_block['blockName'] ?? '' ) ) {
  24              $tab_index = 0;
  25              foreach ( $inner_block['innerBlocks'] ?? array() as $tab_block ) {
  26                  if ( 'core/tab-panel' === ( $tab_block['blockName'] ?? '' ) ) {
  27                      $attrs = $tab_block['attrs'] ?? array();
  28  
  29                      $tab_id = ! empty( $attrs['anchor'] )
  30                          ? $attrs['anchor']
  31                          : ( ! empty( $tabs_id )
  32                              ? $tabs_id . '-tab-' . $tab_index
  33                              : 'tab-' . $tab_index );
  34  
  35                      $tabs_list[] = esc_attr( $tab_id );
  36                      ++$tab_index;
  37                  }
  38              }
  39              break;
  40          }
  41      }
  42  
  43      return $tabs_list;
  44  }
  45  
  46  /**
  47   * Filter to provide tabs list context to core/tabs and core/tab-list blocks.
  48   * It is more performant to do this here, once, rather than in the tabs render and tabs context filters.
  49   * In this way core/tabs is both a provider and a consumer of the core/tabs-list context.
  50   *
  51   * @since 7.1.0
  52   *
  53   * @param array $context      Default block context.
  54   * @param array $parsed_block The block being rendered.
  55   *
  56   * @return array Modified context.
  57   */
  58  function block_core_tabs_provide_context( array $context, array $parsed_block ): array {
  59      if ( 'core/tabs' === $parsed_block['blockName'] ) {
  60          // Generate a unique ID for the tabs instance first, so it can be used
  61          // to derive stable tab IDs.
  62          $tabs_id                   = $parsed_block['attrs']['anchor'] ?? wp_unique_id( 'tabs_' );
  63          $tabs_list                 = block_core_tabs_generate_tabs_list( $parsed_block['innerBlocks'] ?? array(), $tabs_id );
  64          $context['core/tabs-list'] = $tabs_list;
  65          $context['core/tabs-id']   = $tabs_id;
  66      }
  67  
  68      return $context;
  69  }
  70  add_filter( 'render_block_context', 'block_core_tabs_provide_context', 10, 2 );
  71  
  72  /**
  73   * Render callback for core/tabs.
  74   *
  75   * @since 7.1.0
  76   *
  77   * @param array     $attributes Block attributes.
  78   * @param string    $content    Block content.
  79   * @param \WP_Block $block      WP_Block instance.
  80   *
  81   * @return string Updated HTML.
  82   */
  83  function block_core_tabs_render_block_callback( array $attributes, string $content, \WP_Block $block ): string {
  84      $active_tab_index = $attributes['activeTabIndex'] ?? 0;
  85      $tabs_list        = $block->context['core/tabs-list'] ?? array();
  86      $tabs_id          = $block->context['core/tabs-id'] ?? null;
  87  
  88      if ( empty( $tabs_id ) ) {
  89          // If malformed tabs, return early to avoid errors.
  90          return '';
  91      }
  92  
  93      $tag_processor = new WP_HTML_Tag_Processor( $content );
  94  
  95      $tag_processor->next_tag( array( 'class_name' => 'wp-block-tabs' ) );
  96      $tag_processor->set_attribute( 'data-wp-interactive', 'core/tabs' );
  97  
  98      $tag_processor->set_attribute(
  99          'data-wp-context',
 100          wp_json_encode(
 101              array(
 102                  'tabsId'         => $tabs_id,
 103                  'activeTabIndex' => $active_tab_index,
 104              )
 105          )
 106      );
 107      $tag_processor->set_attribute( 'data-wp-init', 'callbacks.onTabsInit' );
 108      $tag_processor->set_attribute( 'data-wp-on--keydown', 'actions.handleTabKeyDown' );
 109  
 110      $output = $tag_processor->get_updated_html();
 111  
 112      /**
 113       * Builds a client side state for just this tabs instance, so each
 114       * core/tabs block manages its own state, like context.
 115       */
 116      wp_interactivity_state(
 117          'core/tabs',
 118          array(
 119              $tabs_id => $tabs_list,
 120          )
 121      );
 122  
 123      return $output;
 124  }
 125  
 126  /**
 127   * Registers the `core/tabs` block on the server.
 128   *
 129   * @since 7.1.0
 130   */
 131  function register_block_core_tabs() {
 132      register_block_type_from_metadata(
 133          __DIR__ . '/tabs',
 134          array(
 135              'render_callback' => 'block_core_tabs_render_block_callback',
 136          )
 137      );
 138  }
 139  add_action( 'init', 'register_block_core_tabs' );


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