IT

WordPress 「SyntaxHighlighter Evolved」プラグイン 投稿記事ごとにテーマを個別指定できるようにする

今回のお題

WordPressプラグインの「SyntaxHighlighter Evolved」ではお好みのカラーテーマを選ぶことができます。ただ、設定はサイト内共通なので投稿記事ごとに設定できません。投稿記事ごとに気分で変えたい場合にはどうすればよいか挑戦してみました。管理画面メニュー「設定」-「SyntaxHighlighter」ページにある以下のテーマリストを投稿編集ページに取り付けて設定できるイメージです。

環境

WordPress 5.2, SyntaxHighlighter Evolved 3.5.1

How To

functions.phpの修正

子テーマのfunctions.phpに、以下のコードを追記します。

/*-------------------------------------------*/
/*  SyntaxHighlighter Evolved プラグイン
/*  投稿記事ごとにテーマを個別指定できるようにする
/*-------------------------------------------*/
class my_syntaxhighlighter_post_theme {
  private const MY_NONCENAME = 'my_syntaxhighlighter_theme_noncename';
  private const MY_SELECT_NAME = 'my_syntaxhighlighter_theme';
  private const MY_ACTION_NAME = 'my_syntaxhighlighter_theme_action';
  private const MY_FIELD_NAME = '_my_syntaxhighlighter_theme';

  function __construct() {

    add_action('admin_menu', function () {
      foreach ( ['post', 'page'] as $screen ) {
        add_meta_box('my_syntaxhighlighter_post_theme', 'SyntaxHighlighter Evolved テーマの個別指定', 'add_meta_box_callback', $screen, 'normal', 'low');
      }
    });
    function add_meta_box_callback() {
      global $post;
      global $SyntaxHighlighter;
      if (!isset($SyntaxHighlighter) || !isset($SyntaxHighlighter->themes)) return;
      echo '<input type="hidden" name="'.self::MY_NONCENAME.'" id="'.self::MY_NONCENAME.'" value="'.wp_create_nonce(self::MY_ACTION_NAME).'" />';
      echo '<select name="'.self::MY_SELECT_NAME.'" id="'.self::MY_SELECT_NAME.'" class="postform">';
      foreach ( $SyntaxHighlighter->themes as $theme => $name ) {
        if ($theme == 'default') continue; // 'default':「デフォルト」は意味が紛らわしくなるので取り除く。
        $resister_theme = get_post_meta($post->ID, self::MY_FIELD_NAME, true) ?: 'none'; // 未登録なら'none':「なし」がリスト選択されるようにする。
        echo '  <option value="' . esc_attr( $theme ) . '"' . (( $theme == $resister_theme ) ? 'selected' : '') . '>' . esc_html( $name ) . " </option>\n";
      }
      echo '</select>';
    }
    add_action('save_post', function ($post_id) {
      if (!$_POST) return $post_id; // $_POST が空の場合はスルー
      if (!wp_verify_nonce($_POST[self::MY_NONCENAME], self::MY_ACTION_NAME)) return $post_id;
      if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) return $post_id;
      update_post_meta($post_id, self::MY_FIELD_NAME, $_POST[self::MY_SELECT_NAME]);
    });
    add_action('wp_head', function() {
      global $SyntaxHighlighter;
      if (is_page() || is_single()) {
        if (have_posts()) : while (have_posts()) : the_post();
          add_filter( 'syntaxhighlighter_cssthemeurl', function($src){
              global $wp_styles;
              $theme = get_post_meta(get_the_ID(), self::MY_FIELD_NAME, true);
              //_log('$theme:'.print_r($theme,true));
              $theme_key = 'syntaxhighlighter-theme-'.$theme;
              if (!$theme || empty($wp_styles->registered[$theme_key]) ) {
                return $src;
              }else{
                return $wp_styles->registered[$theme_key]->src;
              }
          });
        endwhile; endif;
        rewind_posts();
      }
    });
  }
};
new my_syntaxhighlighter_post_theme();

やっていることは

  • admin_menu をフックして投稿編集ページに項目を追加
  • save_post をフックして項目データを保存
  • wp_head をフックして投稿ページの表示の時にテーマが個別指定されていたらそのテーマを適用するため syntaxhighlighter_cssthemeurl をさらにフック

といった感じです。const定数をプライベートにしたいと考えclass化して包含しちゃいましたが一般的にはこのような書き方はしないのかな?フラットに書くんでしょうかね🤔

動作確認

投稿編集ページを開いてみるとページの下部に以下のリスト項目が追加されていることが確認できます。

選択リストを開くとカラーテーマが選択できます。

ここでは「Django」を選択してみました。「SyntaxHighlighter Evolved」で何でもよいのでソースコードを掲載して投稿記事を保存します。

これでこの投稿記事のページの「SyntaxHighlighter Evolved」に「Django」テーマカラーが適用されていたら成功です。

上手く動作しているようです。(個人的には「Django」テーマカラーを選ぶ気分になることはおそらくないと思ってます…。)

ほかの投稿記事も確認してみましたがそちらには影響がなくプラグイン本来の設定値が適用されていたので期待した動作となっているようです。プラグインの本体には手を入れずにフィルタやアクションのフックで機能を拡張できるのが面白いと感じました。

  • ABOUT ME
    tubogo
    自己紹介:SE歴17年、儲からない事ならいろいろかじってます。