register_block_type_from_metadata() │ WP 5.5.0
Регистрирует блок на основе метаданных из файла block.json
.
Смотрите также описание JS функции registerBlockType() многие из параметров этой функции передаются туда.
Возвращает
WP_Block_Type|false
. Зарегистрированный тип блока или false при неудачи.
Использование
register_block_type_from_metadata( $file_or_folder, $args );
$file_or_folder(string) (required)
Путь к файлу JSON с метаданными для блока. Или путь к папке, где расположен файл block.json
.
Если указывается путь к файлу JSON, имя файла должно заканчиваться на block.json
.
Путь к файлу блока:
register_block_type_from_metadata( __DIR__ . '/block.json' );
Или можно указать путь к папке где лежит файл block.json
:
register_block_type_from_metadata( __DIR__ . '/my-block' );
$args(array)
Массив аргументов блока. Принимает любое публичное свойство WP_Block_Type{} . См. WP_Block_Type::__construct() для полного списка принимаемых аргументов.
По умолчанию: пустой массив
Примеры
#1 Использование WP Dashicon для блока
Build In Example
Для этого нужно в $args в параметре icon
указать иконку без префикса dashicons-
:
add_action( 'init', 'wpkama_register_block' );
function wpkama_register_block(){
register_block_type(
__DIR__ . '/block.json',
[
'icon' => 'admin-home', /* omit 'dashicons-' prefix */
]
);
}
Все имена Dashicons: https://developer.wordpress.org/resource/dashicons/
#2 Как написать плагин/тему с несколькими блоками
Build In Example
Создание папки src
Запустите команду:
npx @wordpress/create-block@latest my-blocks --variant=dynamic
cd my-blocks
Подробнее смотрите мануал https://developer.wordpress.org/block-editor/getting-started/tutorial/
Переместите содержимое каталога src
в подкаталог, например block-a
: src/block-a
.
Продублируйте подкаталог block-a
, чтобы создать второй блок, и назовите его, например, block-b
.
Обновите файлы block.json
в каждом подкаталоге, чтобы они соответствовали требованиям блоков.
Должна получится такая структура:
my-blocks
├── package.json
├── package-lock.json
└── src
├── block-a
│ ├── block.json
│ ├── edit.js
│ ├── editor.scss
│ ├── index.js
│ ├── render.php
│ ├── style.scss
│ └── view.js
└── block-b
├── block.json
├── edit.js
├── editor.scss
├── index.js
├── render.php
├── style.scss
└── view.js
Пример содержимого block.json
:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "create-block/block-a",
"version": "0.1.0",
"title": "Block A",
"category": "widgets",
"icon": "smiley",
"description": "Example block scaffolded with Create Block tool.",
"example": {},
"supports": {
"html": false
},
"textdomain": "wpkama",
"render": "file:./render.php",
"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"viewStyle": "file:./style-index.css",
"viewScript": "file:./view.js"
}
Выполните команду npm run build
в каталоге my-blocks
. Будут созданы соответствующие директории в папке my-blocks/build
.
Регистрация блоков
Теперь нужно зарегистрировать блоки в PHP, указав на соответствующую директорию в папке build
:
add_action( 'init', 'wpdocs_create_blocks_mysite_block_init' );
function wpdocs_create_blocks_mysite_block_init() {
register_block_type( __DIR__ . '/build/block-a' );
register_block_type( __DIR__ . '/build/block-b' );
}
Перемещение папки блоков внутрь проекта
Если у вас папка npm пакетов node_modules
находится где-то выше, а блоки должны находится внутри, например в папке темы, то можно указать пути где лежат исходники и куда выкладывать билды.
Для этого добавьте опции в скрипты build
и start
в файле package.json
:
"scripts": {
"build": "wp-scripts build --webpack-src-dir=path/to/my-blocks/src/ --output-path=path/to/my-blocks/build/ --webpack-copy-php",
"start": "wp-scripts start --webpack-src-dir=path/to/my-blocks/src/ --output-path=path/to/my-blocks/build/ --webpack-copy-php",
...
}
Теперь npm run build
можно запускать из папки где лежит package.json
, и блоки будут билдиться в во внутренней папке (там где вы указали).
#3 Авто-создание блоков через .json файлы
Build In Example
class My_Blocks {
public function setup_hooks(): void {
add_action( 'init', [ $this, 'register_blocks' ] );
add_filter( 'block_categories_all', [ $this, 'register_block_category' ] );
}
public function register_blocks(): void {
$blocks = glob( __DIR__ . '/Blocks/*/block.json');
if ( ! $blocks ) {
return;
}
foreach ( $blocks as $block ) {
register_block_type( $block );
}
}
}
( new My_Blocks() )->setup_hooks();
Пример .json файла:
{
"name": "ice-cream/slider",
"title": "Ice Cream Slider",
"description": "Простой настраиваемый слайдер изображений",
"style": "block.css",
"category": "ice-cream",
"icon": "images-alt",
"apiVersion": 2,
"keywords": [],
"styles": [],
"supports": {
"align": false,
"anchor": false,
"alignContent": false,
"color": {
"text": false,
"background": true,
"link": false
},
"alignText": false,
"fullHeight": false
}
}
Read more here: https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/
Добавить свой пример
Список изменений
С версии 5.5.0
Введена.
С версии 5.7.0
Added support for textdomain field and i18n handling for all translatable fields.
С версии 5.9.0
Added support for variations and viewScript fields.
С версии 6.1.0
Added support for render field.
С версии 6.3.0
Added selectors field.
С версии 6.4.0
Added support for blockHooks field.
С версии 6.5.0
Added support for allowedBlocks , viewScriptModule , and viewStyle fields.
С версии 6.7.0
Allow PHP filename as variations argument.
Код register_block_type_from_metadata() register block type from metadata
WP 6.8.1
function register_block_type_from_metadata( $file_or_folder, $args = array() ) {
/*
* Get an array of metadata from a PHP file.
* This improves performance for core blocks as it's only necessary to read a single PHP file
* instead of reading a JSON file per-block, and then decoding from JSON to PHP.
* Using a static variable ensures that the metadata is only read once per request.
*/
$file_or_folder = wp_normalize_path( $file_or_folder );
$metadata_file = ( ! str_ends_with( $file_or_folder, 'block.json' ) ) ?
trailingslashit( $file_or_folder ) . 'block.json' :
$file_or_folder;
$is_core_block = str_starts_with( $file_or_folder, wp_normalize_path( ABSPATH . WPINC ) );
$metadata_file_exists = $is_core_block || file_exists( $metadata_file );
$registry_metadata = WP_Block_Metadata_Registry::get_metadata( $file_or_folder );
if ( $registry_metadata ) {
$metadata = $registry_metadata;
} elseif ( $metadata_file_exists ) {
$metadata = wp_json_file_decode( $metadata_file, array( 'associative' => true ) );
} else {
$metadata = array();
}
if ( ! is_array( $metadata ) || ( empty( $metadata['name'] ) && empty( $args['name'] ) ) ) {
return false;
}
$metadata['file'] = $metadata_file_exists ? wp_normalize_path( realpath( $metadata_file ) ) : null;
/**
* Filters the metadata provided for registering a block type.
*
* @since 5.7.0
*
* @param array $metadata Metadata for registering a block type.
*/
$metadata = apply_filters( 'block_type_metadata', $metadata );
// Add `style` and `editor_style` for core blocks if missing.
if ( ! empty( $metadata['name'] ) && str_starts_with( $metadata['name'], 'core/' ) ) {
$block_name = str_replace( 'core/', '', $metadata['name'] );
if ( ! isset( $metadata['style'] ) ) {
$metadata['style'] = "wp-block-$block_name";
}
if ( current_theme_supports( 'wp-block-styles' ) && wp_should_load_separate_core_block_assets() ) {
$metadata['style'] = (array) $metadata['style'];
$metadata['style'][] = "wp-block-{$block_name}-theme";
}
if ( ! isset( $metadata['editorStyle'] ) ) {
$metadata['editorStyle'] = "wp-block-{$block_name}-editor";
}
}
$settings = array();
$property_mappings = array(
'apiVersion' => 'api_version',
'name' => 'name',
'title' => 'title',
'category' => 'category',
'parent' => 'parent',
'ancestor' => 'ancestor',
'icon' => 'icon',
'description' => 'description',
'keywords' => 'keywords',
'attributes' => 'attributes',
'providesContext' => 'provides_context',
'usesContext' => 'uses_context',
'selectors' => 'selectors',
'supports' => 'supports',
'styles' => 'styles',
'variations' => 'variations',
'example' => 'example',
'allowedBlocks' => 'allowed_blocks',
);
$textdomain = ! empty( $metadata['textdomain'] ) ? $metadata['textdomain'] : null;
$i18n_schema = get_block_metadata_i18n_schema();
foreach ( $property_mappings as $key => $mapped_key ) {
if ( isset( $metadata[ $key ] ) ) {
$settings[ $mapped_key ] = $metadata[ $key ];
if ( $metadata_file_exists && $textdomain && isset( $i18n_schema->$key ) ) {
$settings[ $mapped_key ] = translate_settings_using_i18n_schema( $i18n_schema->$key, $settings[ $key ], $textdomain );
}
}
}
if ( ! empty( $metadata['render'] ) ) {
$template_path = wp_normalize_path(
realpath(
dirname( $metadata['file'] ) . '/' .
remove_block_asset_path_prefix( $metadata['render'] )
)
);
if ( $template_path ) {
/**
* Renders the block on the server.
*
* @since 6.1.0
*
* @param array $attributes Block attributes.
* @param string $content Block default content.
* @param WP_Block $block Block instance.
*
* @return string Returns the block content.
*/
$settings['render_callback'] = static function ( $attributes, $content, $block ) use ( $template_path ) {
ob_start();
require $template_path;
return ob_get_clean();
};
}
}
// If `variations` is a string, it's the name of a PHP file that
// generates the variations.
if ( ! empty( $metadata['variations'] ) && is_string( $metadata['variations'] ) ) {
$variations_path = wp_normalize_path(
realpath(
dirname( $metadata['file'] ) . '/' .
remove_block_asset_path_prefix( $metadata['variations'] )
)
);
if ( $variations_path ) {
/**
* Generates the list of block variations.
*
* @since 6.7.0
*
* @return string Returns the list of block variations.
*/
$settings['variation_callback'] = static function () use ( $variations_path ) {
$variations = require $variations_path;
return $variations;
};
// The block instance's `variations` field is only allowed to be an array
// (of known block variations). We unset it so that the block instance will
// provide a getter that returns the result of the `variation_callback` instead.
unset( $settings['variations'] );
}
}
$settings = array_merge( $settings, $args );
$script_fields = array(
'editorScript' => 'editor_script_handles',
'script' => 'script_handles',
'viewScript' => 'view_script_handles',
);
foreach ( $script_fields as $metadata_field_name => $settings_field_name ) {
if ( ! empty( $settings[ $metadata_field_name ] ) ) {
$metadata[ $metadata_field_name ] = $settings[ $metadata_field_name ];
}
if ( ! empty( $metadata[ $metadata_field_name ] ) ) {
$scripts = $metadata[ $metadata_field_name ];
$processed_scripts = array();
if ( is_array( $scripts ) ) {
for ( $index = 0; $index < count( $scripts ); $index++ ) {
$result = register_block_script_handle(
$metadata,
$metadata_field_name,
$index
);
if ( $result ) {
$processed_scripts[] = $result;
}
}
} else {
$result = register_block_script_handle(
$metadata,
$metadata_field_name
);
if ( $result ) {
$processed_scripts[] = $result;
}
}
$settings[ $settings_field_name ] = $processed_scripts;
}
}
$module_fields = array(
'viewScriptModule' => 'view_script_module_ids',
);
foreach ( $module_fields as $metadata_field_name => $settings_field_name ) {
if ( ! empty( $settings[ $metadata_field_name ] ) ) {
$metadata[ $metadata_field_name ] = $settings[ $metadata_field_name ];
}
if ( ! empty( $metadata[ $metadata_field_name ] ) ) {
$modules = $metadata[ $metadata_field_name ];
$processed_modules = array();
if ( is_array( $modules ) ) {
for ( $index = 0; $index < count( $modules ); $index++ ) {
$result = register_block_script_module_id(
$metadata,
$metadata_field_name,
$index
);
if ( $result ) {
$processed_modules[] = $result;
}
}
} else {
$result = register_block_script_module_id(
$metadata,
$metadata_field_name
);
if ( $result ) {
$processed_modules[] = $result;
}
}
$settings[ $settings_field_name ] = $processed_modules;
}
}
$style_fields = array(
'editorStyle' => 'editor_style_handles',
'style' => 'style_handles',
'viewStyle' => 'view_style_handles',
);
foreach ( $style_fields as $metadata_field_name => $settings_field_name ) {
if ( ! empty( $settings[ $metadata_field_name ] ) ) {
$metadata[ $metadata_field_name ] = $settings[ $metadata_field_name ];
}
if ( ! empty( $metadata[ $metadata_field_name ] ) ) {
$styles = $metadata[ $metadata_field_name ];
$processed_styles = array();
if ( is_array( $styles ) ) {
for ( $index = 0; $index < count( $styles ); $index++ ) {
$result = register_block_style_handle(
$metadata,
$metadata_field_name,
$index
);
if ( $result ) {
$processed_styles[] = $result;
}
}
} else {
$result = register_block_style_handle(
$metadata,
$metadata_field_name
);
if ( $result ) {
$processed_styles[] = $result;
}
}
$settings[ $settings_field_name ] = $processed_styles;
}
}
if ( ! empty( $metadata['blockHooks'] ) ) {
/**
* Map camelCased position string (from block.json) to snake_cased block type position.
*
* @var array
*/
$position_mappings = array(
'before' => 'before',
'after' => 'after',
'firstChild' => 'first_child',
'lastChild' => 'last_child',
);
$settings['block_hooks'] = array();
foreach ( $metadata['blockHooks'] as $anchor_block_name => $position ) {
// Avoid infinite recursion (hooking to itself).
if ( $metadata['name'] === $anchor_block_name ) {
_doing_it_wrong(
__METHOD__,
__( 'Cannot hook block to itself.' ),
'6.4.0'
);
continue;
}
if ( ! isset( $position_mappings[ $position ] ) ) {
continue;
}
$settings['block_hooks'][ $anchor_block_name ] = $position_mappings[ $position ];
}
}
/**
* Filters the settings determined from the block type metadata.
*
* @since 5.7.0
*
* @param array $settings Array of determined settings for registering a block type.
* @param array $metadata Metadata provided for registering a block type.
*/
$settings = apply_filters( 'block_type_metadata_settings', $settings, $metadata );
$metadata['name'] = ! empty( $settings['name'] ) ? $settings['name'] : $metadata['name'];
return WP_Block_Type_Registry::get_instance()->register(
$metadata['name'],
$settings
);
}
Cвязанные функции