Drupal Advent Calendar 2018 20日目の記事です。

Drupal 8からコアに取り込まれているCKEditorですが、標準の機能だけでは物足りないケースもあるかと思います。そのような場合に独自のプラグインを追加できることをご存知でしょうか。今回はDrupal 8のCKEditorにカスタムプラグインを追加する方法をご紹介いたします。

今回の作成物

今回は例として、現在時刻の情報を挿入するTimestampボタンをCKEditorに追加します。

カスタムプラグインを追加してみよう

モジュールの作成

modules
└── custom
    └── cke_timestamp
        ├── cke_timestamp.info.yml
        ├── js
        │   ├── icons
        │   │   └── timestamp.png
        │   └── plugin.js
        └── src
            └── Plugin
                └── CKEditorPlugin
                    └── Timestamp.php

今回作成するモジュールの構成は上図のようになります。モジュール作成全般に言えることですが、ディレクトリ構成が違っているとDrupalがうまく認識できない場合がありますので、特にphpファイルのディレクトリは間違えないようご注意ください。

info.ymlの作成

cke_timestamp.info.ymlには通常のカスタムモジュールと同様にモジュールの定義を記述します。今回はCKEditorのプラグインなので、依存モジュールにckeditorを設定しておきましょう。

name: CKE Timestamp
description: "現在時刻を挿入します"
package: Sample
type: module
core: 8.x
dependencies:
  - ckeditor

Timestamp.phpの作成

Timestamp.phpはプラグインを追加する処理を記述します。とはいってもそれほど難しいことはなく、CKEditorPluginBaseクラスを継承して、idやjsファイルの場所など、必要な設定をオーバーライドしてあげればOKです。

<?php

namespace Drupal\cke_timestamp\Plugin\CKEditorPlugin;

use Drupal\ckeditor\CKEditorPluginBase;
use Drupal\ckeditor\CKEditorPluginConfigurableInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\editor\Entity\Editor;

/**
 * Defines the "timestamp" plugin.
 *
 * @CKEditorPlugin(
 *   id = "timestamp",
 *   label = @Translation("Timestamp")
 * )
 */
class Timestamp extends CKEditorPluginBase implements CKEditorPluginConfigurableInterface {

  /**
   * {@inheritdoc}
   */
  public function getFile() {
    return drupal_get_path('module', 'cke_timestamp') . '/js/plugin.js';
  }

  /**
   * {@inheritdoc}
   */
  public function getConfig(Editor $editor) {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function getButtons() {
    $module_base_path = base_path() . drupal_get_path('module', 'cke_timestamp');
    return [
      'Timestamp' => array(
        'label' => $this->t('Timestamp'),
        'image' => $module_base_path . '/js/icons/timestamp.png',
      ),
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) {
    return [];
  }

}

ファイル内容の説明
  • クラスコメント
    アノテーションでプラグインの定義を行なっています。一意となるidを付与してください。

  • getFile
    エディタ上の処理が記述されているjsファイルのパスを返します。

  • getConfig
    CKEditor.configに追加したい設定の連想配列を返します。今回は特に追加の設定はないため、空の配列を返しています。

  • getButtons
    プラグインが提供するボタンについて、名前や画像パスといった情報の連想配列を返します。

  • settingsForm
    プラグイン設定に使用するフォームを返します。今回は特にプラグイン設定フォームは不要なので、空の配列を返しています。

plugin.jsの作成

plugin.jsには実際のエディタ上での動作を記述します。

var today = new Date();
editor.insertHtml(today.toString());

の部分で、現在時刻を取得してエディタ上に挿入しています。
CKEditorのAPIの話になりますので詳細は割愛いたしますが、CKEditorの公式ページにドキュメントがありますので、詳しくはこちらをご参照ください。

/**
 * @file
 * Timestamp plugin.
 */

(function ($, Drupal, drupalSettings, CKEDITOR) {

  'use strict';

  CKEDITOR.plugins.add('timestamp', {
    icons: 'timestamp',
    init: function (editor) {
      editor.addCommand('timestamp', {
        // editor設定
        exec: function (editor) {
          // CKEditor上の処理を記述.
          var today = new Date();
          editor.insertHtml(today.toString());
        }
      });

      // CKEditorボタン設定
      editor.ui.addButton && editor.ui.addButton('Timestamp', {
        label: Drupal.t('Timestamp'),
        command: 'timestamp'
      });
    }
  });
})(jQuery, Drupal, drupalSettings, CKEDITOR);

最後にcke_timestamp/js/icons内にアイコン画像timestamp.pngを配置し、モジュールを有効化してください。

環境設定

作成したモジュールの有効化が完了したら、追加したプラグインをエディタで使用できるように設定を行います。

  1. 環境設定 > テキストフォーマットとエディタへ遷移します
  2. テキストエディタがCKEditorとなっているテキストフォーマットの設定ボタンをクリックします
  3. 利用可能なボタンの中に、作成したプラグインのボタンがあるかと思いますので、そのボタンをアクティブツールバー上の好きな位置に配置します 作成したプラグインのボタンをCKEditorに追加する
  4. 構成を保存ボタンをクリックします

以上を行うと、CKEditorにカスタムプラグインが追加されます。実際にコンテンツ追加画面で確認してみてください CKEditorにカスタムボタンが追加されている様子

まとめ

実際にはCKEditorのAPIについての知識も必要にはなってきますが、それでもプラグインを追加すること自体は簡単にできることはご理解いただけたのではないでしょうか。
ちょっとした機能でもユーザーエクスペリエンスの向上にも繋がる部分ですので、機会がありましたらぜひお試しください。