View source  
  <?php
namespace Drupal\openid_connect\Form;
use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Language\LanguageInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Link;
use Drupal\Core\Plugin\PluginFormFactoryInterface;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Core\Plugin\PluginWithFormsInterface;
use Drupal\Core\Url;
use Drupal\openid_connect\Plugin\OpenIDConnectClientInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
abstract class OpenIDConnectClientFormBase extends EntityForm {
  
  protected $pluginFormFactory;
  
  protected $languageManager;
  
  public function __construct(PluginFormFactoryInterface $plugin_form_manager, LanguageManagerInterface $language_manager) {
    $this->pluginFormFactory = $plugin_form_manager;
    $this->languageManager = $language_manager;
  }
  
  public static function create(ContainerInterface $container) : OpenIDConnectClientFormBase {
    return new static($container
      ->get('plugin_form.factory'), $container
      ->get('language_manager'));
  }
  
  public function buildForm(array $form, FormStateInterface $form_state) : array {
    $form = parent::buildForm($form, $form_state);
    
    $entity = $this->entity;
    $form['#tree'] = TRUE;
    $form['label'] = [
      '#type' => 'textfield',
      '#title' => $this
        ->t('Name'),
      '#maxlength' => 255,
      '#default_value' => $entity
        ->label(),
      '#required' => TRUE,
    ];
    
    if ($entity
      ->isNew()) {
      $form['label']['#ajax'] = [
        'callback' => '::changeRedirectUrl',
        'event' => 'focusout',
        'disable-refocus' => TRUE,
        'wrapper' => 'redirect-url-value',
      ];
    }
    $form['id'] = [
      '#type' => 'machine_name',
      '#title' => $this
        ->t('Machine name'),
      '#default_value' => $entity
        ->id(),
      '#machine_name' => [
        'exists' => [
          $this,
          'exists',
        ],
        'replace_pattern' => '([^a-z0-9_]+)|(^custom$)',
        'error' => 'The machine-readable name must be unique, and can only contain lowercase letters, numbers, and underscores. Additionally, it can not be the reserved word "custom".',
      ],
      '#disabled' => !$entity
        ->isNew(),
    ];
    $form['settings'] = [];
    $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
    $form['settings'] = $this
      ->getPluginForm($entity
      ->getPlugin())
      ->buildConfigurationForm($form['settings'], $subform_state);
    $form['redirect_url'] = [
      '#title' => $this
        ->t('Redirect URL'),
      '#type' => 'item',
      '#markup' => '<div id="redirect-url-value">' . $this
        ->getRedirectUrl($entity
        ->id()) . '</div>',
    ];
    return $form;
  }
  
  public function exists($entity_id, array $element, FormStateInterface $form_state) : bool {
    $result = $this->entityTypeManager
      ->getStorage('openid_connect_client')
      ->getQuery()
      ->condition('id', $element['#field_prefix'] . $entity_id)
      ->execute();
    return (bool) $result;
  }
  
  public function validateForm(array &$form, FormStateInterface $form_state) {
    
    try {
      
      $entity = $this->entity;
      $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
      $this
        ->getPluginForm($entity
        ->getPlugin())
        ->validateConfigurationForm($form['settings'], $subform_state);
    } catch (InvalidPluginDefinitionException $e) {
    }
  }
  
  public function submitForm(array &$form, FormStateInterface $form_state) {
    parent::submitForm($form, $form_state);
    
    $values = $form_state
      ->getValues()['settings'];
    $this->entity
      ->set('settings', $values);
    
    try {
      
      $entity = $this->entity;
      $subform_state = SubformState::createForSubform($form['settings'], $form, $form_state);
      $this
        ->getPluginForm($entity
        ->getPlugin())
        ->submitConfigurationForm($form, $subform_state);
    } catch (InvalidPluginDefinitionException $e) {
    }
  }
  
  public function save(array $form, FormStateInterface $form_state) : int {
    $status = parent::save($form, $form_state);
    
    $entity = $this->entity;
    
    $edit_link = Link::fromTextAndUrl($this
      ->t('Edit'), $entity
      ->toUrl())
      ->toString();
    if ($status === SAVED_UPDATED) {
      
      $this
        ->messenger()
        ->addMessage($this
        ->t('OpenID Connect client %label has been updated.', [
        '%label' => $entity
          ->label(),
      ]));
      $this
        ->logger('openid_connect')
        ->notice('OpenID Connect client %label has been updated.', [
        '%label' => $entity
          ->label(),
        'alink' => $edit_link,
      ]);
    }
    else {
      
      $this
        ->messenger()
        ->addMessage($this
        ->t('OpenID Connect client %label has been added.', [
        '%label' => $entity
          ->label(),
      ]));
      $this
        ->logger('openid_connect')
        ->notice('OpenID Connect client %label has been added.', [
        '%label' => $entity
          ->label(),
        'alink' => $edit_link,
      ]);
    }
    $form_state
      ->setRedirect('entity.openid_connect_client.list');
    return $status;
  }
  
  protected function getPluginForm(OpenIDConnectClientInterface $openid_client) : ?PluginFormInterface {
    if ($openid_client instanceof PluginWithFormsInterface) {
      return $this->pluginFormFactory
        ->createInstance($openid_client, 'configure');
    }
    return NULL;
  }
  
  public function getRedirectUrl($id = '') : string {
    if ($id) {
      $route_parameters = [
        'openid_connect_client' => $id,
      ];
      return Url::fromRoute('openid_connect.redirect_controller_redirect', $route_parameters, [
        'absolute' => TRUE,
        'language' => $this->languageManager
          ->getLanguage(LanguageInterface::LANGCODE_NOT_APPLICABLE),
      ])
        ->toString();
    }
    return $this
      ->t('Pending name input');
  }
  
  public function changeRedirectUrl(array &$form, FormStateInterface $form_state) : array {
    return [
      '#markup' => '<div id="redirect-url-value">' . $this
        ->getRedirectUrl($form_state
        ->getValue('id')) . '</div>',
    ];
  }
}