Updated to Drupal 8.6.4, which is PHP 7.3 friendly. Also updated HTMLaw library....
[yaffs-website] / web / core / modules / layout_builder / src / Plugin / Block / ExtraFieldBlock.php
1 <?php
2
3 namespace Drupal\layout_builder\Plugin\Block;
4
5 use Drupal\Core\Block\BlockBase;
6 use Drupal\Core\Cache\CacheableMetadata;
7 use Drupal\Core\Entity\EntityFieldManagerInterface;
8 use Drupal\Core\Entity\EntityTypeManagerInterface;
9 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
10 use Drupal\Core\Plugin\ContextAwarePluginInterface;
11 use Drupal\Core\Render\Element;
12 use Drupal\Core\Session\AccountInterface;
13 use Drupal\Core\StringTranslation\TranslatableMarkup;
14 use Symfony\Component\DependencyInjection\ContainerInterface;
15
16 /**
17  * Provides a block that renders an extra field from an entity.
18  *
19  * This block handles fields that are provided by implementations of
20  * hook_entity_extra_field_info().
21  *
22  * @see \Drupal\layout_builder\Plugin\Block\FieldBlock
23  *   This block plugin handles all other field entities not provided by
24  *   hook_entity_extra_field_info().
25  *
26  * @Block(
27  *   id = "extra_field_block",
28  *   deriver = "\Drupal\layout_builder\Plugin\Derivative\ExtraFieldBlockDeriver",
29  * )
30  *
31  * @internal
32  *   Plugin classes are internal.
33  */
34 class ExtraFieldBlock extends BlockBase implements ContextAwarePluginInterface, ContainerFactoryPluginInterface {
35
36   /**
37    * The entity field manager.
38    *
39    * @var \Drupal\Core\Entity\EntityFieldManagerInterface
40    */
41   protected $entityFieldManager;
42
43   /**
44    * The field name.
45    *
46    * @var string
47    */
48   protected $fieldName;
49
50   /**
51    * The entity type manager.
52    *
53    * @var \Drupal\Core\Entity\EntityTypeManagerInterface
54    */
55   protected $entityTypeManager;
56
57   /**
58    * Constructs a new ExtraFieldBlock.
59    *
60    * @param array $configuration
61    *   A configuration array containing information about the plugin instance.
62    * @param string $plugin_id
63    *   The plugin ID for the plugin instance.
64    * @param mixed $plugin_definition
65    *   The plugin implementation definition.
66    * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
67    *   The entity type manager.
68    * @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
69    *   The entity field manager.
70    */
71   public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager) {
72     $this->entityTypeManager = $entity_type_manager;
73     $this->entityFieldManager = $entity_field_manager;
74     // Get field name from the plugin ID.
75     list (, , , $field_name) = explode(static::DERIVATIVE_SEPARATOR, $plugin_id, 4);
76     assert(!empty($field_name));
77     $this->fieldName = $field_name;
78
79     parent::__construct($configuration, $plugin_id, $plugin_definition);
80   }
81
82   /**
83    * {@inheritdoc}
84    */
85   public function defaultConfiguration() {
86     return [
87       'label_display' => FALSE,
88     ];
89   }
90
91   /**
92    * {@inheritdoc}
93    */
94   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
95     return new static(
96       $configuration,
97       $plugin_id,
98       $plugin_definition,
99       $container->get('entity_type.manager'),
100       $container->get('entity_field.manager')
101     );
102   }
103
104   /**
105    * Gets the entity that has the field.
106    *
107    * @return \Drupal\Core\Entity\FieldableEntityInterface
108    *   The entity.
109    */
110   protected function getEntity() {
111     return $this->getContextValue('entity');
112   }
113
114   /**
115    * {@inheritdoc}
116    */
117   public function build() {
118     $entity = $this->getEntity();
119     // Add a placeholder to replace after the entity view is built.
120     // @see layout_builder_entity_view_alter().
121     $extra_fields = $this->entityFieldManager->getExtraFields($entity->getEntityTypeId(), $entity->bundle());
122     if (!isset($extra_fields['display'][$this->fieldName])) {
123       $build = [];
124     }
125     else {
126       $build = [
127         '#extra_field_placeholder_field_name' => $this->fieldName,
128         // Always provide a placeholder. The Layout Builder will NOT invoke
129         // hook_entity_view_alter() so extra fields will not be added to the
130         // render array. If the hook is invoked the placeholder will be
131         // replaced.
132         // @see ::replaceFieldPlaceholder()
133         '#markup' => new TranslatableMarkup('Placeholder for the "@field" field', ['@field' => $extra_fields['display'][$this->fieldName]['label']]),
134       ];
135     }
136     CacheableMetadata::createFromObject($this)->applyTo($build);
137     return $build;
138   }
139
140   /**
141    * Replaces all placeholders for a given field.
142    *
143    * @param array $build
144    *   The built render array for the elements.
145    * @param array $built_field
146    *   The render array to replace the placeholder.
147    * @param string $field_name
148    *   The field name.
149    *
150    * @see ::build()
151    */
152   public static function replaceFieldPlaceholder(array &$build, array $built_field, $field_name) {
153     foreach (Element::children($build) as $child) {
154       if (isset($build[$child]['#extra_field_placeholder_field_name']) && $build[$child]['#extra_field_placeholder_field_name'] === $field_name) {
155         $placeholder_cache = CacheableMetadata::createFromRenderArray($build[$child]);
156         $built_cache = CacheableMetadata::createFromRenderArray($built_field);
157         $merged_cache = $placeholder_cache->merge($built_cache);
158         $build[$child] = $built_field;
159         $merged_cache->applyTo($build);
160       }
161       else {
162         static::replaceFieldPlaceholder($build[$child], $built_field, $field_name);
163       }
164     }
165   }
166
167   /**
168    * {@inheritdoc}
169    */
170   protected function blockAccess(AccountInterface $account) {
171     return $this->getEntity()->access('view', $account, TRUE);
172   }
173
174 }