Custom Drupal Block Visibility Plugins and the Condition Plugin API

Overview

Every Drupal site builder works with blocks. Blocks are an essential building component in Drupal. Block configuration allows for the site builder to determine various conditions in which the block should be shown. Some examples are to show the block only for a given content type, a given role, or a given path.

Drupal block configuration
The Drupal block configuration page, with a custom condition for "Group member". This tutorial will show how to create this custom condition.

Behind the scenes, Drupal uses the Condition Plugin API to define conditions under which blocks are shown. This API allows developers to create Drupal plugins that act as new conditions that can be selected when placing blocks, allowing developers to create dynamic custom conditions that meet specific and complex requirements on websites.

This tutorial will outline the process of creating a new Condition Plugin API plugin, extending the types of conditions that can be applied to block configuration. This tutorial will use the Groups module. A new condition will be created whereby the block is only shown if the user is a member of the current group.

 

Requirements

This tutorial requires an understanding of how to create a Drupal module, what a Drupal plugin is, how to register a plugin through class annotation, and how to inject services as dependencies in Drupal OOP. These are core concepts for Drupal development, and if you don't understand them and intend to develop in Drupal, it is worth taking the time to read and have somewhat of an understanding before reading this tutorial.The tutorial it is dependent upon the Groups module, without which the code shown will throw errors and not work.

 

Goal

The goal is to create a new tab in the vertical tabs on the block configuration page. The tab will add a checkbox for user is member of current group. As conditions come with a negate condition checkbox, there will be three possible states for this condition:

  1. Neither box checked - this is the default state. This condition does nothing, and the block will be shown on all pages.
  2. The display to group members box is checked, and the negate the condition box is unchecked. The block is shown only on group pages, if the current user is a member of the group.
  3. Both boxes are checked. The block is shown on non-group pages, and on group pages where the current user is not a member of the group.

Note that when the display to group members box is unchecked, the negate the condition checkbox has no effect. This example will therefore set this checkbox to only display when the display to group members box has been checked.

A Note on Negating Conditions

When the negate this condition box is checked, the condition is evaluated, and if it is FALSE, the negated condition is satisfied. In the case of this tutorial, the condition evaluates to TRUE when the user is currently in a group context AND they are a member of the group. When the negate checkbox is checked, if the user is not on a group page, the condition evaluates to FALSE, so the negated condition is satisfied, and the block is shown. If the user is on a group page, but is not a member, the condition evaluates to FALSE, meaning the negated condition is satisfied and the block is shown. If the user is on a group page, and is a member, the condition evaluates to TRUE, so the negated condition is not satisfied and the block is not shown.

 

Process

The following steps are required:

  1. Extend ConditionPluginBase to declare a new @Condition plugin.
  2. Register the default configuration for the condition.
  3. Create the configuration form to be shown on the block configuration page.
  4. Create a summary.
  5. Implement the evalute() method to determine if the condition has been met.
  6. Add a cache context for members of the current group, so that the condition is re-evaluated for members and non-members.
  7. (Optional) Set the negate checkbox to only show when the condition is enabled.
  8. (Optional) Add custom JavaScript to show the summary in the vertical tabs.

Step 1: Declare a new Condition Plugin

Creating a new vertical tab on the block configuration page requires creating a new Condition Plugin API plugin. After clearing the registry, Drupal will automatically add it to the vertical tabs on the block configuration page.

@Condition plugins extend ConditionPluginBase, which implements ConditionInterface. @Condition Plugins go into the Drupal\[module]\Plugin\Condition namespace. The class annotation defines a new @Condition plugin.

  1. /**
  2.  * @Condition(
  3.  * id = "group_member",
  4.  * label = @Translation("Group member"),
  5.  * )
  6.  */

The example uses the current_route_match_service, injected as $this->currentRouteMatch, and the current_user service, injected as $this->currentUser.

  1. <?php
  2.  
  3. namespace Drupal\[MODULE]\Plugin\Condition;
  4.  
  5. use Drupal\Core\Condition\ConditionPluginBase;
  6. use Drupal\Core\Form\FormStateInterface;
  7. use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
  8. use Drupal\Core\Routing\ResettableStackedRouteMatchInterface;
  9. use Drupal\Core\Session\AccountProxyInterface;
  10. use Symfony\Component\DependencyInjection\ContainerInterface;
  11.  
  12. /**
  13.  * Provides a condition for members of the current group.
  14.  *
  15.  * This condition evaluates to TRUE when in a group context, and the current
  16.  * user is a member of the group. When the condition is negated, the condition
  17.  * is shown when either not in group context, or in group context but the
  18.  * current user is not a member of the group.
  19.  *
  20.  * @Condition(
  21.  * id = "group_member",
  22.  * label = @Translation("Group member"),
  23.  * )
  24.  */
  25. class GroupMember extends ConditionPluginBase implements ContainerFactoryPluginInterface {
  26.  
  27. /**
  28.   * The current route match service.
  29.   *
  30.   * @var \Drupal\Core\Routing\ResettableStackedRouteMatchInterface
  31.   */
  32. protected $currentRouteMatch;
  33.  
  34. /**
  35.   * The current user.
  36.   *
  37.   * @var \Drupal\Core\Session\AccountProxyInterface
  38.   */
  39. protected $currentUser;
  40.  
  41. /**
  42.   * Creates a new PodcastType instance.
  43.   *
  44.   * @param array $configuration
  45.   * The plugin configuration.
  46.   * @param string $plugin_id
  47.   * The plugin_id for the plugin instance.
  48.   * @param mixed $plugin_definition
  49.   * The plugin implementation definition.
  50.   * @param \Drupal\Core\Routing\ResettableStackedRouteMatchInterface $currentRouteMatch
  51.   * The curretn route match service.
  52.   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
  53.   * The current user.
  54.   */
  55. public function __construct(
  56. array $configuration,
  57. $plugin_id,
  58. $plugin_definition,
  59. ResettableStackedRouteMatchInterface $currentRouteMatch,
  60. AccountProxyInterface $currentUser
  61. ) {
  62. parent::__construct($configuration, $plugin_id, $plugin_definition);
  63.  
  64. $this->currentRouteMatch = $currentRouteMatch;
  65. $this->currentUser = $currentUser;
  66. }
  67.  
  68. /**
  69.   * {@inheritdoc}
  70.   */
  71. public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  72. return new static(
  73. $configuration,
  74. $plugin_id,
  75. $plugin_definition,
  76. $container->get('current_route_match'),
  77. $container->get('current_user')
  78. );
  79. }
  80.  
  81. }

Step 2: Register the Default Configuration

The default configuration needs to be declared for the condition. This condition will be disabled by default, as blocks should be shown for all users on all pages by default, and only have limitations placed on them when the condition is enabled.

  1. /**
  2.  * {@inheritdoc}
  3.  */
  4. public function defaultConfiguration() {
  5. // The default configuration will be have the block hidden (0).
  6. return ['show' => 0] + parent::defaultConfiguration();
  7. }

Step 3: Create the Configuration Form

First, the Next, the configuration form is defined with a checkbox to enable the condition.

  1. /**
  2.  * {@inheritdoc}
  3.  */
  4. public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
  5. // Define the checkbox to enable the condition.
  6. $form['show'] = [
  7. '#title' => $this->t('Display only to group members'),
  8. '#type' => 'checkbox',
  9. // Use whatever value is stored in cofiguration as the default.
  10. '#default_value' => $this->configuration['show'],
  11. '#description' => $this->t('When this box is checked, this block will only be shown on group pages, when the user is a member, and will not be shown on any non-group pages. When negated, the block is shown on all non-group pages, as well as group pages on which the current user is not a member of the group.'),
  12. ];
  13.  
  14. return parent::buildConfigurationForm($form, $form_state);
  15. }

Finally, a submit handler is created to save the submitted value to configuration.

  1. /**
  2.  * {@inheritdoc}
  3.  */
  4. public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
  5. // Save the submitted value to configuration.
  6. $this->configuration['show'] = $form_state->getValue('show');
  7.  
  8. parent::submitConfigurationForm($form, $form_state);
  9. }

Step 4: Create a Summary

ConditionBase implements ConditionInterface, which requires the method summary(). This method outputs a human-readable description of the condition settings. The summary method returns a different value depending on the which of three configuration states is set:

  1. Condition is not enabled
  2. Condition is enabled
  3. Condition is enabled and negated
  1. /**
  2.  * {@inheritdoc}
  3.  */
  4. public function summary() {
  5. if ($this->configuration['show']) {
  6. // Check if the 'negate condition' checkbox was checked.
  7. if ($this->isNegated()) {
  8. // The condition is enabled and negated.
  9. return $this->t('Shown on non-group pages and on group pages to non-members');
  10. }
  11. else {
  12. // The condition is enabled.
  13. return $this->t('Shown on group pages to members of the group');
  14. }
  15. }
  16.  
  17. // The condition is not enabled.
  18. return $this->t('Not Restricted');
  19. }

Unfortunately, the summary is not shown by default in the vertical tabs on the block configuration page. The summary created above allows developers to use conditions programmatically and output human readable summaries that can be used in logs, or messages, or even dashboards.

Vertical tabs screenshot showing absence of summary text
By default, a summary is not shown.

Step 8 will show how to add a summary on the vertical tabs.

Step 5: Evaluate the Condition

ConditionBase implements ConditionInterface, which requires the method evaluate(). This method returns a boolean indicating whether or not the current condition has been met.

  1. /**
  2.  * {@inheritdoc}
  3.  */
  4. public function evaluate() {
  5. // Determine if in a group context.
  6. if ($group = $this->currentRouteMatch->getParameter('group')) {
  7. // Return a boolean based on whether the user is a member of the group.
  8. return (bool) $group->getMember($this->currentUser);
  9. }
  10.  
  11. // Not in a group context.
  12. return FALSE;
  13. }

Step 6: Add a Cache Context

As it stands right now, the condition will work correctly the first time the condition is evaluated, and the result is cached. So, if the condition is enabled, and the first user to visit a group page is a member of the group, the condition evaluates to TRUE and the block is rendered. The problem is when a non-member visits the group, the condition has been cached as TRUE, so the user sees the block, even though they are not a member of the group.

The solution to this is to add cache contexts. The cache context tells Drupal that the condition should be re-evaluated in various contexts. For the example in this tutorial, the condition will have a different result for members and non-members of the group, therefore a cache context must be created that tells the system to cache a different result for each of these contexts.

Cache contexts can be added by extending ContextAwarePluginTrait::getCacheContexts(), and adding a cache context for user.is_group_member:%group_id.

  1. /**
  2.  * {@inheritdoc}
  3.  */
  4. public function getCacheContexts() {
  5. // Get the default cache contexts.
  6. $contexts = parent::getCacheContexts();
  7.  
  8. // Check if in group context.
  9. if ($group = $this->currentRouteMatch->getParameter('group')) {
  10. // Add a context for members of the current group, so that the block
  11. // differs between members and non-members.
  12. $contexts[] = 'user.is_group_member:' . $group->id();
  13. }
  14.  
  15. return $contexts;
  16. }

Step 7 (Optional): Hide the Negate checkbox when the condition is disabled

The negate the condition checkbox only has meaning when the condition is enabled, as the evaluate() method is not called when the condition is not enabled. As such, it does not make sense to show the negate checkbox when the condition is not enabled. This checkbox is provided automatically by the API, however it is always shown regardless of whether the condition is enabled. To improve the UX, the negate checkbox can be set to be hidden until the display only to group members checkbox has been clicked.

This is done by implementing hook_form_FORM_ID_alter() as hook_form_block_form_alter() in the [MODULE].module file for the module, and adding #states to the negate checkbox.

  1. /**
  2.  * Implements hook_form_FORM_ID_alter().
  3.  */
  4. function HOOK_form_block_form_alter(&$form, FormStateInterface $form_state) {
  5. if (isset($form['visibility']['group_member'])) {
  6. // Add a #state for visibility tot he group member negate checkbox.
  7. $form['visibility']['group_member']['negate']['#states'] = [
  8. 'visible' => [
  9. '[data-drupal-selector="edit-visibility-group-member-show"]' => ['checked' => TRUE],
  10. ],
  11. ];
  12. }
  13. }

Step 8 (Optional): Add JavaScript for the Settings Summary

Drupal core adds settings summary to the vertical tabs on the block settings page for tabs provided by core. Custom modules must add their own JavaScript and tie into the API to show the summary.

The first step is to create a library in [MODULE].libraries.yml linking to the .js file.

  1. block:
  2. js:
  3. js/group_member_condition.js: {}
  4. dependencies:
  5. - 'block/drupal.block'

Then, back to hook_form_block_form_alter() (see step 5) to attach the library to the form.

  1. /**
  2.  * Implements hook_form_FORM_ID_alter().
  3.  */
  4. function HOOK_form_block_form_alter(&$form, FormStateInterface $form_state) {
  5. if (isset($form['visibility']['group_member'])) {
  6. // Attach the library for the vertical tab.
  7. $form['visibility_tabs']['#attached']['library'][] = '[MODULE]/block';
  8.  
  9. // Add a #state for visibility tot he group member negate checkbox.
  10. $form['visibility']['group_member']['negate']['#states'] = [
  11. 'visible' => [
  12. '[data-drupal-selector="edit-visibility-group-member-show"]' => ['checked' => TRUE],
  13. ],
  14. ];
  15. }
  16. }

You will need to replace [MODULE] with your module key.

And finally, group_member_condition.js. Note that for consistency's sake, the text for the summary messages should be manually aligned with the text from the summary() method of the plugin (see step 3).

  1. /**
  2.  * @file
  3.  * Sets up the summary for group members on vertical tabs of block forms.
  4.  */
  5.  
  6. (function ($, Drupal) {
  7.  
  8. 'use strict';
  9.  
  10. function checkboxesSummary(context) {
  11. // Determine if the condition has been enabled (the box is checked).
  12. var conditionChecked = $(context).find('[data-drupal-selector="edit-visibility-group-member-show"]:checked').length;
  13. // Determine if the negate condition has been enabled (the box is checked).
  14. var negateChecked = $(context).find('[data-drupal-selector="edit-visibility-group-member-negate"]:checked').length;
  15.  
  16. if (conditionChecked) {
  17. if (negateChecked) {
  18. // Both boxes have been checked.
  19. return Drupal.t("Shown on non-group pages and on group pages to non-members");
  20. }
  21.  
  22. // The condition has been enabled.
  23. return Drupal.t("Shown on group pages to members of the group");
  24. }
  25.  
  26. // The condition has not been enabled and is not negated.
  27. return Drupal.t('Not restricted');
  28. }
  29.  
  30. /**
  31.   * Provide the summary information for the block settings vertical tabs.
  32.   *
  33.   * @type {Drupal~behavior}
  34.   *
  35.   * @prop {Drupal~behaviorAttach} attach
  36.   * Attaches the behavior for the block settings summaries.
  37.   */
  38. Drupal.behaviors.blockSettingsSummaryGroupMember = {
  39. attach: function () {
  40. // Only do something if the function drupalSetSummary is defined.
  41. if (jQuery.fn.drupalSetSummary !== undefined) {
  42. // Set the summary on the vertical tab.
  43. $('[data-drupal-selector="edit-visibility-group-member"]').drupalSetSummary(checkboxesSummary);
  44. }
  45. }
  46. };
  47.  
  48. }(jQuery, Drupal));

 

Using Conditions Programmatically

Conditions can also be used programatically in other ways on Drupal sites. Here is an example how the condition created above could be used in a programmatic context to determine if the current user is a member of the current group:

  1. $condition = \Drupal::service('plugin.manager.condition')->createInstance('group_member');
  2.  
  3. $condition->setConfiguration(['show' => 1]);
  4.  
  5. // Test if the condition is satisfied - IE the user is in a group context, and
  6. // is a member of the group.
  7. if ($condition->evaluate()) {
  8. \Drupal::messenger()->addStatus(t('The condition was evaluated as %message', [
  9. '%message' => $condition->summary(),
  10. ]);
  11. }

 

Summary

This tutorial examined the Condition Plugin API for Drupal, providing an example of creating a new condition to restrict block visibility to group members with the Groups module. After reading this tutorial you should have an understanding of how this API works, and how to create your own custom conditions for blocks on your Drupal sites.

Complete Code

GroupMember.php:

  1. <?php
  2.  
  3. namespace Drupal\[MODULE]\Plugin\Condition;
  4.  
  5. use Drupal\Core\Condition\ConditionPluginBase;
  6. use Drupal\Core\Form\FormStateInterface;
  7. use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
  8. use Drupal\Core\Routing\ResettableStackedRouteMatchInterface;
  9. use Drupal\Core\Session\AccountProxyInterface;
  10. use Symfony\Component\DependencyInjection\ContainerInterface;
  11.  
  12. /**
  13.  * Provides a condition for members of the current group.
  14.  *
  15.  * This condition evaluates to TRUE when in a group context, and the current
  16.  * user is a member of the group. When the condition is negated, the condition
  17.  * is shown when either not in group context, or in group context but the
  18.  * current user is not a member of the group.
  19.  *
  20.  * @Condition(
  21.  * id = "group_member",
  22.  * label = @Translation("Group member"),
  23.  * )
  24.  */
  25. class GroupMember extends ConditionPluginBase implements ContainerFactoryPluginInterface {
  26.  
  27. /**
  28.   * The current route match service.
  29.   *
  30.   * @var \Drupal\Core\Routing\ResettableStackedRouteMatchInterface
  31.   */
  32. protected $currentRouteMatch;
  33.  
  34. /**
  35.   * The current user.
  36.   *
  37.   * @var \Drupal\Core\Session\AccountProxyInterface
  38.   */
  39. protected $currentUser;
  40.  
  41. /**
  42.   * Creates a new PodcastType instance.
  43.   *
  44.   * @param array $configuration
  45.   * The plugin configuration.
  46.   * @param string $plugin_id
  47.   * The plugin_id for the plugin instance.
  48.   * @param mixed $plugin_definition
  49.   * The plugin implementation definition.
  50.   * @param \Drupal\Core\Routing\ResettableStackedRouteMatchInterface $currentRouteMatch
  51.   * The curretn route match service.
  52.   * @param \Drupal\Core\Session\AccountProxyInterface $currentUser
  53.   * The current user.
  54.   */
  55. public function __construct(
  56. array $configuration,
  57. $plugin_id,
  58. $plugin_definition,
  59. ResettableStackedRouteMatchInterface $currentRouteMatch,
  60. AccountProxyInterface $currentUser
  61. ) {
  62. parent::__construct($configuration, $plugin_id, $plugin_definition);
  63.  
  64. $this->currentRouteMatch = $currentRouteMatch;
  65. $this->currentUser = $currentUser;
  66. }
  67.  
  68. /**
  69.   * {@inheritdoc}
  70.   */
  71. public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
  72. return new static(
  73. $configuration,
  74. $plugin_id,
  75. $plugin_definition,
  76. $container->get('current_route_match'),
  77. $container->get('current_user')
  78. );
  79. }
  80.  
  81. /**
  82.   * {@inheritdoc}
  83.   */
  84. public function defaultConfiguration() {
  85. // Set the default value for the checkbox on the block configuration page.
  86. // This condition is not be enabled by default, so the default is set to
  87. // zero.
  88. return ['show' => 0] + parent::defaultConfiguration();
  89. }
  90.  
  91. /**
  92.   * {@inheritdoc}
  93.   */
  94. public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
  95. // Define the checkbox to enable the condition.
  96. $form['show'] = [
  97. '#title' => $this->t('Display only to group members'),
  98. '#type' => 'checkbox',
  99. // Use whatever value is stored in cofiguration as the default.
  100. '#default_value' => $this->configuration['show'],
  101. '#description' => $this->t('When this box is checked, this block will only be shown on group pages, when the user is a member, and will not be shown on any non-group pages. When negated, the block is shown on all non-group pages, as well as group pages on which the current user is not a member of the group.'),
  102. ];
  103.  
  104. return parent::buildConfigurationForm($form, $form_state);
  105. }
  106.  
  107. /**
  108.   * {@inheritdoc}
  109.   */
  110. public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
  111. // Save the submitted value to configuration.
  112. $this->configuration['show'] = $form_state->getValue('show');
  113.  
  114. parent::submitConfigurationForm($form, $form_state);
  115. }
  116.  
  117. /**
  118.   * {@inheritdoc}
  119.   */
  120. public function summary() {
  121. if ($this->configuration['show']) {
  122. // Check if the 'negate condition' checkbox was checked.
  123. if ($this->isNegated()) {
  124. // The condition is enabled and negated.
  125. return $this->t('Shown on non-group pages and on group pages to non-members');
  126. }
  127. else {
  128. // The condition is enabled.
  129. return $this->t('Shown on group pages to members of the group');
  130. }
  131. }
  132.  
  133. // The condition is not enabled.
  134. return $this->t('Not Restricted');
  135. }
  136.  
  137. /**
  138.   * {@inheritdoc}
  139.   */
  140. public function evaluate() {
  141. // Determine if in a group context.
  142. if ($group = $this->currentRouteMatch->getParameter('group')) {
  143. // Return a boolean based on whether the user is a member of the group.
  144. return (bool) $group->getMember($this->currentUser);
  145. }
  146.  
  147. // Not in a group context.
  148. return FALSE;
  149. }
  150.  
  151. /**
  152.   * {@inheritdoc}
  153.   */
  154. public function getCacheContexts() {
  155. $contexts = parent::getCacheContexts();
  156.  
  157. // Check if in group context.
  158. if ($group = $this->currentRouteMatch->getParameter('group')) {
  159. // Add a context for members of the current group, so that the block
  160. // differs between members and non-members.
  161. $contexts[] = 'user.is_group_member:' . $group->id();
  162. }
  163.  
  164. return $contexts;
  165. }
  166.  
  167. }

[MODULE].module:

  1. /**
  2.  * Implements hook_form_FORM_ID_alter().
  3.  */
  4. function HOOK_form_block_form_alter(&$form, FormStateInterface $form_state) {
  5. if (isset($form['visibility']['group_member'])) {
  6. $form['visibility_tabs']['#attached']['library'][] = '[MODULE]/block';
  7. // Add a #state for visibility tot he group member negate checkbox.
  8. $form['visibility']['group_member']['negate']['#states'] = [
  9. 'visible' => [
  10. '[data-drupal-selector="edit-visibility-group-member-show"]' => ['checked' => TRUE],
  11. ],
  12. ];
  13. }
  14. }

[MODULE].libraries.yml:

  1. block:
  2. version: 'VERSION'
  3. js:
  4. js/group_member_condition.js: {}
  5. dependencies:
  6. - 'block/drupal.block'

group_member_condition.js:

  1. /**
  2.  * @file
  3.  * Sets up the summary on vertical tabs of block forms.
  4.  */
  5.  
  6. /*global jQuery, Drupal*/
  7.  
  8.  
  9. (function ($, Drupal) {
  10.  
  11. 'use strict';
  12.  
  13. /**
  14.   * Create a summary for checkboxes in the provided context.
  15.   *
  16.   * @param {HTMLDocument|HTMLElement} context
  17.   * A context where one would find checkboxes to summarize.
  18.   *
  19.   * @return {string}
  20.   * A string with the summary.
  21.   */
  22. function checkboxesSummary(context) {
  23. // Determine if the condition has been enabled (the box is checked).
  24. var conditionChecked = $(context).find('[data-drupal-selector="edit-visibility-group-member-show"]:checked').length;
  25. // Determine if the negate condition has been enabled (the box is checked).
  26. var negateChecked = $(context).find('[data-drupal-selector="edit-visibility-group-member-negate"]:checked').length;
  27.  
  28. if (conditionChecked) {
  29. if (negateChecked) {
  30. // Both boxes have been checked.
  31. return Drupal.t("Shown on non-group pages and on group pages to non-members");
  32. }
  33.  
  34. // The condition has been enabled.
  35. return Drupal.t("Shown on group pages to members of the group");
  36. }
  37.  
  38. // The condition has not been enabled and is not negated.
  39. return Drupal.t('Not restricted');
  40. }
  41.  
  42. /**
  43.   * Provide the summary information for the block settings vertical tabs.
  44.   *
  45.   * @type {Drupal~behavior}
  46.   *
  47.   * @prop {Drupal~behaviorAttach} attach
  48.   * Attaches the behavior for the block settings summaries.
  49.   */
  50. Drupal.behaviors.blockSettingsSummaryGroupMember = {
  51. attach: function () {
  52. // Only do something if the function drupalSetSummary is defined.
  53. if (jQuery.fn.drupalSetSummary !== undefined) {
  54. // Set the summary on the vertical tab.
  55. $('[data-drupal-selector="edit-visibility-group-member"]').drupalSetSummary(checkboxesSummary);
  56. }
  57. }
  58. };
  59.  
  60. }(jQuery, Drupal));