public function LayoutParagraphsWidget::entityForm in Layout Paragraphs 1.0.x
Builds an entity form for a paragraph item.
Add form components in this rendering order: 1. Layout selection, if this is a layout paragraph. 2. The entity's fields from the form display. 3. The layout plugin config form, if exists. 4. The paragraph behaviors plugins form, if any exist.
Parameters
array $element: The form element.
\Drupal\Core\Form\FormStateInterface $form_state: The form_state object.
array $form: The form array.
Return value
array The entity form element.
1 call to LayoutParagraphsWidget::entityForm()
- LayoutParagraphsWidget::formMultipleElements in src/
Plugin/ Field/ FieldWidget/ LayoutParagraphsWidget.php - Builds the main widget form array container/wrapper.
File
- src/
Plugin/ Field/ FieldWidget/ LayoutParagraphsWidget.php, line 952
Class
- LayoutParagraphsWidget
- Entity Reference with Layout field widget.
Namespace
Drupal\layout_paragraphs\Plugin\Field\FieldWidgetCode
public function entityForm(array &$element, FormStateInterface $form_state, array &$form) {
$parents = $element['#parents'];
$widget_state = static::getWidgetState($parents, $this->fieldName, $form_state);
$delta = $widget_state['open_form'];
/** @var \Drupal\paragraphs\Entity\Paragraph $entity */
$entity = $widget_state['items'][$delta]['entity'];
// Set correct default language for the entity.
if ($this->isTranslating && ($language = $form_state
->get('langcode'))) {
$entity = $entity
->getTranslation($language);
}
$display = EntityFormDisplay::collectRenderDisplay($entity, 'default');
$bundle_label = $entity->type->entity
->label();
$element['entity_form'] = [
'#entity' => $entity,
'#prefix' => '<div class="layout-paragraphs-form entity-type-' . $entity
->bundle() . '">',
'#suffix' => '</div>',
'#type' => 'container',
'#parents' => array_merge($parents, [
$this->fieldName,
'entity_form',
$delta,
]),
'#weight' => 1000,
'#delta' => $delta,
'#display' => $display,
'#attributes' => [
'data-dialog-title' => [
$entity
->id() ? $this
->t('Edit @type', [
'@type' => $bundle_label,
]) : $this
->t('Create new @type', [
'@type' => $bundle_label,
]),
],
],
];
// Support for Field Group module based on Paragraphs module.
// @todo Remove as part of https://www.drupal.org/node/2640056
if ($this->moduleHandler
->moduleExists('field_group')) {
$context = [
'entity_type' => $entity
->getEntityTypeId(),
'bundle' => $entity
->bundle(),
'entity' => $entity,
'context' => 'form',
'display_context' => 'form',
'mode' => $display
->getMode(),
];
field_group_attach_groups($element['entity_form'], $context);
if (method_exists(FormatterHelper::class, 'formProcess')) {
$element['entity_form']['#process'][] = [
FormatterHelper::class,
'formProcess',
];
}
elseif (function_exists('field_group_form_pre_render')) {
$element['entity_form']['#pre_render'][] = 'field_group_form_pre_render';
}
elseif (function_exists('field_group_form_process')) {
$element['entity_form']['#process'][] = 'field_group_form_process';
}
}
$display
->buildForm($entity, $element['entity_form'], $form_state);
// Add layout selection form if "paragraphs layout" behavior is enabled.
if ($this
->isLayoutParagraph($entity)) {
$available_layouts = $this
->getAvailableLayouts($entity);
$layout_settings = $this
->getLayoutSettings($entity);
$layout = !empty($layout_settings['layout']) ? $layout_settings['layout'] : key($available_layouts);
$layout_plugin_config = $layout_settings['config'] ?? [];
$element['entity_form']['layout_selection'] = [
'#type' => 'container',
'#weight' => -1000,
'layout' => [
'#type' => 'radios',
'#title' => $this
->t('Select a layout:'),
'#options' => $available_layouts,
'#default_value' => $layout,
'#attributes' => [
'class' => [
'layout-paragraphs-layout-select',
],
],
'#required' => TRUE,
'#after_build' => [
[
$this,
'buildLayoutRadios',
],
],
],
'update' => [
'#type' => 'button',
'#value' => $this
->t('Update'),
'#name' => 'update_layout',
'#delta' => $delta,
'#limit_validation_errors' => [
array_merge($parents, [
$this->fieldName,
'entity_form',
$delta,
'layout_selection',
]),
],
'#attributes' => [
'class' => [
'js-hide',
],
],
'#element_parents' => $parents,
],
];
// Switching layouts should change the layout plugin options form
// with Ajax for users with adequate permissions.
if ($this->currentUser
->hasPermission('edit layout paragraphs plugin config')) {
$element['entity_form']['layout_selection']['layout']['#ajax'] = [
'event' => 'change',
'callback' => [
$this,
'buildLayoutConfigurationFormAjax',
],
'trigger_as' => [
'name' => 'update_layout',
],
'wrapper' => 'layout-config',
'progress' => 'none',
];
$element['entity_form']['layout_selection']['update']['#ajax'] = [
'callback' => [
$this,
'buildLayoutConfigurationFormAjax',
],
'wrapper' => 'layout-config',
'progress' => 'none',
];
}
$element['entity_form']['layout_plugin_form'] = [
'#prefix' => '<div id="layout-config">',
'#suffix' => '</div>',
'#access' => $this->currentUser
->hasPermission('edit layout paragraphs plugin config'),
];
// Add the layout configuration form if applicable.
$layout_select_parents = array_merge($parents, [
$this->fieldName,
'entity_form',
$delta,
'layout_selection',
'layout',
]);
$updated_layout = $form_state
->getValue($layout_select_parents) ?? $layout;
if (!empty($updated_layout)) {
try {
$updated_layout_instance = $this->layoutPluginManager
->createInstance($updated_layout, $layout_plugin_config);
// If the user selects a new layout,
// we provide a way for them to choose
// what to do with items from regions
// that no longer exist.
if ($layout && $updated_layout != $layout) {
$move_items = [];
$original_layout = $this->layoutPluginManager
->createInstance($layout);
$original_definition = $original_layout
->getPluginDefinition();
$original_regions = $original_definition
->getRegions();
$updated_layout_definition = $updated_layout_instance
->getPluginDefinition();
$updated_regions = $updated_layout_definition
->getRegions();
$updated_regions_options = [];
foreach ($updated_regions as $region_name => $region) {
$updated_regions_options[$region_name] = $region['label'];
}
$updated_regions_options['_disabled'] = $this
->t('Disabled');
foreach ($original_regions as $region_name => $region) {
if (!isset($updated_regions[$region_name]) && $this
->hasChildren($entity, $widget_state['items'], $region_name)) {
$move_items[$region_name] = [
'#type' => 'select',
'#wrapper_attributes' => [
'class' => [
'container-inline',
],
],
'#title' => $this
->t('Move items from the "@region" region to', [
'@region' => $region['label'],
]),
'#options' => $updated_regions_options,
];
}
}
if (count($move_items)) {
$element['entity_form']['layout_selection']['move_items'] = [
'#type' => 'fieldset',
'#title' => $this
->t('Move orphaned items'),
'#description' => $this
->t('The layout you selected has different regions than the previous one.'),
'items' => $move_items,
];
}
}
if ($layout_plugin = $this
->getLayoutPluginForm($updated_layout_instance)) {
$element['entity_form']['layout_plugin_form'] += [
'#type' => 'details',
'#title' => $this
->t('Layout Configuration'),
'#weight' => 999,
];
$element['entity_form']['layout_plugin_form'] += $layout_plugin
->buildConfigurationForm([], $form_state);
}
} catch (\Exception $e) {
watchdog_exception('Layout Paragraphs, updating_layout', $e);
}
}
}
// Add behavior forms if applicable.
$paragraphs_type = $entity
->getParagraphType();
// @todo: Check translation functionality.
if ($paragraphs_type && $this->currentUser
->hasPermission('edit behavior plugin settings') && (!$this->isTranslating || !$entity
->isDefaultTranslationAffectedOnly()) && ($behavior_plugins = $paragraphs_type
->getEnabledBehaviorPlugins())) {
$has_behavior_plugin_form = FALSE;
$element['entity_form']['behavior_plugins'] = [
'#type' => 'details',
'#title' => $this
->t('Behaviors'),
'#element_validate' => [
[
$this,
'validateBehaviors',
],
],
'#entity' => $entity,
'#weight' => -99,
];
foreach ($behavior_plugins as $plugin_id => $plugin) {
$element['entity_form']['behavior_plugins'][$plugin_id] = [
'#type' => 'container',
];
$subform_state = SubformState::createForSubform($element['entity_form']['behavior_plugins'][$plugin_id], $form, $form_state);
$plugin_form = $plugin
->buildBehaviorForm($entity, $element['entity_form']['behavior_plugins'][$plugin_id], $subform_state);
if (!empty(Element::children($plugin_form))) {
$element['entity_form']['behavior_plugins'][$plugin_id] = $plugin_form;
$has_behavior_plugin_form = TRUE;
}
}
if (!$has_behavior_plugin_form) {
unset($element['entity_form']['behavior_plugins']);
}
}
// Add save, cancel, etc.
$element['entity_form'] += [
'actions' => [
'#weight' => 1000,
'#type' => 'actions',
'#attributes' => [
'class' => [
'layout-paragraphs-item-form-actions',
],
],
'submit' => [
'#type' => 'submit',
'#name' => 'save',
'#value' => $this
->t('Save'),
'#delta' => $delta,
'#uuid' => $entity
->uuid(),
'#limit_validation_errors' => [
array_merge($parents, [
$this->fieldName,
'entity_form',
$delta,
]),
],
'#submit' => [
[
$this,
'saveItemSubmit',
],
],
'#ajax' => [
'callback' => [
$this,
'saveItemAjax',
],
'progress' => 'none',
],
'#element_parents' => $parents,
],
'cancel' => [
'#type' => 'submit',
'#name' => 'cancel',
'#value' => $this
->t('Cancel'),
'#limit_validation_errors' => [],
'#delta' => $delta,
'#submit' => [
[
$this,
'cancelItemSubmit',
],
],
'#attributes' => [
'class' => [
'layout-paragraphs-cancel',
'button--danger',
],
],
'#ajax' => [
'callback' => [
$this,
'closeDialogAjax',
],
'progress' => 'none',
],
'#element_parents' => $parents,
],
],
];
$hide_untranslatable_fields = $entity
->isDefaultTranslationAffectedOnly();
foreach (Element::children($element['entity_form']) as $field) {
if ($entity
->hasField($field)) {
/** @var \Drupal\Core\Field\FieldDefinitionInterface $field_definition */
$field_definition = $entity
->get($field)
->getFieldDefinition();
$translatable = $entity->{$field}
->getFieldDefinition()
->isTranslatable();
// Do a check if we have to add a class to the form element. We need
// those classes (paragraphs-content and paragraphs-behavior) to show
// and hide elements, depending of the active perspective.
// We need them to filter out entity reference revisions fields that
// reference paragraphs, cause otherwise we have problems with showing
// and hiding the right fields in nested paragraphs.
$is_paragraph_field = FALSE;
if ($field_definition
->getType() == 'entity_reference_revisions') {
// Check if we are referencing paragraphs.
if ($field_definition
->getSetting('target_type') == 'paragraph') {
$is_paragraph_field = TRUE;
}
}
if (!$translatable && $this->isTranslating && !$is_paragraph_field) {
if ($hide_untranslatable_fields) {
$element['entity_form'][$field]['#access'] = FALSE;
}
else {
$element['entity_form'][$field]['widget']['#after_build'][] = [
static::class,
'addTranslatabilityClue',
];
}
}
}
}
// Add compatibility for Inline Entity Form module.
// See https://www.drupal.org/project/inline_entity_form/issues/3160809
// and https://www.drupal.org/project/layout_paragraphs/issues/3160806
$ief_widget_state = $form_state
->get('inline_entity_form');
if (!is_null($ief_widget_state)) {
ElementSubmit::attach($element['entity_form'], $form_state);
WidgetSubmit::attach($element['entity_form'], $form_state);
}
// Allow others modules to adjust the Layout Paragraph Element Dialog Form.
$this->moduleHandler
->alter('layout_paragraph_element_form', $element['entity_form'], $form_state, $form);
return $element;
}