【WordPress】指定した期間までNEWマークを出すブロックを作ってみる
習作シリーズ(?)です。
create-blockをする
block.jsonを用意する
NEWアイコンにつけるCSSはすべてブロックのCSSで完結させます。
なので、supports
で色やフォントサイズ、余白を有効にします。
attributes
は、NEW用に表示するテキストと、NEWを表示させる期間をもたせておきます。
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "chiilog-block/new-icon",
"version": "0.1.0",
"title": "New Icon Block",
"category": "text",
"icon": "smiley",
"example": {},
"supports": {
"html": false,
"align": true,
"color": {
"gradients": true,
"background": true,
"text": true
},
"typography": {
"fontSize": true,
"lineHeight": true
},
"spacing": {
"padding": true,
"margin": true
}
},
"attributes": {
"text": {
"type": "string",
"default": "NEW"
},
"period": {
"type": "number",
"default": "7"
}
},
"usesContext": [ "postType", "postId" ],
"textdomain": "new-icon",
"editorScript": "file:./index.js",
"render": "file:./render.php"
}
edit.tsxを用意
またもやベース風味なものを用意します。
type BlockAttributes = {
text: string;
period: number;
};
export default function Edit( {
attributes: { text, period },
setAttributes,
}: BlockEditProps< BlockAttributes > ) {
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<RichText
value={ text }
onChange={ ( value ) => {
setAttributes( { text: value } );
} }
/>
</div>
);
}
このNEWアイコンは編集画面では出しっぱなしにするので、(消えると編集できなくなってしまうので)RichText
まわりはこのまま出すことにします。
次に、period
の設定パネルをつけます。
period
はnumber
だよ、という型を定義しているので、NumberControl
を使ってみたいところではありますが、これはまだ__experimentalNumberControl
とのこと。
まだ実験段階であれば、実際の案件では使うのは控えた方がいいですね。というわけで、この練習でもTextControl
を使うことにします。
type BlockAttributes = {
text: string;
period: number;
};
export default function Edit( {
attributes: { text, period },
setAttributes,
}: BlockEditProps< BlockAttributes > ) {
const blockProps = useBlockProps();
return (
<>
+ <TextControl
+ label="Period to display Text"
+ value={ period }
+ onChange={ ( value ) => setAttributes({ period: value } ) }
+ />
<div { ...blockProps }>
<RichText
value={ text }
onChange={ ( value ) => {
setAttributes( { text: value } );
} }
/>
</div>
</>
);
}
TextControl
のvalue
はstring
型なので、型やblock.jsonを修正します。
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "chiilog-block/new-icon",
"version": "0.1.0",
"title": "New Icon Block",
"category": "text",
"icon": "smiley",
"example": {},
"supports": {
"html": false,
"align": true,
"color": {
"gradients": true,
"background": true,
"text": true
},
"typography": {
"fontSize": true,
"lineHeight": true
},
"spacing": {
"padding": true,
"margin": true
}
},
"attributes": {
"text": {
"type": "string",
"default": "NEW"
},
"period": {
- "type": "number",
+ "type": "string",
"default": "7"
}
},
"usesContext": [ "postType", "postId" ],
"textdomain": "new-icon",
"editorScript": "file:./index.js",
"render": "file:./render.php"
}
type BlockAttributes = {
text: string;
- period: number;
+ period: string;
};
...
ここがnumber
型のままだと、TextControl
でうまく値が更新されなくなります。string
型なので数字以外も入ってしまいますが、ここはrender.phpでカバーすることにします。
このままだと
こんな感じで入力エリアにTextControl
が表示されてしまいます。これは右の設定パネルにいれたいので、InspectorControls
とPanelBody
を追加します。
export default function Edit( {
attributes: { text, period },
setAttributes,
}: BlockEditProps< BlockAttributes > ) {
const blockProps = useBlockProps();
return (
<>
+ <InspectorControls>
+ <PanelBody
+ title="Settings"
+ initialOpen={ true }
+ >
+ <TextControl
+ label="Period to display Text"
+ value={ period }
+ onChange={ ( value ) =>
+ setAttributes( { period: value } )
+ }
+ />
+ </PanelBody>
+ </InspectorControls>
- <TextControl
- label="Period to display Text"
- value={ period }
- onChange={ ( value ) =>
- setAttributes( { period: value } )
- }
- />
<div { ...blockProps }>
<RichText
value={ text }
onChange={ ( value ) => {
setAttributes( { text: value } );
} }
/>
</div>
</>
);
}
こんな感じになりました!
あとはrender.phpを作っていきます。
render.phpを用意
<?php
/**
* @var array $attributes The block attributes.
* @var string $content The block content.
* @var WP_Block $block The block object.
*
* @see https://github.com/WordPress/gutenberg/blob/trunk/docs/reference-guides/block-api/block-metadata.md#render
*/
// 期間を取得。ここで半角に変換しておく
$period = mb_convert_kana( $attributes['period'], 'n', 'UTF-8' );
// 期間が数値でない場合はデフォルト値をセット
if ( ! is_numeric( $period ) ) {
$period = 7;
}
// 投稿日から指定日数後の日付を取得
$post_date = new DateTime( get_the_date( 'Y-m-d' ) );
$post_date->modify( '+' . $period . ' days' );
// 今日の日付
$current_date = new DateTime();
if ( $post_date >= $current_date ) :
?>
<div <?php echo get_block_wrapper_attributes(); ?>>
<?php echo esc_html( $attributes['text'] ); ?>
</div>
<?php
endif;
TextControl
がstring
型なので、全角数字やそもそも数字以外が入ったときの処理を入れておきます。ありがちなミスとして全角数字があるかなーと思ったので、mb_convert_kana
で事前に半角に変換してからif文に入れます。
これでNEWマークを出すことはできましたが、PhpStormで「未処理の\Exception」というエラーが出ます🤔
ヒントに「try-catchで囲む」と出たので調べてみました。
PhpStorm的にnew DateTime( get_the_date( 'Y-m-d' ) )
が例外投げられるんじゃね?という心配をしてくれた模様?
というわけで、render.phpの中身はこうなりました。
$content = '<div ' . get_block_wrapper_attributes() . '>' . esc_html( $attributes['text'] ) . '</div>';
try {
// 期間を取得。ここで半角に変換しておく
$period = mb_convert_kana( $attributes['period'], 'n', 'UTF-8' );
// 期間が数値でない場合はデフォルト値をセット
if ( ! is_numeric( $period ) ) {
$period = 7;
}
// 投稿日から指定日数後の日付を取得
$post_date = new DateTime( get_the_date( 'Y-m-d' ) );
$post_date->modify( '+' . $period . ' days' );
// 今日の日付
$current_date = new DateTime();
if ( $post_date >= $current_date ) :
echo wp_kses_post( $content );
endif;
} catch ( Exception $e ) {
echo wp_kses_post( $content );
}
まとめ
編集画面はこんな感じで、背景色や文字色も変えられます。
表示画面も値がきちんと適用されています。
指定した期間が過ぎた場合は、編集画面はそのままに表示側では消えてしまいます。
アーカイブテンプレートでもこのように配置して、
表示はこの通り。
※Hello world!で表示させるために日付変更
こういうのすでにプラグインディレクトリにありそうだなーと思ってプラグインディレクトリで検索かけてみたんですが、意外とありませんでした。……が、探し方が悪いだけかも。こういうNEWマーク、っていうか期間絞って表示するブロックってどう検索するのがいいのかなあ🤔
今回作ったブロックはGitHubにあげています。フルでコード見たい方はどうぞ。
Discussion