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


Generated : Sun Jul 5 08:20:13 2026 Cross-referenced by PHPXref