View source
<?php
namespace Drupal\layout_paragraphs\Form;
use Drupal\Core\Form\FormBase;
use Drupal\Component\Utility\Html;
use Drupal\Core\Ajax\AjaxResponse;
use Drupal\Core\Form\SubformState;
use Drupal\Core\Access\AccessResult;
use Drupal\field_group\FormatterHelper;
use Drupal\Core\Extension\ModuleHandler;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Ajax\AjaxFormHelperTrait;
use Drupal\Core\Ajax\CloseDialogCommand;
use Drupal\Core\Layout\LayoutPluginManager;
use Drupal\Core\Entity\Entity\EntityFormDisplay;
use Drupal\Core\Entity\EntityRepositoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Drupal\layout_paragraphs\LayoutParagraphsLayoutRefreshTrait;
use Drupal\layout_paragraphs\LayoutParagraphsLayoutTempstoreRepository;
use Drupal\layout_paragraphs\DialogHelperTrait;
abstract class ComponentFormBase extends FormBase {
use AjaxFormHelperTrait;
use LayoutParagraphsLayoutRefreshTrait;
use DialogHelperTrait;
protected $tempstore;
protected $entityTypeManager;
protected $layoutPluginManager;
protected $paragraphType;
protected $paragraph;
protected $moduleHandler;
protected $entityRepository;
public function __construct(LayoutParagraphsLayoutTempstoreRepository $tempstore, EntityTypeManagerInterface $entity_type_manager, LayoutPluginManager $layout_plugin_manager, ModuleHandler $module_handler, EventDispatcherInterface $event_dispatcher, EntityRepositoryInterface $entity_repository) {
$this->tempstore = $tempstore;
$this->entityTypeManager = $entity_type_manager;
$this->layoutPluginManager = $layout_plugin_manager;
$this->moduleHandler = $module_handler;
$this->eventDispatcher = $event_dispatcher;
$this->entityRepository = $entity_repository;
}
public static function create(ContainerInterface $container) {
return new static($container
->get('layout_paragraphs.tempstore_repository'), $container
->get('entity_type.manager'), $container
->get('plugin.manager.core.layout'), $container
->get('module_handler'), $container
->get('event_dispatcher'), $container
->get('entity.repository'));
}
public function getFormId() {
return 'layout_paragraphs_component_form';
}
protected function buildComponentForm(array $form, FormStateInterface $form_state) {
$this
->initFormLangcodes($form_state);
$display = EntityFormDisplay::collectRenderDisplay($this->paragraph, 'default');
$display
->buildForm($this->paragraph, $form, $form_state);
$this->paragraphType = $this->paragraph
->getParagraphType();
$lp_config = $this
->config('layout_paragraphs.settings');
$form += [
'#title' => $this
->formTitle(),
'#paragraph' => $this->paragraph,
'#display' => $display,
'#tree' => TRUE,
'#after_build' => [
[
$this,
'afterBuild',
],
],
'actions' => [
'#weight' => 100,
'#type' => 'actions',
'submit' => [
'#type' => 'submit',
'#value' => $this
->t('Save'),
'#ajax' => [
'callback' => '::ajaxSubmit',
'progress' => 'none',
],
'#attributes' => [
'class' => [
'lpb-btn--save',
],
'data-disable-refocus' => 'true',
],
],
'cancel' => [
'#type' => 'button',
'#value' => $this
->t('Cancel'),
'#ajax' => [
'callback' => '::cancel',
'progress' => 'none',
],
'#attributes' => [
'class' => [
'dialog-cancel',
'lpb-btn--cancel',
],
],
],
],
];
if ($this->paragraphType
->hasEnabledBehaviorPlugin('layout_paragraphs')) {
$form['layout_paragraphs'] = [
'#process' => [
[
$this,
'layoutParagraphsBehaviorForm',
],
],
];
}
if (count($this
->getEnabledBehaviorPlugins())) {
$form['behavior_plugins'] = [
'#weight' => $lp_config
->get('paragraph_behaviors_position') ?? -99,
'#type' => 'details',
'#title' => $lp_config
->get('paragraph_behaviors_label') ?? $this
->t('Behaviors'),
'#process' => [
[
$this,
'behaviorPluginsForm',
],
],
];
}
if ($this->moduleHandler
->moduleExists('field_group')) {
$context = [
'entity_type' => $this->paragraph
->getEntityTypeId(),
'bundle' => $this->paragraph
->bundle(),
'entity' => $this->paragraph,
'context' => 'form',
'display_context' => 'form',
'mode' => $display
->getMode(),
];
field_group_attach_groups($form, $context);
if (method_exists(FormatterHelper::class, 'formProcess')) {
$form['#process'][] = [
FormatterHelper::class,
'formProcess',
];
}
elseif (function_exists('field_group_form_pre_render')) {
$form['#pre_render'][] = 'field_group_form_pre_render';
}
elseif (function_exists('field_group_form_process')) {
$form['#process'][] = 'field_group_form_process';
}
}
return $form;
}
public function validateForm(array &$form, FormStateInterface $form_state) {
foreach ($this
->getEnabledBehaviorPlugins() as $behavior_id => $behavior_plugin) {
if (!empty($form['behavior_plugins'][$behavior_id])) {
$subform_state = SubformState::createForSubform($form['behavior_plugins'][$behavior_id], $form_state
->getCompleteForm(), $form_state);
$behavior_plugin
->validateBehaviorForm($this->paragraph, $form['behavior_plugins'][$behavior_id], $subform_state);
}
}
$paragraph = $this
->buildParagraphComponent($form, $form_state);
$violations = $paragraph
->validate();
$violations
->filterByFieldAccess($this
->currentUser());
$paragraph
->setValidationRequired(FALSE);
foreach ($violations
->getEntityViolations() as $violation) {
$form_state
->setErrorByName('', $violation
->getMessage());
}
$form['#display']
->flagWidgetsErrorsFromViolations($violations, $form, $form_state);
}
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->paragraph = $this
->buildParagraphComponent($form, $form_state);
}
protected function buildParagraphComponent(array $form, FormStateInterface $form_state) {
$display = $form['#display'];
$paragraph = clone $this->paragraph;
$paragraph
->getAllBehaviorSettings();
$paragraphs_type = $paragraph
->getParagraphType();
if ($paragraphs_type
->hasEnabledBehaviorPlugin('layout_paragraphs')) {
$layout_paragraphs_plugin = $paragraphs_type
->getEnabledBehaviorPlugins()['layout_paragraphs'];
$subform_state = SubformState::createForSubform($form['layout_paragraphs'], $form, $form_state);
$layout_paragraphs_plugin
->submitBehaviorForm($paragraph, $form['layout_paragraphs'], $subform_state);
}
foreach ($this
->getEnabledBehaviorPlugins() as $behavior_id => $behavior_plugin) {
$subform_state = SubformState::createForSubform($form['behavior_plugins'][$behavior_id], $form, $form_state);
$behavior_plugin
->submitBehaviorForm($paragraph, $form['behavior_plugins'][$behavior_id], $subform_state);
}
$paragraph
->setNeedsSave(TRUE);
$display
->extractFormValues($paragraph, $form, $form_state);
return $paragraph;
}
protected function formTitle() {
return $this
->t('Component form');
}
public function afterBuild(array $element, FormStateInterface $form_state) {
$parents = array_merge($element['#parents'], [
$this
->getFormId(),
]);
$unprocessed_id = 'edit-' . implode('-', $parents);
$element['#attributes']['data-drupal-selector'] = Html::getId($unprocessed_id);
$element['#dialog_id'] = $unprocessed_id . '-dialog';
return $element;
}
public function layoutParagraphsBehaviorForm(array $element, FormStateInterface $form_state, array &$form) {
$layout_paragraphs_plugin = $this->paragraphType
->getEnabledBehaviorPlugins()['layout_paragraphs'];
$subform_state = SubformState::createForSubform($element, $form, $form_state);
if ($layout_paragraphs_plugin_form = $layout_paragraphs_plugin
->buildBehaviorForm($this->paragraph, $element, $subform_state)) {
$element = $layout_paragraphs_plugin_form;
$element_id = Html::getId('layout-paragraphs-element');
$element['#prefix'] = '<div id="' . $element_id . '">';
$element['#suffix'] = '</div>';
$element['layout']['#ajax']['callback'] = [
$this,
'ajaxCallback',
];
$element['layout']['#ajax']['wrapper'] = $element_id;
}
return $element;
}
public function behaviorPluginsForm(array $element, FormStateInterface $form_state, array &$form) {
$element['#type'] = 'container';
$element['#attributes']['class'][] = 'lpb-behavior-plugins';
foreach ($this
->getEnabledBehaviorPlugins() as $behavior_id => $behavior_plugin) {
$element[$behavior_id] = [
'#parents' => array_merge($element['#parents'], [
$behavior_id,
]),
'#type' => 'container',
'#attributes' => [
'class' => [
'lpb-behavior-plugins__' . Html::cleanCssIdentifier($behavior_id),
],
],
];
$subform_state = SubformState::createForSubform($element[$behavior_id], $form, $form_state);
if ($behavior_form = $behavior_plugin
->buildBehaviorForm($this->paragraph, $element[$behavior_id], $subform_state)) {
$element[$behavior_id] = $behavior_form;
}
}
return $element;
}
public function ajaxCallback(array $form, FormStateInterface $form_state) {
return $form['layout_paragraphs'];
}
public function cancel(array &$form, FormStateInterface $form_state) {
$response = new AjaxResponse();
$this
->ajaxCloseForm($response);
return $response;
}
public function access() {
return AccessResult::allowed();
}
protected function ajaxCloseForm(AjaxResponse &$response) {
$selector = $this
->dialogSelector($this->layoutParagraphsLayout);
$response
->addCommand(new CloseDialogCommand($selector));
}
protected function renderParagraph(string $uuid) {
return [
'#type' => 'layout_paragraphs_builder',
'#layout_paragraphs_layout' => $this->layoutParagraphsLayout,
'#uuid' => $uuid,
];
}
protected function getLayoutRegionNames($layout_id) {
return array_map(function ($region) {
return $region['label'];
}, $this
->getLayoutRegions($layout_id));
}
protected function getLayoutRegions($layout_id) {
if (!$layout_id) {
return [];
}
$instance = $this->layoutPluginManager
->createInstance($layout_id);
$definition = $instance
->getPluginDefinition();
return $definition
->getRegions();
}
protected function initFormLangcodes(FormStateInterface $form_state) {
if (!$form_state
->has('entity_default_langcode')) {
$form_state
->set('entity_default_langcode', $this->paragraph
->getUntranslated()
->language()
->getId());
}
if (!$form_state
->has('langcode')) {
$form_state
->set('langcode', $this->entityRepository
->getTranslationFromContext($this->paragraph)
->language()
->getId());
}
}
protected function getEnabledBehaviorPlugins() {
if ($this
->currentUser()
->hasPermission('edit behavior plugin settings')) {
return array_filter($this->paragraphType
->getEnabledBehaviorPlugins(), function ($key) {
return $key != 'layout_paragraphs';
}, ARRAY_FILTER_USE_KEY);
}
return [];
}
}