Repository URL to install this package:
|
Version:
2.0.2 ▾
|
<?php
namespace Drupal\custom_forms\Form;
use Drupal\Component\Datetime\Time;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Form\FormBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\custom_forms\CustomFormItemFactory;
use Drupal\custom_forms\CustomFormsFieldMappingManager;
use Drupal\custom_forms\CustomFormsFieldTypeManager;
use Drupal\custom_forms\CustomFormItem;
use Drupal\custom_forms\Entity\CustomForm;
use Drupal\custom_forms\Entity\CustomFormType;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Class CustomFormFieldForm
*
* Form for adding new fields to the custom form.
*
* @package Drupal\custom_forms\Form
*/
class CustomFormFieldForm extends FormBase {
/**
* The custom forms field type manager.
*
* @var CustomFormsFieldTypeManager $fieldTypeManager
*/
protected $fieldTypeManager;
/**
* The custom forms field mapping manager.
*
* @var CustomFormsFieldMappingManager $fieldMappingManager
*/
protected $fieldMappingManager;
/**
* The factory in charge of CRUD operations for custom form items.
*
* @var \Drupal\custom_forms\CustomFormItemFactory
*/
protected $itemFactory;
/**
* @inheritDoc
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.custom_forms_field_types'),
$container->get('plugin.manager.custom_forms_field_mappings'),
$container->get('custom_forms.factory.item')
);
}
/**
* {@inheritdoc}
*/
public function __construct(CustomFormsFieldTypeManager $field_type_manager, CustomFormsFieldMappingManager $field_mapping_manager, CustomFormItemFactory $item_factory) {
$this->fieldTypeManager = $field_type_manager;
$this->fieldMappingManager = $field_mapping_manager;
$this->itemFactory = $item_factory;
}
/**
* {@inheritdoc}
*/
public function getFormId() {
return 'custom_form_field_form';
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state) : array {
$attributes = \Drupal::request()->attributes;
/** @var \Drupal\custom_forms\CustomFormInterface $custom_form */
$custom_form = $attributes->get('custom_form');
$available_types = $this->fieldTypeManager->getDefinitions();
$available_mappings = $this->fieldMappingManager->getDefinitions();
if (count($available_types) > 0 && count($available_mappings) > 0) {
$form['form'] = [
'#type' => 'value',
'#value' => $custom_form
];
$form['label'] = [
'#type' => 'textfield',
'#title' => $this->t('Label'),
'#placeholder' => $this->t('Label'),
'#description' => $this->t('The label shown above the field.'),
'#required' => TRUE,
'#weight' => -100,
];
$form['machine_name'] = [
'#type' => 'machine_name',
'#maxlength' => EntityTypeInterface::BUNDLE_MAX_LENGTH,
'#machine_name' => [
'exists' => '\Drupal\custom_forms\CustomFormItemFactory::itemMachineNameExists',
'source' => ['label'],
],
'#weight' => -99,
'#description' => $this->t('A unique machine-readable name for this field. It must only contain lowercase letters, numbers, and underscores.'),
];
$form['message'] = ['#markup' => $this->t('Please select the field type and mapping you want to use in the form.')];
$field_types = $this->itemFactory->getCompatibleFields($custom_form);
$form['field_type'] = [
'#type' => 'select',
'#title' => $this->t('Field type'),
'#description' => $this->t('Select the field type to use.'),
'#required' => TRUE,
'#empty_option' => '- ' . $this->t('Choose field type') . ' -',
'#options' => $field_types,
'#ajax' => [
'callback' => '::update_available_mappings',
'wrapper' => 'mappings-wrapper',
'event' => 'change',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Getting compatible mappings...')
],
],
];
$form['mappings-wrapper'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#attributes' => [
'id' => 'mappings-wrapper'
],
];
$form['mappings-wrapper']['mapping'] = [
'#type' => 'select',
'#disabled' => TRUE,
'#title' => $this->t('Mapping'),
'#description' => $this->t('Select the mapping to use.'),
'#required' => TRUE,
'#empty_option' => '- ' . $this->t('Choose mapping') . ' -',
];
if (!empty($form_state->getValue('field_type'))) {
$compatible_mappings = $this->itemFactory->getCompatibleMappings($custom_form, $form_state->getValue('field_type'));
$mapping_options = [];
// Generate the options array.
foreach ($compatible_mappings as $mapping_id => $mapping_definition) {
$mapping_options[$mapping_id] = $mapping_definition['label'];
}
if (count($compatible_mappings) > 0) {
$form['mappings-wrapper']['mapping']['#options'] = $mapping_options;
$form['mappings-wrapper']['mapping']['#disabled'] = FALSE;
if (count($compatible_mappings) === 1) {
$form['mappings-wrapper']['mapping']['#disabled'] = TRUE;
$form['mappings-wrapper']['mapping']['#value'] = key($mapping_options);
$form['mappings-wrapper']['mapping']['#default_value'] = key($mapping_options);
$form['mappings-wrapper']['mapping']['#description'] = $compatible_mappings[key($mapping_options)]['description'];
}
}
else {
// Show an error message to the user to avoid confusion.
$this->messenger()->addError($this->t('No compatible field mappings were found for the selected field type.'));
}
}
} else {
$messages = [];
if (count($available_types) <= 0) {
$messages[] = $this->t('No field type plugins found.');
}
if (count($available_mappings) <= 0) {
$messages[] = $this->t('No field mapping plugins found.');
}
$form['message'] = [
'#type' => 'markup',
'#markup' => $this->t('Unable to load form, see reason(s) below.'),
'reasons' => [
'#theme' => 'item_list',
'#list_type' => 'ul',
'#items' => $messages,
]
];
}
$form['actions'] = [
'#type' => 'actions',
];
if (count($available_types) > 0 && count($available_mappings) > 0) {
$form['actions']['create'] = [
'#type' => 'submit',
'#value' => $this->t('Create'),
'#attributes' => [
'class' => [
'button',
'button-action',
'button--primary',
]
],
];
}
$form['actions']['cancel'] = [
'#type' => 'link',
'#title' => $this->t('Cancel'),
'#url' => Url::fromRoute('entity.custom_form.fields_form', ['custom_form' => $custom_form->id()]),
'#attributes' => [
'class' => [
'button',
'button-action',
'button--secondary',
],
],
'#limit_validation_errors' => [],
];
if (count($available_types) <= 0 || count($available_mappings) <= 0) {
$form['actions']['cancel']['#title'] = $this->t('Back');
$form['actions']['cancel']['#attributes']['style'][] = 'margin-left: 0;';
$form['actions']['cancel']['#attributes']['class'] = [
'button',
'button-action',
'button--primary',
];
}
return $form;
}
/**
* Updates the render array for field mappings through ajax callback.
*
* @param array $form
* @param \Drupal\Core\Form\FormStateInterface $form_state
*
* @return array
*/
public function update_available_mappings(array &$form, FormStateInterface $form_state) {
return $form['mappings-wrapper'];
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$attributes = \Drupal::request()->attributes;
$values = $form_state->cleanValues()->getValues();
/** @var CustomForm $custom_form */
$custom_form = $attributes->get('custom_form');
$field_definition = $this->fieldTypeManager->getDefinition($values['field_type']);
/** @var Time $time */
$time = \Drupal::service('datetime.time');
$timestamp = $time->getCurrentTime();
// Construct the basic settings.
$settings = [
'label' => $values['label'],
'machine_name' => $values['machine_name']
];
if (isset($field_definition['no_ui']) && (boolean) $field_definition['no_ui']) {
$settings['no_ui'] = TRUE;
}
// Create a new custom form revision since we are modifying it by adding a new 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('Added new field: @field-label', ['@field-label' => $values['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')->error($error_message);
$this->messenger()->addError($this->t('Failed during creation of new revision, please try again. If it continues please contact an administrator.'));
}
// We only want to create the new field if the revision was able to be saved.
if ($revision_saved) {
$item = new CustomFormItem($custom_form->id(), $custom_form->getLoadedRevisionId(), $timestamp, $timestamp, $custom_form->language()->getId(), 'field', $values['field_type'], $values['machine_name'], serialize($settings), serialize([]), $values['mapping'], 1000);
try {
$item->getPlugin()->setEmptyDefaults($item);
$item->save();
$this->messenger()->addMessage($this->t('%item-label was successfully created.', ['%item-label' => $values['label']]));
} catch (\Exception $e) {
$error_message = $this->t('Field saving failed. Message = %message. Trace = @trace', [
'%message' => $e->getMessage(),
'@trace' => $e->getTraceAsString()
]);
\Drupal::logger('Custom Forms')->error($error_message);
$this->messenger()->addError($this->t('Failed during creation of new field, please try again. If it continues please contact an administrator.'));
}
}
$form_state->setRedirect('entity.custom_form.fields_form', ['custom_form' => $custom_form->id()]);
}
}