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 / SectionStorage / DefaultsSectionStorage.php
1 <?php
2
3 namespace Drupal\layout_builder\Plugin\SectionStorage;
4
5 use Drupal\Component\Utility\NestedArray;
6 use Drupal\Core\Access\AccessResult;
7 use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
8 use Drupal\Core\Entity\EntityTypeInterface;
9 use Drupal\Core\Entity\EntityTypeManagerInterface;
10 use Drupal\Core\Entity\FieldableEntityInterface;
11 use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
12 use Drupal\Core\Plugin\Context\EntityContext;
13 use Drupal\Core\Session\AccountInterface;
14 use Drupal\Core\Url;
15 use Drupal\field_ui\FieldUI;
16 use Drupal\layout_builder\DefaultsSectionStorageInterface;
17 use Drupal\layout_builder\Entity\LayoutBuilderSampleEntityGenerator;
18 use Drupal\layout_builder\Entity\LayoutEntityDisplayInterface;
19 use Drupal\layout_builder\SectionListInterface;
20 use Symfony\Component\DependencyInjection\ContainerInterface;
21 use Symfony\Component\Routing\RouteCollection;
22
23 /**
24  * Defines the 'defaults' section storage type.
25  *
26  * @SectionStorage(
27  *   id = "defaults",
28  * )
29  *
30  * @internal
31  *   Layout Builder is currently experimental and should only be leveraged by
32  *   experimental modules and development releases of contributed modules.
33  *   See https://www.drupal.org/core/experimental for more information.
34  */
35 class DefaultsSectionStorage extends SectionStorageBase implements ContainerFactoryPluginInterface, DefaultsSectionStorageInterface {
36
37   /**
38    * The entity type manager.
39    *
40    * @var \Drupal\Core\Entity\EntityTypeManagerInterface
41    */
42   protected $entityTypeManager;
43
44   /**
45    * The entity type bundle info.
46    *
47    * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
48    */
49   protected $entityTypeBundleInfo;
50
51   /**
52    * {@inheritdoc}
53    *
54    * @var \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface
55    */
56   protected $sectionList;
57
58   /**
59    * The sample entity generator.
60    *
61    * @var \Drupal\layout_builder\Entity\LayoutBuilderSampleEntityGenerator
62    */
63   protected $sampleEntityGenerator;
64
65   /**
66    * {@inheritdoc}
67    */
68   public function __construct(array $configuration, $plugin_id, $plugin_definition, EntityTypeManagerInterface $entity_type_manager, EntityTypeBundleInfoInterface $entity_type_bundle_info, LayoutBuilderSampleEntityGenerator $sample_entity_generator) {
69     parent::__construct($configuration, $plugin_id, $plugin_definition);
70
71     $this->entityTypeManager = $entity_type_manager;
72     $this->entityTypeBundleInfo = $entity_type_bundle_info;
73     $this->sampleEntityGenerator = $sample_entity_generator;
74   }
75
76   /**
77    * {@inheritdoc}
78    */
79   public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
80     return new static(
81       $configuration,
82       $plugin_id,
83       $plugin_definition,
84       $container->get('entity_type.manager'),
85       $container->get('entity_type.bundle.info'),
86       $container->get('layout_builder.sample_entity_generator')
87     );
88   }
89
90   /**
91    * {@inheritdoc}
92    */
93   public function setSectionList(SectionListInterface $section_list) {
94     if (!$section_list instanceof LayoutEntityDisplayInterface) {
95       throw new \InvalidArgumentException('Defaults expect a display-based section list');
96     }
97
98     return parent::setSectionList($section_list);
99   }
100
101   /**
102    * Gets the entity storing the overrides.
103    *
104    * @return \Drupal\layout_builder\Entity\LayoutEntityDisplayInterface
105    *   The entity storing the defaults.
106    */
107   protected function getDisplay() {
108     return $this->getSectionList();
109   }
110
111   /**
112    * {@inheritdoc}
113    */
114   public function getStorageId() {
115     return $this->getDisplay()->id();
116   }
117
118   /**
119    * {@inheritdoc}
120    */
121   public function getRedirectUrl() {
122     return Url::fromRoute("entity.entity_view_display.{$this->getDisplay()->getTargetEntityTypeId()}.view_mode", $this->getRouteParameters());
123   }
124
125   /**
126    * {@inheritdoc}
127    */
128   public function getLayoutBuilderUrl($rel = 'view') {
129     return Url::fromRoute("layout_builder.{$this->getStorageType()}.{$this->getDisplay()->getTargetEntityTypeId()}.$rel", $this->getRouteParameters());
130   }
131
132   /**
133    * Provides the route parameters needed to generate a URL for this object.
134    *
135    * @return mixed[]
136    *   An associative array of parameter names and values.
137    */
138   protected function getRouteParameters() {
139     $display = $this->getDisplay();
140     $entity_type = $this->entityTypeManager->getDefinition($display->getTargetEntityTypeId());
141     $route_parameters = FieldUI::getRouteBundleParameter($entity_type, $display->getTargetBundle());
142     $route_parameters['view_mode_name'] = $display->getMode();
143     return $route_parameters;
144   }
145
146   /**
147    * {@inheritdoc}
148    */
149   public function buildRoutes(RouteCollection $collection) {
150     foreach ($this->getEntityTypes() as $entity_type_id => $entity_type) {
151       // Try to get the route from the current collection.
152       if (!$entity_route = $collection->get($entity_type->get('field_ui_base_route'))) {
153         continue;
154       }
155
156       $path = $entity_route->getPath() . '/display-layout/{view_mode_name}';
157
158       $defaults = [];
159       $defaults['entity_type_id'] = $entity_type_id;
160       // If the entity type has no bundles and it doesn't use {bundle} in its
161       // admin path, use the entity type.
162       if (strpos($path, '{bundle}') === FALSE) {
163         if (!$entity_type->hasKey('bundle')) {
164           $defaults['bundle'] = $entity_type_id;
165         }
166         else {
167           $defaults['bundle_key'] = $entity_type->getBundleEntityType();
168         }
169       }
170
171       $requirements = [];
172       $requirements['_field_ui_view_mode_access'] = 'administer ' . $entity_type_id . ' display';
173
174       $options = $entity_route->getOptions();
175       $options['_admin_route'] = FALSE;
176
177       $this->buildLayoutRoutes($collection, $this->getPluginDefinition(), $path, $defaults, $requirements, $options, $entity_type_id);
178
179       $route_names = [
180         "entity.entity_view_display.{$entity_type_id}.default",
181         "entity.entity_view_display.{$entity_type_id}.view_mode",
182       ];
183       foreach ($route_names as $route_name) {
184         if (!$route = $collection->get($route_name)) {
185           continue;
186         }
187
188         $route->addDefaults([
189           'section_storage_type' => $this->getStorageType(),
190           'section_storage' => '',
191         ] + $defaults);
192         $parameters['section_storage']['layout_builder_tempstore'] = TRUE;
193         $parameters = NestedArray::mergeDeep($parameters, $route->getOption('parameters') ?: []);
194         $route->setOption('parameters', $parameters);
195       }
196     }
197   }
198
199   /**
200    * Returns an array of relevant entity types.
201    *
202    * @return \Drupal\Core\Entity\EntityTypeInterface[]
203    *   An array of entity types.
204    */
205   protected function getEntityTypes() {
206     return array_filter($this->entityTypeManager->getDefinitions(), function (EntityTypeInterface $entity_type) {
207       return $entity_type->entityClassImplements(FieldableEntityInterface::class) && $entity_type->hasViewBuilderClass() && $entity_type->get('field_ui_base_route');
208     });
209   }
210
211   /**
212    * {@inheritdoc}
213    */
214   public function extractIdFromRoute($value, $definition, $name, array $defaults) {
215     if (is_string($value) && strpos($value, '.') !== FALSE) {
216       return $value;
217     }
218
219     // If a bundle is not provided but a value corresponding to the bundle key
220     // is, use that for the bundle value.
221     if (empty($defaults['bundle']) && isset($defaults['bundle_key']) && !empty($defaults[$defaults['bundle_key']])) {
222       $defaults['bundle'] = $defaults[$defaults['bundle_key']];
223     }
224
225     if (!empty($defaults['entity_type_id']) && !empty($defaults['bundle']) && !empty($defaults['view_mode_name'])) {
226       return $defaults['entity_type_id'] . '.' . $defaults['bundle'] . '.' . $defaults['view_mode_name'];
227     }
228   }
229
230   /**
231    * {@inheritdoc}
232    */
233   public function getSectionListFromId($id) {
234     if (strpos($id, '.') === FALSE) {
235       throw new \InvalidArgumentException(sprintf('The "%s" ID for the "%s" section storage type is invalid', $id, $this->getStorageType()));
236     }
237
238     $storage = $this->entityTypeManager->getStorage('entity_view_display');
239     // If the display does not exist, create a new one.
240     if (!$display = $storage->load($id)) {
241       list($entity_type_id, $bundle, $view_mode) = explode('.', $id, 3);
242       $display = $storage->create([
243         'targetEntityType' => $entity_type_id,
244         'bundle' => $bundle,
245         'mode' => $view_mode,
246         'status' => TRUE,
247       ]);
248     }
249     return $display;
250   }
251
252   /**
253    * {@inheritdoc}
254    */
255   public function getContexts() {
256     $display = $this->getDisplay();
257     $entity = $this->sampleEntityGenerator->get($display->getTargetEntityTypeId(), $display->getTargetBundle());
258
259     $contexts = [];
260     $contexts['layout_builder.entity'] = EntityContext::fromEntity($entity);
261     return $contexts;
262   }
263
264   /**
265    * {@inheritdoc}
266    */
267   public function label() {
268     return $this->getDisplay()->label();
269   }
270
271   /**
272    * {@inheritdoc}
273    */
274   public function save() {
275     return $this->getDisplay()->save();
276   }
277
278   /**
279    * {@inheritdoc}
280    */
281   public function isOverridable() {
282     return $this->getDisplay()->isOverridable();
283   }
284
285   /**
286    * {@inheritdoc}
287    */
288   public function setOverridable($overridable = TRUE) {
289     $this->getDisplay()->setOverridable($overridable);
290     return $this;
291   }
292
293   /**
294    * {@inheritdoc}
295    */
296   public function setThirdPartySetting($module, $key, $value) {
297     $this->getDisplay()->setThirdPartySetting($module, $key, $value);
298     return $this;
299   }
300
301   /**
302    * {@inheritdoc}
303    */
304   public function isLayoutBuilderEnabled() {
305     return $this->getDisplay()->isLayoutBuilderEnabled();
306   }
307
308   /**
309    * {@inheritdoc}
310    */
311   public function enableLayoutBuilder() {
312     $this->getDisplay()->enableLayoutBuilder();
313     return $this;
314   }
315
316   /**
317    * {@inheritdoc}
318    */
319   public function disableLayoutBuilder() {
320     $this->getDisplay()->disableLayoutBuilder();
321     return $this;
322   }
323
324   /**
325    * {@inheritdoc}
326    */
327   public function getThirdPartySetting($module, $key, $default = NULL) {
328     return $this->getDisplay()->getThirdPartySetting($module, $key, $default);
329   }
330
331   /**
332    * {@inheritdoc}
333    */
334   public function getThirdPartySettings($module) {
335     return $this->getDisplay()->getThirdPartySettings($module);
336   }
337
338   /**
339    * {@inheritdoc}
340    */
341   public function unsetThirdPartySetting($module, $key) {
342     $this->getDisplay()->unsetThirdPartySetting($module, $key);
343     return $this;
344   }
345
346   /**
347    * {@inheritdoc}
348    */
349   public function getThirdPartyProviders() {
350     return $this->getDisplay()->getThirdPartyProviders();
351   }
352
353   /**
354    * {@inheritdoc}
355    */
356   public function access($operation, AccountInterface $account = NULL, $return_as_object = FALSE) {
357     $result = AccessResult::allowedIf($this->isLayoutBuilderEnabled());
358     return $return_as_object ? $result : $result->isAllowed();
359   }
360
361 }