WordPress 指定のキーワードの自動リンク

WordPress フォーラムに「指定のキーワードに自動的にリンクを貼るプラグインで日本語に対応したもを探しています」というような内容のトピックが起ったので調べてみました。

指定のキーワードに自動的にリンクを貼るプラグインを、いくつか見つけることができましたが、日本語 (分かち書なし) に対応しているものはありませんでした。(ご存知の方はコメントお願いします)

単語を正しく抽出(形態素解析)するのはパフォーマンスなど実装が難しいですが、単純文字列でもいいというケースは多いと思います。また、キーワードとリンクの設定も WordPress の標準機能であるリンクマネージャーを使用することで僅かなコードで実装することができそうだったので作ってみました。

functions.php

下記のコードをテーマの functions.php に追記するだけで完了です。これで WordPress のリンクマネージャーが使える (管理画面のメニューに「リンク」が追加される) ようになります。このリンクマネージャーに登録したリンクのタイトルをキーワードとして、投稿や固定ページの本文(コンテンツ)のキーワード(単語ではなく単純文字列)に自動的にリンクが貼られるようになります。

// Enable Link Manager. 
add_filter( 'pre_option_link_manager_enabled', '__return_true' );

/**
 * Filters the post content.
 *
 * @since 0.0.1
 * @since 0.0.2 Changed the keyword to be set after sorting in descending order.
 * 
 * @param string $content Content.
 * @return string Content.
 */
function auto_linker_the_content( $content ) {
	$links = array();

	$bookmarks = get_bookmarks( array ( 'orderby' => 'name', 'order' => 'DESC' ) );
	foreach ( (array) $bookmarks as $bookmark ) {
		$links[ $bookmark->link_name ] = array( 'url' => $bookmark->link_url, 'blank' => '_blank' === $bookmark->link_target );
	}

	if ( 0 === count( $links ) ) {
		return $content;
	}

	$regex = implode( '|', array_map( function( $key ) { return preg_quote( $key, '/' ); }, array_keys( $links ) ) );
	$regex = "/($regex)/i";

	$textarr = wp_html_split( $content );
	$ignore_elements = array( 'a', '/a', 'code', '/code', 'pre', '/pre', 'option', '/option' );
	$inside_block = array();
	foreach ( $textarr as &$element ) {
		if ( 0 === strpos( $element, '<' ) ) {
			$offset = 1;
			$is_end_tag = false;

			if ( 1 === strpos( $element, '/' ) ) {
				$offset = 2;
				$is_end_tag = true;
			}

			preg_match( '/^.+(\b|\n|$)/U', substr( $element, $offset ), $matches );
			if ( $matches && in_array( $matches[0], $ignore_elements, true ) ) {
				if ( ! $is_end_tag ) {
					array_unshift( $inside_block, $matches[0] );
				} elseif ( $inside_block && $matches[0] === $inside_block[0] ) {
					array_shift( $inside_block );
				}
			}
		} else {
			if ( empty( $inside_block ) ) {
				if ( false === strpos( $element, 'http://' ) && false === strpos( $element, 'https://' ) ) {
					$element = preg_replace_callback( $regex, function( $matches ) use ( $links ) {
						$key = $matches[0];
						$target = $links[$key]['blank'] ? ' target="_blank" rel="noopener"' : '';
						return '<a href="' . esc_url( $links[$key]['url'] ) . '"' . $target . '>' . $key . '</a>';
					}, $element );
				}
			}
		}
	}

	return join( $textarr );
}

add_action( 'the_content', 'auto_linker_the_content', 12 );

プラグイン

同様の機能を持つプラグインも作成しました。プラグインで簡単に設定したいという方は、こちらをどうぞ。

auto-linker.0.0.2.zip

変更履歴

バージョン説明
0.0.1最初のリリース。
0.0.2キーワード (リンクのタイトル) を降順ソートしてから設定するようにしました。

コメント

  • 初めまして。
    趣味で個人サイトを作っている者で、久遠と申します。
    指定のキーワードに自動的にリンクを貼るプラグインで、日本語に対応しているものを探していたのですが、なかなか見つからず、そんな折、こちらの記事を拝見いたしまして、たいへん助かりました。
    本当にありがとうございます。

    2つ教えていただきたい点があり、連絡いたしました。

    (1)
    当方、こちらのプラグインはWordPressの派生物であり、GPLライセンスが適用されるため、一部を改変して利用しても問題ない、という認識でおりますが、その認識で大丈夫でしたでしょうか。
    一部のみがGPLである(CSSやJSなどが含まれている場合?)などの場合はその限りではない、との文面も見かけ、こちらのプラグインは改変可能であるという認識で問題ないかを確認させていただければと思った次第です。
    (初歩的な質問でたいへん申し訳ありません)

    (2)
    もし、コードを編集して利用しても大丈夫な場合の話になるのですが、特定のカテゴリーに属する投稿ページのみ、自動的にリンクが作成されるようにするためには、どのようなコードを追加すればいいのかをご教授いただくことは可能でしょうか。
    有償依頼となる、受け付けていない、別途メールでのやり取りで行っているなどありましたら、教えていただければ幸いです。

    どうぞよろしくお願い申しいたします。

    • はじめまして、こんにちは。
      1) この投稿のコードは CC0 ライセンスです。ご自由にご利用ください。もちろん改変して配布しても問題ありません。プラグイン自体は GPL としていますが、この投稿のコードと同じコードなので、ライセンスはご自由に選択してください。
      2) 下記のようなコードで特定のカテゴリーのみを対象にできます。

      function auto_linker_the_content( $content ) {
      	$links = array();
      

      function auto_linker_the_content( $content ) {
      	if ( ! in_category( 'cat1' ) ) { return $content; }
      	$links = array();
      

      ※ コード内の cat1 は対象のカテゴリー名(スラッグ)です。

  • 石鷹さま

    こんばんは。お返事とコードまでありがとうございます!
    自分が作りたいサイトにまた一歩近づくことができました。
    本当に感謝いたします。

    追伸

    XO Featured Image Toolsもインストールさせていただきました。
    あったらいいな、と思っていたプラグインをいろいろ開発されていらっしゃって、サイトを作るのがまた楽しくなりそうです。
    (本当に無償で使わせていただいてもいいのだろうか、と思ってしまうぐらいです。ありがとうございます)

コメントを残す

メールアドレスが公開されることはありません。

日本語でコメントを入力してください。(スパム対策)