You are here

class OptionsLimitWebformHandler in Webform 8.5

Same name and namespace in other branches
  1. 6.x modules/webform_options_limit/src/Plugin/WebformHandler/OptionsLimitWebformHandler.php \Drupal\webform_options_limit\Plugin\WebformHandler\OptionsLimitWebformHandler

Webform options and boolean (boolean) limit handler.

Plugin annotation


@WebformHandler(
  id = "options_limit",
  label = @Translation("Options/Checkbox limit"),
  category = @Translation("Options"),
  description = @Translation("Define options or checkbox submission limits."),
  cardinality = \Drupal\webform\Plugin\WebformHandlerInterface::CARDINALITY_UNLIMITED,
  results = \Drupal\webform\Plugin\WebformHandlerInterface::RESULTS_IGNORED,
  submission = \Drupal\webform\Plugin\WebformHandlerInterface::SUBMISSION_REQUIRED,
)

Hierarchy

Expanded class hierarchy of OptionsLimitWebformHandler

File

modules/webform_options_limit/src/Plugin/WebformHandler/OptionsLimitWebformHandler.php, line 44

Namespace

Drupal\webform_options_limit\Plugin\WebformHandler
View source
class OptionsLimitWebformHandler extends WebformHandlerBase implements WebformOptionsLimitHandlerInterface {
  use WebformAjaxElementTrait;

  /**
   * The database object.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * The webform token manager.
   *
   * @var \Drupal\webform\WebformTokenManagerInterface
   */
  protected $tokenManager;

  /**
   * The webform element plugin manager.
   *
   * @var \Drupal\webform\Plugin\WebformElementManagerInterface
   */
  protected $elementManager;

  /**
   * The source entity.
   *
   * @var \Drupal\Core\Entity\EntityInterface
   */
  protected $sourceEntity = NULL;

  /**
   * {@inheritdoc}
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, LoggerChannelFactoryInterface $logger_factory, ConfigFactoryInterface $config_factory, EntityTypeManagerInterface $entity_type_manager, WebformSubmissionConditionsValidatorInterface $conditions_validator, Connection $database, WebformTokenManagerInterface $token_manager, WebformElementManagerInterface $element_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $logger_factory, $config_factory, $entity_type_manager, $conditions_validator);
    $this->database = $database;
    $this->tokenManager = $token_manager;
    $this->elementManager = $element_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
    return new static($configuration, $plugin_id, $plugin_definition, $container
      ->get('logger.factory'), $container
      ->get('config.factory'), $container
      ->get('entity_type.manager'), $container
      ->get('webform_submission.conditions_validator'), $container
      ->get('database'), $container
      ->get('webform.token_manager'), $container
      ->get('plugin.manager.webform.element'));
  }

  /**
   * {@inheritdoc}
   */
  public function hasAnonymousSubmissionTracking() {
    return $this->configuration['limit_user'];
  }

  /**
   * {@inheritdoc}
   */
  public function setSourceEntity(EntityInterface $source_entity = NULL) {
    $this->sourceEntity = $source_entity;
    return $this;
  }

  /**
   * {@inheritdoc}
   */
  public function getSourceEntity() {
    if ($this->sourceEntity) {
      return $this->sourceEntity;
    }
    elseif ($this
      ->getWebformSubmission()) {
      return $this
        ->getWebformSubmission()
        ->getSourceEntity();
    }
    else {
      return NULL;
    }
  }

  /**
   * {@inheritdoc}
   */
  public function defaultConfiguration() {
    return [
      'element_key' => '',
      // Boolean limit.
      'limit' => NULL,
      // Options limit.
      'limits' => [],
      'limit_reached_message' => '@name is not available',
      'limit_source_entity' => TRUE,
      'limit_user' => FALSE,
      'option_none_action' => 'disable',
      'option_message_display' => 'label',
      'option_multiple_message' => '[@remaining remaining]',
      'option_single_message' => '[@remaining remaining]',
      'option_unlimited_message' => '[Unlimited]',
      'option_none_message' => '[@remaining remaining]',
      'option_error_message' => '@name: @label is unavailable.',
      'tableselect_header' => '',
    ];
  }

  /**
   * {@inheritdoc}
   */
  public function getSummary() {
    $settings = $this
      ->getSettings();
    $element = $this
      ->getWebform()
      ->getElement($settings['element_key']);
    if ($element) {
      $webform_element = $this->elementManager
        ->getElementInstance($element);
      $t_args = [
        '@title' => $webform_element
          ->getAdminLabel($element),
        '@type' => $webform_element
          ->getPluginLabel(),
      ];
      $settings['element_key'] = $this
        ->t('@title (@type)', $t_args);
    }
    elseif (empty($settings['element_key'])) {
      $settings['element_key'] = [
        '#type' => 'link',
        '#title' => $this
          ->t('Please add a new options or checkbox element.'),
        '#url' => $this
          ->getWebform()
          ->toUrl('edit-form'),
      ];
    }
    else {
      $settings['element_key'] = [
        '#markup' => $this
          ->t("'@element_key' is missing.", [
          '@element_key' => $settings['element_key'],
        ]),
        '#prefix' => '<b class="color-error">',
        '#suffix' => '</b>',
      ];
    }

    // Unset limit if element type is not a boolean.
    if (!$this
      ->isBooleanElement()) {
      unset($settings['limit']);
    }
    return [
      '#settings' => $settings,
    ] + parent::getSummary();
  }

  /**
   * {@inheritdoc}
   */
  public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
    $this
      ->applyFormStateToConfiguration($form_state);

    // Get elements with options.
    $elements_with_options = $this
      ->getElements();

    // Make sure that there an options element available.
    if (empty($elements_with_options)) {
      $form['message'] = [
        '#type' => 'webform_message',
        '#message_type' => 'warning',
        '#message_message' => [
          'message' => [
            '#markup' => $this
              ->t('No options or checkbox elements are available.'),
            '#prefix' => '<p>',
            '#suffix' => '</p>',
          ],
          'link' => [
            '#type' => 'link',
            '#title' => $this
              ->t('Please add a new options or checkbox element.'),
            '#url' => $this
              ->getWebform()
              ->toUrl('edit-form'),
            '#prefix' => '<p>',
            '#suffix' => '</p>',
          ],
        ],
      ];
      return $form;
    }

    // Element settings.
    $form['element_settings'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Element settings'),
      '#open' => TRUE,
    ];
    $form['element_settings']['element_key'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Element'),
      '#options' => $this
        ->getElements(),
      '#default_value' => $this->configuration['element_key'],
      '#required' => TRUE,
      '#empty_option' => empty($this->configuration['element_key']) ? $this
        ->t('- Select -') : NULL,
    ];
    $form['element_settings']['options_container'] = [];
    $element = $this
      ->getElement();
    if ($element) {
      $webform_element = $this
        ->getWebformElement();
      $t_args = [
        '@title' => $webform_element
          ->getAdminLabel($element),
        '@type' => $this
          ->t('option'),
      ];
      if ($this
        ->isOptionsElement()) {
        $element_options = $this
          ->getElementOptions() + [
          WebformOptionsLimitHandlerInterface::DEFAULT_LIMIT => $this
            ->t('Default (Used when option has no limit)'),
        ];
        $form['element_settings']['options_container']['limits'] = [
          '#type' => 'webform_mapping',
          '#title' => $this
            ->t('@title @type limits', $t_args),
          '#description_display' => 'before',
          '#source' => $element_options,
          '#source__title' => $this
            ->t('Options'),
          '#destination__type' => 'number',
          '#destination__min' => 0,
          '#destination__title' => $this
            ->t('Limit'),
          '#destination__description' => NULL,
          '#default_value' => $this->configuration['limits'],
          '#filter' => FALSE,
        ];
      }
      else {
        $form['element_settings']['options_container']['limit'] = [
          '#type' => 'number',
          '#title' => $this
            ->t('@title @type limit', $t_args),
          '#min' => 0,
          '#default_value' => $this->configuration['limit'],
        ];
      }
    }
    else {
      $form['element_settings']['options_container']['limits'] = [
        '#type' => 'value',
        '#value' => [],
      ];
      $form['element_settings']['options_container']['limit'] = [
        '#type' => 'value',
        '#value' => NULL,
      ];
    }
    $this
      ->buildAjaxElement('webform-options-limit', $form['element_settings']['options_container'], $form['element_settings']['element_key']);

    // Limit settings.
    $form['limit_settings'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Limit settings'),
    ];
    $form['limit_settings']['limit_reached_message'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Limit reached message'),
      '#description' => $this
        ->t('This message will be displayed when all limits are reached.') . '<br/><br/>' . $this
        ->t('Leave blank to hide this message.'),
      '#default_value' => $this->configuration['limit_reached_message'],
    ];
    $form['limit_settings']['limit_source_entity'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Apply limits to each source entity'),
      '#description' => $this
        ->t('If checked, limits will be applied to this webform and each source entity individually.'),
      '#return_value' => TRUE,
      '#default_value' => $this->configuration['limit_source_entity'],
    ];
    $form['limit_settings']['limit_user'] = [
      '#type' => 'checkbox',
      '#title' => $this
        ->t('Apply limits to per user'),
      '#description' => $this
        ->t("If checked, limits will be applied per submission for authenticated and anonymous users. Anonymous user limits are only tracked by the user's browser sessions. Per user limits work best for authenticated users."),
      '#return_value' => TRUE,
      '#default_value' => $this->configuration['limit_user'],
    ];
    $form['limit_settings']['limit_user_message'] = [
      '#type' => 'webform_message',
      '#message_type' => 'warning',
      '#message_message' => $this
        ->t("Anonymous user limits are only tracked by the user's browser session. It is recommended that limits per user only be used on forms restricted to authenticated users."),
      '#message_close' => TRUE,
      '#message_storage' => WebformMessage::STORAGE_SESSION,
      '#states' => [
        'visible' => [
          ':input[name="settings[limit_user]"]' => [
            'checked' => TRUE,
          ],
        ],
      ],
    ];

    // Option settings.
    $form['option_settings'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Option/checkbox settings'),
    ];
    $form['option_settings']['option_none_action'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Limit reached behavior'),
      '#options' => [
        WebformOptionsLimitHandlerInterface::LIMIT_ACTION_DISABLE => $this
          ->t('Disable the option/checkbox'),
        WebformOptionsLimitHandlerInterface::LIMIT_ACTION_REMOVE => $this
          ->t('Remove the option/checkbox'),
        WebformOptionsLimitHandlerInterface::LIMIT_ACTION_NONE => $this
          ->t('Do not alter the option/checkbox'),
      ],
      '#default_value' => $this->configuration['option_none_action'],
    ];
    $form['option_settings']['option_message_display'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Message display'),
      '#options' => [
        WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_LABEL => $this
          ->t("Append message to the option/checkbox's text"),
        WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_DESCRIPTION => $this
          ->t("Append message to the option/checkbox's description"),
        WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_NONE => $this
          ->t("Do not display a message"),
      ],
      '#default_value' => $this->configuration['option_message_display'],
    ];
    $form['option_settings']['option_message'] = [
      '#type' => 'container',
      '#states' => [
        'visible' => [
          ':input[name="settings[option_message_display]"]' => [
            '!value' => 'none',
          ],
        ],
      ],
    ];
    $form['option_settings']['option_message']['option_multiple_message'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Multiple remaining message'),
      '#description' => $this
        ->t('This message is displayed when the remaining submission is greater than one.') . '<br/><br/>' . $this
        ->t('Leave blank to hide this message.'),
      '#default_value' => $this->configuration['option_multiple_message'],
    ];
    $form['option_settings']['option_message']['option_single_message'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('One remaining message'),
      '#description' => $this
        ->t('This message is displayed when there is only one remaining submission available.') . '<br/><br/>' . $this
        ->t('Leave blank to hide this message.'),
      '#default_value' => $this->configuration['option_single_message'],
    ];
    $form['option_settings']['option_message']['option_none_message'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('None remaining message'),
      '#description' => $this
        ->t('This message is displayed when there are remaining submissions allows.') . '<br/><br/>' . $this
        ->t('Leave blank to hide this message.'),
      '#default_value' => $this->configuration['option_none_message'],
    ];
    $form['option_settings']['option_message']['option_unlimited_message'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Unlimited message'),
      '#description' => $this
        ->t('This message is displayed when there are not submissions limits.') . '<br/><br/>' . $this
        ->t('Leave blank to hide this message.'),
      '#default_value' => $this->configuration['option_unlimited_message'],
    ];
    $form['option_settings']['option_error_message'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Validation error message'),
      '#description' => $this
        ->t('The message is displayed when an element has validation error is submitted.'),
      '#default_value' => $this->configuration['option_error_message'],
      '#required' => TRUE,
    ];
    if ($tableselect_elements = $this
      ->getTableSelectElements()) {
      $tableselect_states = [];
      foreach ($tableselect_elements as $tableselect_element_key) {
        if ($tableselect_states) {
          $tableselect_states[] = 'or';
        }
        $tableselect_states[] = [
          ':input[name="settings[element_key]"]' => [
            'value' => $tableselect_element_key,
          ],
        ];
      }
      $form['option_settings']['tableselect_header'] = [
        '#type' => 'textfield',
        '#title' => $this
          ->t('Table select description header'),
        '#description' => $this
          ->t("The label is displayed in the header for the table select's option limit column."),
        '#default_value' => $this->configuration['tableselect_header'],
        '#states' => [
          'visible' => [
            ':input[name="settings[option_message_display]"]' => [
              'value' => WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_DESCRIPTION,
            ],
            $tableselect_states,
          ],
        ],
      ];
    }

    // Placeholder help.
    $form['placeholder_help'] = [
      '#type' => 'details',
      '#title' => $this
        ->t('Placeholder help'),
      'description' => [
        '#markup' => $this
          ->t('The following placeholders can be used:'),
      ],
      'items' => [
        '#theme' => 'item_list',
        '#items' => [
          $this
            ->t('@limit - The total number of submissions allowed for the option/checkbox.'),
          $this
            ->t('@total - The current number of submissions for the option/checkbox.'),
          $this
            ->t('@remaining - The remaining number of submissions for the option/checkbox.'),
          $this
            ->t("@label - The element option/checkbox's label."),
          $this
            ->t("@name - The element's title."),
        ],
      ],
    ];
    return $this
      ->setSettingsParents($form);
  }

  /**
   * {@inheritdoc}
   */
  public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
    parent::submitConfigurationForm($form, $form_state);
    $this
      ->applyFormStateToConfiguration($form_state);
    foreach ($this->configuration['limits'] as $key => $value) {
      if ($value === '') {
        unset($this->configuration['limits'][$key]);
      }
      else {
        $this->configuration['limits'][$key] = (int) $value;
      }
    }
    if ($this
      ->isOptionsElement()) {
      $this->configuration['limit'] = NULL;
    }
    else {
      $this->configuration['limits'] = [];
    }
  }

  /****************************************************************************/

  // Alter element methods.

  /****************************************************************************/

  /**
   * {@inheritdoc}
   */
  public function alterElement(array &$element, FormStateInterface $form_state, array $context) {
    if (empty($element['#webform_key']) || $element['#webform_key'] !== $this->configuration['element_key']) {
      return;
    }

    // Set webform submission for form object.

    /** @var \Drupal\webform\WebformSubmissionForm $form_object */
    $form_object = $form_state
      ->getFormObject();
    $operation = $form_object
      ->getOperation();

    /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
    $webform_submission = $form_object
      ->getEntity();
    $this
      ->setWebformSubmission($webform_submission);
    if ($this
      ->isOptionsElement()) {

      // Get options limits, reached, and (form) operation.
      $limits = $this
        ->getOptionsLimits();
      $reached = $this
        ->getOptionsReached($limits);

      // Set table select description in header.
      if ($this
        ->isTableSelectElement()) {
        $message_display = $this->configuration['option_message_display'];
        if ($message_display === WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_DESCRIPTION) {
          $element['#header']['webform_options_limit'] = $this->configuration['tableselect_header'] ?: '';
        }
      }

      // Cleanup options element default value.
      $this
        ->setOptionsElementDefaultValue($element, $limits, $reached, $operation);

      // Alter options element.
      $this
        ->alterOptionsElement($element, $limits, $reached);
    }
    else {

      // Get boolean limit.
      $limits = $this
        ->getBooleanLimits();
      $limit = reset($limits);

      // Cleanup boolean element default value.
      $this
        ->setBooleanElementDefaultValue($element, $limit, $operation);

      // Alter boolean element.
      $this
        ->alterBooleanElement($element, $limit);
    }

    // Add element validate callback.
    $element['#webform_option_limit_handler_id'] = $this
      ->getHandlerId();
    $element['#element_validate'][] = [
      get_called_class(),
      'validateElement',
    ];
  }

  /****************************************************************************/

  // Element methods.

  /****************************************************************************/

  /**
   * Validate webform element limit.
   */
  public static function validateElement(&$element, FormStateInterface $form_state, &$complete_form) {

    // Skip if element is not visible.
    if (!Element::isVisibleElement($element)) {
      return;
    }

    /** @var \Drupal\webform\WebformSubmissionForm $form_object */
    $form_object = $form_state
      ->getFormObject();
    $webform = $form_object
      ->getWebform();

    /** @var \Drupal\webform_options_limit\Plugin\WebformHandler\OptionsLimitWebformHandler $handler */
    $handler = $webform
      ->getHandler($element['#webform_option_limit_handler_id']);
    if ($handler
      ->isOptionsElement()) {
      $handler
        ->validateOptionsElement($element, $form_state);
    }
    else {
      $handler
        ->validateBooleanElement($element, $form_state);
    }
  }

  /**
   * Set element's limit reached message.
   *
   * @param array $element
   *   An element with limits.
   */
  protected function setElementLimitReachedMessage(array &$element) {
    if (empty($this->configuration['limit_reached_message'])) {
      return;
    }
    $args = [
      '@name' => $this
        ->getElementLabel(),
    ];
    $element['#description'] = [
      '#type' => 'webform_message',
      '#message_type' => 'warning',
      '#message_message' => new FormattableMarkup($this->configuration['limit_reached_message'], $args),
    ];
  }

  /****************************************************************************/

  // Options element methods.

  /****************************************************************************/

  /**
   * Set an options element's default value.
   *
   * @param array $element
   *   An options element with limits.
   * @param array $limits
   *   An options element's option limits.
   * @param array $reached
   *   An options element's reached options.
   * @param string $operation
   *   The form's current operation.
   */
  protected function setOptionsElementDefaultValue(array &$element, array $limits, array $reached, $operation) {
    $webform_element = $this
      ->getWebformElement();
    $has_multiple_values = $webform_element
      ->hasMultipleValues($element);

    // Make sure the test default value is an enabled option.
    if ($operation === 'test') {
      $test_values = array_keys($reached ? array_diff_key($limits, $reached) : $limits);
      if ($test_values) {
        $test_value = $test_values[array_rand($test_values)];
        $element['#default_value'] = $has_multiple_values ? [
          $test_value,
        ] : $test_value;
      }
      else {
        $element['#default_value'] = $has_multiple_values ? [] : NULL;
      }
    }
    elseif (!empty($element['#default_value'])) {
      $default_value = $element['#default_value'];
      if ($has_multiple_values) {
        if ($this
          ->isTableSelectElement()) {
          $element['#default_value'] = array_diff($default_value, $reached);
        }
        else {
          $element['#default_value'] = array_values(array_diff($default_value, $reached));
        }
      }
      else {
        if (isset($reached[$default_value])) {
          $element['#default_value'] = $has_multiple_values ? [] : NULL;
        }
      }
    }
  }

  /**
   * Alter an options element.
   *
   * @param array $element
   *   An options element with limits.
   * @param array $limits
   *   An options element's option limits.
   * @param array $reached
   *   An options element's reached options.
   */
  protected function alterOptionsElement(array &$element, array $limits, array $reached) {

    // Set options element's options labels.
    $options =& $element['#options'];
    $this
      ->alterOptionsElementLabels($options, $limits);

    // Disable or remove reached options.
    if ($reached) {
      switch ($this->configuration['option_none_action']) {
        case WebformOptionsLimitHandlerInterface::LIMIT_ACTION_DISABLE:
          $this
            ->disableOptionsElement($element, $reached);
          break;
        case WebformOptionsLimitHandlerInterface::LIMIT_ACTION_REMOVE:
          $this
            ->removeOptionsElement($element, $reached);
          break;
      }
    }

    // Display limit reached message.
    if (count($limits) === count($reached)) {
      $this
        ->setElementLimitReachedMessage($element);
    }
  }

  /**
   * Alter an options element's option labels recursively.
   *
   * @param array $options
   *   An options element with limits.
   * @param array $limits
   *   An options element's option limits.
   */
  protected function alterOptionsElementLabels(array &$options, array $limits) {
    $message_display = $this->configuration['option_message_display'];
    foreach ($options as $option_value => $option_text) {
      if ($this
        ->isTableSelectElement()) {
        if (isset($limits[$option_value])) {
          $label = $this
            ->getOptionsLimitLabel($option_text[0]['value'], $limits[$option_value]);
          $message_display = $this->configuration['option_message_display'];
          $option =& $options[$option_value][0];
          switch ($message_display) {
            case WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_DESCRIPTION:
              list($option['value'], $option['webform_options_limit']) = explode(' --', $label);
              break;
            case WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_LABEL:
              $option['value'] = $label;
              break;
          }
        }
      }
      elseif (is_array($option_text)) {
        $this
          ->alterOptionsElementLabels($option_text, $limits);
      }
      elseif (isset($limits[$option_value])) {
        $options[$option_value] = $this
          ->getOptionsLimitLabel($option_text, $limits[$option_value]);
      }
    }
  }

  /**
   * Disable options element's reached options.
   *
   * @param array $element
   *   An options element with limits.
   * @param array $reached
   *   An options element's reached options.
   */
  protected function disableOptionsElement(array &$element, array $reached) {
    $webform_element = $this
      ->getWebformElement();
    if ($this
      ->isTableSelectElement()) {

      // Hide disabled table select checkbox or radio.
      foreach ($reached as $reached_option) {
        $element[$reached_option]['#access'] = FALSE;
      }
    }
    elseif ($webform_element
      ->hasProperty('options__properties')) {

      // Set element options disabled properties.
      foreach ($reached as $reached_option) {
        $element['#options__properties'][$reached_option] = [
          '#disabled' => TRUE,
        ];
      }
    }
    else {

      // Set select menu disabled attribute.
      // @see Drupal.behaviors.webformSelectOptionsDisabled
      // @see webform.element.select.js
      $element['#attributes']['data-webform-select-options-disabled'] = implode(',', $reached);
    }
  }

  /**
   * Remove options element's reached options.
   *
   * @param array $element
   *   An options element with limits.
   * @param array $reached
   *   An options element's reached options.
   */
  protected function removeOptionsElement(array &$element, array $reached) {
    $options =& $element['#options'];
    $this
      ->removeOptionsElementRecursive($options, $reached);
  }

  /**
   * Remove options element's reached options.
   *
   * @param array $options
   *   An array options (and optgroups).
   * @param array $reached
   *   An options element's reached options.
   */
  protected function removeOptionsElementRecursive(array &$options, array $reached) {
    foreach ($options as $option_value => &$option_text) {
      if (is_array($option_text)) {
        $this
          ->removeOptionsElementRecursive($option_text, $reached);
        if (empty($option_text)) {
          unset($options[$option_value]);
        }
      }
      elseif (isset($reached[$option_value])) {
        unset($options[$option_value]);
      }
    }
  }

  /**
   * Validate an options element with limit(s).
   *
   * @param array $element
   *   An options element with limits.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @internal
   *   This method should only called by
   *   OptionsLimitWebformHandler::validateElementLimit.
   */
  public function validateOptionsElement(array $element, FormStateInterface $form_state) {

    /** @var \Drupal\webform\WebformSubmissionForm $form_object */
    $form_object = $form_state
      ->getFormObject();

    /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
    $webform_submission = $form_object
      ->getEntity();
    $this
      ->setWebformSubmission($webform_submission);
    $element_key = $this->configuration['element_key'];

    // Get casting as array to support multiple options.
    $original_values = (array) $webform_submission
      ->getElementOriginalData($element_key);
    $updated_values = (array) $form_state
      ->getValue($element_key);
    if (empty($updated_values) || $updated_values === [
      '',
    ]) {
      return;
    }
    $limits = $this
      ->getOptionsLimits($updated_values);
    foreach ($limits as $value => $limit) {

      // Do not apply option limit to any previously selected option value.
      if (in_array($value, $original_values)) {
        continue;
      }
      if ($limit['status'] === WebformOptionsLimitHandlerInterface::LIMIT_STATUS_NONE) {
        $message = $this
          ->getElementLimitStatusMessage(WebformOptionsLimitHandlerInterface::LIMIT_STATUS_ERROR, $limit);
        $form_state
          ->setError($element, $message);
      }
    }
  }

  /****************************************************************************/

  // Boolean element methods.

  /****************************************************************************/

  /**
   * Set a boolean element's default value.
   *
   * @param array $element
   *   A boolean element with limits.
   * @param array $limit
   *   A boolean element's limit information.
   * @param string $operation
   *   The form's current operation.
   */
  protected function setBooleanElementDefaultValue(array &$element, array $limit, $operation) {
    if ($operation === 'test') {
      if ($limit['status'] === WebformOptionsLimitHandlerInterface::LIMIT_STATUS_NONE) {
        unset($element['#default_value']);
      }
    }
    else {
      $element_key = $this->configuration['element_key'];
      $webform_submission = $this
        ->getWebformSubmission();
      $original_value = $webform_submission
        ->getElementOriginalData($element_key);
      if ($limit['status'] === WebformOptionsLimitHandlerInterface::LIMIT_STATUS_NONE && !$original_value) {
        unset($element['#default_value']);
      }
    }
  }

  /**
   * Alter a boolean element's.
   *
   * @param array $element
   *   An boolean element.
   * @param array $limit
   *   A webform boolean element's limit.
   */
  protected function alterBooleanElement(array &$element, array $limit) {

    // Set message.
    $message_display = $this->configuration['option_message_display'];
    if ($message_display !== WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_NONE) {
      $message = $this
        ->getElementLimitStatusMessage($limit['status'], $limit);
      if ($message) {
        switch ($message_display) {
          case WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_LABEL:
            $t_args = [
              '@label' => $element['#title'],
              '@message' => $message,
            ];
            $element['#title'] = $this
              ->t('@label @message', $t_args);
            break;
          case WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_DESCRIPTION:
            $element += [
              '#description' => '',
            ];
            $element['#description'] .= $element['#description'] ? '<br/>' . $message : $message;
            break;
        }
      }
    }

    // Disable or remove boolean element.
    $element_key = $this->configuration['element_key'];
    $webform_submission = $this
      ->getWebformSubmission();
    $boolean_value = (bool) ($webform_submission
      ->getElementOriginalData($element_key) ?: FALSE);
    if ($limit['status'] === WebformOptionsLimitHandlerInterface::LIMIT_STATUS_NONE && !$boolean_value) {
      switch ($this->configuration['option_none_action']) {
        case WebformOptionsLimitHandlerInterface::LIMIT_ACTION_DISABLE:
          $element['#disabled'] = TRUE;
          break;
        case WebformOptionsLimitHandlerInterface::LIMIT_ACTION_REMOVE:
          $element['#access'] = FALSE;
          break;
      }

      // Display limit reached message.
      $this
        ->setElementLimitReachedMessage($element);
    }
  }

  /**
   * Validate a boolean element with limit(s).
   *
   * Please note that this should never be called because disabled checkbox
   * elements do not post back any value. This code would be executed if
   * some one manually triggers for validation.
   *
   * @param array $element
   *   A boolean element with limits.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @internal
   *   This method should only called by
   *   OptionsLimitWebformHandler::validateElementLimit.
   */
  public function validateBooleanElement(array $element, FormStateInterface $form_state) {

    /** @var \Drupal\webform\WebformSubmissionForm $form_object */
    $form_object = $form_state
      ->getFormObject();

    /** @var \Drupal\webform\WebformSubmissionInterface $webform_submission */
    $webform_submission = $form_object
      ->getEntity();
    $this
      ->setWebformSubmission($webform_submission);
    $element_key = $this->configuration['element_key'];
    $original_value = $webform_submission
      ->getElementOriginalData($element_key);
    $updated_value = $form_state
      ->getValue($element_key);
    if (empty($updated_value) || !empty($original_value)) {
      return;
    }
    $limit = $this->configuration['limit'];
    $total = $this
      ->getBooleanTotal();
    if ($total >= $limit) {
      $limits = $this
        ->getBooleanLimits();
      $message = $this
        ->getElementLimitStatusMessage(WebformOptionsLimitHandlerInterface::LIMIT_STATUS_ERROR, reset($limits));
      $form_state
        ->setError($element, $message);
    }
  }

  /****************************************************************************/

  // Form methods.

  /****************************************************************************/

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state, WebformSubmissionInterface $webform_submission) {

    // Must invalidate webform cache tags.
    Cache::invalidateTags([
      'webform:' . $this
        ->getWebform()
        ->id(),
    ]);
  }

  /****************************************************************************/

  // Summary method.
  // @see \Drupal\webform_options_limit\Controller\WebformOptionsLimitController

  /****************************************************************************/

  /**
   * Build summary table.
   *
   * @return array
   *   A renderable containing the options limit summary table.
   */
  public function buildSummaryTable() {
    $element = $this
      ->getElement();
    if (!$element) {
      return [];
    }
    if ($this->configuration['limit_user']) {
      return [];
    }
    $webform_element = $this
      ->getWebformElement();
    $rows = [];
    $limits = $this
      ->isOptionsElement() ? $this
      ->getOptionsLimits() : $this
      ->getBooleanLimits();
    foreach ($limits as $limit) {
      if ($limit['limit']) {
        $percentage = number_format($limit['total'] / $limit['limit'] * 100) . '% ';
        $progress = [
          '#type' => 'html_tag',
          '#tag' => 'progress',
          '#attributes' => [
            'max' => $limit['limit'],
            'value' => $limit['total'],
          ],
        ];
      }
      else {
        $percentage = '';
        $progress = [];
      }
      $rows[] = [
        [
          'data' => $limit['label'],
          'style' => 'font-weight: bold',
        ],
        [
          'data' => $limit['limit'] ?: '∞',
          'style' => 'text-align: right',
        ],
        [
          'data' => $limit['limit'] ? $limit['remaining'] : '∞',
          'style' => 'text-align: right',
        ],
        [
          'data' => $limit['total'],
          'style' => 'text-align: right',
        ],
        [
          'data' => $progress,
          'style' => 'text-align: center',
        ],
        [
          'data' => $percentage,
          'style' => 'text-align: right',
        ],
      ];
    }
    return [
      'title' => [
        '#markup' => $webform_element
          ->getLabel($element),
        '#prefix' => '<h2>',
        '#suffix' => '</h2>',
      ],
      'table' => [
        '#type' => 'table',
        '#header' => [
          '',
          [
            'data' => $this
              ->t('Limit'),
            'style' => 'text-align: right',
          ],
          [
            'data' => $this
              ->t('Remaining'),
            'style' => 'text-align: right',
            'class' => [
              RESPONSIVE_PRIORITY_LOW,
            ],
          ],
          [
            'data' => $this
              ->t('Total'),
            'style' => 'text-align: right',
            'class' => [
              RESPONSIVE_PRIORITY_LOW,
            ],
          ],
          [
            'data' => $this
              ->t('Progress'),
            'style' => 'text-align: center',
            'class' => [
              RESPONSIVE_PRIORITY_LOW,
            ],
          ],
          '',
        ],
        '#rows' => $rows,
      ],
    ];
  }

  /****************************************************************************/

  // Element methods.

  /****************************************************************************/

  /**
   * Get element.
   *
   * @return array
   *   Selected element.
   */
  protected function getElement() {
    return $this
      ->getWebform()
      ->getElement($this->configuration['element_key']);
  }

  /**
   * Get selected webform element plugin.
   *
   * @return \Drupal\webform\Plugin\WebformElementInterface|null
   *   A webform element plugin instance.
   */
  protected function getWebformElement() {
    $element = $this
      ->getElement();
    return $element ? $this->elementManager
      ->getElementInstance($element) : NULL;
  }

  /**
   * Determine if options element.
   *
   * @return string
   *   TRUE if options element.
   */
  protected function isOptionsElement() {
    $webform_element = $this
      ->getWebformElement();
    return $webform_element instanceof OptionsBase;
  }

  /**
   * Determine if boolean element.
   *
   * @return string
   *   TRUE if boolean element.
   */
  protected function isBooleanElement() {
    $webform_element = $this
      ->getWebformElement();
    return $webform_element instanceof BooleanBase;
  }

  /**
   * Determine if table select  element.
   *
   * @return string
   *   TRUE if table select element.
   */
  protected function isTableSelectElement() {
    $webform_element = $this
      ->getWebformElement();
    return $webform_element instanceof TableSelect;
  }

  /**
   * Get selected webform element label.
   *
   * @return string
   *   A webform element label.
   */
  protected function getElementLabel() {
    $element = $this
      ->getElement();
    $webform_element = $this
      ->getWebformElement();
    return $webform_element
      ->getLabel($element);
  }

  /**
   * Get key/value array of webform options or boolean elements.
   *
   * @return array
   *   A key/value array of webform options or boolean elements.
   */
  protected function getElements() {
    $webform = $this
      ->getWebform();
    $elements = $webform
      ->getElementsInitializedAndFlattened();
    $options = [];
    foreach ($elements as $element) {
      $webform_element = $this->elementManager
        ->getElementInstance($element);
      $is_options_element = $webform_element
        ->hasProperty('options');
      $is_entity_options_element = $webform_element instanceof WebformElementEntityOptionsInterface;
      $is_boolean_element = $webform_element instanceof BooleanBase;
      if ($is_options_element || $is_entity_options_element || $is_boolean_element) {
        $webform_key = $element['#webform_key'];
        $t_args = [
          '@title' => $webform_element
            ->getAdminLabel($element),
          '@type' => $webform_element
            ->getPluginLabel(),
        ];
        $options[$webform_key] = $this
          ->t('@title (@type)', $t_args);
      }
    }

    // Exclude elements being used by other options limit handlers.
    $handlers = $webform
      ->getHandlers();
    foreach ($handlers as $handler) {
      if ($handler instanceof WebformOptionsLimitHandlerInterface && $handler
        ->getHandlerId() !== $this
        ->getHandlerId()) {
        $element_key = $handler
          ->getSetting('element_key');
        unset($options[$element_key]);
      }
    }
    return $options;
  }

  /**
   * Get table select elements.
   *
   * @return array
   *   An array containing table select elements.
   */
  protected function getTableSelectElements() {
    $webform = $this
      ->getWebform();
    $elements = $webform
      ->getElementsInitializedAndFlattened();
    $tableselect_elements = [];
    foreach ($elements as $element_key => $element) {
      $webform_element = $this->elementManager
        ->getElementInstance($element);
      if ($webform_element instanceof TableSelect) {
        $tableselect_elements[$element_key] = $element_key;
      }
    }
    return $tableselect_elements;
  }

  /**
   * Get selected element's options.
   *
   * @return array
   *   A key/value array of options.
   */
  protected function getElementOptions() {
    $element = $this
      ->getElement();

    // Set entity options.
    $webform_element = $this
      ->getWebformElement();
    if ($webform_element instanceof WebformElementEntityOptionsInterface) {
      WebformEntityTrait::setOptions($element);
    }
    return $element ? OptGroup::flattenOptions($element['#options']) : [];
  }

  /****************************************************************************/

  // Limits methods.

  /****************************************************************************/

  /**
   * Get an associative array of options limits.
   *
   * @param array $values
   *   Optional array of values to get options limit.
   *
   * @return array
   *   An associative array of options limits keyed by option value and
   *   including the option's limit, total, remaining, and status.
   */
  protected function getOptionsLimits(array $values = []) {
    $default_limit = isset($this->configuration['limits'][WebformOptionsLimitHandlerInterface::DEFAULT_LIMIT]) ? $this->configuration['limits'][WebformOptionsLimitHandlerInterface::DEFAULT_LIMIT] : NULL;
    $totals = $this
      ->getOptionsTotals($values);
    $options = $this
      ->getElementOptions();
    if ($values) {
      $options = array_intersect_key($options, array_combine($values, $values));
    }
    $limits = [];
    foreach ($options as $option_key => $option_label) {
      $limit = isset($this->configuration['limits'][$option_key]) ? $this->configuration['limits'][$option_key] : $default_limit;
      $total = isset($totals[$option_key]) ? $totals[$option_key] : 0;
      $limits[$option_key] = $this
        ->getLimitInformation($option_label, $limit, $total);
    }
    return $limits;
  }

  /**
   * Get an associative array of boolean limits.
   *
   * @return array
   *   An associative array of boolean limits keyed by boolean key and
   *   includes the boolean's limit, total, remaining, and status.
   */
  protected function getBooleanLimits() {
    $element = $this
      ->getElement();
    $key = $element['#webform_key'];
    $label = $element['#title'];
    $limit = $this->configuration['limit'];
    $total = $this
      ->getBooleanTotal();
    return [
      $key => $this
        ->getLimitInformation($label, $limit, $total),
    ];
  }

  /**
   * Get limit information including label, limit, total, remaining, and status.
   *
   * @param string $label
   *   The element or option label.
   * @param int $limit
   *   The limit.
   * @param int $total
   *   The total.
   *
   * @return array
   *   The limit information including label, limit, total,
   *   remaining, and status.
   */
  protected function getLimitInformation($label, $limit, $total) {
    $total = $total ?: 0;
    $remaining = $limit ? $limit - $total : 0;
    if (empty($limit) && $limit !== 0) {
      $status = WebformOptionsLimitHandlerInterface::LIMIT_STATUS_UNLIMITED;
    }
    elseif ($remaining <= 0) {
      $status = WebformOptionsLimitHandlerInterface::LIMIT_STATUS_NONE;
    }
    elseif ($remaining === 1) {
      $status = WebformOptionsLimitHandlerInterface::LIMIT_STATUS_SINGLE;
    }
    else {
      $status = WebformOptionsLimitHandlerInterface::LIMIT_STATUS_MULTIPLE;
    }
    return [
      'label' => $label,
      'limit' => $limit,
      'total' => $total,
      'remaining' => $remaining,
      'status' => $status,
    ];
  }

  /**
   * Get value array of options reached.
   *
   * @param array $limits
   *   An associative array of options limits.
   *
   * @return array
   *   A value array of disabled options.
   */
  protected function getOptionsReached(array $limits) {
    $element_key = $this->configuration['element_key'];
    $webform_submission = $this
      ->getWebformSubmission();
    $element_values = (array) $webform_submission
      ->getElementOriginalData($element_key) ?: [];
    $reached = [];
    foreach ($limits as $option_value => $limit) {
      if ($element_values && in_array($option_value, $element_values)) {
        continue;
      }
      if ($limit['status'] === WebformOptionsLimitHandlerInterface::LIMIT_STATUS_NONE) {
        $reached[$option_value] = $option_value;
      }
    }
    return $reached;
  }

  /**
   * Get options submission totals for the current webform and source entity.
   *
   * @param array $values
   *   Optional array of values to get totals.
   *
   * @return array
   *   A key/value array of options totals.
   */
  protected function getOptionsTotals(array $values = []) {
    $query = $this
      ->getTotalQuery();
    if (!$query) {
      return [];
    }
    $query
      ->addExpression('COUNT(value)', 'total');
    $query
      ->groupBy('value');
    if ($values) {
      $query
        ->condition('sd.value', $values, 'IN');
    }
    return $query
      ->execute()
      ->fetchAllKeyed();
  }

  /**
   * Get boolean submission total for the current webform and source entity.
   *
   * @return int
   *   Boolean totals.
   */
  protected function getBooleanTotal() {
    $query = $this
      ->getTotalQuery();
    if (!$query) {
      return NULL;
    }
    $query
      ->condition('sd.value', '1');
    return $query
      ->countQuery()
      ->execute()
      ->fetchField();
  }

  /**
   * Get base query for options and boolean limit totals.
   *
   * @return bool|\Drupal\Core\Database\Query\SelectInterface
   *   The base query for options and boolean limit totals.
   */
  protected function getTotalQuery() {
    $webform = $this
      ->getWebform();

    /** @var \Drupal\Core\Database\StatementInterface $result */
    $query = $this->database
      ->select('webform_submission', 's');
    $query
      ->join('webform_submission_data', 'sd', 's.sid = sd.sid');
    $query
      ->fields('sd', [
      'value',
    ]);
    $query
      ->condition('sd.name', $this->configuration['element_key']);
    $query
      ->condition('sd.webform_id', $webform
      ->id());

    // Limit by source entity.
    if ($this->configuration['limit_source_entity']) {
      $source_entity = $this
        ->getSourceEntity();
      if ($source_entity) {
        $query
          ->condition('s.entity_type', $source_entity
          ->getEntityTypeId());
        $query
          ->condition('s.entity_id', $source_entity
          ->id());
      }
      else {
        $query
          ->isNull('s.entity_type');
        $query
          ->isNull('s.entity_id');
      }
    }

    // Limit by authenticated or anonymous user.
    if ($this->configuration['limit_user']) {
      $account = \Drupal::currentUser();
      if ($account
        ->isAuthenticated()) {
        $query
          ->condition('s.uid', $account
          ->id());
      }
      else {
        $sids = $this->submissionStorage
          ->getAnonymousSubmissionIds($account);
        if ($sids) {
          $query
            ->condition('s.sid', $sids, 'IN');
          $query
            ->condition('s.uid', 0);
        }
        else {
          return FALSE;
        }
      }
    }
    return $query;
  }

  /****************************************************************************/

  // Labels and messages methods.

  /****************************************************************************/

  /**
   * Get an options or boolean element's limit status message.
   *
   * @param string $type
   *   Type of message.
   * @param array $limit
   *   Associative array containing limit, total, remaining, and label.
   *
   * @return \Drupal\Component\Render\FormattableMarkup|string
   *   A limit status message.
   */
  protected function getElementLimitStatusMessage($type, array $limit) {
    $message = $this->configuration['option_' . $type . '_message'];
    if (!$message) {
      return '';
    }
    return new FormattableMarkup($message, [
      '@name' => $this
        ->getElementLabel(),
      '@label' => $limit['label'],
      '@limit' => $limit['limit'],
      '@total' => $limit['total'],
      '@remaining' => $limit['remaining'],
    ]);
  }

  /**
   * Get option limit label.
   *
   * @param string $label
   *   An option's label.
   * @param array $limit
   *   The option's limit information.
   *
   * @return \Drupal\Core\StringTranslation\TranslatableMarkup|string
   *   An option's limit label.
   */
  protected function getOptionsLimitLabel($label, array $limit) {
    $message_display = $this->configuration['option_message_display'];
    if ($message_display === WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_NONE) {
      return $label;
    }
    $message = $this
      ->getElementLimitStatusMessage($limit['status'], $limit);
    if (!$message) {
      return $label;
    }
    switch ($message_display) {
      case WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_LABEL:
        $t_args = [
          '@label' => $label,
          '@message' => $message,
        ];
        return $this
          ->t('@label @message', $t_args);
      case WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_DESCRIPTION:
        return $label . (!WebformOptionsHelper::hasOptionDescription($label) ? WebformOptionsHelper::DESCRIPTION_DELIMITER : '') . $message;
    }
  }

}

Members

Namesort descending Modifiers Type Description Overrides
DependencySerializationTrait::$_entityStorages protected property An array of entity type IDs keyed by the property name of their storages.
DependencySerializationTrait::$_serviceIds protected property An array of service IDs keyed by property name used for serialization.
DependencySerializationTrait::__sleep public function 1
DependencySerializationTrait::__wakeup public function 2
MessengerTrait::$messenger protected property The messenger. 29
MessengerTrait::messenger public function Gets the messenger. 29
MessengerTrait::setMessenger public function Sets the messenger.
OptionsLimitWebformHandler::$database protected property The database object.
OptionsLimitWebformHandler::$elementManager protected property The webform element plugin manager.
OptionsLimitWebformHandler::$sourceEntity protected property The source entity.
OptionsLimitWebformHandler::$tokenManager protected property The webform token manager. Overrides WebformHandlerBase::$tokenManager
OptionsLimitWebformHandler::alterBooleanElement protected function Alter a boolean element's.
OptionsLimitWebformHandler::alterElement public function Alter webform element. Overrides WebformHandlerBase::alterElement
OptionsLimitWebformHandler::alterOptionsElement protected function Alter an options element.
OptionsLimitWebformHandler::alterOptionsElementLabels protected function Alter an options element's option labels recursively.
OptionsLimitWebformHandler::buildConfigurationForm public function Form constructor. Overrides WebformHandlerBase::buildConfigurationForm
OptionsLimitWebformHandler::buildSummaryTable public function Build summary table. Overrides WebformOptionsLimitHandlerInterface::buildSummaryTable
OptionsLimitWebformHandler::create public static function Creates an instance of the plugin. Overrides WebformHandlerBase::create
OptionsLimitWebformHandler::defaultConfiguration public function Gets default configuration for this plugin. Overrides WebformHandlerBase::defaultConfiguration
OptionsLimitWebformHandler::disableOptionsElement protected function Disable options element's reached options.
OptionsLimitWebformHandler::getBooleanLimits protected function Get an associative array of boolean limits.
OptionsLimitWebformHandler::getBooleanTotal protected function Get boolean submission total for the current webform and source entity.
OptionsLimitWebformHandler::getElement protected function Get element.
OptionsLimitWebformHandler::getElementLabel protected function Get selected webform element label.
OptionsLimitWebformHandler::getElementLimitStatusMessage protected function Get an options or boolean element's limit status message.
OptionsLimitWebformHandler::getElementOptions protected function Get selected element's options.
OptionsLimitWebformHandler::getElements protected function Get key/value array of webform options or boolean elements.
OptionsLimitWebformHandler::getLimitInformation protected function Get limit information including label, limit, total, remaining, and status.
OptionsLimitWebformHandler::getOptionsLimitLabel protected function Get option limit label.
OptionsLimitWebformHandler::getOptionsLimits protected function Get an associative array of options limits.
OptionsLimitWebformHandler::getOptionsReached protected function Get value array of options reached.
OptionsLimitWebformHandler::getOptionsTotals protected function Get options submission totals for the current webform and source entity.
OptionsLimitWebformHandler::getSourceEntity public function Get the webform source entity. Overrides WebformOptionsLimitHandlerInterface::getSourceEntity
OptionsLimitWebformHandler::getSummary public function Returns a render array summarizing the configuration of the webform handler. Overrides WebformHandlerBase::getSummary
OptionsLimitWebformHandler::getTableSelectElements protected function Get table select elements.
OptionsLimitWebformHandler::getTotalQuery protected function Get base query for options and boolean limit totals.
OptionsLimitWebformHandler::getWebformElement protected function Get selected webform element plugin.
OptionsLimitWebformHandler::hasAnonymousSubmissionTracking public function Determine if the webform handler requires anonymous submission tracking. Overrides WebformHandlerBase::hasAnonymousSubmissionTracking
OptionsLimitWebformHandler::isBooleanElement protected function Determine if boolean element.
OptionsLimitWebformHandler::isOptionsElement protected function Determine if options element.
OptionsLimitWebformHandler::isTableSelectElement protected function Determine if table select element.
OptionsLimitWebformHandler::removeOptionsElement protected function Remove options element's reached options.
OptionsLimitWebformHandler::removeOptionsElementRecursive protected function Remove options element's reached options.
OptionsLimitWebformHandler::setBooleanElementDefaultValue protected function Set a boolean element's default value.
OptionsLimitWebformHandler::setElementLimitReachedMessage protected function Set element's limit reached message.
OptionsLimitWebformHandler::setOptionsElementDefaultValue protected function Set an options element's default value.
OptionsLimitWebformHandler::setSourceEntity public function Set the webform source entity. Overrides WebformOptionsLimitHandlerInterface::setSourceEntity
OptionsLimitWebformHandler::submitConfigurationForm public function Form submission handler. Overrides WebformHandlerBase::submitConfigurationForm
OptionsLimitWebformHandler::submitForm public function Submit webform submission form. Overrides WebformHandlerBase::submitForm
OptionsLimitWebformHandler::validateBooleanElement public function Validate a boolean element with limit(s).
OptionsLimitWebformHandler::validateElement public static function Validate webform element limit.
OptionsLimitWebformHandler::validateOptionsElement public function Validate an options element with limit(s).
OptionsLimitWebformHandler::__construct public function Constructs a WebformHandlerBase object. Overrides WebformHandlerBase::__construct
PluginBase::$configuration protected property Configuration information passed into the plugin. 1
PluginBase::$pluginDefinition protected property The plugin implementation definition. 1
PluginBase::$pluginId protected property The plugin_id.
PluginBase::DERIVATIVE_SEPARATOR constant A string which is used to separate base plugin IDs from the derivative ID.
PluginBase::getBaseId public function Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface::getBaseId
PluginBase::getDerivativeId public function Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface::getDerivativeId
PluginBase::getPluginDefinition public function Gets the definition of the plugin implementation. Overrides PluginInspectionInterface::getPluginDefinition 3
PluginBase::getPluginId public function Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface::getPluginId
PluginBase::isConfigurable public function Determines if the plugin is configurable.
StringTranslationTrait::$stringTranslation protected property The string translation service. 1
StringTranslationTrait::formatPlural protected function Formats a string containing a count of items.
StringTranslationTrait::getNumberOfPlurals protected function Returns the number of plurals supported by a given language.
StringTranslationTrait::getStringTranslation protected function Gets the string translation service.
StringTranslationTrait::setStringTranslation public function Sets the string translation service to use. 2
StringTranslationTrait::t protected function Translates a string to the current language or to a given language.
WebformAjaxElementTrait::buildAjaxElement public function Build an Ajax element.
WebformAjaxElementTrait::buildAjaxElementTrigger public function Build an Ajax element's trigger.
WebformAjaxElementTrait::buildAjaxElementUpdate public function Build an Ajax element's update (submit) button.
WebformAjaxElementTrait::buildAjaxElementWrapper public function Build an Ajax element's wrapper.
WebformAjaxElementTrait::getAjaxElementUpdateClass public function Get Ajax element update class.
WebformAjaxElementTrait::getAjaxElementUpdateName public function Get Ajax element update name.
WebformAjaxElementTrait::getAjaxElementWrapperId public function Get Ajax element wrapper id.
WebformAjaxElementTrait::getAjaxElementWrapperRecursive protected static function Get ajax element wrapper.
WebformAjaxElementTrait::submitAjaxElementCallback public static function Ajax element submit callback. 2
WebformAjaxElementTrait::updateAjaxElementCallback public static function Ajax element update callback.
WebformAjaxElementTrait::validateAjaxElementCallback public static function Ajax element validate callback.
WebformHandlerBase::$conditions protected property The webform handler's conditions.
WebformHandlerBase::$conditionsResultCache protected property The webform handler's conditions result cache.
WebformHandlerBase::$conditionsValidator protected property The webform submission (server-side) conditions (#states) validator.
WebformHandlerBase::$configFactory protected property The configuration factory. 1
WebformHandlerBase::$handler_id protected property The webform handler ID.
WebformHandlerBase::$label protected property The webform handler label.
WebformHandlerBase::$loggerFactory protected property The logger factory.
WebformHandlerBase::$notes protected property The webform variant notes.
WebformHandlerBase::$status protected property The webform handler status.
WebformHandlerBase::$submissionStorage protected property The webform submission storage.
WebformHandlerBase::$webform protected property The webform.
WebformHandlerBase::$webformSubmission protected property The webform submission.
WebformHandlerBase::$weight protected property The weight of the webform handler.
WebformHandlerBase::access public function Controls entity operation access to webform submission. Overrides WebformHandlerInterface::access 1
WebformHandlerBase::accessElement public function Controls entity operation access to webform submission element. Overrides WebformHandlerInterface::accessElement 1
WebformHandlerBase::alterElements public function Alter webform submission webform elements. Overrides WebformHandlerInterface::alterElements 2
WebformHandlerBase::alterForm public function Alter webform submission form. Overrides WebformHandlerInterface::alterForm 3
WebformHandlerBase::applyFormStateToConfiguration protected function Apply submitted form state to configuration.
WebformHandlerBase::buildTokenTreeElement protected function Build token tree element. 2
WebformHandlerBase::cardinality public function Returns the webform handler cardinality settings. Overrides WebformHandlerInterface::cardinality
WebformHandlerBase::checkConditions public function Check handler conditions against a webform submission. Overrides WebformHandlerInterface::checkConditions
WebformHandlerBase::confirmForm public function Confirm webform submission form. Overrides WebformHandlerInterface::confirmForm 2
WebformHandlerBase::createElement public function Acts on a element after it has been created. Overrides WebformHandlerInterface::createElement 2
WebformHandlerBase::createHandler public function Acts on handler after it has been created and added to webform. Overrides WebformHandlerInterface::createHandler 2
WebformHandlerBase::deleteElement public function Acts on a element after it has been deleted. Overrides WebformHandlerInterface::deleteElement 2
WebformHandlerBase::deleteHandler public function Acts on handler after it has been removed. Overrides WebformHandlerInterface::deleteHandler 3
WebformHandlerBase::description public function Returns the webform handler description. Overrides WebformHandlerInterface::description
WebformHandlerBase::disable public function Disables the webform handler. Overrides WebformHandlerInterface::disable
WebformHandlerBase::elementTokenValidate protected function Validate form that should have tokens in it.
WebformHandlerBase::enable public function Enables the webform handler. Overrides WebformHandlerInterface::enable
WebformHandlerBase::getConditions public function Returns the conditions the webform handler. Overrides WebformHandlerInterface::getConditions
WebformHandlerBase::getConfiguration public function Gets this plugin's configuration. Overrides ConfigurableInterface::getConfiguration
WebformHandlerBase::getHandlerId public function Returns the unique ID representing the webform handler. Overrides WebformHandlerInterface::getHandlerId
WebformHandlerBase::getLabel public function Returns the label of the webform handler. Overrides WebformHandlerInterface::getLabel
WebformHandlerBase::getLogger protected function Get webform or webform_submission logger.
WebformHandlerBase::getNotes public function Returns notes of the webform variant. Overrides WebformHandlerInterface::getNotes
WebformHandlerBase::getOffCanvasWidth public function Get configuration form's off-canvas width. Overrides WebformHandlerInterface::getOffCanvasWidth 1
WebformHandlerBase::getStatus public function Returns the status of the webform handler. Overrides WebformHandlerInterface::getStatus
WebformHandlerBase::getWebform public function Get the webform that this handler is attached to. Overrides WebformHandlerInterface::getWebform
WebformHandlerBase::getWebformSubmission public function Get the webform submission that this handler is handling. Overrides WebformHandlerInterface::getWebformSubmission
WebformHandlerBase::getWeight public function Returns the weight of the webform handler. Overrides WebformHandlerInterface::getWeight
WebformHandlerBase::isApplicable public function Determine if this handle is applicable to the webform. Overrides WebformHandlerInterface::isApplicable
WebformHandlerBase::isDisabled public function Returns the webform handler disabled indicator. Overrides WebformHandlerInterface::isDisabled
WebformHandlerBase::isEnabled public function Returns the webform handler enabled indicator. Overrides WebformHandlerInterface::isEnabled 1
WebformHandlerBase::isExcluded public function Checks if the handler is excluded via webform.settings. Overrides WebformHandlerInterface::isExcluded
WebformHandlerBase::isSubmissionOptional public function Returns the webform submission is optional indicator. Overrides WebformHandlerInterface::isSubmissionOptional
WebformHandlerBase::isSubmissionRequired public function Returns the webform submission is required indicator. Overrides WebformHandlerInterface::isSubmissionRequired
WebformHandlerBase::label public function Returns the webform handler label. Overrides WebformHandlerInterface::label
WebformHandlerBase::log Deprecated protected function Log a webform handler's submission operation.
WebformHandlerBase::overrideSettings public function Alter/override a webform submission webform settings. Overrides WebformHandlerInterface::overrideSettings 3
WebformHandlerBase::postCreate public function Acts on a webform submission after it is created. Overrides WebformHandlerInterface::postCreate 2
WebformHandlerBase::postDelete public function Acts on deleted a webform submission before the delete hook is invoked. Overrides WebformHandlerInterface::postDelete 4
WebformHandlerBase::postLoad public function Acts on loaded webform submission. Overrides WebformHandlerInterface::postLoad 2
WebformHandlerBase::postPurge public function Acts on webform submissions after they are purged. Overrides WebformHandlerInterface::postPurge 1
WebformHandlerBase::postSave public function Acts on a saved webform submission before the insert or update hook is invoked. Overrides WebformHandlerInterface::postSave 5
WebformHandlerBase::preCreate public function Changes the values of an entity before it is created. Overrides WebformHandlerInterface::preCreate 2
WebformHandlerBase::preDelete public function Acts on a webform submission before they are deleted and before hooks are invoked. Overrides WebformHandlerInterface::preDelete 2
WebformHandlerBase::prepareForm public function Acts on an webform submission about to be shown on a webform submission form. Overrides WebformHandlerInterface::prepareForm
WebformHandlerBase::preprocessConfirmation public function Prepares variables for webform confirmation templates. Overrides WebformHandlerInterface::preprocessConfirmation 2
WebformHandlerBase::prePurge public function Acts on webform submissions before they are purged. Overrides WebformHandlerInterface::prePurge 1
WebformHandlerBase::preSave public function Acts on a webform submission before the presave hook is invoked. Overrides WebformHandlerInterface::preSave 2
WebformHandlerBase::replaceTokens protected function Replace tokens in text with no render context.
WebformHandlerBase::setConditions public function Sets the conditions for this webform handler. Overrides WebformHandlerInterface::setConditions
WebformHandlerBase::setConfiguration public function Sets the configuration for this plugin instance. Overrides ConfigurableInterface::setConfiguration 1
WebformHandlerBase::setHandlerId public function Sets the id for this webform handler. Overrides WebformHandlerInterface::setHandlerId
WebformHandlerBase::setLabel public function Sets the label for this webform handler. Overrides WebformHandlerInterface::setLabel
WebformHandlerBase::setNotes public function Set notes for this webform variant. Overrides WebformHandlerInterface::setNotes
WebformHandlerBase::setSettingsParents protected function Set configuration settings parents.
WebformHandlerBase::setSettingsParentsRecursively protected function Set configuration settings parents.
WebformHandlerBase::setStatus public function Sets the status for this webform handler. Overrides WebformHandlerInterface::setStatus
WebformHandlerBase::setWebform public function Set the webform that this is handler is attached to. Overrides WebformHandlerInterface::setWebform
WebformHandlerBase::setWebformSubmission public function Set the webform submission that this handler is handling. Overrides WebformHandlerInterface::setWebformSubmission
WebformHandlerBase::setWeight public function Sets the weight for this webform handler. Overrides WebformHandlerInterface::setWeight
WebformHandlerBase::supportsConditions public function Determine if webform handler supports conditions. Overrides WebformHandlerInterface::supportsConditions
WebformHandlerBase::supportsTokens public function Determine if webform handler supports tokens. Overrides WebformHandlerInterface::supportsTokens
WebformHandlerBase::updateElement public function Acts on a element after it has been updated. Overrides WebformHandlerInterface::updateElement 2
WebformHandlerBase::updateHandler public function Acts on handler after it has been updated. Overrides WebformHandlerInterface::updateHandler 3
WebformHandlerBase::validateConfigurationForm public function Form validation handler. Overrides PluginFormInterface::validateConfigurationForm 3
WebformHandlerBase::validateForm public function Validate webform submission form. Overrides WebformHandlerInterface::validateForm 2
WebformHandlerInterface::CARDINALITY_SINGLE constant Value indicating a single plugin instances are permitted.
WebformHandlerInterface::CARDINALITY_UNLIMITED constant Value indicating unlimited plugin instances are permitted.
WebformHandlerInterface::RESULTS_IGNORED constant Value indicating webform submissions are not processed (i.e. email or saved) by the handler.
WebformHandlerInterface::RESULTS_PROCESSED constant Value indicating webform submissions are processed (i.e. email or saved) by the handler.
WebformHandlerInterface::SUBMISSION_OPTIONAL constant Value indicating webform submissions do not have to be stored in the database.
WebformHandlerInterface::SUBMISSION_REQUIRED constant Value indicating webform submissions must be stored in the database.
WebformOptionsLimitHandlerInterface::DEFAULT_LIMIT constant Default option value.
WebformOptionsLimitHandlerInterface::LIMIT_ACTION_DISABLE constant Option limit action disable.
WebformOptionsLimitHandlerInterface::LIMIT_ACTION_NONE constant Option limit action none.
WebformOptionsLimitHandlerInterface::LIMIT_ACTION_REMOVE constant Option limit action remove.
WebformOptionsLimitHandlerInterface::LIMIT_STATUS_ERROR constant Option limit eror.
WebformOptionsLimitHandlerInterface::LIMIT_STATUS_MULTIPLE constant Option limit multiple remaining.
WebformOptionsLimitHandlerInterface::LIMIT_STATUS_NONE constant Option limit none remaining.
WebformOptionsLimitHandlerInterface::LIMIT_STATUS_SINGLE constant Option limit single remaining.
WebformOptionsLimitHandlerInterface::LIMIT_STATUS_UNLIMITED constant Option limit unlimited.
WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_DESCRIPTION constant Option message none.
WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_LABEL constant Option message label.
WebformOptionsLimitHandlerInterface::MESSAGE_DISPLAY_NONE constant Option message none.
WebformPluginSettingsTrait::getSetting public function
WebformPluginSettingsTrait::getSettings public function
WebformPluginSettingsTrait::setSetting public function
WebformPluginSettingsTrait::setSettings public function