Mercurial > hg > isophonics-drupal-site
comparison 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 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Drupal\field_layout; | |
4 | |
5 use Drupal\Core\DependencyInjection\ContainerInjectionInterface; | |
6 use Drupal\Core\Entity\EntityFieldManagerInterface; | |
7 use Drupal\Core\Field\FieldDefinitionInterface; | |
8 use Drupal\field_layout\Display\EntityDisplayWithLayoutInterface; | |
9 use Drupal\Core\Layout\LayoutPluginManagerInterface; | |
10 use Symfony\Component\DependencyInjection\ContainerInterface; | |
11 | |
12 /** | |
13 * Builds a field layout. | |
14 */ | |
15 class FieldLayoutBuilder implements ContainerInjectionInterface { | |
16 | |
17 /** | |
18 * The layout plugin manager. | |
19 * | |
20 * @var \Drupal\Core\Layout\LayoutPluginManagerInterface | |
21 */ | |
22 protected $layoutPluginManager; | |
23 | |
24 /** | |
25 * The entity field manager. | |
26 * | |
27 * @var \Drupal\Core\Entity\EntityFieldManagerInterface | |
28 */ | |
29 protected $entityFieldManager; | |
30 | |
31 /** | |
32 * Constructs a new FieldLayoutBuilder. | |
33 * | |
34 * @param \Drupal\Core\Layout\LayoutPluginManagerInterface $layout_plugin_manager | |
35 * The layout plugin manager. | |
36 * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager | |
37 * The entity field manager. | |
38 */ | |
39 public function __construct(LayoutPluginManagerInterface $layout_plugin_manager, EntityFieldManagerInterface $entity_field_manager) { | |
40 $this->layoutPluginManager = $layout_plugin_manager; | |
41 $this->entityFieldManager = $entity_field_manager; | |
42 } | |
43 | |
44 /** | |
45 * {@inheritdoc} | |
46 */ | |
47 public static function create(ContainerInterface $container) { | |
48 return new static( | |
49 $container->get('plugin.manager.core.layout'), | |
50 $container->get('entity_field.manager') | |
51 ); | |
52 } | |
53 | |
54 /** | |
55 * Applies the layout to an entity build. | |
56 * | |
57 * @param array $build | |
58 * A renderable array representing the entity content or form. | |
59 * @param \Drupal\field_layout\Display\EntityDisplayWithLayoutInterface $display | |
60 * The entity display holding the display options configured for the entity | |
61 * components. | |
62 */ | |
63 public function buildView(array &$build, EntityDisplayWithLayoutInterface $display) { | |
64 $layout_definition = $this->layoutPluginManager->getDefinition($display->getLayoutId(), FALSE); | |
65 if ($layout_definition && $fields = $this->getFields($build, $display, 'view')) { | |
66 // Add the regions to the $build in the correct order. | |
67 $regions = array_fill_keys($layout_definition->getRegionNames(), []); | |
68 | |
69 foreach ($fields as $name => $field) { | |
70 // Move the field from the top-level of $build into a region-specific | |
71 // section. | |
72 // @todo Ideally the array structure would remain unchanged, see | |
73 // https://www.drupal.org/node/2846393. | |
74 $regions[$field['region']][$name] = $build[$name]; | |
75 unset($build[$name]); | |
76 } | |
77 // Ensure this will not conflict with any existing array elements by | |
78 // prefixing with an underscore. | |
79 $build['_field_layout'] = $display->getLayout()->build($regions); | |
80 } | |
81 } | |
82 | |
83 /** | |
84 * Applies the layout to an entity form. | |
85 * | |
86 * @param array $build | |
87 * A renderable array representing the entity content or form. | |
88 * @param \Drupal\field_layout\Display\EntityDisplayWithLayoutInterface $display | |
89 * The entity display holding the display options configured for the entity | |
90 * components. | |
91 */ | |
92 public function buildForm(array &$build, EntityDisplayWithLayoutInterface $display) { | |
93 $layout_definition = $this->layoutPluginManager->getDefinition($display->getLayoutId(), FALSE); | |
94 if ($layout_definition && $fields = $this->getFields($build, $display, 'form')) { | |
95 $fill = []; | |
96 $fill['#process'][] = '\Drupal\Core\Render\Element\RenderElement::processGroup'; | |
97 $fill['#pre_render'][] = '\Drupal\Core\Render\Element\RenderElement::preRenderGroup'; | |
98 // Add the regions to the $build in the correct order. | |
99 $regions = array_fill_keys($layout_definition->getRegionNames(), $fill); | |
100 | |
101 foreach ($fields as $name => $field) { | |
102 // As this is a form, #group can be used to relocate the fields. This | |
103 // avoids breaking hook_form_alter() implementations by not actually | |
104 // moving the field in the form structure. If a #group is already set, | |
105 // do not overwrite it. | |
106 if (!isset($build[$name]['#group'])) { | |
107 $build[$name]['#group'] = $field['region']; | |
108 } | |
109 } | |
110 // Ensure this will not conflict with any existing array elements by | |
111 // prefixing with an underscore. | |
112 $build['_field_layout'] = $display->getLayout()->build($regions); | |
113 } | |
114 } | |
115 | |
116 /** | |
117 * Gets the fields that need to be processed. | |
118 * | |
119 * @param array $build | |
120 * A renderable array representing the entity content or form. | |
121 * @param \Drupal\field_layout\Display\EntityDisplayWithLayoutInterface $display | |
122 * The entity display holding the display options configured for the entity | |
123 * components. | |
124 * @param string $display_context | |
125 * The display context, either 'form' or 'view'. | |
126 * | |
127 * @return array | |
128 * An array of configurable fields present in the build. | |
129 */ | |
130 protected function getFields(array $build, EntityDisplayWithLayoutInterface $display, $display_context) { | |
131 $components = $display->getComponents(); | |
132 | |
133 // Ignore any extra fields from the list of field definitions. Field | |
134 // definitions can have a non-configurable display, but all extra fields are | |
135 // always displayed. | |
136 $field_definitions = array_diff_key( | |
137 $this->entityFieldManager->getFieldDefinitions($display->getTargetEntityTypeId(), $display->getTargetBundle()), | |
138 $this->entityFieldManager->getExtraFields($display->getTargetEntityTypeId(), $display->getTargetBundle()) | |
139 ); | |
140 | |
141 $fields_to_exclude = array_filter($field_definitions, function (FieldDefinitionInterface $field_definition) use ($display_context) { | |
142 // Remove fields with a non-configurable display. | |
143 return !$field_definition->isDisplayConfigurable($display_context); | |
144 }); | |
145 $components = array_diff_key($components, $fields_to_exclude); | |
146 | |
147 // Only include fields present in the build. | |
148 $components = array_intersect_key($components, $build); | |
149 | |
150 return $components; | |
151 } | |
152 | |
153 } |