Вопрос или проблема
Как я могу поделиться повторно используемыми блоками с основного сайта со всеми сайтами в подкаталогах?
Предыстория:
Я нахожусь на стадии планирования многосайтовой сети WordPress, где я планирую создать пользовательскую тему с нуля и использовать блоковый редактор для макетов страниц. Страница предназначена для организации с несколькими местоположениями: один основной национальный сайт и отдельный сайт в подкаталоге для каждого местоположения. Это необходимо для ограничения доступа редакторов к своему местоположению. Страница будет сильно полагаться на повторно используемые блоки и шаблоны блоков. Я закодирую шаблоны блоков в тему.
Я нашел решение здесь: https://krautpress.de/2020/wiederverwendbare-bloecke-zwischen-sites-einer-multisite-synchronisieren/
/**
* Синхронизация повторно используемых блоков между сайтами многосайтовой сети.
*
* @param int $post_id Идентификатор поста.
* @param WP_Post $post Объект поста.
*/
add_action( 'publish_wp_block', 'slug_sync_reusable_blocks', 10, 2 );
function slug_sync_reusable_blocks( $post_id, $post ) {
// Проверяем, есть ли у поста уже sync_hash или создаем его.
if ( get_post_meta( $post_id, 'sync_hash', true ) !== '' ) {
$sync_hash = get_post_meta( $post_id, 'sync_hash', true );
} else {
$sync_hash = uniqid( $post->post_title );
update_post_meta( $post_id, 'sync_hash', $sync_hash );
}
$current_site_id = get_current_blog_id();
// Получаем идентификаторы сайтов.
$sites = get_sites(
[
'fields' => 'ids',
]
);
remove_action( 'publish_wp_block', 'slug_sync_reusable_blocks', 10 );
foreach ( $sites as $site_id ) {
if ( $current_site_id !== $site_id ) {
switch_to_blog( $site_id );
// Проверяем, уже ли блок синхронизирован, и обновляем его, если нужно.
$existing_block_query = new WP_Query(
[
'post_type' => 'wp_block',
'no_found_rows' => true,
'update_post_meta_cache' => false,
'update_post_term_cache' => false,
'fields' => 'ids',
'meta_key' => 'sync_hash',
'meta_value' => $sync_hash,
'posts_per_page' => 1,
]
);
if ( $existing_block_query->have_posts() ) {
// Обновляем пост.
$existing_post_id = $existing_block_query->posts[0];
wp_update_post(
[
'ID' => $existing_block_query->posts[0],
'post_content' => $post->post_content,
'post_title' => $post->post_title,
'post_status' => 'publish',
]
);
} else {
// Создаем пост, если блока еще нет.
wp_insert_post(
[
'post_type' => 'wp_block',
'post_content' => $post->post_content,
'post_title' => $post->post_title,
'post_status' => 'publish',
'meta_input' =>
[
'sync_hash' => $sync_hash,
],
]
);
}
restore_current_blog();
}
}
add_action( 'publish_wp_block', 'slug_sync_reusable_blocks', 10, 2 );
}
Я добавил код на свой сайт с помощью плагина “Code Snippets”, и он отлично работает. Если у вас есть “мастер” сайт, как у меня, и все остальные сайты в многосайтовой сети должны использовать точно такой же повторно используемый блок-шаблон, код нужно активировать только на этом мастер-сайте.
Я решил опубликовать свой собственный ответ, потому что ранее забыли упомянуть о:
- Нет необходимости создавать уникальный
$sync_hash
, чтобы обновить соответствующий шаблон, когда он существует на суб-сайте, плюс хранить эту связь в метаданных поста! Почему — потому что шаблоны не являются постами, они не могут иметь дублирующиеся заголовки. Мы можем соединять шаблоны по заголовкам. - Также нет упоминания о
wp_pattern_sync_status
, который может быть синхронизирован/несинхронизирован.
Исходя из всего вышесказанного, я получил правильный код из этой статьи: https://rudrastyh.com/wordpress-multisite/sync-patterns-and-template-parts-across-sites.html
add_action( 'publish_wp_block', 'rudr_sync_reusable_blocks', 25, 2 );
function rudr_sync_reusable_blocks( $post_id, $post ) {
$sync_status = get_post_meta( $post_id, 'wp_pattern_sync_status', true );
$site_ids = get_sites(
array(
'fields' => 'ids',
'site__not_in' => get_current_blog_id(),
)
);
remove_action( 'publish_wp_block', 'rudr_sync_reusable_blocks', 25, 2 );
foreach( $site_ids as $site_id ) {
switch_to_blog( $site_id );
$crossposted_block = get_page_by_title( $post->post_title, OBJECT, 'wp_block' );
if( $crossposted_block ) {
$crossposted_block_id = wp_update_post(
array(
'ID' => $crossposted_block->ID,
'post_content' => $post->post_content,
)
);
} else {
$crossposted_block_id = wp_insert_post(
array(
'post_type' => 'wp_block',
'post_content' => $post->post_content,
'post_title' => $post->post_title,
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_status' => 'publish',
)
);
}
if( ! is_wp_error( $crossposted_block_id ) ) {
if( 'unsynced' === $sync_status ) {
update_post_meta( $crossposted_block_id, 'wp_pattern_sync_status', 'unsynced' );
}
}
restore_current_blog();
}
add_action( 'publish_wp_block', 'rudr_sync_reusable_blocks', 25, 2 );
}
Код работает следующим образом — когда шаблон публикуется или обновляется на сайте, где установлен этот код, этот шаблон будет автоматически опубликован или обновлен на всех сайтах в сети многосайтовых сайтов.
.
Ответ или решение
Обмен многоразовыми блоками и блок-узорами между сайтами в сети WordPress-Мультисайт может быть в некоторых случаях сложной задачей, особенно если вы разрабатываете пользовательскую тему с нуля и поддерживаете единообразие между несколькими сайтами. Рассмотрим, как можно организовать этот процесс на практике.
Теория
WordPress-Мультисайт позволяет создавать и управлять несколькими сайтами с одним набором файлов WordPress и одной базой данных. При использовании блокового редактора Gutenberg перед вами стоит задача повторного использования блоков и блок-узоров по всей сети, чтобы обеспечить согласованное представление и простоту администрирования. Однако, стандартные функциональные возможности WordPress по обмену многоразовыми блоками между сайтами отсутствуют, что требует использования пользовательского кода.
Пример
Рассмотрим, как можно достичь этой цели с помощью пользовательских действий и фильтров WordPress. Рассуждая по примеру с сайта KrautPress и усовершенствованным вариантом Rudrastyh, мы видим, что код использует действие publish_wp_block
для синхронизации многоразовых блоков между сайтами. Ниже приведен экстракт кода, который выполняет эту функцию:
add_action( 'publish_wp_block', 'rudr_sync_reusable_blocks', 25, 2 );
function rudr_sync_reusable_blocks( $post_id, $post ) {
$sync_status = get_post_meta( $post_id, 'wp_pattern_sync_status', true );
$site_ids = get_sites(
array(
'fields' => 'ids',
'site__not_in' => get_current_blog_id(),
)
);
remove_action( 'publish_wp_block', 'rudr_sync_reusable_blocks', 25, 2 );
foreach( $site_ids as $site_id ) {
switch_to_blog( $site_id );
$crossposted_block = get_page_by_title( $post->post_title, OBJECT, 'wp_block' );
if( $crossposted_block ) {
$crossposted_block_id = wp_update_post(
array(
'ID' => $crossposted_block->ID,
'post_content' => $post->post_content,
)
);
} else {
$crossposted_block_id = wp_insert_post(
array(
'post_type' => 'wp_block',
'post_content' => $post->post_content,
'post_title' => $post->post_title,
'comment_status' => 'closed',
'ping_status' => 'closed',
'post_status' => 'publish',
)
);
}
if( !is_wp_error( $crossposted_block_id ) ) {
if( 'unsynced' === $sync_status ) {
update_post_meta( $crossposted_block_id, 'wp_pattern_sync_status', 'unsynced' );
}
}
restore_current_blog();
}
add_action( 'publish_wp_block', 'rudr_sync_reusable_blocks', 25, 2 );
}
#### Применение
1. **Подготовка окружения**: Имейте четкое представление о структуре вашей сети мультисайтов. Четкое понимание того, какие именно блоки необходимо синхронизировать и на каких сайтах, является ключевым.
2. **Создание многоразовых блоков**: На мастер-сайте создайте или отредактируйте многоразовые блоки. Эти блоки должны быть тщательно спроектированы с учетом нужд всех сайтов сети, так как их синхронизация практически оконечна без дополнительной кастомизации на уровне субсайтов.
3. **Настройка функциональности синхронизации**: Реализуйте код для синхронизации внутри файла функций (`functions.php`) вашей темы или используйте плагин типа "Code Snippets", чтобы внедрить код без изменений в тему. Проверяйте работоспособность на тестовом окружении, прежде чем внедрять на живом сайте.
4. **Тестирование и проверка**: Проведите серию тестов, чтобы убедиться, что блоки синхронизируются на всех сайтах, как ожидается. Убедитесь, что все редакторы на субсайтах могут использовать новые блоки без каких-либо проблем.
5. **Обеспечение поддержки и обновлений**: После внедрения необходимо регулярно обновлять функциональность и следить за интеграцией с последними версиями WordPress и Gutenberg, чтобы гарантировать, что пользовательские решения продолжают работать без сбоев.
Таким образом, правильно организованная и закодированная процедура позволяет эффективно управлять многоразовыми блоками в сети WordPress-Мультисайт, что значительно упрощает редакторский процесс и поддерживает единообразие в рамках всей сети.