entity_value_inheritance-1.3.0/src/Form/InheritanceForm.php
src/Form/InheritanceForm.php
<?php
namespace Drupal\entity_value_inheritance\Form;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Ajax\HtmlCommand;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Plugin\PluginFormFactoryInterface;
use Drupal\Core\Plugin\PluginWithFormsInterface;
use Drupal\Core\Render\Element;
use Drupal\entity_value_inheritance\EntityValueInheritanceUpdaterPluginInterface;
use Drupal\entity_value_inheritance\Services\Helper;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Inheritance form.
*
* @property \Drupal\entity_value_inheritance\Entity\InheritanceInterface $entity
*/
class InheritanceForm extends EntityForm {
/**
* Helper Service.
*
* @var \Drupal\entity_value_inheritance\Services\Helper
*/
protected Helper $helper;
/**
* Plugin Form Factory Service.
*
* @var \Drupal\Core\Plugin\PluginFormFactoryInterface
*/
protected PluginFormFactoryInterface $pluginFormFactory;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->helper = $container->get('entity_value_inheritance.helper');
$instance->pluginFormFactory = $container->get('plugin_form.factory');
return $instance;
}
/**
* {@inheritdoc}
*/
public function form(array $form, FormStateInterface $form_state) {
$form = parent::form($form, $form_state);
$inheritance = $this->entity;
$form['#prefix'] = '<div id="field-inheritance-add-form--wrapper">';
$form['#suffix'] = '</div>';
$default_values = ['' => $this->t('- Select -')];
$entityTypes = $this->helper->getEntities();
$sourceEntityBundles = $destinationEntityBundles = [];
$sourceEntityFields = $destinationEntityFields = [];
$destinationEntityReferenceFields = [];
$field_values = [];
$form_values = $form_state->getValues();
if (!$inheritance->isNew()) {
$field_values['source_entity_type'] = $inheritance->get('source_entity_type');
$field_values['source_entity_bundle'] = $inheritance->get('source_entity_bundle');
$field_values['source_entity_field'] = $inheritance->get('source_entity_field');
$field_values['destination_entity_type'] = $inheritance->get('destination_entity_type');
$field_values['destination_entity_bundle'] = $inheritance->get('destination_entity_bundle');
$field_values['destination_entity_field'] = $inheritance->get('destination_entity_field');
$field_values['destination_entity_referencing_field'] = $inheritance->get('destination_entity_referencing_field');
}
elseif (!empty($form_values)) {
$field_values['source_entity_type'] = $form_values['source_entity_type'];
$field_values['source_entity_bundle'] = $form_values['source_entity_bundle'];
$field_values['source_entity_field'] = $form_values['source_entity_field'];
$field_values['destination_entity_type'] = $form_values['destination_entity_type'];
$field_values['destination_entity_bundle'] = $form_values['destination_entity_bundle'];
$field_values['destination_entity_referencing_field'] = $form_values['destination_entity_referencing_field'];
}
if (!empty($inheritance->get('source_entity_type')) && empty($form_values)) {
$field_values['source_entity_type'] = $inheritance->get('source_entity_type');
}
if (!empty($inheritance->get('source_entity_bundle')) && empty($form_values)) {
$field_values['source_entity_bundle'] = $inheritance->get('source_entity_bundle');
}
if (!empty($form_values['source_entity_field'])) {
$field_values['source_entity_field'] = $form_values['source_entity_field'];
}
if (!empty($inheritance->get('destination_entity_type')) && empty($form_values)) {
$field_values['destination_entity_type'] = $inheritance->get('destination_entity_type');
}
if (!empty($inheritance->get('destination_entity_bundle')) && empty($form_values)) {
$field_values['destination_entity_bundle'] = $inheritance->get('destination_entity_bundle');
}
if (!empty($form_values['destination_entity_field'])) {
$field_values['destination_entity_field'] = $form_values['destination_entity_field'];
}
if (!empty($field_values['source_entity_type'])) {
$sourceEntityBundles = $this->helper->getBundlesOptions($field_values['source_entity_type']);
if (!empty($field_values['source_entity_bundle'])) {
$sourceEntityFields = $this->helper->getEntityBundleFieldsOptions($field_values['source_entity_type'], $field_values['source_entity_bundle']);
}
}
if (!empty($field_values['destination_entity_type'])) {
$destinationEntityBundles = $this->helper->getBundlesOptions($field_values['destination_entity_type']);
if (!empty($field_values['destination_entity_bundle']) && !empty($field_values['source_entity_field'])) {
if (!empty($field_values['source_entity_type'])) {
$destinationEntityReferenceFields = $this->helper->getEntityReferenceFieldsOptions($field_values['destination_entity_type'], $field_values['destination_entity_bundle'], $field_values['source_entity_type']);
}
if (!empty($field_values['destination_entity_referencing_field'])) {
$destinationEntityFields = $this->helper->getEntityBundleFieldsOptions(
$field_values['destination_entity_type'],
$field_values['destination_entity_bundle'],
sprintf('%s.%s.%s',
$field_values['source_entity_type'],
$field_values['source_entity_bundle'],
$field_values['source_entity_field']
)
);
if (isset($destinationEntityFields[$field_values['destination_entity_referencing_field']])) {
unset($destinationEntityFields[$field_values['destination_entity_referencing_field']]);
}
}
// @todo Remove Field selected in Source From Destination.
// @todo Remove Reference selected in Source Field From Destination.
}
}
$form['label'] = [
'#type' => 'textfield',
'#title' => $this->t('Label'),
'#maxlength' => 255,
'#default_value' => $this->entity->label(),
'#description' => $this->t('Label for the inheritance.'),
'#required' => TRUE,
];
$form['id'] = [
'#type' => 'machine_name',
'#default_value' => $inheritance->id(),
'#machine_name' => [
'exists' => '\Drupal\entity_value_inheritance\Entity\Inheritance::load',
],
'#disabled' => !$inheritance->isNew(),
];
$form['status'] = [
'#type' => 'checkbox',
'#title' => $this->t('Enabled'),
'#default_value' => $inheritance->status(),
];
$form['description'] = [
'#type' => 'textarea',
'#title' => $this->t('Description'),
'#default_value' => $inheritance->get('description'),
'#description' => $this->t('Description of the inheritance.'),
];
$plugins = $this->helper->getPlugins();
$form['strategy'] = [
'#title' => $this->t('Field Strategy'),
'#description' => $this->t('Select the strategy used to inherit data.'),
'#type' => 'radios',
'#required' => TRUE,
'#options' => $default_values + array_map(function ($item) {
return sprintf('<strong>%s</strong><br/>%s', $item['title'], $item['description']);
}, $plugins),
'#default_value' => $inheritance->getStrategy(),
'#ajax' => [
'callback' => '::updateFieldOptions',
'wrapper' => 'field-inheritance-add-form--wrapper',
'event' => 'change',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Getting strategy options...'),
],
],
];
$form['plugin']['settings'] = [];
$subform_state = SubformState::createForSubform($form['plugin']['settings'], $form, $form_state);
$form['plugin']['settings'] = $this
->getPluginForm($inheritance->getPlugin())
->buildConfigurationForm($form['plugin']['settings'], $subform_state);
$form['plugin']['settings']['#tree'] = TRUE;
if (count(Element::getVisibleChildren($form['plugin']['settings'])) > 0) {
$form['plugin']['#title'] = $this->t('Strategy Configuration');
$form['plugin']['#type'] = 'fieldset';
}
$form['config'] = [
'#type' => 'container',
'#attributes' => ['id' => 'field-inheritance-add-form--wrapper'],
];
$form['config']['source'] = [
'#title' => $this->t('Source Entity Configuration'),
'#type' => 'fieldset',
];
$form['config']['source']['source_entity_type'] = [
'#title' => $this->t('Source Entity Type'),
'#description' => $this->t('Entity type where the data should come from.'),
'#type' => 'select',
'#required' => TRUE,
'#options' => $default_values + $entityTypes,
'#default_value' => $inheritance->getSourceEntityType(),
'#ajax' => [
'callback' => '::updateFieldOptions',
'wrapper' => 'field-inheritance-add-form--wrapper',
'event' => 'change',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Fetching source options...'),
],
],
];
$form['config']['source']['source_entity_bundle'] = [
'#title' => $this->t('Source Entity Bundle'),
'#description' => $this->t('Entity bundle where the data should come from.'),
'#type' => 'select',
'#required' => TRUE,
'#options' => $default_values + $sourceEntityBundles,
'#default_value' => $inheritance->getSourceBundle(),
'#ajax' => [
'callback' => '::updateFieldOptions',
'wrapper' => 'field-inheritance-add-form--wrapper',
'event' => 'change',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Fetching source options...'),
],
],
'#states' => [
'visible' => [
'select[name="source_entity_type"]' => ['!value' => ''],
],
],
];
$form['config']['source']['source_entity_field'] = [
'#title' => $this->t('Source Entity Field'),
'#description' => $this->t('Field on the Entity and Bundle where the data should come from.'),
'#type' => 'select',
'#required' => TRUE,
'#options' => $default_values + $sourceEntityFields,
'#default_value' => $inheritance->getSourceField(),
'#ajax' => [
'callback' => '::updateFieldOptions',
'wrapper' => 'field-inheritance-add-form--wrapper',
'event' => 'change',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Fetching source options...'),
],
],
'#states' => [
'visible' => [
'select[name="source_entity_type"]' => ['!value' => ''],
'select[name="source_entity_bundle"]' => ['!value' => ''],
],
],
];
$form['config']['destination'] = [
'#title' => $this->t('Destination Entity Configuration'),
'#type' => 'fieldset',
'#attributes' => ['id' => 'destination-wrapper'],
];
$form['config']['destination']['destination_entity_type'] = [
'#title' => $this->t('Destination Entity Type'),
'#description' => $this->t('The entity type that should be used for updating the data.'),
'#type' => 'select',
'#required' => TRUE,
'#options' => $default_values + $entityTypes,
'#default_value' => $inheritance->getDestinationEntityType(),
'#ajax' => [
'callback' => '::updateFieldOptions',
'wrapper' => 'field-inheritance-add-form--wrapper',
'event' => 'change',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Fetching destination options...'),
],
],
];
$form['config']['destination']['destination_entity_bundle'] = [
'#title' => $this->t('Destination Entity Bundle'),
'#description' => $this->t('The entity bundle to target.'),
'#type' => 'select',
'#required' => TRUE,
'#options' => $default_values + $destinationEntityBundles,
'#default_value' => $inheritance->getDestinationBundle(),
'#ajax' => [
'callback' => '::updateFieldOptions',
'wrapper' => 'field-inheritance-add-form--wrapper',
'event' => 'change',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Fetching destination options...'),
],
],
'#states' => [
'visible' => [
'select[name="destination_entity_type"]' => ['!value' => ''],
],
],
];
$form['config']['destination']['destination_entity_referencing_field'] = [
'#title' => $this->t('Destination Referencing Field'),
'#description' => $this->t('Field on the destination that references the destination entity.'),
'#type' => 'select',
'#required' => TRUE,
'#options' => $default_values + $destinationEntityReferenceFields,
'#default_value' => $inheritance->getDestinationReferenceField(),
'#ajax' => [
'callback' => '::updateFieldOptions',
'wrapper' => 'field-inheritance-add-form--wrapper',
'event' => 'change',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Fetching destination options...'),
],
],
'#states' => [
'visible' => [
'select[name="source_entity_type"]' => ['!value' => ''],
'select[name="destination_entity_type"]' => ['!value' => ''],
'select[name="destination_entity_bundle"]' => ['!value' => ''],
],
],
];
$form['config']['destination']['destination_entity_field'] = [
'#title' => $this->t('Destination Entity Field'),
'#description' => $this->t('The field to use for sending the data from the source.'),
'#type' => 'select',
'#required' => TRUE,
'#options' => $default_values + $destinationEntityFields,
'#default_value' => $inheritance->getDestinationField(),
'#ajax' => [
'callback' => '::updateFieldOptions',
'wrapper' => 'field-inheritance-add-form--wrapper',
'event' => 'change',
'progress' => [
'type' => 'throbber',
'message' => $this->t('Fetching destination options...'),
],
],
'#states' => [
'visible' => [
'select[name="source_entity_type"]' => ['!value' => ''],
'select[name="destination_entity_type"]' => ['!value' => ''],
'select[name="destination_entity_bundle"]' => ['!value' => ''],
'select[name="destination_entity_referencing_field"]' => ['!value' => ''],
],
],
];
return $form;
}
/**
* AJAX Callback: Update Field Options.
*/
public function updateFieldOptions(array &$form, FormStateInterface $form_state): AjaxResponse {
$form_state->setRebuild();
$response = new AjaxResponse();
$response->addCommand(new HtmlCommand('#field-inheritance-add-form--wrapper', $form));
return $response;
}
/**
* {@inheritdoc}
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
parent::validateForm($form, $form_state);
// Check if item with same source and destination exists.
if ($this->inheritanceExists([
'source_entity_type' => $form_state->getValue('source_entity_type'),
'source_entity_bundle' => $form_state->getValue('source_entity_bundle'),
'source_entity_field' => $form_state->getValue('source_entity_field'),
'destination_entity_type' => $form_state->getValue('destination_entity_type'),
'destination_entity_bundle' => $form_state->getValue('destination_entity_bundle'),
'destination_entity_field' => $form_state->getValue('destination_entity_field'),
], $form_state->getValue('id'))) {
$form_state->setErrorByName('', 'Configuration with source and destination already exist.');
}
// Check if item with the same destination exists.
if ($this->inheritanceExists([
'destination_entity_type' => $form_state->getValue('destination_entity_type'),
'destination_entity_bundle' => $form_state->getValue('destination_entity_bundle'),
'destination_entity_field' => $form_state->getValue('destination_entity_field'),
], $form_state->getValue('id'))) {
$form_state->setErrorByName('', 'Configuration with destination already exist.');
}
$this->getPluginForm($this->entity->getPlugin())->validateConfigurationForm($form['plugin']['settings'], SubformState::createForSubform($form['plugin']['settings'], $form, $form_state));
}
/**
* {@inheritdoc}
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
parent::submitForm($form, $form_state);
$inheritance = $this->entity;
$sub_form_state = SubformState::createForSubform($form['plugin']['settings'], $form, $form_state);
// Call the plugin submit handler.
$updater = $inheritance->getPlugin();
$this->getPluginForm($updater)->submitConfigurationForm($form, $sub_form_state);
}
/**
* Check to see if the inheritance configuration exists already.
*
* @param array $data
* Data to search for.
* @param string|null $id
* ID to remove if is found in the list.
*
* @return bool
* If items are found in the list.
*/
protected function inheritanceExists(array $data, ?string $id = NULL): bool {
$find = $this
->entityTypeManager
->getStorage('inheritance')
->loadByProperties($data);
if (!is_null($id)) {
unset($find[$id]);
}
return count($find) > 0;
}
/**
* {@inheritdoc}
*/
public function save(array $form, FormStateInterface $form_state) {
$result = parent::save($form, $form_state);
$message_args = ['%label' => $this->entity->label()];
$message = $result == SAVED_NEW
? $this->t('Created new inheritance configuration %label.', $message_args)
: $this->t('Updated inheritance configuration %label.', $message_args);
$this->messenger()->addStatus($message);
$form_state->setRedirectUrl($this->entity->toUrl('collection'));
return $result;
}
/**
* Retrieves the plugin form for a given inheritance updater and operation.
*
* @param \Drupal\entity_value_inheritance\EntityValueInheritanceUpdaterPluginInterface $inheritanceUpdaterPlugin
* The updater plugin.
*
* @return \Drupal\Core\Plugin\PluginFormInterface
* The plugin form for the block.
*/
protected function getPluginForm(EntityValueInheritanceUpdaterPluginInterface $inheritanceUpdaterPlugin) {
if ($inheritanceUpdaterPlugin instanceof PluginWithFormsInterface) {
return $this->pluginFormFactory->createInstance($inheritanceUpdaterPlugin, 'configure');
}
return $inheritanceUpdaterPlugin;
}
}
