web-dev-qa-db-ja.com

特定のフィールドにカスタムビューフィルターハンドラーを追加する方法

現在、ブールフィールド_field_private_content_があります。このフィールドが設定されている場合、コンテンツは認証されたユーザーにのみ表示され、匿名ユーザーにはティーザーとログインフォームしか表示されません。これまでのところ、私はそのフィールドにフィルターを追加したビューでもうまく機能しています。フィルターは、カスタムモジュールのhook_views_pre_view()の実装によって自動的に削除されます。

_function custom_module_views_pre_view(ViewExecutable $view, $display_id, array &$args) {
  // Remove filter on field_private_content != TRUE for authenticated users.
  if ($view->getHandler($view->current_display, 'filter', 'field_private_content') && \Drupal::currentUser()->isAuthenticated()) {
    $view->removeHandler($view->current_display, 'filter', 'field_private_content');
  }
}
_

これは非常にうまく機能しますが、動作はビューUIからは明らかではありません。私はfield_private_contentフィルターの複製を用意します。これは、デフォルトで前述の動作があり、適切にラベル付けできるはずです-元のフィルターは元の動作を維持する必要があります。

どうすればそれを達成できますか?

特定のフィールドにカスタムビューフィルターハンドラーを追加する方法

6
LarS

Drupal 8.でカスタムビューフィルターを作成するために使用した記事への主要な部分と参照のみをここに配置するので、これは少しの努力を必要とします。

まず、hook_views_data_alter()実装内でフィルターを宣言する必要があります。

_$data['node_field_data']['nodes_titles'] = array(
  'title' => t('Node titles'),
  'filter' => array(
    'title' => t('Node titles'),
    'help' => t('Specify a list of titles a node can have.'),
    'field' => 'title',
    'id' => 'd8views_node_titles'
  ),
)
_

タイトル列でフィルタリングしているため、node_field_dataテーブルを拡張していますが、タイトル列を使用する実際のフィールドとして使用しています。さらに、今回は_d8views_node_titles_として識別されるフィルタリングを処理するプラグインを作成しています。次に、このクラスを作成します。

src/Plugin/views/filter/NodeTitles.php

_    /**
     * @file
     * Definition of Drupal\d8views\Plugin\views\filter\NodeTitles.
     */

    namespace Drupal\d8views\Plugin\views\filter;

    use Drupal\views\Plugin\views\display\DisplayPluginBase;
    use Drupal\views\Plugin\views\filter\InOperator;
    use Drupal\views\ViewExecutable;

    /**
     * Filters by given list of node title options.
     *
     * @ingroup views_filter_handlers
     *
     * @ViewsFilter("d8views_node_titles")
     */
    class NodeTitles extends InOperator {

      /**
       * {@inheritdoc}
       */
      public function init(ViewExecutable $view, DisplayPluginBase $display, array &$options = NULL) {
        parent::init($view, $display, $options);
        $this->valueTitle = t('Allowed node titles');
        $this->definition['options callback'] = array($this, 'generateOptions');
      }

      /**
       * Override the query so that no filtering takes place if the user doesn't
       * select any options.
       */
      public function query() {
        if (!empty($this->value)) {
          parent::query();
        }
      }

      /**
       * Skip validation if no options have been chosen so we can use it as a
       * non-filter.
       */
      public function validate() {
        if (!empty($this->value)) {
          parent::validate();
        }
      }

      /**
       * Helper function that generates the options.
       * @return array
       */
      public function generateOptions() {
        // Array keys are used to compare with the table field values.
        return array(
          'my title' => 'my title',
          'another title' => 'another title',
        );
      }

    }
_

Drupal 8 でカスタムビューフィルターを作成する)で説明されているように、プラグイン内で3つのメソッドをオーバーライドする必要があります。

init()内で、フィルターオプションのセットのタイトルと、オプションの値を生成するコールバックを指定します。このコールバックは呼び出し可能である必要があり、この場合、このクラスでgenerateOptions()メソッドを選択しました。後者は、ユーザーに提示するオプションの配列を返すだけで、そのキーはクエリの変更で使用されます。または、_$this->valueOptions_プロパティに使用可能なタイトルを入力して、init()メソッド内にオプションを直接作成することもできます。必要なノードタイトルの配信を担当するさまざまなロジックを実行できるため、コールバックの使用はよりクリーンです。

query()およびvalidate()メソッドをオーバーライドする目的は、ユーザーがタイトルを選択せず​​にフィルターを作成した場合にクエリと検証が行われないようにすることでした。この方法では、フィルターは結果に影響を与えず、結果を0に戻すのではありません。これは、さまざまな機能をオーバーライドしてプラグインをニーズに合わせて調整する方法を説明するための単純な設定です。

12