acquia_vwo-1.0.x-dev/src/Form/VisibilityForm.php
src/Form/VisibilityForm.php
<?php
namespace Drupal\acquia_vwo\Form;
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 Drupal\acquia_vwo\Service\Condition\ConditionResolver;
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',
];
}
}
