View source  
  <?php
namespace Drupal\theme_switcher\Form;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Executable\ExecutableManagerInterface;
use Drupal\Core\Extension\ThemeHandlerInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Plugin\Context\ContextRepositoryInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ThemeSwitcherRuleForm extends EntityForm {
  
  protected $messenger;
  
  protected $logger;
  
  protected $themeHandler;
  
  protected $conditionPluginManager;
  
  protected $contextRepository;
  
  protected $languageManager;
  
  public function __construct(MessengerInterface $messenger, LoggerChannelInterface $logger, ThemeHandlerInterface $theme_handler, ExecutableManagerInterface $condition_plugin_manager, ContextRepositoryInterface $context_repository, LanguageManagerInterface $language_manager) {
    $this->messenger = $messenger;
    $this->logger = $logger;
    $this->themeHandler = $theme_handler;
    $this->conditionPluginManager = $condition_plugin_manager;
    $this->contextRepository = $context_repository;
    $this->languageManager = $language_manager;
  }
  
  public static function create(ContainerInterface $container) {
    return new static($container
      ->get('messenger'), $container
      ->get('logger.factory')
      ->get('theme_switcher'), $container
      ->get('theme_handler'), $container
      ->get('plugin.manager.condition'), $container
      ->get('context.repository'), $container
      ->get('language_manager'));
  }
  
  public function form(array $form, FormStateInterface $form_state) {
    $available_contexts = $this->contextRepository
      ->getAvailableContexts();
    $form_state
      ->setTemporaryValue('gathered_contexts', $available_contexts);
    
    $entity = $this->entity;
    $form['#tree'] = TRUE;
    $form['label'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Theme Switcher Rule'),
      '#maxlength' => 255,
      '#default_value' => $entity
        ->label(),
      '#description' => $this
        ->t('The human-readable name is shown in the Theme Switcher list.'),
      '#required' => TRUE,
    ];
    $form['id'] = [
      '#type' => 'machine_name',
      '#default_value' => $entity
        ->id(),
      '#machine_name' => [
        'source' => [
          'label',
        ],
        'exists' => [
          $this,
          'exist',
        ],
      ],
      '#disabled' => !$entity
        ->isNew(),
    ];
    $form['status'] = [
      '#type' => 'radios',
      '#title' => $this
        ->t('Theme Switcher Rule status'),
      '#options' => [
        1 => $this
          ->t('Active'),
        0 => $this
          ->t('Inactive'),
      ],
      '#default_value' => (int) $entity
        ->status(),
      '#description' => $this
        ->t('The Theme Switcher Rule will only work if the active option is set.'),
    ];
    $form['weight'] = [
      '#type' => 'weight',
      '#title' => $this
        ->t('Weight'),
      '#access' => FALSE,
      '#default_value' => $entity
        ->getWeight(),
      '#description' => $this
        ->t('The sort order for this record. Lower values display first.'),
    ];
    $form['theme'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Theme'),
      '#description' => $this
        ->t('The theme to apply in all pages that meet the conditions below.'),
      '#options' => $this
        ->getThemeOptions(),
      '#default_value' => $entity
        ->getTheme() ?? '',
      '#required' => TRUE,
    ];
    $form['admin_theme'] = [
      '#type' => 'select',
      '#title' => $this
        ->t('Admin Theme'),
      '#description' => $this
        ->t('The theme to apply in just the admin pages that meet the conditions below.'),
      '#options' => $this
        ->getThemeOptions(),
      '#default_value' => $entity
        ->getAdminTheme() ?? '',
    ];
    
    $form['visibility'] = [
      'visibility_tabs' => [
        '#type' => 'vertical_tabs',
        '#title' => $this
          ->t('Conditions'),
        '#parents' => [
          'visibility_tabs',
        ],
      ],
    ];
    $visibility = $entity
      ->getVisibility();
    $definitions = $this->conditionPluginManager
      ->getFilteredDefinitions('theme_switcher_ui', $form_state
      ->getTemporaryValue('gathered_contexts'), [
      'theme_switcher_rule' => $entity,
    ]);
    
    $this->moduleHandler
      ->alter('available_conditions', $definitions);
    foreach ($definitions as $condition_id => $definition) {
      
      $condition = $this->conditionPluginManager
        ->createInstance($condition_id, $visibility[$condition_id] ?? []);
      $form_state
        ->set([
        'conditions',
        $condition_id,
      ], $condition);
      $condition_form = $condition
        ->buildConfigurationForm([], $form_state);
      $form['visibility'][$condition_id] = [
        '#type' => 'details',
        '#title' => $condition
          ->getPluginDefinition()['label'],
        '#group' => 'visibility_tabs',
      ] + $condition_form;
    }
    return $form;
  }
  
  public function submitForm(array &$form, FormStateInterface $form_state) {
    parent::submitForm($form, $form_state);
    
    $entity = $this->entity;
    foreach ($form_state
      ->getValue('visibility') as $condition_id => $values) {
      
      $condition = $form_state
        ->get([
        'conditions',
        $condition_id,
      ]);
      $subform = SubformState::createForSubform($form['visibility'][$condition_id], $form, $form_state);
      $condition
        ->submitConfigurationForm($form['visibility'][$condition_id], $subform);
      
      $entity
        ->getVisibilityConditions()
        ->addInstanceId($condition_id, $condition
        ->getConfiguration());
    }
    
    $status = $entity
      ->save();
    $message = $this
      ->t("The Theme Switcher Rule '%label' has been %op.", [
      '%label' => $entity
        ->label(),
      '%op' => $status == SAVED_NEW ? 'created' : 'updated',
    ]);
    $this->messenger
      ->addStatus($message);
    $this->logger
      ->notice($message);
    $form_state
      ->setRedirect('theme_switcher.admin');
  }
  
  public function validateForm(array &$form, FormStateInterface $form_state) {
    parent::validateForm($form, $form_state);
    
    $form_state
      ->setValue('weight', (int) $form_state
      ->getValue('weight'));
    
    foreach ($form_state
      ->getValue('visibility') as $condition_id => $values) {
      
      if (array_key_exists('negate', $values)) {
        $form_state
          ->setValue([
          'visibility',
          $condition_id,
          'negate',
        ], (bool) $values['negate']);
      }
      
      $condition = $form_state
        ->get([
        'conditions',
        $condition_id,
      ]);
      $subform = SubformState::createForSubform($form['visibility'][$condition_id], $form, $form_state);
      $condition
        ->validateConfigurationForm($form['visibility'][$condition_id], $subform);
    }
  }
  
  protected function getThemeOptions() {
    $output[''] = '- None -';
    foreach ($this->themeHandler
      ->listInfo() as $key => $value) {
      $output[$key] = $value
        ->getName();
    }
    return $output;
  }
  
  public function exist($id) {
    $entity = $this->entityTypeManager
      ->getStorage('theme_switcher_rule')
      ->getQuery()
      ->condition('id', $id)
      ->execute();
    return (bool) $entity;
  }
}