google_tag-8.x-1.x-dev/src/Form/TagContainerForm.php

src/Form/TagContainerForm.php
<?php

namespace Drupal\google_tag\Form;

use Drupal\Component\Utility\Html;
use Drupal\Core\Condition\ConditionManager;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\Url;
use Drupal\google_tag\Entity\TagContainer;
use Drupal\google_tag\GoogleTagEventManager;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Defines the Google tag container settings form.
 *
 * @property \Drupal\google_tag\Entity\TagContainer $entity
 */
class TagContainerForm extends EntityForm {

  // @todo move this into something pluggable.
  use GoogleTagManagerSettingsTrait;
  /**
   * The condition plugin manager.
   *
   * @var \Drupal\Core\Condition\ConditionManager
   */
  protected ConditionManager $conditionManager;

  /**
   * Context repository.
   *
   * @var \Drupal\Core\Plugin\Context\ContextRepositoryInterface
   */
  protected ContextRepositoryInterface $contextRepository;

  /**
   * Google Tag Events Plugin Manager.
   *
   * @var \Drupal\google_tag\GoogleTagEventManager
   */
  protected GoogleTagEventManager $tagEventManager;

  /**
   * The language manager service.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected LanguageManagerInterface $languageManager;

  /**
   * Constructs a ContainerForm object.
   *
   * @param \Drupal\Core\Condition\ConditionManager $condition_manager
   *   The ConditionManager for building the insertion conditions.
   * @param \Drupal\Core\Plugin\Context\ContextRepositoryInterface $context_repository
   *   Context repository.
   * @param \Drupal\google_tag\GoogleTagEventManager $tag_event_manager
   *   Tag event manager.
   * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
   *   Language manager.
   */
  public function __construct(ConditionManager $condition_manager, ContextRepositoryInterface $context_repository, GoogleTagEventManager $tag_event_manager, LanguageManagerInterface $language_manager) {
    $this->conditionManager = $condition_manager;
    $this->contextRepository = $context_repository;
    $this->tagEventManager = $tag_event_manager;
    $this->languageManager = $language_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new self(
      $container->get('plugin.manager.condition'),
      $container->get('context.repository'),
      $container->get('plugin.manager.google_tag_event'),
      $container->get('language_manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function form(array $form, FormStateInterface $form_state) {
    $form = parent::form($form, $form_state);
    $form['#id'] = Html::getId($form_state->getBuildInfo()['form_id']);

    // Store the gathered contexts in the form state for other objects to use
    // during form building.
    $form_state->setTemporaryValue('gathered_contexts', $this->contextRepository->getAvailableContexts());

    $accounts_wrapper_id = Html::getUniqueId('accounts-add-more-wrapper');
    $form['accounts_wrapper'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Google Tag ID(s)'),
      '#prefix' => '<div id="' . $accounts_wrapper_id . '">',
      '#description' => $this->t('This ID is unique to each site you want to track separately, and is in the form of UA-xxxxx-yy, G-xxxxxxxx, AW-xxxxxxxxx, or DC-xxxxxxxx. To get a Web Property ID, <a href=":analytics">register your site with Google Analytics</a>, or if you already have registered your site, go to your Google Analytics Settings page to see the ID next to every site profile. <a href=":webpropertyid">Find more information in the documentation</a>.', [
        ':analytics' => 'https://marketingplatform.google.com/about/analytics/',
        ':webpropertyid' => Url::fromUri('https://developers.google.com/analytics/resources/concepts/gaConceptsAccounts', ['fragment' => 'webProperty'])->toString(),
      ]),
      '#suffix' => '</div>',
    ];
    // Filter order (tabledrag).
    $form['accounts_wrapper']['accounts'] = [
      '#input' => FALSE,
      '#tree' => TRUE,
      '#type' => 'table',
      '#tabledrag' => [
        [
          'action' => 'order',
          'relationship' => 'sibling',
          'group' => 'account-order-weight',
        ],
      ],
    ];

    $accounts = $form_state->getValue('accounts', []);
    if ($accounts === []) {
      $entity_accounts = $this->entity->get('tag_container_ids');
      foreach ($entity_accounts as $index => $account) {
        $accounts[$index]['value'] = $account;
        $accounts[$index]['weight'] = $index;
      }
      // Default fallback.
      if (count($accounts) === 0) {
        $accounts[] = ['value' => '', 'weight' => 0];
      }
    }

    foreach ($accounts as $index => $account) {
      $form['accounts_wrapper']['accounts'][$index]['#attributes']['class'][] = 'draggable';
      $form['accounts_wrapper']['accounts'][$index]['#weight'] = $account['weight'];
      $form['accounts_wrapper']['accounts'][$index]['value'] = [
        '#default_value' => (string) ($account['value'] ?? ''),
        '#maxlength' => 20,
        '#required' => (count($accounts) === 1),
        '#size' => 20,
        '#type' => 'textfield',
        '#pattern' => TagContainer::GOOGLE_TAG_MATCH,
        '#ajax' => [
          'callback' => [self::class, 'storeGtagAccountsCallback'],
          'disable-refocus' => TRUE,
          'event' => 'change',
          'wrapper' => 'advanced-settings-wrapper',
        ],
        '#attributes' => [
          'data-disable-refocus' => 'true',
        ],
      ];

      $form['accounts_wrapper']['accounts'][$index]['weight'] = [
        '#type' => 'weight',
        '#title' => $this->t('Weight for @title', ['@title' => (string) ($account['value'] ?? '')]),
        '#title_display' => 'invisible',
        '#delta' => 50,
        '#default_value' => $index,
        '#parents' => ['accounts', $index, 'weight'],
        '#attributes' => ['class' => ['account-order-weight']],
      ];

      // If there is more than one id, add the remove button.
      if (count($accounts) > 1) {
        $form['accounts_wrapper']['accounts'][$index]['remove'] = [
          '#type' => 'submit',
          '#value' => $this->t('Remove'),
          '#name' => 'remove_gtag_id_' . $index,
          '#parameter_index' => $index,
          '#limit_validation_errors' => [
            ['accounts'],
          ],
          '#submit' => [
            [self::class, 'removeGtagCallback'],
          ],
          '#ajax' => [
            'callback' => [self::class, 'gtagFormCallback'],
            'wrapper' => $form['#id'],
          ],
        ];
      }
    }

    $id_prefix = implode('-', ['accounts_wrapper', 'accounts']);
    // Add blank account.
    $form['accounts_wrapper']['add_gtag_id'] = [
      '#type' => 'submit',
      '#value' => $this->t('Add another ID'),
      '#name' => str_replace('-', '_', $id_prefix) . '_add_gtag_id',
      '#submit' => [
        [self::class, 'addGtagCallback'],
      ],
      '#ajax' => [
        'callback' => [self::class, 'ajaxRefreshAccounts'],
        'wrapper' => $accounts_wrapper_id,
        'effect' => 'fade',
      ],
    ];

    $dimensions_metrics_wrapper_id = Html::getUniqueId('metrics-dimensions-add-more-wrapper');
    $form['dimensions_metrics_wrapper'] = [
      '#type' => 'fieldset',
      '#title' => $this->t('Custom dimensions and metrics'),
      '#prefix' => '<div id="' . $dimensions_metrics_wrapper_id . '">',
      '#suffix' => '</div>',
    ];
    $form['dimensions_metrics_wrapper']['dimensions_metrics'] = [
      '#input' => FALSE,
      '#tree' => TRUE,
      '#type' => 'table',
      '#header' => [
        ['data' => $this->t('Type')],
        ['data' => $this->t('Name')],
        ['data' => $this->t('Value')],
        ['data' => $this->t('Remove')],
      ],
      '#empty' => $this->t('No custom dimensions or metrics added.'),
      '#rows' => [],
    ];

    $token_exists = $this->moduleHandler->moduleExists('token');
    $dimensions_metrics = $form_state->getValue('dimensions_metrics', $this->entity->getDimensionsAndMetrics());
    foreach ($dimensions_metrics as $index => $item) {
      $form['dimensions_metrics_wrapper']['dimensions_metrics'][$index]['type'] = [
        '#type' => 'select',
        '#title' => $this->t('Type for parameter #@index', ['@index' => $index]),
        '#title_display' => 'invisible',
        '#options' => [
          'dimension' => $this->t('Dimension'),
          'metric' => $this->t('Metric'),
        ],
        '#default_value' => $item['type'],
        '#disabled' => TRUE,
      ];
      $form['dimensions_metrics_wrapper']['dimensions_metrics'][$index]['name'] = [
        '#type' => 'textfield',
        '#title' => $this->t('Name for parameter #@index', ['@index' => $index]),
        '#title_display' => 'invisible',
        '#maxlength' => 255,
        '#default_value' => $item['name'],
      ];
      $form['dimensions_metrics_wrapper']['dimensions_metrics'][$index]['value'] = [
        '#type' => 'textfield',
        '#title' => $this->t('Value for parameter #@index', ['@index' => $index]),
        '#title_display' => 'invisible',
        '#maxlength' => 255,
        '#default_value' => $item['value'],
      ];
      if ($token_exists) {
        $form['dimensions_metrics_wrapper']['dimensions_metrics'][$index]['value']['#element_validate'] = [
          'token_element_validate',
        ];
      }
      $form['dimensions_metrics_wrapper']['dimensions_metrics'][$index]['remove'] = [
        '#type' => 'submit',
        '#value' => $this->t('Remove'),
        '#name' => 'remove_parameter' . $index,
        '#parameter_index' => $index,
        '#limit_validation_errors' => [
          ['dimensions_metrics'],
        ],
        '#submit' => [
          [self::class, 'removeDimensionMetric'],
        ],
        '#ajax' => [
          'callback' => [self::class, 'ajaxRefreshMetricsDimensions'],
          'wrapper' => $dimensions_metrics_wrapper_id,
        ],
      ];
    }
    $form['dimensions_metrics_wrapper']['new_dimensions_metrics'] = [
      '#type' => 'container',
      '#attributes' => [
        'class' => ['container-inline'],
      ],
      'new_metric_dimension_type' => [
        '#type' => 'select',
        '#options' => [
          'dimension' => $this->t('Dimension'),
          'metric' => $this->t('Metric'),
        ],
        '#title' => $this->t('New parameter type'),
        '#title_display' => 'invisible',
        '#empty_option' => t('- Select -'),
        '#empty_value' => '',
      ],
      'new_metric_dimension_submit' => [
        '#type' => 'submit',
        '#value' => $this->t('Add new parameter'),
        '#submit' => [
          [self::class, 'addNewDimensionMetric'],
        ],
        '#ajax' => [
          'callback' => [self::class, 'ajaxRefreshMetricsDimensions'],
          'wrapper' => $dimensions_metrics_wrapper_id,
        ],
      ],
    ];
    if ($token_exists) {
      $form['dimensions_metrics_wrapper']['token_tree'] = [
        '#theme' => 'token_tree_link',
        '#token_types' => ['node'],
      ];
    }

    $form['events_settings'] = $this->getEventSettings([], $form_state);

    $form['conditions'] = $this->conditionsForm([], $form_state);

    $form['advanced_settings'] = $this->getAdvancedSettings([], $form_state, $accounts);

    $form['status'] = [
      '#type' => 'checkbox',
      '#title' => 'Enabled',
      '#default_value' => $this->entity->status(),
      '#description' => 'Check this checkbox to enable Tag Container.',
    ];

    return $form;
  }

  /**
   * Builds form elements for event plugin configuration.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @return array
   *   The augmented form array with the insertion condition elements.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  protected function getEventSettings(array $form, FormStateInterface $form_state) {
    $form['#tree'] = TRUE;
    $form['events_tabs'] = [
      '#type' => 'vertical_tabs',
      '#title' => $this->t('Events'),
      '#description' => $this->t('Events which will be sent to GA.'),
      '#description_display' => 'before',
      '#parents' => ['events_tabs'],
    ];
    $events = $this->entity->get('events');
    $event_definitions = $this->tagEventManager->getDefinitions();

    foreach ($event_definitions as $event_id => $definition) {
      $event_config = $events[$event_id] ?? [];
      $event_plugin = $this->tagEventManager->createInstance($event_id, $event_config);
      $form[$event_id] = [
        '#type' => 'details',
        '#title' => $definition['label'],
        '#group' => 'events_tabs',
      ];
      $form[$event_id]['enabled'] = [
        '#type' => 'checkbox',
        '#title' => $this->t('Enable event :label', [':label' => $definition['label']]),
        '#default_value' => isset($events[$event_id]) || $this->entity->isNew(),
        '#parameter_index' => $event_id,
      ];
      if ($event_plugin instanceof PluginFormInterface) {
        $form_state->set(['events', $event_id], $event_plugin);
        $form[$event_id]['event_form'] = $event_plugin->buildConfigurationForm([], $form_state);
        $form[$event_id]['event_form']['#type'] = 'fieldset';
        $selector = 'events_settings[' . $event_id . '][enabled]';
        $states = [
          'visible' => [
            ':input[name="' . $selector . '"]' => ['checked' => TRUE],
          ],
        ];
        $form[$event_id]['event_form']['#states'] = $states;
      }
    }
    return $form;
  }

  /**
   * Builds the form elements for the insertion conditions.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @return array
   *   The augmented form array with the insertion condition elements.
   */
  protected function conditionsForm(array $form, FormStateInterface $form_state): array {
    $form['#tree'] = TRUE;
    $form['condition_tabs'] = [
      '#type' => 'vertical_tabs',
      '#title' => $this->t('Conditions'),
      '#description' => $this->t('Conditions in which the tag will be processed on a request.'),
      '#description_display' => 'before',
      '#parents' => ['condition_tabs'],
    ];
    /** @var array<string, array<string, mixed>> $conditions */
    $conditions = $this->entity->get('conditions');
    $definitions = $this->conditionManager->getFilteredDefinitions(
      'google_tag',
      $form_state->getTemporaryValue('gathered_contexts')
    );
    foreach (array_keys($definitions) as $condition_id) {
      // Don't display the current theme condition.
      if ($condition_id === 'current_theme') {
        continue;
      }
      // Don't display the language condition until we have multiple languages.
      if ($condition_id === 'language' && !$this->languageManager->isMultilingual()) {
        continue;
      }

      /** @var \Drupal\Core\Condition\ConditionInterface $condition */
      $condition = $this->conditionManager->createInstance($condition_id, $conditions[$condition_id] ?? []);
      $form_state->set(['conditions', $condition_id], $condition);
      $condition_form = $condition->buildConfigurationForm([], $form_state);
      $condition_form['#type'] = 'details';
      $condition_form['#title'] = $condition->getPluginDefinition()['label'];
      $condition_form['#group'] = 'condition_tabs';
      $form[$condition_id] = $condition_form;
    }

    return $form;
  }

  /**
   * Builds form elements for advanced settings configuration.
   *
   * Currently, only Google Tag Manager has advanced settings. However, this
   * form could be used to add Google Tag / GA / etc options as well.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   * @param array $accounts
   *   A keyed array containing the all the gtag accounts for the container.
   *
   * @return array
   *   The augmented form array with the insertion condition elements.
   */
  protected function getAdvancedSettings(array $form, FormStateInterface $form_state, array $accounts) {
    // Advanced Settings. These are specific settings per ID.
    $advanced_settings = [
      '#type' => 'fieldset',
      '#title' => $this->t('Advanced settings'),
      '#description' => $this->t('The settings affecting the snippet contents for this container.'),
      '#attributes' => ['class' => ['google-tag']],
      '#prefix' => '<div id="advanced-settings-wrapper">',
      '#suffix' => '</div>',
      '#open' => FALSE,
      '#tree' => TRUE,
    ];
    // Allow disabling of consent options when using non Ads tags.
    $advanced_settings['consent_mode'] = [
      '#type' => 'checkbox',
      '#title' => $this->t('Enforce Privacy Consent Policy'),
      '#description' => $this->t("In certain countries and for certain tags (Ads), user consent is required before sending any data. Please review this  <a href='https://www.google.com/about/company/user-consent-policy-help/'>Google FAQ</a> before disabling."),
      '#default_value' => !empty($this->entity->get('advanced_settings')['consent_mode']),
    ];

    // Only show Advanced GTM settings if one of the IDs belong to GTM.
    $gtm_ids = array_slice(
      array_filter(
        $accounts,
        static fn ($id) => preg_match(TagContainer::GOOGLE_TAG_MANAGER_MATCH, $id['value'])
      ),
      0);

    // Add processing / ajax input and append it to the form.
    foreach ($gtm_ids as $gtm_id) {
      $advanced_settings_data = $this->entity->getGtmSettings($gtm_id['value']);
      $advanced_settings['gtm'][$gtm_id['value']] = $this->gtmAdvancedFieldset($advanced_settings_data, $gtm_id['value']);
    }

    return $advanced_settings;
  }

  /**
   * {@inheritdoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {
    $this->validateGtmFormValues($form, $form_state);
    $this->validateConditionsForm($form, $form_state);

    $this->buildEntity($form, $form_state);

    $this->validateEventsForm($form, $form_state);
  }

  /**
   * Form validation handler for the event plugins.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  protected function validateEventsForm(array $form, FormStateInterface $form_state) {
    $events = $form_state->getValue('events_settings');
    $events = array_filter($events, static function (array $event) {
      return (int) $event['enabled'] === 1;
    });
    foreach (array_keys($events) as $event_id) {
      /** @var \Drupal\Core\Plugin\PluginFormInterface $configurable_event */
      if ($configurable_event = $form_state->get(['events', $event_id])) {
        $configurable_event->validateConfigurationForm($form['events_settings'][$event_id]['event_form'], SubformState::createForSubform($form['events_settings'][$event_id]['event_form'], $form, $form_state));
      }
    }
  }

  /**
   * Form submission handler for the event plugins.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   *
   * @throws \Drupal\Component\Plugin\Exception\PluginException
   */
  protected function submitEventsForm(array $form, FormStateInterface $form_state) {
    $events = $form_state->getValue('events_settings');
    $events = array_filter($events, static function (array $event) {
      return (int) $event['enabled'] === 1;
    });
    $event_data = [];
    foreach (array_keys($events) as $event_id) {
      if ($event_plugin = $form_state->get(['events', $event_id])) {
        $event_plugin->submitConfigurationForm($form['events_settings'][$event_id]['event_form'], SubformState::createForSubform($form['events_settings'][$event_id]['event_form'], $form, $form_state));
      }
      else {
        /** @var \Drupal\google_tag\Plugin\GoogleTag\Event\GoogleTagEventInterface $event_plugin */
        $event_plugin = $this->tagEventManager->createInstance($event_id);
      }
      $event_data[$event_id] = $event_plugin->getConfiguration();
    }
    $this->entity->set('events', $event_data);
  }

  /**
   * Form validation handler for the insertion conditions.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  protected function validateConditionsForm(array $form, FormStateInterface $form_state) {
    // Validate visibility condition settings.
    foreach ($form_state->getValue('conditions') as $condition_id => $values) {
      // All condition plugins use 'negate' as a Boolean in their schema.
      // However, certain form elements may return it as 0/1. Cast here to
      // ensure the data is in the expected type.
      if (array_key_exists('negate', $values)) {
        $form_state->setValue(['conditions', $condition_id, 'negate'], (bool) $values['negate']);
      }
      /** @var \Drupal\Core\Condition\ConditionInterface $condition */
      $condition = $form_state->get(['conditions', $condition_id]);
      $condition->validateConfigurationForm($form['conditions'][$condition_id], SubformState::createForSubform($form['conditions'][$condition_id], $form, $form_state));
    }
  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {
    parent::submitForm($form, $form_state);

    $default_id = '';
    // No need to fetch again from entity,
    // ids should already be available in form state values now.
    $tag_container_ids = [];
    foreach ($form_state->getValue('accounts') as $account) {
      if (!$default_id) {
        $default_id = $account['value'];
      }
      $tag_container_ids[$account['weight']] = $account['value'];
    }
    // Need to save tags without weights otherwise it doesn't show up on UI.
    $this->entity->set('tag_container_ids', array_values($tag_container_ids));

    if ($this->entity->id() === NULL) {
      // Set the ID and Label based on the first Google Tag.
      $config_id = uniqid($default_id . '.', TRUE);
      $this->entity->setOriginalId($config_id);
      $this->entity->set('id', $config_id);
      $this->entity->set('label', $default_id);
    }

    $this->submitConditionsForm($form, $form_state);
    $this->submitEventsForm($form, $form_state);

    // Save config entity a first time so that the conditions form can be
    // properly filtered.
    // @see https://www.drupal.org/project/google_tag/issues/3345719#comment-15009415
    // @see BlockForm::submitForm()
    // The fix on https://www.drupal.org/project/google_tag/issues/3357105
    // may not be necessary, but as BlockForm::submitForm() is still
    // doing we are leaving it for now.
    $this->entity->save();

    $this->messenger()->addStatus($this->t('The configuration options have been saved.'));

    // Redirect to collection page.
    $form_state->setRedirect('entity.google_tag_container.single_form');
  }

  /**
   * {@inheritDoc}
   */
  public function save(array $form, FormStateInterface $form_state) {
    $result = parent::save($form, $form_state);
    // Store the resulting entity ID in the global Google tag settings.
    $config = $this->configFactory()->getEditable('google_tag.settings');
    $config->set('default_google_tag_entity', $this->entity->id())->save();
    return $result;
  }

  /**
   * Form submission handler for the insertion conditions.
   *
   * @param array $form
   *   An associative array containing the structure of the form.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
   */
  protected function submitConditionsForm(array $form, FormStateInterface $form_state) {
    foreach ($form_state->getValue('conditions') as $condition_id => $values) {
      /** @var \Drupal\Core\Condition\ConditionInterface $condition */
      $condition = $form_state->get(['conditions', $condition_id]);
      $condition->submitConfigurationForm($form['conditions'][$condition_id], SubformState::createForSubform($form['conditions'][$condition_id], $form, $form_state));
      $configuration = $condition->getConfiguration();

      // Due to strict type checking, cast negation to a boolean.
      $configuration['negate'] = (bool) (array_key_exists('negate', $configuration) ? $configuration['negate'] : FALSE);

      // Update the insertion conditions on the container.
      $this->entity->getInsertionConditions()->addInstanceId($condition_id, $configuration);
    }
  }

  /**
   * Callback for both ajax account buttons.
   *
   * Selects and returns the fieldset with the names in it.
   */
  public static function gtagFormCallback(array &$form, FormStateInterface $form_state) {
    return $form;
  }

  /**
   * Submit handler for the "remove one" button.
   *
   * Decrements the max counter and causes a form rebuild.
   */
  public static function removeGtagCallback(array &$form, FormStateInterface $form_state) {
    $triggering_element = $form_state->getTriggeringElement();
    $index = $triggering_element['#parameter_index'];
    $accounts = $form_state->getValue('accounts', []);
    unset($accounts[$index]);
    $form_state->setValue('accounts', $accounts);
    $form_state->setRebuild();
  }

  /**
   * Submit handler for the "add-one-more" button.
   *
   * Increments the max counter and causes a rebuild.
   */
  public static function addGtagCallback(array &$form, FormStateInterface $form_state) {
    $accounts = $form_state->getValue('accounts', []);
    $accounts[] = [
      'value' => '',
      'weight' => count($accounts),
    ];
    $form_state->setValue('accounts', $accounts);
    $form_state->setRebuild();
  }

  /**
   * Submit handler for the "add-one-more" button.
   *
   * Increments the max counter and causes a rebuild.
   */
  public static function storeGtagAccountsCallback(array &$form, FormStateInterface $form_state) {
    // Update Advanced Settings Form.
    return $form['advanced_settings'];
  }

  /**
   * Ajax handler for removing dimension metric.
   *
   * @param array $form
   *   Form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   */
  public static function removeDimensionMetric(array $form, FormStateInterface $form_state) {
    $triggering_element = $form_state->getTriggeringElement();
    $index = $triggering_element['#parameter_index'];
    $dimensions_metrics = $form_state->getValue('dimensions_metrics', []);
    unset($dimensions_metrics[$index]);
    $form_state->setValue('dimensions_metrics', $dimensions_metrics);
    $form_state->setRebuild();
  }

  /**
   * Ajax handler for adding dimension metric.
   *
   * @param array $form
   *   Form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   */
  public static function addNewDimensionMetric(array $form, FormStateInterface $form_state) {
    $dimensions_metrics = $form_state->getValue('dimensions_metrics', []);
    $dimensions_metrics[] = [
      'type' => $form_state->getValue('new_metric_dimension_type'),
      'name' => '',
      'value' => '',
    ];
    $form_state->setValue('dimensions_metrics', $dimensions_metrics);
    $form_state->setRebuild();
  }

  /**
   * Ajax handler for refreshing the form metrics wrapper after metrics change.
   *
   * @param array $form
   *   Form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   *
   * @return mixed
   *   Metrics wrapper.
   */
  public static function ajaxRefreshMetricsDimensions(array $form, FormStateInterface $form_state) {
    return $form['dimensions_metrics_wrapper'];
  }

  /**
   * Callback for add more gtag accounts.
   *
   * @param array $form
   *   Form array.
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   Form state.
   *
   * @return mixed
   *   Accounts wrapper.
   */
  public static function ajaxRefreshAccounts(array $form, FormStateInterface $form_state) {
    return $form['accounts_wrapper'];
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc