EntityDisplayModeFormBase.php
Same filename in other branches
Namespace
Drupal\field_ui\FormFile
-
core/
modules/ field_ui/ src/ Form/ EntityDisplayModeFormBase.php
View source
<?php
namespace Drupal\field_ui\Form;
use Drupal\Core\Entity\Display\EntityFormDisplayInterface;
use Drupal\Core\Entity\Display\EntityViewDisplayInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityForm;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Url;
use Drupal\field_ui\FieldUI;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides the generic base class for entity display mode forms.
*/
abstract class EntityDisplayModeFormBase extends EntityForm {
/**
* The entity type definition.
*
* @var \Drupal\Core\Entity\EntityTypeInterface
*/
protected $entityType;
/**
* The display context. Either 'view' or 'form'.
*
* @var string
*/
protected string $displayContext;
/**
* The entity type for which the display mode is being created or edited.
*
* @var string|null
*/
protected ?string $targetEntityTypeId;
/**
* {@inheritdoc}
*/
protected function init(FormStateInterface $form_state) {
parent::init($form_state);
$this->entityType = $this->entityTypeManager
->getDefinition($this->entity
->getEntityTypeId());
$this->displayContext = str_replace([
'entity_',
'_mode',
], '', $this->entityType
->id());
}
/**
* Constructs a EntityDisplayModeFormBase object.
*
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entityTypeBundleInfo
* The entity type bundle service.
* @param \Drupal\Core\Entity\EntityDisplayRepository $entityDisplayRepository
* The entity display repository.
*/
public function __construct(EntityTypeBundleInfoInterface $entityTypeBundleInfo, EntityDisplayRepositoryInterface $entityDisplayRepository) {
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static($container->get('entity_type.bundle.info'), $container->get('entity_display.repository'));
}
/**
* {@inheritdoc}
*/
public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL) {
if (!$entity_type_id && !$this->entity
->isNew()) {
$entity_type_id = $this->entity
->getTargetType();
}
$this->targetEntityTypeId = $entity_type_id;
return parent::buildForm($form, $form_state);
}
/**
* {@inheritdoc}
*/
public function form(array $form, FormStateInterface $form_state) {
$form['label'] = [
'#type' => 'textfield',
'#title' => $this->t('Name'),
'#maxlength' => 100,
'#default_value' => $this->entity
->label(),
'#required' => TRUE,
];
$form['description'] = [
'#title' => $this->t('Description'),
'#type' => 'textarea',
'#default_value' => $this->entity
->getDescription(),
'#description' => $this->t('This text will be displayed on the @mode_label list page.', [
'@mode_label' => $this->entity
->getEntityType()
->getPluralLabel(),
]),
];
$form['id'] = [
'#type' => 'machine_name',
'#description' => $this->t('A unique machine-readable name. Can only contain lowercase letters, numbers, and underscores.'),
'#disabled' => !$this->entity
->isNew(),
'#default_value' => $this->entity
->id(),
'#field_prefix' => $this->entity
->isNew() ? $this->entity
->getTargetType() . '.' : '',
'#machine_name' => [
'exists' => [
$this,
'exists',
],
'replace_pattern' => '[^a-z0-9_.]+',
],
];
$bundle_info_service = $this->entityTypeBundleInfo;
$bundles = $bundle_info_service->getAllBundleInfo();
$definition = $this->entityTypeManager
->getDefinition($this->entity
->isNew() ? $this->targetEntityTypeId : $this->entity
->getTargetType());
$bundles_by_entity = [];
$defaults = [];
foreach (array_keys($bundles[$definition->id()]) as $bundle) {
$bundles_by_entity[$bundle] = $bundles[$definition->id()][$bundle]['label'];
// Determine default display modes.
if (!$this->entity
->isNew()) {
[
,
$display_mode_name,
] = explode('.', $this->entity
->id());
if ($this->getDisplayByContext($bundle, $display_mode_name)) {
$defaults[$bundle] = $bundle;
}
}
}
$form['bundles_by_entity'] = [
'#type' => 'checkboxes',
'#title' => $this->t('Enable this @display-mode for the following @bundle-label types:', [
'@display-mode' => $this->entityType
->getSingularLabel(),
'@bundle-label' => $definition->getLabel(),
]),
'#description' => $this->t('This @display-mode will still be available for the rest of the @bundle-label types if not checked here, but it will not be enabled by default.', [
'@bundle-label' => $definition->getLabel(),
'@display-mode' => $this->entityType
->getSingularLabel(),
]),
'#options' => $bundles_by_entity,
'#default_value' => $defaults,
];
return $form;
}
/**
* Determines if the display mode already exists.
*
* @param string|int $entity_id
* The entity ID.
* @param array $element
* The form element.
*
* @return bool
* TRUE if the display mode exists, FALSE otherwise.
*/
public function exists($entity_id, array $element) {
// Do not allow to add internal 'default' view mode.
if ($entity_id == 'default') {
return TRUE;
}
/** @var \Drupal\Core\Config\Entity\ConfigEntityStorageInterface $storage */
$storage = $this->entityTypeManager
->getStorage($this->entity
->getEntityTypeId());
return (bool) $storage->getQuery()
->condition('id', $element['#field_prefix'] . $entity_id)
->execute();
}
/**
* {@inheritdoc}
*/
public function save(array $form, FormStateInterface $form_state) {
$this->messenger()
->addStatus($this->t('Saved the %label @entity-type.', [
'%label' => $this->entity
->label(),
'@entity-type' => $this->entityType
->getSingularLabel(),
]));
$this->entity
->save();
\Drupal::service('entity_field.manager')->clearCachedFieldDefinitions();
$form_state->setRedirectUrl($this->entity
->toUrl('collection'));
[
,
$display_mode_name,
] = explode('.', $form_state->getValue('id'));
$target_entity_id = $this->targetEntityTypeId;
foreach ($form_state->getValue('bundles_by_entity') as $bundle => $value) {
if (!empty($value)) {
// Add a new entity view/form display if it doesn't already exist.
if (!$this->getDisplayByContext($bundle, $display_mode_name)) {
$display = $this->getEntityDisplay($target_entity_id, $bundle, 'default')
->createCopy($display_mode_name);
$display->save();
}
// This message is still helpful, even if the view/form display hasn't
// changed, so we keep it outside the above check.
$url = $this->getOverviewUrl($display_mode_name, $value);
$bundle_info_service = $this->entityTypeBundleInfo;
$bundles = $bundle_info_service->getAllBundleInfo();
$bundle_label = $bundles[$target_entity_id][$bundle]['label'];
$display_mode_label = $form_state->getValue('label');
$this->messenger()
->addStatus($this->t('<a href=":url">Configure the %display_mode_label %mode mode for %bundle_label</a>.', [
'%mode' => $this->displayContext,
'%display_mode_label' => $display_mode_label,
'%bundle_label' => $bundle_label,
':url' => $url->toString(),
]));
}
else {
// The view/form display has been unchecked, so we need to delete this.
// There's no confirmation of deleting the view/form display on the node
// content type forms either, so we match that behavior.
if ($display = $this->getDisplayByContext($bundle, $display_mode_name)) {
$display->delete();
}
}
}
}
/**
* Returns an entity display object to be used by this form.
*
* @param string $entity_type_id
* The target entity type ID of the entity display.
* @param string $bundle
* The target bundle of the entity display.
* @param string $mode
* A view or form mode.
*
* @return \Drupal\Core\Entity\Display\EntityDisplayInterface
* An entity display.
*/
private function getEntityDisplay($entity_type_id, $bundle, $mode) {
return match ($this->displayContext) { 'view' => $this->entityDisplayRepository
->getViewDisplay($entity_type_id, $bundle, $mode),
'form' => $this->entityDisplayRepository
->getFormDisplay($entity_type_id, $bundle, $mode),
};
}
/**
* Returns the Url object for a specific entity (form) display edit form.
*
* @param string $mode
* The form or view mode.
* @param string $bundle
* The entity bundle name.
*
* @return \Drupal\Core\Url
* A Url object for the overview route.
*/
private function getOverviewUrl($mode, $bundle) : Url {
$entity_type = $this->entityTypeManager
->getDefinition($this->targetEntityTypeId);
return match ($this->displayContext) { 'view' => Url::fromRoute('entity.entity_view_display.' . $this->targetEntityTypeId . '.view_mode', [
'view_mode_name' => $mode,
] + FieldUI::getRouteBundleParameter($entity_type, $bundle)),
'form' => Url::fromRoute('entity.entity_form_display.' . $this->targetEntityTypeId . '.form_mode', [
'form_mode_name' => $mode,
] + FieldUI::getRouteBundleParameter($entity_type, $bundle)),
};
}
/**
* Load the view display for a given bundle and view mode name.
*
* @param string $bundle
* The entity bundle to load the view display for.
* @param string $view_mode_name
* The view mode name such as "full_content" to load the view display for.
*
* @return \Drupal\Core\Entity\Display\EntityViewDisplayInterface|null
* Returns the view display, or NULL if one does not exist.
*/
private function getViewDisplay(string $bundle, string $view_mode_name) : ?EntityViewDisplayInterface {
$view_mode_id = $this->targetEntityTypeId . '.' . $bundle . '.' . $view_mode_name;
return $this->entityTypeManager
->getStorage('entity_view_display')
->load($view_mode_id);
}
/**
* Load the form display for a given bundle and form mode name.
*
* @param string $bundle
* The entity bundle to load the form display for.
* @param string $form_mode_name
* The form mode name to load the form display for.
*
* @return \Drupal\Core\Entity\Display\EntityFormDisplayInterface|null
* Returns the form display, or NULL if one does not exist.
*/
private function getFormDisplay(string $bundle, string $form_mode_name) : ?EntityFormDisplayInterface {
$form_mode_id = $this->targetEntityTypeId . '.' . $bundle . '.' . $form_mode_name;
return $this->entityTypeManager
->getStorage('entity_form_display')
->load($form_mode_id);
}
/**
* Returns View or Form display based on display context.
*
* @param string $bundle
* The entity bundle to load the display for.
* @param string $display_mode_name
* The display mode name to load the display for.
*
* @return \Drupal\Core\Entity\Display\EntityFormDisplayInterface|\Drupal\Core\Entity\Display\EntityViewDisplayInterface|null
* Returns the display, or NULL if one does not exist.
*/
private function getDisplayByContext(string $bundle, string $display_mode_name) : EntityFormDisplayInterface|EntityViewDisplayInterface|null {
return match ($this->displayContext) { 'view' => $this->getViewDisplay($bundle, $display_mode_name),
'form' => $this->getFormDisplay($bundle, $display_mode_name),
};
}
}
Classes
Title | Deprecated | Summary |
---|---|---|
EntityDisplayModeFormBase | Provides the generic base class for entity display mode forms. |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.