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']
に定義されていることが分かります。
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 の作者のスライドに書いてあるのでそちらを参照してください。