[Drupal] Views Bulk Operationにカスタムのアクションを追加する方法


Views Bulk Operation(VBO)って何

コンテンツ一覧やユーザー一覧はデフォルトで画像のように複数のエンティティに対して一括でアクション(操作)を行えるようになっていますが、

Views Bulk Operationを使うと他のビューにもこのようなチェックボックスとアクション選択フォームを追加することができます。

使い方は簡単で、VBOをインストール→任意のビューのフィールド設定からviews bulk operationsを追加すれば完了なのですが...

デフォルトで選べるアクションが10種類くらいしか無く。

これ以外のアクションを使えるようにする場合はカスタムアクションを作る必要があります。(例: 「選択されたコンテンツのフィールドAの値をXXにする」「選択されたコンテンツのモデレーション状態をXXにする」等)

というわけで今回はカスタムのアクションを追加する方法を紹介したいと思います。

カスタムのアクションを追加する方法

今回は例として「選択されたコンテンツのフィールドAの値を◯◯にする」というアクションを追加してみます。

プラグインファイルの作成

カスタムモジュールに/src/Plugin/Actionというディレクトリを作成し、MyAction.phpファイルを配置します。必要なファイルはこれだけです。ファイル名(=クラス名)はControllerなどと同様に〇〇Actionで終わる方がわかりやすいですが、適当でも機能的には問題ありません。

MyAction.phpを作成

プラグインクラスを書いていきます。

まず、通常のプラグインと同様にアノテーションを書きます。type="node"でノードのビューにしかこのアクションを適用できないようにしています。他にはrequirementsというプロパティでこのアクションを実行できるユーザーを制限することができます。今回はこのビューにアクセスできる人は誰でもこのアクションを実行できるようにしたいのでrequirementsは定義しません。詳しくは公式ドキュメントをご覧ください。

クラスはDrupal\views_bulk_operations\Action\ViewsBulkOperationsActionBaseを継承します。(Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionInterfaceを埋め込めば継承しなくてもOK)

<?php

namespace Drupal\my_module\Plugin\Action;
use Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionBase;

/**
 * Myアクションを定義する.
 *
 * @Action(
 *   id = "my_module_my_action",
 *   label = "フィールドAの値をtestにする",
 *   type = "node",
 * )
 */
class MyAction extends ViewsBulkOperationsActionBase {

必須のメソッドを書いていきます。まずはexecuteメソッドです。引数の$entityでエンティティが渡されるので、このエンティティに対して好きな処理を施します。(エンティティはノードの一覧ならノード、タクソノミーの一覧ならタクソノミーが渡ってきます)


 /**
   * {@inheritdoc}
   */
  public function execute($entity = NULL) {
    if ($entity->bundle() == 'article') {
      $entity->set('field_a', 'test')->save();
    }
    return 'フィールドAの値を更新しました。';
  }

時間記録などループの前後で処理を行いたい場合はexecuteの呼び出し元のexecuteMultipleを上書きします。

(ViewsBulkOperationsActionBaseexecuteMultiple)

/**
   * {@inheritdoc}
   */
  public function executeMultiple(array $objects) {
    $results = [];
    foreach ($objects as $entity) {
      $results[] = $this->execute($entity);
    }

    return $results;
  }

次にaccessメソッドを定義します。ここで個々のエンティティに対するアクセスチェックを行ってると思われます。(間違ってたらすいません。)今回は特にエンティティごとの制御は行わないのでAccessResult::neutral()(意見なし)を返しておきます。

use Drupal\Core\Access\AccessResult;

/**
   * {@inheritdoc}
   */
  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
    return AccessResult::neutral();
  }

全部つなげるとこんな感じです。(今回はexecuteMultipleは未使用)

<?php

namespace Drupal\my_module\Plugin\Action;

use Drupal\views_bulk_operations\Action\ViewsBulkOperationsActionBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Access\AccessResult;

/**
 * Myアクションを定義する.
 *
 * @Action(
 *   id = "my_module_my_action",
 *   label = "フィールドAの値を'test'にする",
 *   type = "node",
 * )
 */
class MyAction extends ViewsBulkOperationsActionBase {

  /**
   * {@inheritdoc}
   */
  public function execute($entity = NULL) {
    if ($entity->bundle() == 'article') {
      $entity->set('field_a', 'test')->save();
    }
    return 'フィールドAの値を更新しました。';
  }

  /**
   * {@inheritdoc}
   */
  public function access($object, AccountInterface $account = NULL, $return_as_object = FALSE) {
    return AccessResult::neutral();
  }

}

これでビューのVBOの設定にこのアクションが追加されます。

ビューの画面ではこんな感じに表示されます。

一括処理終了後のステータスメッセージ。

アクションを実行するとフィールド値もちゃんと更新されます

というわけでVBOにカスタムのアクションを追加する方法の紹介でした。