external_entity-1.0.x-dev/src/Form/ExternalEntityConnectionForm.php
src/Form/ExternalEntityConnectionForm.php
<?php
declare(strict_types=1);
namespace Drupal\external_entity\Form;
use Drupal\Component\Utility\DeprecationHelper;
use Drupal\Core\Utility\Error;
use Drupal\Core\Render\Element;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Form\FormStateInterface;
use Drupal\external_entity\AjaxFormTrait;
use Drupal\Core\Plugin\PluginFormInterface;
use Drupal\Component\Plugin\PluginManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\external_entity\Contracts\ExternalEntityConnectionAwareInterface;
use Drupal\external_entity\Contracts\ExternalEntityConnectionTypeManagerInterface;
use Drupal\external_entity\Contracts\ExternalEntityAuthenticationTypeManagerInterface;
/**
* Define the external entity connection default form.
*/
class ExternalEntityConnectionForm extends EntityForm {
use AjaxFormTrait;
/**
* The external entity connection type manager.
*
* @var \Drupal\external_entity\Contracts\ExternalEntityConnectionTypeManagerInterface
*/
protected $connectionTypeManager;
/**
* @var \Drupal\external_entity\Contracts\ExternalEntityAuthenticationTypeManagerInterface
*/
protected $authenticationTypeManager;
/**
* External entity connection form constructor.
*
* @param \Drupal\external_entity\Contracts\ExternalEntityConnectionTypeManagerInterface $connection_type_manager
* The external entity connection type manager service.
* @param \Drupal\external_entity\Contracts\ExternalEntityAuthenticationTypeManagerInterface $authentication_type_manager
* The external entity connection type manager service.
*/
public function __construct(
ExternalEntityConnectionTypeManagerInterface $connection_type_manager,
ExternalEntityAuthenticationTypeManagerInterface $authentication_type_manager,
) {
$this->connectionTypeManager = $connection_type_manager;
$this->authenticationTypeManager = $authentication_type_manager;
}
/**
* {@inheritDoc}
*/
public static function create(ContainerInterface $container): self {
return new static(
$container->get('plugin.manager.external_entity.connection_type'),
$container->get('plugin.manager.external_entity.authentication_type')
);
}
/**
* {@inheritDoc}
*/
public function buildForm(array $form, FormStateInterface $form_state): array {
/** @var \Drupal\external_entity\Entity\ExternalEntityConnection $entity */
$entity = $this->entity;
$form['#parents'] = [];
$form['#prefix'] = '<div id="external-entity-connection">';
$form['#suffix'] = '</div>';
$form['label'] = [
'#type' => 'textfield',
'#title' => $this->t('Name'),
'#maxlength' => 255,
'#default_value' => $entity->label(),
'#description' => $this->t('Input the connection name.'),
'#required' => TRUE,
];
$form['id'] = [
'#type' => 'machine_name',
'#machine_name' => [
'exists' => [$entity, 'exists'],
],
'#disabled' => !$entity->isNew(),
'#default_value' => $entity->id(),
];
$this->buildPluginConfigurationForm(
$form,
$form_state,
);
return parent::buildForm($form, $form_state);
}
/**
* {@inheritDoc}
*/
public function validateForm(
array &$form,
FormStateInterface $form_state,
): void {
$this->validatePluginConfigurationForm(
$form,
$form_state
);
parent::validateForm($form, $form_state);
}
/**
* {@inheritDoc}
*/
public function submitForm(
array &$form,
FormStateInterface $form_state,
): void {
$this->submitPluginConfigurationForm(
$form,
$form_state
);
parent::submitForm($form, $form_state);
}
/**
* {@inheritDoc}
*/
public function save(array $form, FormStateInterface $form_state) {
/** @var \Drupal\external_entity\Entity\ExternalEntityConnection $entity */
$entity = $this->entity;
$entity->save();
$form_state->setRedirectUrl(
$entity->toUrl('collection')
);
}
/**
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*
* @return array
*/
public function externalEntityConnectionAjax(
array $form,
FormStateInterface $form_state,
): array {
return $form;
}
/**
* Define the ajax element base.
*
* @return array
*/
protected function ajaxElementBase(): array {
return [
'event' => 'change',
'method' => 'replaceWith',
'wrapper' => 'external-entity-connection',
'callback' => [$this, 'externalEntityConnectionAjax'],
];
}
/**
* Define the plugin dependency form information.
*
* @return array[]
* An array keyed by the element plugin id, which provides:
* - title: Set the element title.
* - description: Set the element description.
* - settings: An array of plugin settings.
* - title: Set the setting title/.
* - key: Set the element key which captures the settings.
* - plugin_manager: A plugin manager to use to create the plugin.
*/
protected function pluginDependencyFormInfo(): array {
/** @var \Drupal\external_entity\Entity\ExternalEntityConnection $entity */
$entity = $this->entity;
return [
'authentication_type' => [
'title' => $this->t('Authentication Type'),
'description' => $this->t('Select the external entity authentication type.'),
'default_value' => $entity->authenticationTypeId(),
'settings' => [
'key' => 'authentication_settings',
'title' => $this->t('Authentication Settings'),
'configuration' => $entity->authenticationSettings(),
],
'plugin_manager' => $this->authenticationTypeManager,
],
'connection_type' => [
'title' => $this->t('Connection Type'),
'description' => $this->t('Select the external entity connection type.'),
'default_value' => $entity->connectionTypeId(),
'required' => TRUE,
'settings' => [
'key' => 'connection_settings',
'title' => $this->t('Connection Settings'),
'configuration' => $entity->connectionSettings(),
],
'plugin_manager' => $this->connectionTypeManager,
],
];
}
/**
* Build the plugin configuration form.
*
* @param array $form
* An array of form elements.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state instance.
* @param string|array $key
* The plugin configuration form element keys.
*
* @return void
*/
protected function buildPluginConfigurationForm(
array &$form,
FormStateInterface $form_state,
$key = NULL,
): void {
if (!is_array($key)) {
$key = isset($key) ? [$key] : [];
}
$form_info = $this->pluginDependencyFormInfo();
$form_keys = !empty($key)
? array_intersect_key($form_info, array_flip($key))
: $form_info;
foreach ($form_keys as $input => $plugin_info) {
if (
!isset($plugin_info['plugin_manager'])
|| !$plugin_info['plugin_manager'] instanceof PluginManagerInterface
) {
continue;
}
$plugin_id = $this->getFormStateValue(
$input,
$form_state,
$plugin_info['default_value'] ?? NULL
);
$plugin_manager = $plugin_info['plugin_manager'];
$plugin_options = $plugin_manager->getDefinitionOptions();
$plugin_settings = $plugin_info['settings'] ?? [];
$form[$input] = [
'#type' => 'select',
'#title' => $plugin_info['title'] ?? NULL,
'#description' => $plugin_info['description'] ?? NULL,
'#options' => $plugin_options,
'#empty_option' => $this->t('- None -'),
'#default_value' => $plugin_id,
'#required' => $plugin_info['required'] ?? FALSE,
'#ajax' => $this->ajaxElementBase(),
];
if (isset($plugin_id, $plugin_options[$plugin_id], $plugin_settings['key'])) {
$setting_key = $plugin_settings['key'];
$configuration = $plugin_settings['configuration'] ?? [];
$form[$setting_key] = [
'#type' => 'fieldset',
'#title' => $plugin_info['settings']['title'] ?? NULL,
'#tree' => TRUE,
];
try {
$instance = $plugin_manager->createInstance(
$plugin_id,
$configuration
);
if ($instance instanceof ExternalEntityConnectionAwareInterface) {
$instance->setConnection($this->entity);
}
if ($instance instanceof PluginFormInterface) {
$subform = ['#parents' => [$setting_key]];
$form[$setting_key] += $instance->buildConfigurationForm(
$subform,
SubformState::createForSubform($subform, $form, $form_state)
);
if (count(Element::children($form[$setting_key])) === 0) {
unset($form[$setting_key]);
}
}
}
catch (\Exception $exception) {
DeprecationHelper::backwardsCompatibleCall(
\Drupal::VERSION,
'10.1.0',
static fn() => Error::logException(\Drupal::logger('external_entity'), $exception),
static fn() => watchdog_exception('external_entity', $exception)
);
}
}
}
}
/**
* Validate the plugin configuration form.
*
* @param array $form
* An array form elements.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state instance.
*
* @return void
*/
protected function validatePluginConfigurationForm(
array $form,
FormStateInterface $form_state,
): void {
foreach ($this->pluginDependencyFormInfo() as $input => $info) {
if (
!isset($info['plugin_manager'], $info['settings']['key'])
|| !$info['plugin_manager'] instanceof PluginManagerInterface
) {
continue;
}
$manager = $info['plugin_manager'];
$setting_key = $info['settings']['key'];
if (
($connection_type = $form_state->getValue($input))
&& $manager->hasDefinition($connection_type)
) {
try {
$instance = $manager->createInstance(
$connection_type,
$form_state->getValue($setting_key, [])
);
if ($instance instanceof ExternalEntityConnectionAwareInterface) {
$instance->setConnection($this->entity);
}
if ($instance instanceof PluginFormInterface) {
$subform = $form[$setting_key] ?? [];
$instance->validateConfigurationForm(
$subform,
SubformState::createForSubform($subform, $form, $form_state)
);
}
}
catch (\Exception $exception) {
DeprecationHelper::backwardsCompatibleCall(
\Drupal::VERSION,
'10.1.0',
static fn() => Error::logException(\Drupal::logger('external_entity'), $exception),
static fn() => watchdog_exception('external_entity', $exception)
);
}
}
}
}
/**
* Submit the plugin configuration form.
*
* @param array $form
* An array of form elements.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state instance.
*
* @return void
*/
protected function submitPluginConfigurationForm(
array $form,
FormStateInterface $form_state,
): void {
foreach ($this->pluginDependencyFormInfo() as $input => $info) {
if (
!isset($info['plugin_manager'], $info['settings']['key'])
|| !$info['plugin_manager'] instanceof PluginManagerInterface
) {
continue;
}
$manager = $info['plugin_manager'];
$setting_key = $info['settings']['key'];
if (
($plugin_id = $form_state->getValue($input))
&& $manager->hasDefinition($plugin_id)
) {
try {
$instance = $manager->createInstance(
$plugin_id,
$form_state->getValue($setting_key, [])
);
if ($instance instanceof ExternalEntityConnectionAwareInterface) {
$instance->setConnection($this->entity);
}
if ($instance instanceof PluginFormInterface) {
$subform = $form[$setting_key];
$instance->submitConfigurationForm(
$subform,
SubformState::createForSubform($subform, $form, $form_state)
);
$form_state->setValueForElement(
$subform, $instance->getConfiguration()
);
}
}
catch (\Exception $exception) {
DeprecationHelper::backwardsCompatibleCall(
\Drupal::VERSION,
'10.1.0',
static fn() => Error::logException(\Drupal::logger('external_entity'), $exception),
static fn() => watchdog_exception('external_entity', $exception)
);
}
}
}
}
}
