headless_cms-1.0.3/modules/headless_cms_notify/src/Form/HeadlessNotifyTransportForm.php
modules/headless_cms_notify/src/Form/HeadlessNotifyTransportForm.php
<?php
declare(strict_types=1);
namespace Drupal\headless_cms_notify\Form;
use Drupal\Component\Plugin\ConfigurableInterface;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\headless_cms_notify\Entity\HeadlessNotifyTransportInterface;
use Drupal\headless_cms_notify\HeadlessNotifyTransportServiceInterface;
use Drupal\headless_cms_notify\Plugin\HeadlessNotifyTransportPluginFormInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides the form to add / edit an HeadlessNotifyTransport entity.
*/
class HeadlessNotifyTransportForm extends EntityForm {
/**
* The original transport.
*/
protected ?HeadlessNotifyTransportInterface $originalTransport = NULL;
public function __construct(
ConfigFactoryInterface $configFactory,
protected HeadlessNotifyTransportServiceInterface $transportService,
) {
$this->configFactory = $configFactory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('config.factory'),
$container->get('headless_cms_notify.transport_service'),
);
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
// If the form is rebuilding.
if ($form_state->isRebuilding()) {
// If an transport plugin change triggered the rebuild.
if ($form_state->getTriggeringElement()['#name'] == 'transport_plugin') {
// Update the transport plugin.
$this->updateTransportPlugin($form_state);
}
}
elseif ($this->operation == "edit") {
// Only when the form is first built.
/** @var \Drupal\headless_cms_notify\Entity\HeadlessNotifyTransport $transport */
$transport = $this->entity;
$this->originalTransport = clone $transport;
}
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
/** @var \Drupal\headless_cms_notify\Entity\HeadlessNotifyTransport $transport */
$transport = $this->entity;
$form['label'] = [
'#type' => 'textfield',
'#title' => $this->t('Label'),
'#maxlength' => 255,
'#default_value' => $transport->label(),
'#description' => $this->t("Label for the transport."),
'#required' => TRUE,
];
$form['id'] = [
'#type' => 'machine_name',
'#default_value' => $transport->id(),
'#machine_name' => [
'exists' => '\Drupal\headless_cms_notify\Entity\HeadlessNotifyTransport::load',
],
'#disabled' => !$transport->isNew(),
];
// This is the element that contains all of the dynamic parts of the form.
$form['transport'] = [
'#type' => 'container',
'#prefix' => '<div id="transport-settings">',
'#suffix' => '</div>',
];
$plugins = $this->transportService->loadTransportPlugins();
$pluginOptions = [];
// Show the current transport plugin.
if (!$transport->isNew()) {
$plugin = $transport->getTransportPlugin();
$pluginOptions[$plugin->getPluginId()] = $plugin->getLabel();
}
// Populate the plugin options.
foreach ($plugins as $pluginId => $definition) {
$pluginOptions[$pluginId] = (string) $definition['label'];
}
if (count($pluginOptions) === 0) {
$form['transport']['transport_plugin'] = [
'#type' => 'fieldset',
'#title' => $this->t('Transport Plugin'),
'#description' => $this->t('No transport plugins available!<br />Please install a module that provides a transport plugin, e.g. `headless_cms_notify_webhook`.'),
];
}
else {
$form['transport']['transport_plugin'] = [
'#type' => 'select',
'#title' => $this->t('Transport Plugin'),
'#description' => $this->t('Select the plugin used for transport'),
'#options' => $pluginOptions,
'#required' => TRUE,
'#default_value' => $transport->getTransportPluginId(),
'#ajax' => [
'callback' => [$this, 'ajaxUpdateSettings'],
'event' => 'change',
'wrapper' => 'transport-settings',
],
];
}
$form['transport']['transport_plugin_configuration'] = [
'#type' => 'container',
'#title' => $this->t('Transport plugin settings'),
'#title_display' => FALSE,
'#tree' => TRUE,
];
$plugin = $transport->getTransportPlugin();
if ($plugin instanceof HeadlessNotifyTransportPluginFormInterface) {
$plugin_form_state = $this->createPluginFormState($form_state);
$form['transport']['transport_plugin_configuration'] += $plugin->buildConfigurationForm([], $plugin_form_state);
$form_state->setValue('transport_plugin_configuration', $plugin_form_state->getValues());
}
return $form;
}
/**
* Creates a FormStateInterface object for a plugin.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state to copy values from.
*
* @return \Drupal\Core\Form\FormStateInterface
* A clone of the form state object with values from the plugin.
*/
protected function createPluginFormState(FormStateInterface $form_state) {
// Clone the form state.
$plugin_form_state = clone $form_state;
// Clear the values, except for this plugin type's settings.
$plugin_form_state->setValues($form_state->getValue('transport_plugin_configuration', []));
return $plugin_form_state;
}
/**
* AJAX callback to update the dynamic settings on the form.
*/
public function ajaxUpdateSettings(array &$form, FormStateInterface $form_state) {
return $form['transport'];
}
/**
* Update the transport plugin.
*/
protected function updateTransportPlugin(FormStateInterface $form_state) {
/** @var \Drupal\headless_cms_notify\Entity\HeadlessNotifyTransport $transport */
$transport = $this->entity;
/** @var \Drupal\headless_cms_notify\HeadlessNotifyTransportPluginInterface $plugin */
$plugin = $transport->getTransportPlugin();
if (!$plugin instanceof ConfigurableInterface) {
return;
}
$transport->setTransportPlugin($plugin);
// If an original transport exists and the
// plugin ID matches the existing one.
if ($this->originalTransport && $this->originalTransport->getTransportPluginId() == $plugin->getPluginId()) {
// Use the configuration from the original profile's plugin.
/** @var \Drupal\Component\Plugin\ConfigurableInterface $originalPlugin */
$originalPlugin = $this->originalTransport->getTransportPlugin();
if ($originalPlugin instanceof ConfigurableInterface) {
$configuration = $originalPlugin->getConfiguration();
}
}
else {
// Use the plugin's default configuration.
$configuration = $plugin->defaultConfiguration();
}
$plugin->setConfiguration($configuration);
$form_state->setValue('transport_plugin_configuration', []);
$form_state->getUserInput()['transport_plugin_configuration'] = [];
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
// Only validate when submitting the form, not on AJAX rebuild.
if (!$form_state->isSubmitted()) {
return;
}
/** @var \Drupal\headless_cms_notify\Entity\HeadlessNotifyTransport $transport */
$transport = $this->entity;
// If the transport plugin contains a config form, validate it as well.
if ($plugin = $transport->getTransportPlugin()) {
if ($plugin instanceof HeadlessNotifyTransportPluginFormInterface) {
$plugin_form_state = $this->createPluginFormState($form_state);
$plugin->validateConfigurationForm($form, $plugin_form_state);
$form_state->setValue('transport_plugin_configuration', $plugin_form_state->getValues());
$this->moveFormStateErrors($plugin_form_state, $form_state);
$this->moveFormStateStorage($plugin_form_state, $form_state);
}
}
else {
$form_state->setErrorByName('transport_plugin', $this->t('No transport plugin selected.'));
}
$form_state->cleanValues();
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
/** @var \Drupal\headless_cms_notify\Entity\HeadlessNotifyTransport $transport */
$transport = $this->entity;
// Submit plugin configuration if available.
if ($plugin = $transport->getTransportPlugin()) {
if ($plugin instanceof HeadlessNotifyTransportPluginFormInterface) {
$plugin_form_state = $this->createPluginFormState($form_state);
$plugin->submitConfigurationForm($form, $plugin_form_state);
$form_state->setValue('transport_plugin_configuration', $plugin_form_state->getValues());
}
}
parent::submitForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function save(array $form, FormStateInterface $form_state) {
/** @var \Drupal\headless_cms_notify\Entity\HeadlessNotifyTransport $transport */
$transport = $this->entity;
$status = $transport->save();
if ($status) {
$this->messenger()->addMessage($this->t('Saved the %label transport.', [
'%label' => $transport->label(),
]));
}
else {
$this->messenger()->addMessage($this->t('The %label transport was not saved.', [
'%label' => $transport->label(),
]));
}
$form_state->setRedirectUrl($transport->toUrl('collection'));
return $status;
}
/**
* Moves form errors from one form state to another.
*
* @param \Drupal\Core\Form\FormStateInterface $from
* The form state object to move from.
* @param \Drupal\Core\Form\FormStateInterface $to
* The form state object to move to.
*/
protected function moveFormStateErrors(FormStateInterface $from, FormStateInterface $to) {
foreach ($from->getErrors() as $name => $error) {
$to->setErrorByName($name, $error);
}
}
/**
* Moves storage variables from one form state to another.
*
* @param \Drupal\Core\Form\FormStateInterface $from
* The form state object to move from.
* @param \Drupal\Core\Form\FormStateInterface $to
* The form state object to move to.
*/
protected function moveFormStateStorage(FormStateInterface $from, FormStateInterface $to) {
foreach ($from->getStorage() as $index => $value) {
$to->set($index, $value);
}
}
}
