Mercurial > hg > isophonics-drupal-site
diff core/modules/field_layout/src/FieldLayoutBuilder.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 7a779792577d |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/core/modules/field_layout/src/FieldLayoutBuilder.php Wed Nov 29 16:09:58 2017 +0000 @@ -0,0 +1,153 @@ +<?php + +namespace Drupal\field_layout; + +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\Entity\EntityFieldManagerInterface; +use Drupal\Core\Field\FieldDefinitionInterface; +use Drupal\field_layout\Display\EntityDisplayWithLayoutInterface; +use Drupal\Core\Layout\LayoutPluginManagerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Builds a field layout. + */ +class FieldLayoutBuilder implements ContainerInjectionInterface { + + /** + * The layout plugin manager. + * + * @var \Drupal\Core\Layout\LayoutPluginManagerInterface + */ + protected $layoutPluginManager; + + /** + * The entity field manager. + * + * @var \Drupal\Core\Entity\EntityFieldManagerInterface + */ + protected $entityFieldManager; + + /** + * Constructs a new FieldLayoutBuilder. + * + * @param \Drupal\Core\Layout\LayoutPluginManagerInterface $layout_plugin_manager + * The layout plugin manager. + * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager + * The entity field manager. + */ + public function __construct(LayoutPluginManagerInterface $layout_plugin_manager, EntityFieldManagerInterface $entity_field_manager) { + $this->layoutPluginManager = $layout_plugin_manager; + $this->entityFieldManager = $entity_field_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.core.layout'), + $container->get('entity_field.manager') + ); + } + + /** + * Applies the layout to an entity build. + * + * @param array $build + * A renderable array representing the entity content or form. + * @param \Drupal\field_layout\Display\EntityDisplayWithLayoutInterface $display + * The entity display holding the display options configured for the entity + * components. + */ + public function buildView(array &$build, EntityDisplayWithLayoutInterface $display) { + $layout_definition = $this->layoutPluginManager->getDefinition($display->getLayoutId(), FALSE); + if ($layout_definition && $fields = $this->getFields($build, $display, 'view')) { + // Add the regions to the $build in the correct order. + $regions = array_fill_keys($layout_definition->getRegionNames(), []); + + foreach ($fields as $name => $field) { + // Move the field from the top-level of $build into a region-specific + // section. + // @todo Ideally the array structure would remain unchanged, see + // https://www.drupal.org/node/2846393. + $regions[$field['region']][$name] = $build[$name]; + unset($build[$name]); + } + // Ensure this will not conflict with any existing array elements by + // prefixing with an underscore. + $build['_field_layout'] = $display->getLayout()->build($regions); + } + } + + /** + * Applies the layout to an entity form. + * + * @param array $build + * A renderable array representing the entity content or form. + * @param \Drupal\field_layout\Display\EntityDisplayWithLayoutInterface $display + * The entity display holding the display options configured for the entity + * components. + */ + public function buildForm(array &$build, EntityDisplayWithLayoutInterface $display) { + $layout_definition = $this->layoutPluginManager->getDefinition($display->getLayoutId(), FALSE); + if ($layout_definition && $fields = $this->getFields($build, $display, 'form')) { + $fill = []; + $fill['#process'][] = '\Drupal\Core\Render\Element\RenderElement::processGroup'; + $fill['#pre_render'][] = '\Drupal\Core\Render\Element\RenderElement::preRenderGroup'; + // Add the regions to the $build in the correct order. + $regions = array_fill_keys($layout_definition->getRegionNames(), $fill); + + foreach ($fields as $name => $field) { + // As this is a form, #group can be used to relocate the fields. This + // avoids breaking hook_form_alter() implementations by not actually + // moving the field in the form structure. If a #group is already set, + // do not overwrite it. + if (!isset($build[$name]['#group'])) { + $build[$name]['#group'] = $field['region']; + } + } + // Ensure this will not conflict with any existing array elements by + // prefixing with an underscore. + $build['_field_layout'] = $display->getLayout()->build($regions); + } + } + + /** + * Gets the fields that need to be processed. + * + * @param array $build + * A renderable array representing the entity content or form. + * @param \Drupal\field_layout\Display\EntityDisplayWithLayoutInterface $display + * The entity display holding the display options configured for the entity + * components. + * @param string $display_context + * The display context, either 'form' or 'view'. + * + * @return array + * An array of configurable fields present in the build. + */ + protected function getFields(array $build, EntityDisplayWithLayoutInterface $display, $display_context) { + $components = $display->getComponents(); + + // Ignore any extra fields from the list of field definitions. Field + // definitions can have a non-configurable display, but all extra fields are + // always displayed. + $field_definitions = array_diff_key( + $this->entityFieldManager->getFieldDefinitions($display->getTargetEntityTypeId(), $display->getTargetBundle()), + $this->entityFieldManager->getExtraFields($display->getTargetEntityTypeId(), $display->getTargetBundle()) + ); + + $fields_to_exclude = array_filter($field_definitions, function (FieldDefinitionInterface $field_definition) use ($display_context) { + // Remove fields with a non-configurable display. + return !$field_definition->isDisplayConfigurable($display_context); + }); + $components = array_diff_key($components, $fields_to_exclude); + + // Only include fields present in the build. + $components = array_intersect_key($components, $build); + + return $components; + } + +}