acquia_vwo-1.0.x-dev/src/Form/VisibilityForm.php
src/Form/VisibilityForm.php
<?php namespace Drupal\acquia_vwo\Form; use Drupal\acquia_vwo\Service\Condition\ConditionResolver; use Drupal\Core\Config\ConfigFactoryInterface; use Drupal\Core\Config\TypedConfigManagerInterface; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Form\SubformState; use Symfony\Component\DependencyInjection\ContainerInterface; // cspell:ignore user_opt nocontrol optout optin /** * Defines Visibility settings form. */ class VisibilityForm extends ConfigFormBase { /** * The condition plugin manager. * * @var \Drupal\acquia_vwo\Service\Condition\ConditionResolver */ protected ConditionResolver $conditionResolver; /** * Constructs a ContainerForm object. * * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory * The config factory. * @param \Drupal\Core\Config\TypedConfigManagerInterface $typed_config * The typed configuration manager. * @param \Drupal\acquia_vwo\Service\Condition\ConditionResolver $condition_resolver * The Condition Resolver for building the insertion conditions. */ public function __construct( ConfigFactoryInterface $config_factory, TypedConfigManagerInterface $typed_config, ConditionResolver $condition_resolver, ) { parent::__construct($config_factory, $typed_config); $this->conditionResolver = $condition_resolver; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('config.factory'), $container->get('config.typed'), $container->get('acquia_vwo.service.condition.condition_resolver'), ); } /** * {@inheritdoc} */ public function getFormId() { return 'acquia_vwo_settings_visibility'; } /** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $form = parent::buildForm($form, $form_state); $form['enabled'] = [ '#type' => 'radios', '#title' => $this->t('VWO script'), '#description' => $this->t('The VWO scripts are added to every page by default. You can customize the scripts visibility.'), '#options' => [ 'off' => $this->t('Attach the scripts to every page'), 'on' => $this->t('Customize scripts visibility'), ], '#required' => TRUE, '#config_target' => 'acquia_vwo.settings:visibility.enabled', ]; $form['custom'] = [ '#type' => 'fieldset', '#title' => $this->t('User specific visibility settings'), '#states' => [ 'visible' => [ ':input[name=enabled]' => ['value' => 'on'], ], ], ]; $form['custom']['user'] = [ '#type' => 'radios', '#title' => $this->t('Allow individual users to opt in/out to being included in the tests.'), '#options' => [ 'nocontrol' => $this->t('Users cannot control whether or not the VWO integration is enabled.'), 'optout' => $this->t('Enabled default, but let individual users turn it off.'), 'optin' => $this->t('Disabled by default but let individual users turn it on.'), ], '#description' => $this->t('Users can view this setting when they edit their account details.'), '#config_target' => 'acquia_vwo.settings:visibility.user_control', ]; $form['conditions'] = $this->conditionsForm([], $form_state); 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('If more than one condition is set, they are treated as boolean (AND).'), '#description_display' => 'before', '#parents' => ['condition_tabs'], '#states' => [ 'visible' => [ ':input[name=enabled]' => ['value' => 'on'], ], ], ]; // Populate conditions. $config = $this->config('acquia_vwo.settings'); $conditions_config = $config->get('visibility.conditions') ?? []; $conditions = $this->conditionResolver->getConfigConditions($conditions_config); foreach ($conditions as $condition_id => $condition) { $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; } /** * {@inheritdoc} */ public function validateForm(array &$form, FormStateInterface $form_state) { $this->validateConditionsForm($form, $form_state); } /** * 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); $this->submitConditionsForm($form, $form_state); } /** * 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) { $conditions = []; 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 config. $conditions[$condition_id] = $configuration; } $config = $this->config('acquia_vwo.settings'); $config->set('visibility.conditions', $conditions)->save(); } /** * {@inheritdoc} */ protected function getEditableConfigNames() { return [ 'acquia_vwo.settings', ]; } }