3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

DrupalAdvent Calendar 2017

Day 1

Drupal 8 の Display Suite にカスタムのフィールドを追加する

Last updated at Posted at 2017-11-30

Drupal でノードなどの表示形式を変更する場合、Display Suite を使用してカスタマイズすることがあります。この際、ノードなどで定義されているフィールドは表示・非表示を切り替えることはできます。しかし、固定の文言を表示するためのフィールドや複数フィールドの値を組み合わせといったフィールドの表示を行うことは、Display Suite が標準で提供する機能だけでは難しいです。そこで、Display Suite にカスタムフィールドを追加するための方法を記載します。

Display Suite のカスタムフィールド追加の基本形

Display Suite にカスタムフィールドを実装する際の基本形は下記になります。

<?php

namespace Drupal\some_module\Plugin\DsField;

use Drupal\ds\Plugin\DsField\DsFieldBase;

/**
 * Generated field.
 *
 * @DsField(
 *   id = "some_module_DSFieldTest",
 *   title = @Translation("DSFieldTest"),
 *   entity_type = "user"
 * )
 */
class DSFieldTest extends DsFieldBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    return [
      '#markup' => 'Something field value.',
    ];
  }

}

コメント文のようになっている場所はアノテーションで、Display Suite フィールドの定義を行う場所です。
build() は、Display Suite で追加されたフィールドの出力を行う場所です。メソッドの返り値に Render arrays を与えることで、表示内容を決定することができます。
なお、Display Suite の drush コマンドでフィールドを作成した場合、テンプレートは下記のようになります。build() 以外に関しては後述する Display Suite 作者のスライドがあるので、そちらで確認してください。

<?php

namespace Drupal\some_module\Plugin\DsField;

use Drupal\Core\Form\FormStateInterface;
use Drupal\ds\Plugin\DsField\DsFieldBase;

/**
 * Generated field.
 *
 * @DsField(
 *   id = "some_module_DSFieldTest",
 *   title = @Translation("DSFieldTest"),
 *   entity_type = "user"
 * )
 */
class DSFieldTest extends DsFieldBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    return [];
  }

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

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function formatters() {
    return [];
  }

  /**
   * {@inheritdoc}
   */
  public function isAllowed() {
    return TRUE;
  }

}

フィールドを呼び出す Entity の制約をかける 

アノテーションに ui_limit を追加し、{}内に"エンティティID|ディスプレイモード" という値を設定することで、特定のエンティティや特定のディスプレイモードにのみフィールドを追加するように制約をかけることができます。例えば、下記のように "article|*" という値を設定すれば、article コンテンツタイプのみにフィールドを作成することができ、その他のコンテンツタイプでは出てこなくなります。逆に特定のディスプレイモードにのみ表示するように制約をかけるには、"*|some_display_mode" という値を設定します。

<?php

namespace Drupal\some_module\Plugin\DsField;

use Drupal\ds\Plugin\DsField\DsFieldBase;

/**
 * Generated limited field.
 *
 * @DsField(
 *   id = "some_module_DSFieldLimitTest",
 *   title = @Translation("DSFieldLimitTest"),
 *   entity_type = "node",
 *   ui_limit = {"article|*"}
 * )
 */
class DSFieldLimitTest extends DsFieldBase {

  /**
   * {@inheritdoc}
   */
  public function build() {
    return [];
  }

}

複数の制約条件を書く際は、下記のようにカンマ区切りで値を設定していきます。

/**
 * @DsField(
 *   id = "some_module_DSFieldMultiLimitTest",
 *   title = @Translation("DSFieldMultiLimitTest"),
 *   entity_type = "node",
 *   ui_limit = {
 *     "page|hogehoge",
 *     "article|foobar"
 *   }
 * )
 */

フィールドを使用している Entity を呼び出す

Display Suite で作成したフィールドは、呼び出し元の Entity を取得可能です。
Display Suite にある DsFieldBase 抽象クラスのソースコードを見ると、下記のように $this->counfiguration['entity'] に定義されていることが分かります。

/ds/src/Plugin/DsField/DsFieldBase.php
  public function entity() {
    return $this->configuration['entity'];
  }

作成したフィールドでは、$this->entity() を呼び出せるのでそれを使って呼び出し元の Entity の他のフィールドの値を使って処理を書くことができます。

DI の設定

Display Suite では、ブロックなどとは違い DsFieldBase に DI するためのサービスコンテナを呼び出す処理が書かれているため、DsFieldBase を呼び出すだけで DI を設定することができます。例えば、ログイン中のユーザを取得して何かしらの処理をする場合は下記のようになります。

<?php

namespace Drupal\some_module\Plugin\DsField;

use Drupal\ds\Plugin\DsField\DsFieldBase;

/**
 * Generated field.
 *
 * @DsField(
 *   id = "some_module_DSFieldTest",
 *   title = @Translation("DSFieldTest"),
 *   entity_type = "user"
 * )
 */
class DSFieldTest extends DsFieldBase {

  /**
   * Current User AccountProxy definition.
   *
   * @var \Drupal\Core\Session\AccountProxy
   */
  protected $currentUser;


  /**
   * DSFieldTest constructor.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin_id for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\Core\Session\AccountProxy $current_user
   *   The current user account proxy.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, AccountProxy $current_user) {
    parent::__construct($configuration, $plugin_id, $plugin_definition);
    $this->currentUser = $current_user;
  }


  /**
   * {@inheritdoc}
   */
  public function create() {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $container->get('current_user')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function build() {
    $uid = $this->currentUser->id();
    return [
      '#markup' => $uid . ':',
    ];
  }

}

まとめ

この記事では、Display Suite で追加可能になるフィールドを作成する方法を記載しました。
Display Suite のフィールドの設定フォームやフォーマッタの作成などといった、さらに詳しいことは、Display Suite の作者のスライドに書いてあるのでそちらを参照してください。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?