[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

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

   1  <?php
   2  /**
   3   * Functions related to registering and parsing blocks.
   4   *
   5   * @package WordPress
   6   * @subpackage Blocks
   7   * @since 5.0.0
   8   */
   9  
  10  /**
  11   * Registers a block type.
  12   *
  13   * @since 5.0.0
  14   *
  15   * @param string|WP_Block_Type $name Block type name including namespace, or alternatively
  16   *                                   a complete WP_Block_Type instance. In case a WP_Block_Type
  17   *                                   is provided, the $args parameter will be ignored.
  18   * @param array                $args {
  19   *     Optional. Array of block type arguments. Accepts any public property of `WP_Block_Type`.
  20   *     Any arguments may be defined, however the ones described below are supported by default.
  21   *     Default empty array.
  22   *
  23   *     @type callable $render_callback Callback used to render blocks of this block type.
  24   * }
  25   * @return WP_Block_Type|false The registered block type on success, or false on failure.
  26   */
  27  function register_block_type( $name, $args = array() ) {
  28      return WP_Block_Type_Registry::get_instance()->register( $name, $args );
  29  }
  30  
  31  /**
  32   * Unregisters a block type.
  33   *
  34   * @since 5.0.0
  35   *
  36   * @param string|WP_Block_Type $name Block type name including namespace, or alternatively
  37   *                                   a complete WP_Block_Type instance.
  38   * @return WP_Block_Type|false The unregistered block type on success, or false on failure.
  39   */
  40  function unregister_block_type( $name ) {
  41      return WP_Block_Type_Registry::get_instance()->unregister( $name );
  42  }
  43  
  44  /**
  45   * Removes the block asset's path prefix if provided.
  46   *
  47   * @since 5.5.0
  48   *
  49   * @param string $asset_handle_or_path Asset handle or prefixed path.
  50   * @return string Path without the prefix or the original value.
  51   */
  52  function remove_block_asset_path_prefix( $asset_handle_or_path ) {
  53      $path_prefix = 'file:';
  54      if ( 0 !== strpos( $asset_handle_or_path, $path_prefix ) ) {
  55          return $asset_handle_or_path;
  56      }
  57      return substr(
  58          $asset_handle_or_path,
  59          strlen( $path_prefix )
  60      );
  61  }
  62  
  63  /**
  64   * Generates the name for an asset based on the name of the block
  65   * and the field name provided.
  66   *
  67   * @since 5.5.0
  68   *
  69   * @param string $block_name Name of the block.
  70   * @param string $field_name Name of the metadata field.
  71   * @return string Generated asset name for the block's field.
  72   */
  73  function generate_block_asset_handle( $block_name, $field_name ) {
  74      $field_mappings = array(
  75          'editorScript' => 'editor-script',
  76          'script'       => 'script',
  77          'editorStyle'  => 'editor-style',
  78          'style'        => 'style',
  79      );
  80      return str_replace( '/', '-', $block_name ) .
  81          '-' . $field_mappings[ $field_name ];
  82  }
  83  
  84  /**
  85   * Finds a script handle for the selected block metadata field. It detects
  86   * when a path to file was provided and finds a corresponding asset file
  87   * with details necessary to register the script under automatically
  88   * generated handle name. It returns unprocessed script handle otherwise.
  89   *
  90   * @since 5.5.0
  91   *
  92   * @param array  $metadata   Block metadata.
  93   * @param string $field_name Field name to pick from metadata.
  94   * @return string|bool Script handle provided directly or created through
  95   *                     script's registration, or false on failure.
  96   */
  97  function register_block_script_handle( $metadata, $field_name ) {
  98      if ( empty( $metadata[ $field_name ] ) ) {
  99          return false;
 100      }
 101      $script_handle = $metadata[ $field_name ];
 102      $script_path   = remove_block_asset_path_prefix( $metadata[ $field_name ] );
 103      if ( $script_handle === $script_path ) {
 104          return $script_handle;
 105      }
 106  
 107      $script_handle     = generate_block_asset_handle( $metadata['name'], $field_name );
 108      $script_asset_path = realpath(
 109          dirname( $metadata['file'] ) . '/' .
 110          substr_replace( $script_path, '.asset.php', - strlen( '.js' ) )
 111      );
 112      if ( ! file_exists( $script_asset_path ) ) {
 113          $message = sprintf(
 114              /* translators: %1: field name. %2: block name */
 115              __( 'The asset file for the "%1$s" defined in "%2$s" block definition is missing.', 'default' ),
 116              $field_name,
 117              $metadata['name']
 118          );
 119          _doing_it_wrong( __FUNCTION__, $message, '5.5.0' );
 120          return false;
 121      }
 122      $script_asset = require $script_asset_path;
 123      $result       = wp_register_script(
 124          $script_handle,
 125          plugins_url( $script_path, $metadata['file'] ),
 126          $script_asset['dependencies'],
 127          $script_asset['version']
 128      );
 129      return $result ? $script_handle : false;
 130  }
 131  
 132  /**
 133   * Finds a style handle for the block metadata field. It detects when a path
 134   * to file was provided and registers the style under automatically
 135   * generated handle name. It returns unprocessed style handle otherwise.
 136   *
 137   * @since 5.5.0
 138   *
 139   * @param array  $metadata Block metadata.
 140   * @param string $field_name Field name to pick from metadata.
 141   * @return string|boolean Style handle provided directly or created through
 142   *                        style's registration, or false on failure.
 143   */
 144  function register_block_style_handle( $metadata, $field_name ) {
 145      if ( empty( $metadata[ $field_name ] ) ) {
 146          return false;
 147      }
 148      $style_handle = $metadata[ $field_name ];
 149      $style_path   = remove_block_asset_path_prefix( $metadata[ $field_name ] );
 150      if ( $style_handle === $style_path ) {
 151          return $style_handle;
 152      }
 153  
 154      $style_handle = generate_block_asset_handle( $metadata['name'], $field_name );
 155      $block_dir    = dirname( $metadata['file'] );
 156      $result       = wp_register_style(
 157          $style_handle,
 158          plugins_url( $style_path, $metadata['file'] ),
 159          array(),
 160          filemtime( realpath( "$block_dir/$style_path" ) )
 161      );
 162      return $result ? $style_handle : false;
 163  }
 164  
 165  /**
 166   * Registers a block type from metadata stored in the `block.json` file.
 167   *
 168   * @since 5.5.0
 169   *
 170   * @param string $file_or_folder Path to the JSON file with metadata definition for
 171   *                               the block or path to the folder where the `block.json` file is located.
 172   * @param array  $args {
 173   *     Optional. Array of block type arguments. Accepts any public property of `WP_Block_Type`.
 174   *     Any arguments may be defined, however the ones described below are supported by default.
 175   *     Default empty array.
 176   *
 177   *     @type callable $render_callback Callback used to render blocks of this block type.
 178   * }
 179   * @return WP_Block_Type|false The registered block type on success, or false on failure.
 180   */
 181  function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
 182      $filename      = 'block.json';
 183      $metadata_file = ( substr( $file_or_folder, -strlen( $filename ) ) !== $filename ) ?
 184          trailingslashit( $file_or_folder ) . $filename :
 185          $file_or_folder;
 186      if ( ! file_exists( $metadata_file ) ) {
 187          return false;
 188      }
 189  
 190      $metadata = json_decode( file_get_contents( $metadata_file ), true );
 191      if ( ! is_array( $metadata ) || empty( $metadata['name'] ) ) {
 192          return false;
 193      }
 194      $metadata['file'] = $metadata_file;
 195  
 196      $settings          = array();
 197      $property_mappings = array(
 198          'title'           => 'title',
 199          'category'        => 'category',
 200          'parent'          => 'parent',
 201          'icon'            => 'icon',
 202          'description'     => 'description',
 203          'keywords'        => 'keywords',
 204          'attributes'      => 'attributes',
 205          'providesContext' => 'provides_context',
 206          'usesContext'     => 'uses_context',
 207          'supports'        => 'supports',
 208          'styles'          => 'styles',
 209          'example'         => 'example',
 210      );
 211  
 212      foreach ( $property_mappings as $key => $mapped_key ) {
 213          if ( isset( $metadata[ $key ] ) ) {
 214              $settings[ $mapped_key ] = $metadata[ $key ];
 215          }
 216      }
 217  
 218      if ( ! empty( $metadata['editorScript'] ) ) {
 219          $settings['editor_script'] = register_block_script_handle(
 220              $metadata,
 221              'editorScript'
 222          );
 223      }
 224  
 225      if ( ! empty( $metadata['script'] ) ) {
 226          $settings['script'] = register_block_script_handle(
 227              $metadata,
 228              'script'
 229          );
 230      }
 231  
 232      if ( ! empty( $metadata['editorStyle'] ) ) {
 233          $settings['editor_style'] = register_block_style_handle(
 234              $metadata,
 235              'editorStyle'
 236          );
 237      }
 238  
 239      if ( ! empty( $metadata['style'] ) ) {
 240          $settings['style'] = register_block_style_handle(
 241              $metadata,
 242              'style'
 243          );
 244      }
 245  
 246      return register_block_type(
 247          $metadata['name'],
 248          array_merge(
 249              $settings,
 250              $args
 251          )
 252      );
 253  }
 254  
 255  /**
 256   * Determine whether a post or content string has blocks.
 257   *
 258   * This test optimizes for performance rather than strict accuracy, detecting
 259   * the pattern of a block but not validating its structure. For strict accuracy,
 260   * you should use the block parser on post content.
 261   *
 262   * @since 5.0.0
 263   *
 264   * @see parse_blocks()
 265   *
 266   * @param int|string|WP_Post|null $post Optional. Post content, post ID, or post object. Defaults to global $post.
 267   * @return bool Whether the post has blocks.
 268   */
 269  function has_blocks( $post = null ) {
 270      if ( ! is_string( $post ) ) {
 271          $wp_post = get_post( $post );
 272          if ( $wp_post instanceof WP_Post ) {
 273              $post = $wp_post->post_content;
 274          }
 275      }
 276  
 277      return false !== strpos( (string) $post, '<!-- wp:' );
 278  }
 279  
 280  /**
 281   * Determine whether a $post or a string contains a specific block type.
 282   *
 283   * This test optimizes for performance rather than strict accuracy, detecting
 284   * the block type exists but not validating its structure. For strict accuracy,
 285   * you should use the block parser on post content.
 286   *
 287   * @since 5.0.0
 288   *
 289   * @see parse_blocks()
 290   *
 291   * @param string                  $block_name Full Block type to look for.
 292   * @param int|string|WP_Post|null $post Optional. Post content, post ID, or post object. Defaults to global $post.
 293   * @return bool Whether the post content contains the specified block.
 294   */
 295  function has_block( $block_name, $post = null ) {
 296      if ( ! has_blocks( $post ) ) {
 297          return false;
 298      }
 299  
 300      if ( ! is_string( $post ) ) {
 301          $wp_post = get_post( $post );
 302          if ( $wp_post instanceof WP_Post ) {
 303              $post = $wp_post->post_content;
 304          }
 305      }
 306  
 307      /*
 308       * Normalize block name to include namespace, if provided as non-namespaced.
 309       * This matches behavior for WordPress 5.0.0 - 5.3.0 in matching blocks by
 310       * their serialized names.
 311       */
 312      if ( false === strpos( $block_name, '/' ) ) {
 313          $block_name = 'core/' . $block_name;
 314      }
 315  
 316      // Test for existence of block by its fully qualified name.
 317      $has_block = false !== strpos( $post, '<!-- wp:' . $block_name . ' ' );
 318  
 319      if ( ! $has_block ) {
 320          /*
 321           * If the given block name would serialize to a different name, test for
 322           * existence by the serialized form.
 323           */
 324          $serialized_block_name = strip_core_block_namespace( $block_name );
 325          if ( $serialized_block_name !== $block_name ) {
 326              $has_block = false !== strpos( $post, '<!-- wp:' . $serialized_block_name . ' ' );
 327          }
 328      }
 329  
 330      return $has_block;
 331  }
 332  
 333  /**
 334   * Returns an array of the names of all registered dynamic block types.
 335   *
 336   * @since 5.0.0
 337   *
 338   * @return string[] Array of dynamic block names.
 339   */
 340  function get_dynamic_block_names() {
 341      $dynamic_block_names = array();
 342  
 343      $block_types = WP_Block_Type_Registry::get_instance()->get_all_registered();
 344      foreach ( $block_types as $block_type ) {
 345          if ( $block_type->is_dynamic() ) {
 346              $dynamic_block_names[] = $block_type->name;
 347          }
 348      }
 349  
 350      return $dynamic_block_names;
 351  }
 352  
 353  /**
 354   * Given an array of attributes, returns a string in the serialized attributes
 355   * format prepared for post content.
 356   *
 357   * The serialized result is a JSON-encoded string, with unicode escape sequence
 358   * substitution for characters which might otherwise interfere with embedding
 359   * the result in an HTML comment.
 360   *
 361   * @since 5.3.1
 362   *
 363   * @param array $block_attributes Attributes object.
 364   * @return string Serialized attributes.
 365   */
 366  function serialize_block_attributes( $block_attributes ) {
 367      $encoded_attributes = json_encode( $block_attributes );
 368      $encoded_attributes = preg_replace( '/--/', '\\u002d\\u002d', $encoded_attributes );
 369      $encoded_attributes = preg_replace( '/</', '\\u003c', $encoded_attributes );
 370      $encoded_attributes = preg_replace( '/>/', '\\u003e', $encoded_attributes );
 371      $encoded_attributes = preg_replace( '/&/', '\\u0026', $encoded_attributes );
 372      // Regex: /\\"/
 373      $encoded_attributes = preg_replace( '/\\\\"/', '\\u0022', $encoded_attributes );
 374  
 375      return $encoded_attributes;
 376  }
 377  
 378  /**
 379   * Returns the block name to use for serialization. This will remove the default
 380   * "core/" namespace from a block name.
 381   *
 382   * @since 5.3.1
 383   *
 384   * @param string $block_name Original block name.
 385   * @return string Block name to use for serialization.
 386   */
 387  function strip_core_block_namespace( $block_name = null ) {
 388      if ( is_string( $block_name ) && 0 === strpos( $block_name, 'core/' ) ) {
 389          return substr( $block_name, 5 );
 390      }
 391  
 392      return $block_name;
 393  }
 394  
 395  /**
 396   * Returns the content of a block, including comment delimiters.
 397   *
 398   * @since 5.3.1
 399   *
 400   * @param string $block_name       Block name.
 401   * @param array  $block_attributes Block attributes.
 402   * @param string $block_content    Block save content.
 403   * @return string Comment-delimited block content.
 404   */
 405  function get_comment_delimited_block_content( $block_name = null, $block_attributes, $block_content ) {
 406      if ( is_null( $block_name ) ) {
 407          return $block_content;
 408      }
 409  
 410      $serialized_block_name = strip_core_block_namespace( $block_name );
 411      $serialized_attributes = empty( $block_attributes ) ? '' : serialize_block_attributes( $block_attributes ) . ' ';
 412  
 413      if ( empty( $block_content ) ) {
 414          return sprintf( '<!-- wp:%s %s/-->', $serialized_block_name, $serialized_attributes );
 415      }
 416  
 417      return sprintf(
 418          '<!-- wp:%s %s-->%s<!-- /wp:%s -->',
 419          $serialized_block_name,
 420          $serialized_attributes,
 421          $block_content,
 422          $serialized_block_name
 423      );
 424  }
 425  
 426  /**
 427   * Returns the content of a block, including comment delimiters, serializing all
 428   * attributes from the given parsed block.
 429   *
 430   * This should be used when preparing a block to be saved to post content.
 431   * Prefer `render_block` when preparing a block for display. Unlike
 432   * `render_block`, this does not evaluate a block's `render_callback`, and will
 433   * instead preserve the markup as parsed.
 434   *
 435   * @since 5.3.1
 436   *
 437   * @param WP_Block_Parser_Block $block A single parsed block object.
 438   * @return string String of rendered HTML.
 439   */
 440  function serialize_block( $block ) {
 441      $block_content = '';
 442  
 443      $index = 0;
 444      foreach ( $block['innerContent'] as $chunk ) {
 445          $block_content .= is_string( $chunk ) ? $chunk : serialize_block( $block['innerBlocks'][ $index++ ] );
 446      }
 447  
 448      if ( ! is_array( $block['attrs'] ) ) {
 449          $block['attrs'] = array();
 450      }
 451  
 452      return get_comment_delimited_block_content(
 453          $block['blockName'],
 454          $block['attrs'],
 455          $block_content
 456      );
 457  }
 458  
 459  /**
 460   * Returns a joined string of the aggregate serialization of the given parsed
 461   * blocks.
 462   *
 463   * @since 5.3.1
 464   *
 465   * @param WP_Block_Parser_Block[] $blocks Parsed block objects.
 466   * @return string String of rendered HTML.
 467   */
 468  function serialize_blocks( $blocks ) {
 469      return implode( '', array_map( 'serialize_block', $blocks ) );
 470  }
 471  
 472  /**
 473   * Filters and sanitizes block content to remove non-allowable HTML from
 474   * parsed block attribute values.
 475   *
 476   * @since 5.3.1
 477   *
 478   * @param string         $text              Text that may contain block content.
 479   * @param array[]|string $allowed_html      An array of allowed HTML elements
 480   *                                          and attributes, or a context name
 481   *                                          such as 'post'.
 482   * @param string[]       $allowed_protocols Array of allowed URL protocols.
 483   * @return string The filtered and sanitized content result.
 484   */
 485  function filter_block_content( $text, $allowed_html = 'post', $allowed_protocols = array() ) {
 486      $result = '';
 487  
 488      $blocks = parse_blocks( $text );
 489      foreach ( $blocks as $block ) {
 490          $block   = filter_block_kses( $block, $allowed_html, $allowed_protocols );
 491          $result .= serialize_block( $block );
 492      }
 493  
 494      return $result;
 495  }
 496  
 497  /**
 498   * Filters and sanitizes a parsed block to remove non-allowable HTML from block
 499   * attribute values.
 500   *
 501   * @since 5.3.1
 502   *
 503   * @param WP_Block_Parser_Block $block             The parsed block object.
 504   * @param array[]|string        $allowed_html      An array of allowed HTML
 505   *                                                 elements and attributes, or a
 506   *                                                 context name such as 'post'.
 507   * @param string[]              $allowed_protocols Allowed URL protocols.
 508   * @return array The filtered and sanitized block object result.
 509   */
 510  function filter_block_kses( $block, $allowed_html, $allowed_protocols = array() ) {
 511      $block['attrs'] = filter_block_kses_value( $block['attrs'], $allowed_html, $allowed_protocols );
 512  
 513      if ( is_array( $block['innerBlocks'] ) ) {
 514          foreach ( $block['innerBlocks'] as $i => $inner_block ) {
 515              $block['innerBlocks'][ $i ] = filter_block_kses( $inner_block, $allowed_html, $allowed_protocols );
 516          }
 517      }
 518  
 519      return $block;
 520  }
 521  
 522  /**
 523   * Filters and sanitizes a parsed block attribute value to remove non-allowable
 524   * HTML.
 525   *
 526   * @since 5.3.1
 527   *
 528   * @param string[]|string $value             The attribute value to filter.
 529   * @param array[]|string  $allowed_html      An array of allowed HTML elements
 530   *                                           and attributes, or a context name
 531   *                                           such as 'post'.
 532   * @param string[]        $allowed_protocols Array of allowed URL protocols.
 533   * @return string[]|string The filtered and sanitized result.
 534   */
 535  function filter_block_kses_value( $value, $allowed_html, $allowed_protocols = array() ) {
 536      if ( is_array( $value ) ) {
 537          foreach ( $value as $key => $inner_value ) {
 538              $filtered_key   = filter_block_kses_value( $key, $allowed_html, $allowed_protocols );
 539              $filtered_value = filter_block_kses_value( $inner_value, $allowed_html, $allowed_protocols );
 540  
 541              if ( $filtered_key !== $key ) {
 542                  unset( $value[ $key ] );
 543              }
 544  
 545              $value[ $filtered_key ] = $filtered_value;
 546          }
 547      } elseif ( is_string( $value ) ) {
 548          return wp_kses( $value, $allowed_html, $allowed_protocols );
 549      }
 550  
 551      return $value;
 552  }
 553  
 554  /**
 555   * Parses blocks out of a content string, and renders those appropriate for the excerpt.
 556   *
 557   * As the excerpt should be a small string of text relevant to the full post content,
 558   * this function renders the blocks that are most likely to contain such text.
 559   *
 560   * @since 5.0.0
 561   *
 562   * @param string $content The content to parse.
 563   * @return string The parsed and filtered content.
 564   */
 565  function excerpt_remove_blocks( $content ) {
 566      $allowed_inner_blocks = array(
 567          // Classic blocks have their blockName set to null.
 568          null,
 569          'core/freeform',
 570          'core/heading',
 571          'core/html',
 572          'core/list',
 573          'core/media-text',
 574          'core/paragraph',
 575          'core/preformatted',
 576          'core/pullquote',
 577          'core/quote',
 578          'core/table',
 579          'core/verse',
 580      );
 581  
 582      $allowed_blocks = array_merge( $allowed_inner_blocks, array( 'core/columns' ) );
 583  
 584      /**
 585       * Filters the list of blocks that can contribute to the excerpt.
 586       *
 587       * If a dynamic block is added to this list, it must not generate another
 588       * excerpt, as this will cause an infinite loop to occur.
 589       *
 590       * @since 5.0.0
 591       *
 592       * @param array $allowed_blocks The list of allowed blocks.
 593       */
 594      $allowed_blocks = apply_filters( 'excerpt_allowed_blocks', $allowed_blocks );
 595      $blocks         = parse_blocks( $content );
 596      $output         = '';
 597  
 598      foreach ( $blocks as $block ) {
 599          if ( in_array( $block['blockName'], $allowed_blocks, true ) ) {
 600              if ( ! empty( $block['innerBlocks'] ) ) {
 601                  if ( 'core/columns' === $block['blockName'] ) {
 602                      $output .= _excerpt_render_inner_columns_blocks( $block, $allowed_inner_blocks );
 603                      continue;
 604                  }
 605  
 606                  // Skip the block if it has disallowed or nested inner blocks.
 607                  foreach ( $block['innerBlocks'] as $inner_block ) {
 608                      if (
 609                          ! in_array( $inner_block['blockName'], $allowed_inner_blocks, true ) ||
 610                          ! empty( $inner_block['innerBlocks'] )
 611                      ) {
 612                          continue 2;
 613                      }
 614                  }
 615              }
 616  
 617              $output .= render_block( $block );
 618          }
 619      }
 620  
 621      return $output;
 622  }
 623  
 624  /**
 625   * Render inner blocks from the `core/columns` block for generating an excerpt.
 626   *
 627   * @since 5.2.0
 628   * @access private
 629   *
 630   * @param array $columns        The parsed columns block.
 631   * @param array $allowed_blocks The list of allowed inner blocks.
 632   * @return string The rendered inner blocks.
 633   */
 634  function _excerpt_render_inner_columns_blocks( $columns, $allowed_blocks ) {
 635      $output = '';
 636  
 637      foreach ( $columns['innerBlocks'] as $column ) {
 638          foreach ( $column['innerBlocks'] as $inner_block ) {
 639              if ( in_array( $inner_block['blockName'], $allowed_blocks, true ) && empty( $inner_block['innerBlocks'] ) ) {
 640                  $output .= render_block( $inner_block );
 641              }
 642          }
 643      }
 644  
 645      return $output;
 646  }
 647  
 648  /**
 649   * Renders a single block into a HTML string.
 650   *
 651   * @since 5.0.0
 652   *
 653   * @global WP_Post  $post     The post to edit.
 654   * @global WP_Query $wp_query WordPress Query object.
 655   *
 656   * @param array $parsed_block A single parsed block object.
 657   * @return string String of rendered HTML.
 658   */
 659  function render_block( $parsed_block ) {
 660      global $post, $wp_query;
 661  
 662      /**
 663       * Allows render_block() to be short-circuited, by returning a non-null value.
 664       *
 665       * @since 5.1.0
 666       *
 667       * @param string|null $pre_render   The pre-rendered content. Default null.
 668       * @param array       $parsed_block The block being rendered.
 669       */
 670      $pre_render = apply_filters( 'pre_render_block', null, $parsed_block );
 671      if ( ! is_null( $pre_render ) ) {
 672          return $pre_render;
 673      }
 674  
 675      $source_block = $parsed_block;
 676  
 677      /**
 678       * Filters the block being rendered in render_block(), before it's processed.
 679       *
 680       * @since 5.1.0
 681       *
 682       * @param array $parsed_block The block being rendered.
 683       * @param array $source_block An un-modified copy of $parsed_block, as it appeared in the source content.
 684       */
 685      $parsed_block = apply_filters( 'render_block_data', $parsed_block, $source_block );
 686  
 687      $context = array();
 688  
 689      if ( $post instanceof WP_Post ) {
 690          $context['postId'] = $post->ID;
 691  
 692          /*
 693           * The `postType` context is largely unnecessary server-side, since the ID
 694           * is usually sufficient on its own. That being said, since a block's
 695           * manifest is expected to be shared between the server and the client,
 696           * it should be included to consistently fulfill the expectation.
 697           */
 698          $context['postType'] = $post->post_type;
 699      }
 700  
 701      if ( $wp_query instanceof WP_Query && isset( $wp_query->tax_query->queried_terms['category'] ) ) {
 702          $context['query'] = array( 'categoryIds' => array() );
 703          foreach ( $wp_query->tax_query->queried_terms['category']['terms'] as $category_slug_or_id ) {
 704              $context['query']['categoryIds'][] = 'slug' === $wp_query->tax_query->queried_terms['category']['field'] ? get_cat_ID( $category_slug_or_id ) : $category_slug_or_id;
 705          }
 706      }
 707  
 708      /**
 709       * Filters the default context provided to a rendered block.
 710       *
 711       * @since 5.5.0
 712       *
 713       * @param array $context      Default context.
 714       * @param array $parsed_block Block being rendered, filtered by `render_block_data`.
 715       */
 716      $context = apply_filters( 'render_block_context', $context, $parsed_block );
 717  
 718      $block = new WP_Block( $parsed_block, $context );
 719  
 720      return $block->render();
 721  }
 722  
 723  /**
 724   * Parses blocks out of a content string.
 725   *
 726   * @since 5.0.0
 727   *
 728   * @param string $content Post content.
 729   * @return array[] Array of parsed block objects.
 730   */
 731  function parse_blocks( $content ) {
 732      /**
 733       * Filter to allow plugins to replace the server-side block parser
 734       *
 735       * @since 5.0.0
 736       *
 737       * @param string $parser_class Name of block parser class.
 738       */
 739      $parser_class = apply_filters( 'block_parser_class', 'WP_Block_Parser' );
 740  
 741      $parser = new $parser_class();
 742      return $parser->parse( $content );
 743  }
 744  
 745  /**
 746   * Parses dynamic blocks out of `post_content` and re-renders them.
 747   *
 748   * @since 5.0.0
 749   *
 750   * @param string $content Post content.
 751   * @return string Updated post content.
 752   */
 753  function do_blocks( $content ) {
 754      $blocks = parse_blocks( $content );
 755      $output = '';
 756  
 757      foreach ( $blocks as $block ) {
 758          $output .= render_block( $block );
 759      }
 760  
 761      // If there are blocks in this content, we shouldn't run wpautop() on it later.
 762      $priority = has_filter( 'the_content', 'wpautop' );
 763      if ( false !== $priority && doing_filter( 'the_content' ) && has_blocks( $content ) ) {
 764          remove_filter( 'the_content', 'wpautop', $priority );
 765          add_filter( 'the_content', '_restore_wpautop_hook', $priority + 1 );
 766      }
 767  
 768      return $output;
 769  }
 770  
 771  /**
 772   * If do_blocks() needs to remove wpautop() from the `the_content` filter, this re-adds it afterwards,
 773   * for subsequent `the_content` usage.
 774   *
 775   * @access private
 776   *
 777   * @since 5.0.0
 778   *
 779   * @param string $content The post content running through this filter.
 780   * @return string The unmodified content.
 781   */
 782  function _restore_wpautop_hook( $content ) {
 783      $current_priority = has_filter( 'the_content', '_restore_wpautop_hook' );
 784  
 785      add_filter( 'the_content', 'wpautop', $current_priority - 1 );
 786      remove_filter( 'the_content', '_restore_wpautop_hook', $current_priority );
 787  
 788      return $content;
 789  }
 790  
 791  /**
 792   * Returns the current version of the block format that the content string is using.
 793   *
 794   * If the string doesn't contain blocks, it returns 0.
 795   *
 796   * @since 5.0.0
 797   *
 798   * @param string $content Content to test.
 799   * @return int The block format version is 1 if the content contains one or more blocks, 0 otherwise.
 800   */
 801  function block_version( $content ) {
 802      return has_blocks( $content ) ? 1 : 0;
 803  }
 804  
 805  /**
 806   * Registers a new block style.
 807   *
 808   * @since 5.3.0
 809   *
 810   * @param string $block_name       Block type name including namespace.
 811   * @param array  $style_properties Array containing the properties of the style name,
 812   *                                 label, style (name of the stylesheet to be enqueued),
 813   *                                 inline_style (string containing the CSS to be added).
 814   * @return boolean True if the block style was registered with success and false otherwise.
 815   */
 816  function register_block_style( $block_name, $style_properties ) {
 817      return WP_Block_Styles_Registry::get_instance()->register( $block_name, $style_properties );
 818  }
 819  
 820  /**
 821   * Unregisters a block style.
 822   *
 823   * @since 5.3.0
 824   *
 825   * @param string $block_name       Block type name including namespace.
 826   * @param array  $block_style_name Block style name.
 827   * @return boolean True if the block style was unregistered with success and false otherwise.
 828   */
 829  function unregister_block_style( $block_name, $block_style_name ) {
 830      return WP_Block_Styles_Registry::get_instance()->unregister( $block_name, $block_style_name );
 831  }


Generated: Tue Aug 4 01:00:03 2020 Cross-referenced by PHPXref 0.7.1