Make WordPress Core


Ignore:
Timestamp:
06/23/2020 03:43:19 PM (6 years ago)
Author:
gziolo
Message:

Editor: Introduce new API method that register block from block.json metadata file

Backports changes added to Gutenberg in:

register_block_type_from_metadata function is going to be used to register all blocks on the server using block.json metadata files.

Props ocean90, azaozz, aduth, mcsf, jorgefilipecosta, spacedmonkey, nosolosw, swissspidy and noahtallen.
Fixes #50263.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/blocks.php

    r48102 r48141  
    3939function unregister_block_type( $name ) {
    4040        return WP_Block_Type_Registry::get_instance()->unregister( $name );
     41}
     42
     43/**
     44 * Removes the block asset's path prefix if provided.
     45 *
     46 * @since 5.5.0
     47 *
     48 * @param string $asset_handle_or_path Asset handle or prefixed path.
     49 * @return string Path without the prefix or the original value.
     50 */
     51function remove_block_asset_path_prefix( $asset_handle_or_path ) {
     52        $path_prefix = 'file:';
     53        if ( 0 !== strpos( $asset_handle_or_path, $path_prefix ) ) {
     54                return $asset_handle_or_path;
     55        }
     56        return substr(
     57                $asset_handle_or_path,
     58                strlen( $path_prefix )
     59        );
     60}
     61
     62/**
     63 * Generates the name for an asset based on the name of the block
     64 * and the field name provided.
     65 *
     66 * @since 5.5.0
     67 *
     68 * @param string $block_name Name of the block.
     69 * @param string $field_name Name of the metadata field.
     70 * @return string Generated asset name for the block's field.
     71 */
     72function generate_block_asset_handle( $block_name, $field_name ) {
     73        $field_mappings = array(
     74                'editorScript' => 'editor-script',
     75                'script'       => 'script',
     76                'editorStyle'  => 'editor-style',
     77                'style'        => 'style',
     78        );
     79        return str_replace( '/', '-', $block_name ) .
     80                '-' . $field_mappings[ $field_name ];
     81}
     82
     83/**
     84 * Finds a script handle for the selected block metadata field. It detects
     85 * when a path to file was provided and finds a corresponding
     86 * asset file with details necessary to register the script under
     87 * automatically generated handle name. It returns unprocessed script handle
     88 * 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 */
     97function 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 */
     144function 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. Any arguments may be defined, however the
     174 *     ones described below are supported by default. Default empty array.
     175 *
     176 *     @type callable $render_callback Callback used to render blocks of this block type.
     177 * }
     178 * @return WP_Block_Type|false The registered block type on success, or false on failure.
     179 */
     180function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
     181        $filename      = 'block.json';
     182        $metadata_file = ( substr( $file_or_folder, -strlen( $filename ) ) !== $filename ) ?
     183                trailingslashit( $file_or_folder ) . $filename :
     184                $file_or_folder;
     185        if ( ! file_exists( $metadata_file ) ) {
     186                return false;
     187        }
     188
     189        $metadata = json_decode( file_get_contents( $metadata_file ), true );
     190        if ( ! is_array( $metadata ) || empty( $metadata['name'] ) ) {
     191                return false;
     192        }
     193        $metadata['file'] = $metadata_file;
     194
     195        $settings          = array();
     196        $property_mappings = array(
     197                'title'           => 'title',
     198                'category'        => 'category',
     199                'parent'          => 'parent',
     200                'icon'            => 'icon',
     201                'description'     => 'description',
     202                'keywords'        => 'keywords',
     203                'attributes'      => 'attributes',
     204                'providesContext' => 'provides_context',
     205                'usesContext'     => 'uses_context',
     206                'supports'        => 'supports',
     207                'styles'          => 'styles',
     208                'example'         => 'example',
     209        );
     210
     211        foreach ( $property_mappings as $key => $mapped_key ) {
     212                if ( isset( $metadata[ $key ] ) ) {
     213                        $settings[ $mapped_key ] = $metadata[ $key ];
     214                }
     215        }
     216
     217        if ( ! empty( $metadata['editorScript'] ) ) {
     218                $settings['editor_script'] = register_block_script_handle(
     219                        $metadata,
     220                        'editorScript'
     221                );
     222        }
     223
     224        if ( ! empty( $metadata['script'] ) ) {
     225                $settings['script'] = register_block_script_handle(
     226                        $metadata,
     227                        'script'
     228                );
     229        }
     230
     231        if ( ! empty( $metadata['editorStyle'] ) ) {
     232                $settings['editor_style'] = register_block_style_handle(
     233                        $metadata,
     234                        'editorStyle'
     235                );
     236        }
     237
     238        if ( ! empty( $metadata['style'] ) ) {
     239                $settings['style'] = register_block_style_handle(
     240                        $metadata,
     241                        'style'
     242                );
     243        }
     244
     245        return register_block_type(
     246                $metadata['name'],
     247                array_merge(
     248                        $settings,
     249                        $args
     250                )
     251        );
    41252}
    42253
Note: See TracChangeset for help on using the changeset viewer.