Repository URL to install this package:
|
Version:
2.0.2 ▾
|
<?php
namespace Drupal\custom_forms_states\Form;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\CloseDialogCommand;
use Drupal\Core\Ajax\InvokeCommand;
use Drupal\Core\Ajax\ReplaceCommand;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Render\Element\StatusMessages;
use Drupal\custom_forms\CustomFormItem;
use Drupal\custom_forms\CustomFormItemFactory;
use Drupal\custom_forms\Form\CustomFormFieldListForm;
use Drupal\custom_forms\Form\CustomFormItemFormBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* Class CustomFormItemStatesForm
*
* @package Drupal\custom_forms_states\Form
*/
class CustomFormItemStatesForm extends CustomFormItemFormBase {
/**
* The factory in charge of CRUD operations for custom form items.
*
* @var \Drupal\custom_forms\CustomFormItemFactory
*/
protected $itemFactory;
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'custom_form_item_states_form';
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('custom_forms.factory.item')
);
}
/**
* {@inheritdoc}
*/
public function __construct(CustomFormItemFactory $item_factory) {
$this->itemFactory = $item_factory;
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) {
$form = parent::buildForm($form, $form_state);
$request = \Drupal::request();
$attributes = $request->attributes;
$customForm = $attributes->get('custom_form');
$formItem = $this->itemFactory->loadItem($attributes->get('item'));
$form['description'] = [
'#type' => 'container',
'text' => ['#markup' => $this->t('Use the form below to manage the conditional states.')],
'#attributes' => [
'class' => [
'custom-form-item-states--description'
]
]
];
$form['#attached']['library'][] = 'custom_forms_states/states-ui';
$selectors = [];
/** @var CustomFormItem $item */
foreach ($this->itemFactory->getFormItems($customForm) as $item) {
if ($item->id() === $formItem->id()) {
continue;
}
if ($item->getPluginId() === 'checkboxes') {
$option_lines = preg_split("/\r\n|\n|\r/", $item->getSetting('options'));
foreach ($option_lines as $line) {
$split = explode('|', $line);
$selectors[$item->getMachineName() . '[' . (string)$split[0] . ']'] = $item->getSetting('label') . ' (' . $split[1] . ')';
}
} else {
$selectors[$item->getJquerySelector()] = $item->getSetting('label');
}
}
$form['states'] = [
'#type' => 'state_element',
'#selector_options' => $selectors,
'#default_value' => $formItem->getStates()
];
return $form;
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$trigger = $form_state->getTriggeringElement();
$request = \Drupal::request();
if ($trigger['#op'] === 'cancel' || $request->isXmlHttpRequest()) {
return;
}
$values = $form_state->cleanValues()->getValues();
$attributes = $request->attributes;
$custom_form = $attributes->get('custom_form');
$item = $this->itemFactory->loadItem($attributes->get('item'));
// Create a new custom form revision since we are modifying it by removing a field.
$revision_saved = FALSE;
$custom_form->setNewRevision(TRUE);
$custom_form->setRevisionTranslationAffected(TRUE); // for some reason required for log messages to show up?
$custom_form->setRevisionLogMessage(
$this->t('Updated states for @field-label', [
'@field-label' => $item->getSetting('label')
]));
$custom_form->setRevisionCreationTime(\Drupal::time()->getRequestTime());
$custom_form->setRevisionUserId(\Drupal::currentUser()->id());
try {
$custom_form->save();
$revision_saved = TRUE;
} catch (EntityStorageException $e) {
$error_message = $this->t('Failed during creation of new revision. Message = %message', [
'%message' => $e->getMessage()
]);
\Drupal::logger('Custom Forms States')->error($error_message);
$this->messenger()->addError($this->t('Failed during creation of new revision, please try again. If it continues please contact an administrator.'));
}
if ($revision_saved) {
$states = $this->cleanStates($values['states']['states']);
$item->setStates($states);
try {
// We save it without creating a new revision, as that has already been done at this point.
$item->save(FALSE);
$form_state->setRedirect('entity.custom_form.fields_form', ['custom_form' => $custom_form->id()]);
$this->messenger()->addMessage($this->t('%item-label states were successfully saved.', ['%item-label' => $item->getSetting('label')]));
} catch (\Exception $e) {
$error_message = $this->t('Field states saving failed. Message = %message', [
'%message' => $e->getMessage()
]);
\Drupal::logger('Custom Forms States')->error($error_message);
$this->messenger()->addError($this->t('Failed during saving of field states, please try again. If this continues please contact an administrator.'));
}
}
}
/**
* Submit the form through ajax.
*
* @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.
* @param \Symfony\Component\HttpFoundation\Request $request
* The request that is calling this function.
*
* @return \Drupal\Core\Ajax\AjaxResponse
* Returns an AjaxResponse for usage within Drupal's ajax system.
*/
public function ajaxSubmitForm(array &$form, FormStateInterface $form_state, Request $request) {
$response = new AjaxResponse();
$values = $form_state->cleanValues()->getValues();
$settings_config = \Drupal::config('custom_forms.settings');
$attributes = $request->attributes;
/** @var \Drupal\custom_forms\Entity\CustomForm $custom_form */
$custom_form = $attributes->get('custom_form');
/** @var CustomFormItem $item */
$item = $this->itemFactory->loadItem($attributes->get('item'));
// Create a new custom form revision since we are modifying it by removing a field.
$revision_saved = FALSE;
$custom_form->setNewRevision(TRUE);
$custom_form->setRevisionTranslationAffected(TRUE); // for some reason required for log messages to show up?
$custom_form->setRevisionLogMessage(
$this->t('Updated states for @field-label', [
'@field-label' => $item->getSetting('label')
]));
$custom_form->setRevisionCreationTime(\Drupal::time()->getRequestTime());
$custom_form->setRevisionUserId(\Drupal::currentUser()->id());
try {
$custom_form->save();
$revision_saved = TRUE;
} catch (EntityStorageException $e) {
$error_message = $this->t('Failed during creation of new revision. Message = %message. Trace = @trace', [
'%message' => $e->getMessage(),
'@trace' => $e->getTraceAsString()
]);
\Drupal::logger('Custom Forms States')->error($error_message);
$this->messenger()->addError($this->t('Failed during creation of new revision, please try again. If it continues please contact an administrator.'));
}
if ($revision_saved) {
$new_item = $this->itemFactory->loadItem($item->id(), NULL, $custom_form->getLoadedRevisionId(), $custom_form->language()->getId());
// We unset the states sub array to avoid duplicates.
unset($values['states']['states']);
$states = $this->cleanStates($values['states']);
$new_item->setStates($states);
try {
// We save it without creating a new revision, as that has already been done at this point.
$new_item->save(FALSE);
$response->addCommand(new CloseDialogCommand('#drupal-off-canvas'));
$this->messenger()->addMessage($this->t('%item-label states were successfully saved.', ['%item-label' => $new_item->getSetting('label')]));
switch ($settings_config->get('off_screen_field_settings')) {
case 'rebuild':
$form = \Drupal::formBuilder()->getForm(CustomFormFieldListForm::class);
$response->addCommand(new ReplaceCommand('#custom-form__field-list', $form));
// Get the messages for display
$messages = StatusMessages::renderMessages();
// Remove the current messages to avoid showing any sticky messages double.
$response->addCommand(new InvokeCommand('div.region.region-highlighted div.messages', 'remove'));
// Append the new messages to the highlighted region.
$response->addCommand(new InvokeCommand('div.region.region-highlighted', 'append', [\Drupal::service('renderer')->render($messages)]));
break;
case 'reload':
default:
$response->addCommand(new InvokeCommand('form.custom-forms-fields input.form-submit[type="submit"][name="op"]', 'click', []));
break;
}
} catch (\Exception $e) {
$error_message = $this->t('Field states saving failed. Message = %message. Trace = @trace', [
'%message' => $e->getMessage(),
'@trace' => $e->getTraceAsString()
]);
\Drupal::logger('Custom Forms States')->error($error_message);
$this->messenger()->addError($this->t('Failed during saving of field states, please try again. If this continues please contact an administrator.'));
}
}
return $response;
}
/**
* Clean the states array to make is easier to use.
*
* @param array $states
*
* @return array
*/
private function cleanStates($states): array {
// State cleanup
$real_states = [];
$state_index = 0;
foreach ($states as $state) {
if (!empty($state['state'])) {
$real_states[$state_index] = [
'state' => $state['state'],
'value' => $state['value'],
'operator' => $state['operator'],
'condition' => [],
];
$condition_index = 0;
foreach ($state['condition'] as $condition) {
if (!empty($condition['selector']) && !empty($condition['trigger'])) {
$real_states[$state_index]['condition'][$condition_index] = [
'selector' => $condition['selector'],
'trigger' => $condition['trigger'],
'value' => $condition['value'],
];
$condition_index++;
}
}
$state_index++;
}
}
return $real_states;
}
}