abstract class ComponentFormBase in Layout Paragraphs 2.0.x
Class LayoutParagraphsComponentFormBase.
Base form for Layout Paragraphs component forms.
Hierarchy
- class \Drupal\Core\Form\FormBase implements ContainerInjectionInterface, FormInterface uses DependencySerializationTrait, LoggerChannelTrait, MessengerTrait, RedirectDestinationTrait, StringTranslationTrait
- class \Drupal\layout_paragraphs\Form\ComponentFormBase uses AjaxFormHelperTrait, DialogHelperTrait, LayoutParagraphsLayoutRefreshTrait
Expanded class hierarchy of ComponentFormBase
File
- src/
Form/ ComponentFormBase.php, line 30
Namespace
Drupal\layout_paragraphs\FormView source
abstract class ComponentFormBase extends FormBase {
use AjaxFormHelperTrait;
use LayoutParagraphsLayoutRefreshTrait;
use DialogHelperTrait;
/**
* The tempstore service.
*
* @var \Drupal\layout_paragraphs\LayoutParagraphsLayoutTempstoreRepository
*/
protected $tempstore;
/**
* The entity type manager service.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The layout plugin manager service.
*
* @var \Drupal\Core\Layout\LayoutPluginManager
*/
protected $layoutPluginManager;
/**
* The paragraph type.
*
* @var \Drupal\paragraphs\Entity\ParagraphsType
*/
protected $paragraphType;
/**
* The paragraph.
*
* @var \Drupal\paragraphs\Entity\Paragraph
*/
protected $paragraph;
/**
* The module handler service.
*
* @var \Drupal\Core\Extension\ModuleHandler
*/
protected $moduleHandler;
/**
* The entity repository service.
*
* @var \Drupal\Core\Entity\EntityRepositoryInterface
*/
protected $entityRepository;
/**
* {@inheritDoc}
*/
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;
}
/**
* {@inheritDoc}
*/
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'));
}
/**
* {@inheritDoc}
*/
public function getFormId() {
return 'layout_paragraphs_component_form';
}
/**
* Builds a component (paragraph) edit form.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
*/
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',
],
],
];
}
// 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' => $this->paragraph
->getEntityTypeId(),
'bundle' => $this->paragraph
->bundle(),
'entity' => $this->paragraph,
'context' => 'form',
'display_context' => 'form',
'mode' => $display
->getMode(),
];
// phpcs:ignore
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;
}
/**
* Validate the component form.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
*/
public function validateForm(array &$form, FormStateInterface $form_state) {
// First validate paragraph behavior forms.
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);
}
}
// Validate the paragraph with submitted form values.
$paragraph = $this
->buildParagraphComponent($form, $form_state);
$violations = $paragraph
->validate();
// Remove violations of inaccessible fields.
$violations
->filterByFieldAccess($this
->currentUser());
// The paragraph component was validated.
$paragraph
->setValidationRequired(FALSE);
// Flag entity level violations.
foreach ($violations
->getEntityViolations() as $violation) {
/** @var \Symfony\Component\Validator\ConstraintViolationInterface $violation */
$form_state
->setErrorByName('', $violation
->getMessage());
}
$form['#display']
->flagWidgetsErrorsFromViolations($violations, $form, $form_state);
}
/**
* Saves the paragraph component.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
*/
public function submitForm(array &$form, FormStateInterface $form_state) {
$this->paragraph = $this
->buildParagraphComponent($form, $form_state);
}
/**
* Builds the paragraph component using submitted form values.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state object.
*
* @return \Drupal\paragraphs\Entity\Paragraph
* The paragraph entity.
*/
protected function buildParagraphComponent(array $form, FormStateInterface $form_state) {
/** @var Drupal\Core\Entity\Entity\EntityFormDisplay $display */
$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;
}
/**
* Create the form title.
*
* @return \Drupal\Core\StringTranslation\TranslatableMarkup
* The form title.
*/
protected function formTitle() {
return $this
->t('Component form');
}
/**
* After build callback fixes issues with data-drupal-selector.
*
* See https://www.drupal.org/project/drupal/issues/2897377
*
* @param array $element
* The form element.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return array
* The form element.
*/
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;
}
/**
* Form #process callback.
*
* Renders the layout paragraphs behavior form for layout selection.
*
* @param array $element
* The form element.
* @param Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param array $form
* The complete form array.
*
* @return array
* The processed 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;
// Adjust the Ajax callback to include the entire layout paragraphs 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;
}
/**
* Form #process callback.
*
* Attaches the behavior plugin forms.
*
* @param array $element
* The form element.
* @param Drupal\Core\Form\FormStateInterface $form_state
* The form state.
* @param array $form
* The complete form array.
*
* @return array
* The processed 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;
}
/**
* Ajax form callback.
*
* Returns the layout paragraphs behavior form,
* which includes the orphaned items element when necessary.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return array
* The render array.
*/
public function ajaxCallback(array $form, FormStateInterface $form_state) {
return $form['layout_paragraphs'];
}
/**
* Form #ajax callback.
*
* Cancels the edit operation and closes the dialog.
*
* @param array $form
* The form array.
* @param Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return Drupal\Core\Ajax\AjaxResponse
* The Ajax response.
*/
public function cancel(array &$form, FormStateInterface $form_state) {
$response = new AjaxResponse();
$this
->ajaxCloseForm($response);
return $response;
}
/**
* Access check.
*
* @todo Actually check something.
*
* @return bool
* True if access.
*/
public function access() {
return AccessResult::allowed();
}
/**
* Closes the form with ajax.
*
* @param \Drupal\Core\Ajax\AjaxResponse $response
* The ajax response.
*/
protected function ajaxCloseForm(AjaxResponse &$response) {
$selector = $this
->dialogSelector($this->layoutParagraphsLayout);
$response
->addCommand(new CloseDialogCommand($selector));
}
/**
* Renders a single Layout Paragraphs Layout paragraph entity.
*
* @param string $uuid
* The uuid of the paragraph entity to render.
*
* @return array
* The paragraph render array.
*/
protected function renderParagraph(string $uuid) {
return [
'#type' => 'layout_paragraphs_builder',
'#layout_paragraphs_layout' => $this->layoutParagraphsLayout,
'#uuid' => $uuid,
];
}
/**
* Returns an array of region names for a given layout.
*
* @param string $layout_id
* The layout id.
*
* @return array
* An array of regions.
*/
protected function getLayoutRegionNames($layout_id) {
return array_map(function ($region) {
return $region['label'];
}, $this
->getLayoutRegions($layout_id));
}
/**
* Returns an array of regions for a given layout.
*
* @param string $layout_id
* The layout id.
*
* @return array
* An array of regions.
*/
protected function getLayoutRegions($layout_id) {
if (!$layout_id) {
return [];
}
$instance = $this->layoutPluginManager
->createInstance($layout_id);
$definition = $instance
->getPluginDefinition();
return $definition
->getRegions();
}
/**
* Initializes form language code values.
*
* See Drupal\Core\Entity\ContentEntityForm.
*
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The current state of the form.
*/
protected function initFormLangcodes(FormStateInterface $form_state) {
// Store the entity default language to allow checking whether the form is
// dealing with the original entity or a translation.
if (!$form_state
->has('entity_default_langcode')) {
$form_state
->set('entity_default_langcode', $this->paragraph
->getUntranslated()
->language()
->getId());
}
// This value might have been explicitly populated to work with a particular
// entity translation. If not we fall back to the most proper language based
// on contextual information.
if (!$form_state
->has('langcode')) {
// Imply a 'view' operation to ensure users edit entities in the same
// language they are displayed. This allows to keep contextual editing
// working also for multilingual entities.
$form_state
->set('langcode', $this->entityRepository
->getTranslationFromContext($this->paragraph)
->language()
->getId());
}
}
/**
* Returns an array of enabled behavior plugins excluding Layout Paragraphs.
*
* The Layout Paragraphs behavior plugin form is handled separately.
*
* @return array
* An array of enabled plugins.
*/
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 [];
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
AjaxFormHelperTrait:: |
public | function | Submit form dialog #ajax callback. | |
AjaxFormHelperTrait:: |
abstract protected | function | Allows the form to respond to a successful AJAX submission. | 5 |
AjaxHelperTrait:: |
protected | function | Gets the wrapper format of the current request. | |
AjaxHelperTrait:: |
protected | function | Determines if the current request is via AJAX. | |
ComponentFormBase:: |
protected | property | The entity repository service. | |
ComponentFormBase:: |
protected | property | The entity type manager service. | |
ComponentFormBase:: |
protected | property | The layout plugin manager service. | |
ComponentFormBase:: |
protected | property | The module handler service. | |
ComponentFormBase:: |
protected | property | The paragraph. | |
ComponentFormBase:: |
protected | property | The paragraph type. | |
ComponentFormBase:: |
protected | property | The tempstore service. | |
ComponentFormBase:: |
public | function | Access check. | |
ComponentFormBase:: |
public | function | After build callback fixes issues with data-drupal-selector. | |
ComponentFormBase:: |
public | function | Ajax form callback. | |
ComponentFormBase:: |
protected | function | Closes the form with ajax. | |
ComponentFormBase:: |
public | function | Form #process callback. | |
ComponentFormBase:: |
protected | function | Builds a component (paragraph) edit form. | |
ComponentFormBase:: |
protected | function | Builds the paragraph component using submitted form values. | |
ComponentFormBase:: |
public | function | Form #ajax callback. | |
ComponentFormBase:: |
public static | function |
Instantiates a new instance of this class. Overrides FormBase:: |
|
ComponentFormBase:: |
protected | function | Create the form title. | 2 |
ComponentFormBase:: |
protected | function | Returns an array of enabled behavior plugins excluding Layout Paragraphs. | |
ComponentFormBase:: |
public | function |
Returns a unique string identifying the form. Overrides FormInterface:: |
|
ComponentFormBase:: |
protected | function | Returns an array of region names for a given layout. | |
ComponentFormBase:: |
protected | function | Returns an array of regions for a given layout. | |
ComponentFormBase:: |
protected | function | Initializes form language code values. | |
ComponentFormBase:: |
public | function | Form #process callback. | |
ComponentFormBase:: |
protected | function | Renders a single Layout Paragraphs Layout paragraph entity. | |
ComponentFormBase:: |
public | function |
Saves the paragraph component. Overrides FormInterface:: |
2 |
ComponentFormBase:: |
public | function |
Validate the component form. Overrides FormBase:: |
|
ComponentFormBase:: |
public | function | ||
DependencySerializationTrait:: |
protected | property | ||
DependencySerializationTrait:: |
protected | property | ||
DependencySerializationTrait:: |
public | function | 2 | |
DependencySerializationTrait:: |
public | function | 2 | |
DialogHelperTrait:: |
protected | function | Returns a CloseDialogComand with the correct selector. | |
DialogHelperTrait:: |
protected | function | Generates a dialog id for a given layout. | |
DialogHelperTrait:: |
protected | function | Generates a dialog selector for a given layout. | |
DialogHelperTrait:: |
protected | function | Returns an array of dialog settings for modal edit forms. | |
FormBase:: |
protected | property | The config factory. | 3 |
FormBase:: |
protected | property | The request stack. | 1 |
FormBase:: |
protected | property | The route match. | |
FormBase:: |
protected | function | Retrieves a configuration object. | |
FormBase:: |
protected | function | Gets the config factory for this form. | 3 |
FormBase:: |
private | function | Returns the service container. | |
FormBase:: |
protected | function | Gets the current user. | |
FormBase:: |
protected | function | Gets the request object. | |
FormBase:: |
protected | function | Gets the route match. | |
FormBase:: |
protected | function | Gets the logger for a specific channel. | |
FormBase:: |
protected | function | Returns a redirect response object for the specified route. | |
FormBase:: |
public | function | Resets the configuration factory. | |
FormBase:: |
public | function | Sets the config factory for this form. | |
FormBase:: |
public | function | Sets the request stack object to use. | |
FormInterface:: |
public | function | Form constructor. | 192 |
LayoutParagraphsLayoutRefreshTrait:: |
protected | property | The event dispatcher service. | 1 |
LayoutParagraphsLayoutRefreshTrait:: |
protected | property | The layout paragraphs layout object. | |
LayoutParagraphsLayoutRefreshTrait:: |
protected | property | The original paragraphs layout object. | |
LayoutParagraphsLayoutRefreshTrait:: |
protected | function | Returns the event dispatcher service. | 1 |
LayoutParagraphsLayoutRefreshTrait:: |
protected | function | Returns TRUE if the layout needs to be refreshed. | |
LayoutParagraphsLayoutRefreshTrait:: |
protected | function | Decorates an ajax response with a command to refresh an entire layout. | |
LayoutParagraphsLayoutRefreshTrait:: |
protected | function | Renders the layout builder UI render array. | |
LayoutParagraphsLayoutRefreshTrait:: |
protected | function | Setter for layoutParagraphsLayout property. | |
LoggerChannelTrait:: |
protected | property | The logger channel factory service. | |
LoggerChannelTrait:: |
protected | function | Gets the logger for a specific channel. | |
LoggerChannelTrait:: |
public | function | Injects the logger channel factory. | |
MessengerTrait:: |
protected | property | The messenger. | 27 |
MessengerTrait:: |
public | function | Gets the messenger. | 27 |
MessengerTrait:: |
public | function | Sets the messenger. | |
RedirectDestinationTrait:: |
protected | property | The redirect destination service. | 1 |
RedirectDestinationTrait:: |
protected | function | Prepares a 'destination' URL query parameter for use with \Drupal\Core\Url. | |
RedirectDestinationTrait:: |
protected | function | Returns the redirect destination service. | |
RedirectDestinationTrait:: |
public | function | Sets the redirect destination service. | |
StringTranslationTrait:: |
protected | property | The string translation service. | 4 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. |