はじめに

Xwriteの「制限」ブロックは期間を設定できるようになっています。
Cocoonにも期間表示できる独自のcampaignショートコードがあります。
「カスタム HTML」ブロックを用いて[campaign]で囲むことで、期間中だけブロックを表示することが可能です(図1参照)。
この機能をGutenbergブロック化し、設定パネルから開始日時・終了日時を直接設定できるようにします。
さらに、表示をログインユーザーのみに制限するlogin_user_onlyショートコードも存在します。
今回作成するブロックでは、期間制限とログインユーザー制限の切り替えが可能です。
この記事では、この方法について説明します。
完成イメージ

実装手順
以下のコードをfunctions.phpに追加します。
// ブロックを登録
add_action('init', function () {
ob_start();
?>
(function (wp) {
const { registerBlockType } = wp.blocks;
const { createElement: el, Fragment } = wp.element;
const { InnerBlocks, InspectorControls } = wp.blockEditor || wp.editor;
const { PanelBody, TextControl, SelectControl } = wp.components;
registerBlockType('custom/restrict-block', {
title: '制限ブロック',
icon: 'lock',
category: 'layout',
supports: {
html: false
},
attributes: {
mode: { type: 'string', default: 'period' },
from: { type: 'string', default: '' },
to: { type: 'string', default: '' },
msg: {
type: 'string',
default: 'こちらのコンテンツはログインユーザーのみに表示されます。'
}
},
/**
* エディター描画コンポーネント
*
* @param {Object} props ブロックのProps
* @return {import('react').ReactElement} Reactエレメント
*/
edit: function (props) {
const { attributes, setAttributes } = props;
return el(Fragment, null,
el(InspectorControls, null,
el(PanelBody, {
title: '制限設定',
initialOpen: true
},
el(SelectControl, {
label: '制限タイプ',
value: attributes.mode,
options: [
{ label: '期間制限', value: 'period' },
{ label: 'ログイン制限', value: 'login' }
],
onChange: val => setAttributes({ mode: val })
}),
attributes.mode === 'period' && el(Fragment, null,
el(TextControl, {
label: '開始日時 (from)',
value: attributes.from,
onChange: val => setAttributes({ from: val }),
placeholder: 'YYYY-MM-DD HH:MM:SS'
}),
el(TextControl, {
label: '終了日時 (to)',
value: attributes.to,
onChange: val => setAttributes({ to: val }),
placeholder: 'YYYY-MM-DD HH:MM:SS'
})
),
attributes.mode === 'login' && el(TextControl, {
label: 'メッセージ',
value: attributes.msg,
onChange: val => setAttributes({ msg: val })
})
)
),
el('div', {
style: {
border: '1px dashed #999',
padding: '12px'
},
'data-mode': attributes.mode,
'data-from': attributes.from,
'data-to': attributes.to,
'data-msg': attributes.msg
},
attributes.mode === 'period'
? el(
'p',
null,
'表示期間 開始:',
attributes.from || '未設定',
' 終了:',
attributes.to || '未設定'
)
: el(
'p',
null,
'ログイン制限 メッセージ:',
attributes.msg
),
el(InnerBlocks)
)
);
},
/**
* 保存用コンポーネント
*
* @param {Object} props ブロックのProps
* @return {import('react').ReactElement} Reactエレメント
*/
save: function (props) {
const { attributes } = props;
return el(
'div',
{
'data-mode': attributes.mode,
'data-from': attributes.from,
'data-to': attributes.to,
'data-msg': attributes.msg
},
el(InnerBlocks.Content)
);
}
});
})(window.wp);
<?php
$handle = 'restrict-block';
wp_register_script($handle, false, ['wp-blocks', 'wp-element', 'wp-editor', 'wp-components', 'wp-i18n'], false, true);
wp_add_inline_script($handle, ob_get_clean());
// ブロックを登録
register_block_type('custom/restrict-block', [
'editor_script' => $handle,
]);
});
// 本文を変更
add_filter('the_content', function ($content) {
if (!preg_match_all(
'/<div\b[^>]*?\bdata-mode="([^"]*)"[^>]*>(.*?)<\/div>/is',
$content,
$matches,
PREG_SET_ORDER
)) {
return $content;
}
foreach ($matches as $match) {
$mode = $match[1];
$html = $match[0];
$inner = $match[2];
preg_match('/data-from="([^"]*)"/', $html, $from_match);
preg_match('/data-to="([^"]*)"/', $html, $to_match);
preg_match('/data-msg="([^"]*)"/', $html, $msg_match);
$from = $from_match[1] ?? '';
$to = $to_match[1] ?? '';
$msg = $msg_match[1] ?? '';
if ($mode === 'period') {
$replacement =
'[campaign from="' . esc_attr($from) . '" to="' . esc_attr($to) . '"]'
. $inner
. '[/campaign]';
} else {
$replacement =
'[login_user_only msg="' . esc_attr($msg) . '"]'
. $inner
. '[/login_user_only]';
}
$content = str_replace($html, $replacement, $content);
}
return $content;
}, 5);
さいごに
今回紹介した方法を使えば、CocoonのcampaignショートコードをGutenbergブロック化し、投稿編集画面から開始日時・終了日時を直接設定できるようになります。
これにより、期間限定で表示したいコンテンツを直感的に管理でき、テーマ側の既存ショートコード処理ともスムーズに連携可能です。
同様の仕組みをlogin_user_onlyショートコードにも適用することで、ログインユーザー限定コンテンツの管理も簡単に行えます。
この方法を活用して、より柔軟で使いやすい投稿編集環境を実現してください。




