View source
<?php
namespace Drupal\flexiform;
use Drupal\Core\Entity\EntityStorageInterface;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\FieldableEntityInterface;
use Drupal\Core\Render\Element;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Form\FormState;
use Drupal\flexiform\FormComponent\FormComponentWithSubmitInterface;
use Drupal\flexiform\FormComponent\FormComponentWithValidateInterface;
use Drupal\flexiform\FormEntity\FlexiformFormEntityManager;
use Drupal\flexiform\FormEnhancer\ConfigurableFormEnhancerInterface;
class FlexiformEntityFormDisplay extends EntityFormDisplay implements FlexiformEntityFormDisplayInterface {
protected $baseEntityNamespace = '';
protected $formEntities = [];
protected $formEnhancers = [];
protected $formEntityManager;
protected $formEntityManagerSuppliedNamespaces;
protected $componentTypePlugins = [];
protected $providedEntities = [];
public static function collectRenderDisplayLight($entity_type, $bundle, $form_mode) {
if ($form_mode != 'default') {
$candidate_ids[] = $entity_type . '.' . $bundle . '.' . $form_mode;
}
$candidate_ids[] = $entity_type . '.' . $bundle . '.default';
$results = \Drupal::entityQuery('entity_form_display')
->condition('id', $candidate_ids)
->condition('status', TRUE)
->execute();
$storage = \Drupal::entityManager()
->getStorage('entity_form_display');
foreach ($candidate_ids as $candidate_id) {
if (isset($results[$candidate_id])) {
$display = $storage
->load($candidate_id);
break;
}
}
if (empty($display)) {
$display = $storage
->create([
'targetEntityType' => $entity_type,
'bundle' => $bundle,
'mode' => $form_mode,
'status' => TRUE,
]);
}
$display->originalMode = $form_mode;
$display_context = [
'entity_type' => $entity_type,
'bundle' => $bundle,
'form_mode' => $form_mode,
];
\Drupal::moduleHandler()
->alter('entity_form_display', $display, $display_context);
return $display;
}
public function getRegions() {
return [
'content' => [
'title' => t('Content'),
'invisible' => TRUE,
'message' => t('No component is displayed.'),
],
'hidden' => [
'title' => t('Disabled', [], [
'context' => 'Plural',
]),
'message' => t('No component is hidden.'),
],
];
}
public function getRegionOptions() {
$options = [];
foreach ($this
->getRegions() as $region => $data) {
$options[$region] = $data['title'];
}
return $options;
}
public function preSave(EntityStorageInterface $storage, $update = TRUE) {
$enhancer_settings = $this
->getThirdPartySetting('flexiform', 'enhancer', []);
foreach ($this->formEnhancers as $enhancer_name => $enhancer) {
if ($enhancer instanceof ConfigurableFormEnhancerInterface) {
if ($this
->isSyncing()) {
if (isset($enhancer_settings[$enhancer_name])) {
$enhancer
->setConfiguration($enhancer_settings[$enhancer_name]);
}
}
else {
$config = $enhancer
->getConfiguration();
$config['id'] = $enhancer
->getPluginId();
$enhancer_settings[$enhancer_name] = $config;
}
}
}
if (!$this
->isSyncing()) {
$this
->setThirdPartySetting('flexiform', 'enhancer', $enhancer_settings);
}
parent::preSave($storage, $update);
}
public static function postLoad(EntityStorageInterface $storage, array &$entities) {
foreach ($entities as $entity) {
$entity
->initFormEntityConfig();
}
parent::postLoad($storage, $entities);
}
public function getComponentPlugin($name, $options, FlexiformFormEntityManager $form_entity_manager) {
$plugin_id = !empty($options['component_type']) ? $options['component_type'] : (empty($options['type']) ? 'extra_field' : 'field_widget');
return $this
->getComponentTypePlugin($plugin_id, $form_entity_manager)
->getComponent($name, $options)
->setFormEntityManager($form_entity_manager);
}
public function getComponentTypePlugin($plugin_id, FlexiformFormEntityManager $formEntityManager) {
if (empty($this->componentTypePlugins[$plugin_id])) {
$this->componentTypePlugins[$plugin_id] = \Drupal::service('plugin.manager.flexiform.form_component_type')
->createInstance($plugin_id)
->setFormDisplay($this);
if ($formEntityManager) {
$this->componentTypePlugins[$plugin_id]
->setFormEntityManager($formEntityManager);
}
}
return $this->componentTypePlugins[$plugin_id];
}
protected function getProvidedEntities(FormStateInterface $form_state, FieldableEntityInterface $base_entity = NULL) {
$provided = [];
if ($base_entity) {
$provided[$this->baseEntityNamespace] = $base_entity;
}
$provided += $form_state
->get('form_entity_provided') ?: [];
return $provided;
}
public function buildForm(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state) {
$this
->buildAdvancedForm($this
->getProvidedEntities($form_state, $entity), $form, $form_state);
}
public function buildAdvancedForm(array $provided, array &$form, FormStateInterface $form_state) {
$form += [
'#parents' => [],
'#array_parents' => [],
];
$original_parents = $form['#parents'];
$form_state = $this
->decorateFormState($form, $form_state);
$this
->getFormEntityManager($form_state, $provided);
foreach ($this
->getComponents() as $name => $options) {
$component = $this
->getComponentPlugin($name, $options, $form_state
->getFormEntityManager());
$form['#parents'] = $original_parents;
$component
->render($form, $form_state, $this->renderer);
}
$form['#parents'] = $original_parents;
$this->renderer
->addCacheableDependency($form, $this);
$form['#process'][] = [
$this,
'processForm',
];
}
public function processForm($element, FormStateInterface $form_state, $form) {
$element = parent::processForm($element, $form_state, $form);
foreach ($this
->getFormEnhancers('process_form') as $enhancer) {
$element = $enhancer
->processForm($element, $form_state, $form);
}
static::addSaveFormEntitiesSubmit($element, $this);
return $element;
}
public function extractFormValues(FieldableEntityInterface $entity, array &$form, FormStateInterface $form_state) {
$extracted = [];
$form_state = $this
->decorateFormState($form, $form_state);
$this
->getFormEntityManager($form_state, $this
->getProvidedEntities($form_state, $entity), TRUE);
foreach ($this
->getComponents() as $name => $options) {
if (($component = $this
->getComponentPlugin($name, $options, $form_state
->getFormEntityManager())) && !empty($form[$name])) {
$component
->extractFormValues($form[$name], $form_state);
$extracted[$name] = $name;
}
}
return $extracted;
}
public function formValidateComponents(array $form, FormStateInterface $form_state) {
$form_state = $this
->decorateFormState($form, $form_state);
foreach ($this
->getComponents() as $name => $options) {
if ($component = $this
->getComponentPlugin($name, $options, $form_state
->getFormEntityManager())) {
if ($component instanceof FormComponentWithValidateInterface) {
$component
->formValidate($form[$name], $form_state);
}
}
}
}
public function formSubmitComponents(array $form, FormStateInterface $form_state) {
$form_state = $this
->decorateFormState($form, $form_state);
foreach ($this
->getComponents() as $name => $options) {
if ($component = $this
->getComponentPlugin($name, $options, $form_state
->getFormEntityManager())) {
if ($component instanceof FormComponentWithSubmitInterface) {
$component
->formSubmit($form[$name], $form_state);
}
}
}
}
public function saveFormEntities(array $form, FormStateInterface $form_state) {
$form_state = $this
->decorateFormState($form, $form_state);
$form_state
->getFormEntityManager()
->saveFormEntities();
}
public static function addSaveFormEntitiesSubmit(array &$element, FlexiformEntityFormDisplayInterface $form_display) {
if (isset($element['#type']) && $element['#type'] == 'submit') {
if (!empty($element['#submit']) && in_array('::save', $element['#submit'])) {
$new_submit = [];
foreach ($element['#submit'] as $callback) {
if ($callback == '::save') {
$new_submit[] = [
$form_display,
'formSubmitComponents',
];
}
$new_submit[] = $callback;
if ($callback == '::save') {
$new_submit[] = [
$form_display,
'saveFormEntities',
];
}
}
$element['#submit'] = $new_submit;
}
if (!empty($element['#validate'])) {
$element['#validate'][] = [
$form_display,
'formValidateComponents',
];
}
}
else {
foreach (Element::children($element) as $key) {
FlexiformEntityFormDisplay::addSaveFormEntitiesSubmit($element[$key], $form_display);
}
}
}
public function getFormEntityConfig() {
$this
->initFormEntityConfig();
return $this->formEntities;
}
public function initFormEntityConfig() {
if (empty($this->formEntities)) {
$this->formEntities = [];
$form_entities = [];
foreach ($this
->getFormEnhancers('init_form_entity_config') as $enhancer) {
$form_entities += $enhancer
->initFormEntityConfig();
}
if ($this
->getTargetEntityTypeId() && empty($form_entities[$this->baseEntityNamespace])) {
$this->formEntities[$this->baseEntityNamespace] = [
'entity_type' => $this
->getTargetEntityTypeId(),
'bundle' => $this
->getTargetBundle(),
'plugin' => 'provided',
'label' => t('Base @entity_type', [
'@entity_type' => \Drupal::service('entity_type.manager')
->getDefinition($this
->getTargetEntityTypeId())
->getLabel(),
]),
];
}
$this->formEntities += $form_entities;
}
}
public function getFormEntityManager(MultipleEntityFormStateInterface $form_state, array $provided = [], $reset = FALSE) {
$provided += $this->providedEntities;
$this->providedEntities = $provided;
if (!$form_state
->getFormEntityManager() || $reset) {
$form_state
->setFormEntityManager(new FlexiformFormEntityManager($this, $provided));
}
return $form_state
->getFormEntityManager();
}
public function getFormEnhancers($event = NULL) {
if (empty($this->formEnhancers)) {
$enhancer_settings = $this
->getThirdPartySetting('flexiform', 'enhancer', []);
$enhancer_definitions = \Drupal::service('plugin.manager.flexiform.form_enhancer')
->getDefinitions();
foreach ($enhancer_definitions as $plugin_id => $definition) {
$this->formEnhancers[$plugin_id] = \Drupal::service('plugin.manager.flexiform.form_enhancer')
->createInstance($plugin_id, isset($enhancer_settings[$plugin_id]) ? $enhancer_settings[$plugin_id] : [])
->setFormDisplay($this);
}
}
if (is_null($event)) {
return $this->formEnhancers;
}
$applicable_enhancer_names = [];
foreach ($this->formEnhancers as $plugin_id => $enhancer) {
if (($weight = $enhancer
->applies($event)) !== FALSE) {
$applicable_enhancer_names[$plugin_id] = $weight;
}
}
asort($applicable_enhancer_names);
$applicable_enhancers = [];
foreach ($applicable_enhancer_names as $plugin_id => $weight) {
$applicable_enhancers[$plugin_id] = $this->formEnhancers[$plugin_id];
}
return $applicable_enhancers;
}
public function getFormEnhancer($enhancer_name) {
if (empty($this->formEnhancers)) {
$this
->getFormEnhancers();
}
return isset($this->formEnhancers[$enhancer_name]) ? $this->formEnhancers[$enhancer_name] : NULL;
}
public function getFormInformation() {
$operation = $this
->get('originalMode') ?: $this
->get('mode');
$form_object = \Drupal::service('flexiform.manager')
->getFormObject($this);
$default_values = [];
if ($bundle_key = $this
->entityTypeManager()
->getDefinition($this
->getTargetEntityTypeId())
->getKey('bundle')) {
$default_values[$bundle_key] = $this
->getTargetBundle();
}
$form_object
->setEntity($this
->entityTypeManager()
->getStorage($this
->getTargetEntityTypeId())
->create($default_values));
$form_state = new FormState();
return [
'form_object' => $form_object,
'form_state' => $form_state,
'form' => \Drupal::service('form_builder')
->buildForm($form_object, $form_state),
];
}
public function getBaseEntityNamespace() {
return $this->baseEntityNamespace;
}
protected function decorateFormState(array &$form, FormStateInterface $form_state) {
return MultipleEntityFormState::createForForm($form, $form_state);
}
}