[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

title

Body

[close]

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

   1  <?php
   2  /**
   3   * Server-side rendering of the `core/image` block.
   4   *
   5   * @package WordPress
   6   */
   7  
   8  /**
   9   * Renders the `core/image` block on the server,
  10   * adding a data-id attribute to the element if core/gallery has added on pre-render.
  11   *
  12   * @param array    $attributes The block attributes.
  13   * @param string   $content    The block content.
  14   * @param WP_Block $block      The block object.
  15   *
  16   * @return string The block content with the data-id attribute added.
  17   */
  18  function render_block_core_image( $attributes, $content, $block ) {
  19      if ( false === stripos( $content, '<img' ) ) {
  20          return '';
  21      }
  22  
  23      $p = new WP_HTML_Tag_Processor( $content );
  24  
  25      if ( ! $p->next_tag( 'img' ) || null === $p->get_attribute( 'src' ) ) {
  26          return '';
  27      }
  28  
  29      if ( isset( $attributes['data-id'] ) ) {
  30          // Adds the data-id="$id" attribute to the img element to provide backwards
  31          // compatibility for the Gallery Block, which now wraps Image Blocks within
  32          // innerBlocks. The data-id attribute is added in a core/gallery
  33          // `render_block_data` hook.
  34          $p->set_attribute( 'data-id', $attributes['data-id'] );
  35      }
  36  
  37      $link_destination  = isset( $attributes['linkDestination'] ) ? $attributes['linkDestination'] : 'none';
  38      $lightbox_settings = block_core_image_get_lightbox_settings( $block->parsed_block );
  39  
  40      /*
  41       * If the lightbox is enabled and the image is not linked, adds the filter and
  42       * the JavaScript view file.
  43       */
  44      if (
  45          isset( $lightbox_settings ) &&
  46          'none' === $link_destination &&
  47          isset( $lightbox_settings['enabled'] ) &&
  48          true === $lightbox_settings['enabled']
  49      ) {
  50          $suffix = wp_scripts_get_suffix();
  51          if ( defined( 'IS_GUTENBERG_PLUGIN' ) && IS_GUTENBERG_PLUGIN ) {
  52              $module_url = gutenberg_url( '/build/interactivity/image.min.js' );
  53          }
  54  
  55          wp_register_script_module(
  56              '@wordpress/block-library/image',
  57              isset( $module_url ) ? $module_url : includes_url( "blocks/image/view{$suffix}.js" ),
  58              array( '@wordpress/interactivity' ),
  59              defined( 'GUTENBERG_VERSION' ) ? GUTENBERG_VERSION : get_bloginfo( 'version' )
  60          );
  61  
  62          wp_enqueue_script_module( '@wordpress/block-library/image' );
  63  
  64          /*
  65           * This render needs to happen in a filter with priority 15 to ensure that
  66           * it runs after the duotone filter and that duotone styles are applied to
  67           * the image in the lightbox. Lightbox has to work with any plugins that
  68           * might use filters as well. Removing this can be considered in the future
  69           * if the way the blocks are rendered changes, or if a new kind of filter is
  70           * introduced.
  71           */
  72          add_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15, 2 );
  73      } else {
  74          /*
  75           * Remove the filter if previously added by other Image blocks.
  76           */
  77          remove_filter( 'render_block_core/image', 'block_core_image_render_lightbox', 15 );
  78      }
  79  
  80      return $p->get_updated_html();
  81  }
  82  
  83  /**
  84   * Adds the lightboxEnabled flag to the block data.
  85   *
  86   * This is used to determine whether the lightbox should be rendered or not.
  87   *
  88   * @param array $block Block data.
  89   *
  90   * @return array Filtered block data.
  91   */
  92  function block_core_image_get_lightbox_settings( $block ) {
  93      // Gets the lightbox setting from the block attributes.
  94      if ( isset( $block['attrs']['lightbox'] ) ) {
  95          $lightbox_settings = $block['attrs']['lightbox'];
  96      }
  97  
  98      if ( ! isset( $lightbox_settings ) ) {
  99          $lightbox_settings = wp_get_global_settings( array( 'lightbox' ), array( 'block_name' => 'core/image' ) );
 100  
 101          // If not present in global settings, check the top-level global settings.
 102          //
 103          // NOTE: If no block-level settings are found, the previous call to
 104          // `wp_get_global_settings` will return the whole `theme.json` structure in
 105          // which case we can check if the "lightbox" key is present at the top-level
 106          // of the global settings and use its value.
 107          if ( isset( $lightbox_settings['lightbox'] ) ) {
 108              $lightbox_settings = wp_get_global_settings( array( 'lightbox' ) );
 109          }
 110      }
 111  
 112      return $lightbox_settings ?? null;
 113  }
 114  
 115  /**
 116   * Adds the directives and layout needed for the lightbox behavior.
 117   *
 118   * @param string $block_content Rendered block content.
 119   * @param array  $block         Block object.
 120   *
 121   * @return string Filtered block content.
 122   */
 123  function block_core_image_render_lightbox( $block_content, $block ) {
 124      /*
 125       * If there's no IMG tag in the block then return the given block content
 126       * as-is. There's nothing that this code can knowingly modify to add the
 127       * lightbox behavior.
 128       */
 129      $p = new WP_HTML_Tag_Processor( $block_content );
 130      if ( $p->next_tag( 'figure' ) ) {
 131          $p->set_bookmark( 'figure' );
 132      }
 133      if ( ! $p->next_tag( 'img' ) ) {
 134          return $block_content;
 135      }
 136  
 137      $alt              = $p->get_attribute( 'alt' );
 138      $img_uploaded_src = $p->get_attribute( 'src' );
 139      $img_class_names  = $p->get_attribute( 'class' );
 140      $img_styles       = $p->get_attribute( 'style' );
 141      $img_width        = 'none';
 142      $img_height       = 'none';
 143      $aria_label       = __( 'Enlarge image' );
 144  
 145      if ( $alt ) {
 146          /* translators: %s: Image alt text. */
 147          $aria_label = sprintf( __( 'Enlarge image: %s' ), $alt );
 148      }
 149  
 150      if ( isset( $block['attrs']['id'] ) ) {
 151          $img_uploaded_src = wp_get_attachment_url( $block['attrs']['id'] );
 152          $img_metadata     = wp_get_attachment_metadata( $block['attrs']['id'] );
 153          $img_width        = $img_metadata['width'] ?? 'none';
 154          $img_height       = $img_metadata['height'] ?? 'none';
 155      }
 156  
 157      // Figure.
 158      $p->seek( 'figure' );
 159      $figure_class_names = $p->get_attribute( 'class' );
 160      $figure_styles      = $p->get_attribute( 'style' );
 161      $p->add_class( 'wp-lightbox-container' );
 162      $p->set_attribute( 'data-wp-interactive', 'core/image' );
 163      $p->set_attribute(
 164          'data-wp-context',
 165          wp_json_encode(
 166              array(
 167                  'uploadedSrc'      => $img_uploaded_src,
 168                  'figureClassNames' => $figure_class_names,
 169                  'figureStyles'     => $figure_styles,
 170                  'imgClassNames'    => $img_class_names,
 171                  'imgStyles'        => $img_styles,
 172                  'targetWidth'      => $img_width,
 173                  'targetHeight'     => $img_height,
 174                  'scaleAttr'        => $block['attrs']['scale'] ?? false,
 175                  'ariaLabel'        => $aria_label,
 176                  'alt'              => $alt,
 177              ),
 178              JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP
 179          )
 180      );
 181  
 182      // Image.
 183      $p->next_tag( 'img' );
 184      $p->set_attribute( 'data-wp-init', 'callbacks.setButtonStyles' );
 185      $p->set_attribute( 'data-wp-on--load', 'callbacks.setButtonStyles' );
 186      $p->set_attribute( 'data-wp-on-window--resize', 'callbacks.setButtonStyles' );
 187      // Sets an event callback on the `img` because the `figure` element can also
 188      // contain a caption, and we don't want to trigger the lightbox when the
 189      // caption is clicked.
 190      $p->set_attribute( 'data-wp-on--click', 'actions.showLightbox' );
 191  
 192      $body_content = $p->get_updated_html();
 193  
 194      // Adds a button alongside image in the body content.
 195      $img = null;
 196      preg_match( '/<img[^>]+>/', $body_content, $img );
 197  
 198      $button =
 199          $img[0]
 200          . '<button
 201              class="lightbox-trigger"
 202              type="button"
 203              aria-haspopup="dialog"
 204              aria-label="' . esc_attr( $aria_label ) . '"
 205              data-wp-init="callbacks.initTriggerButton"
 206              data-wp-on--click="actions.showLightbox"
 207              data-wp-style--right="context.imageButtonRight"
 208              data-wp-style--top="context.imageButtonTop"
 209          >
 210              <svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" fill="none" viewBox="0 0 12 12">
 211                  <path fill="#fff" d="M2 0a2 2 0 0 0-2 2v2h1.5V2a.5.5 0 0 1 .5-.5h2V0H2Zm2 10.5H2a.5.5 0 0 1-.5-.5V8H0v2a2 2 0 0 0 2 2h2v-1.5ZM8 12v-1.5h2a.5.5 0 0 0 .5-.5V8H12v2a2 2 0 0 1-2 2H8Zm2-12a2 2 0 0 1 2 2v2h-1.5V2a.5.5 0 0 0-.5-.5H8V0h2Z" />
 212              </svg>
 213          </button>';
 214  
 215      $body_content = preg_replace( '/<img[^>]+>/', $button, $body_content );
 216  
 217      add_action( 'wp_footer', 'block_core_image_print_lightbox_overlay' );
 218  
 219      return $body_content;
 220  }
 221  
 222  function block_core_image_print_lightbox_overlay() {
 223      $close_button_label = esc_attr__( 'Close' );
 224  
 225      // If the current theme does NOT have a `theme.json`, or the colors are not
 226      // defined, it needs to set the background color & close button color to some
 227      // default values because it can't get them from the Global Styles.
 228      $background_color   = '#fff';
 229      $close_button_color = '#000';
 230      if ( wp_theme_has_theme_json() ) {
 231          $global_styles_color = wp_get_global_styles( array( 'color' ) );
 232          if ( ! empty( $global_styles_color['background'] ) ) {
 233              $background_color = esc_attr( $global_styles_color['background'] );
 234          }
 235          if ( ! empty( $global_styles_color['text'] ) ) {
 236              $close_button_color = esc_attr( $global_styles_color['text'] );
 237          }
 238      }
 239  
 240      echo <<<HTML
 241          <div 
 242              class="wp-lightbox-overlay zoom"
 243              data-wp-interactive="core/image"
 244              data-wp-context='{}'
 245              data-wp-bind--role="state.roleAttribute"
 246              data-wp-bind--aria-label="state.currentImage.ariaLabel"
 247              data-wp-bind--aria-modal="state.ariaModal"
 248              data-wp-class--active="state.overlayEnabled"
 249              data-wp-class--show-closing-animation="state.showClosingAnimation"
 250              data-wp-watch="callbacks.setOverlayFocus"
 251              data-wp-on--keydown="actions.handleKeydown"
 252              data-wp-on--touchstart="actions.handleTouchStart"
 253              data-wp-on--touchmove="actions.handleTouchMove"
 254              data-wp-on--touchend="actions.handleTouchEnd"
 255              data-wp-on--click="actions.hideLightbox"
 256              data-wp-on-window--resize="callbacks.setOverlayStyles"
 257              data-wp-on-window--scroll="actions.handleScroll"
 258              tabindex="-1"
 259              >
 260                  <button type="button" aria-label="$close_button_label" style="fill: $close_button_color" class="close-button">
 261                      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="20" height="20" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg>
 262                  </button>
 263                  <div class="lightbox-image-container">
 264                      <figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.currentImage.figureStyles">
 265                          <img data-wp-bind--alt="state.currentImage.alt" data-wp-bind--class="state.currentImage.imgClassNames" data-wp-bind--style="state.imgStyles" data-wp-bind--src="state.currentImage.currentSrc">
 266                      </figure>
 267                  </div>
 268                  <div class="lightbox-image-container">
 269                      <figure data-wp-bind--class="state.currentImage.figureClassNames" data-wp-bind--style="state.currentImage.figureStyles">
 270                          <img data-wp-bind--alt="state.currentImage.alt" data-wp-bind--class="state.currentImage.imgClassNames" data-wp-bind--style="state.imgStyles" data-wp-bind--src="state.enlargedSrc">
 271                      </figure>
 272                  </div>
 273                  <div class="scrim" style="background-color: $background_color" aria-hidden="true"></div>
 274                  <style data-wp-text="state.overlayStyles"></style>
 275          </div>
 276  HTML;
 277  }
 278  
 279  /**
 280   * Registers the `core/image` block on server.
 281   */
 282  function register_block_core_image() {
 283      register_block_type_from_metadata(
 284          __DIR__ . '/image',
 285          array(
 286              'render_callback' => 'render_block_core_image',
 287          )
 288      );
 289  }
 290  add_action( 'init', 'register_block_core_image' );


Generated : Fri Apr 26 08:20:02 2024 Cross-referenced by PHPXref