[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

/wp-includes/block-supports/ -> block-visibility.php (source)

   1  <?php
   2  /**
   3   * Block visibility block support flag.
   4   *
   5   * @package WordPress
   6   * @since 6.9.0
   7   */
   8  
   9  /**
  10   * Render nothing if the block is hidden, or add viewport visibility styles.
  11   *
  12   * @since 6.9.0
  13   * @since 7.0.0 Added support for viewport visibility.
  14   * @access private
  15   *
  16   * @param string $block_content Rendered block content.
  17   * @param array  $block         Block object.
  18   * @return string Filtered block content.
  19   */
  20  function wp_render_block_visibility_support( $block_content, $block ) {
  21      $block_type = WP_Block_Type_Registry::get_instance()->get_registered( $block['blockName'] );
  22  
  23      if ( ! $block_type || ! block_has_support( $block_type, 'visibility', true ) ) {
  24          return $block_content;
  25      }
  26  
  27      $block_visibility = $block['attrs']['metadata']['blockVisibility'] ?? null;
  28  
  29      if ( false === $block_visibility ) {
  30          return '';
  31      }
  32  
  33      if ( is_array( $block_visibility ) && ! empty( $block_visibility ) ) {
  34          $viewport_config = $block_visibility['viewport'] ?? null;
  35  
  36          if ( ! is_array( $viewport_config ) || empty( $viewport_config ) ) {
  37              return $block_content;
  38          }
  39          /*
  40           * Viewport size definitions are in several places in WordPress packages.
  41           * The following are taken from: https://github.com/WordPress/gutenberg/blob/trunk/packages/base-styles/_breakpoints.scss
  42           * The array is in a future, potential JSON format, and will be centralized
  43           * as the feature is developed.
  44           *
  45           * Viewport sizes as array items are defined sequentially. The first item's size is the max value.
  46           * Each subsequent item starts after the previous size (using > operator), and its size is the max.
  47           * The last item starts after the previous size (using > operator), and it has no max.
  48           */
  49          $viewport_sizes = array(
  50              array(
  51                  'name' => 'Mobile',
  52                  'slug' => 'mobile',
  53                  'size' => '480px',
  54              ),
  55              array(
  56                  'name' => 'Tablet',
  57                  'slug' => 'tablet',
  58                  'size' => '782px',
  59              ),
  60              array(
  61                  'name' => 'Desktop',
  62                  'slug' => 'desktop',
  63                  /*
  64                   * Note: the last item in the $viewport_sizes array does not technically require a 'size' key,
  65                   * as the last item's media query is calculated using `width > previous size`.
  66                   * The last item is present for validating the attribute values, and in order to indicate
  67                   * that this is the final viewport size, and to calculate the previous media query accordingly.
  68                   */
  69              ),
  70          );
  71  
  72          /*
  73           * Build media queries from viewport size definitions using the CSS range syntax.
  74           * Could be absorbed into the style engine,
  75           * as well as classname building, and declaration of the display property, if required.
  76           */
  77          $viewport_media_queries = array();
  78          $previous_size          = null;
  79          foreach ( $viewport_sizes as $index => $viewport_size ) {
  80              // First item: width <= size.
  81              if ( 0 === $index ) {
  82                  $viewport_media_queries[ $viewport_size['slug'] ] = "@media (width <= {$viewport_size['size']})";
  83              } elseif ( count( $viewport_sizes ) - 1 === $index && $previous_size ) {
  84                  // Last item: width > previous size.
  85                  $viewport_media_queries[ $viewport_size['slug'] ] = "@media (width > $previous_size)";
  86              } else {
  87                  // Middle items: previous size < width <= size.
  88                  $viewport_media_queries[ $viewport_size['slug'] ] = "@media ({$previous_size} < width <= {$viewport_size['size']})";
  89              }
  90  
  91              $previous_size = $viewport_size['size'] ?? null;
  92          }
  93  
  94          $hidden_on = array();
  95  
  96          // Collect which viewport the block is hidden on (only known viewport sizes).
  97          foreach ( $viewport_config as $viewport_config_size => $is_visible ) {
  98              if ( false === $is_visible && isset( $viewport_media_queries[ $viewport_config_size ] ) ) {
  99                  $hidden_on[] = $viewport_config_size;
 100              }
 101          }
 102  
 103          // If no viewport sizes have visibility set to false, return unchanged.
 104          if ( empty( $hidden_on ) ) {
 105              return $block_content;
 106          }
 107  
 108          // Maintain consistent order of viewport sizes for class name generation.
 109          sort( $hidden_on );
 110  
 111          $css_rules   = array();
 112          $class_names = array();
 113  
 114          foreach ( $hidden_on as $hidden_viewport_size ) {
 115              /*
 116               * If these values ever become user-defined,
 117               * they should be sanitized and kebab-cased.
 118               */
 119              $visibility_class = 'wp-block-hidden-' . $hidden_viewport_size;
 120              $class_names[]    = $visibility_class;
 121              $css_rules[]      = array(
 122                  'selector'     => '.' . $visibility_class,
 123                  'declarations' => array(
 124                      'display' => 'none !important',
 125                  ),
 126                  'rules_group'  => $viewport_media_queries[ $hidden_viewport_size ],
 127              );
 128          }
 129  
 130          wp_style_engine_get_stylesheet_from_css_rules(
 131              $css_rules,
 132              array(
 133                  'context'  => 'block-supports',
 134                  'prettify' => false,
 135              )
 136          );
 137  
 138          if ( ! empty( $block_content ) ) {
 139              $processor = new WP_HTML_Tag_Processor( $block_content );
 140              if ( $processor->next_tag() ) {
 141                  $processor->add_class( implode( ' ', $class_names ) );
 142  
 143                  /*
 144                   * Set all IMG tags to be `fetchpriority=auto` so that wp_get_loading_optimization_attributes() won't add
 145                   * `fetchpriority=high` or increment the media count to affect whether subsequent IMG tags get `loading=lazy`.
 146                   */
 147                  do {
 148                      if ( 'IMG' === $processor->get_tag() ) {
 149                          $processor->set_attribute( 'fetchpriority', 'auto' );
 150                      }
 151                  } while ( $processor->next_tag() );
 152                  $block_content = $processor->get_updated_html();
 153              }
 154          }
 155      }
 156  
 157      return $block_content;
 158  }
 159  
 160  add_filter( 'render_block', 'wp_render_block_visibility_support', 10, 2 );


Generated : Mon Jun 15 08:20:09 2026 Cross-referenced by PHPXref