|
6 | 6 | use Drupal\Core\Database\Database; |
7 | 7 | use Drupal\Core\DependencyInjection\ContainerInjectionInterface; |
8 | 8 | use Drupal\Core\Entity\EntityInterface; |
| 9 | +use Drupal\Core\Entity\EntityTypeInterface; |
9 | 10 | use Drupal\Core\Entity\EntityTypeManagerInterface; |
10 | 11 | use Drupal\Core\Entity\FieldableEntityInterface; |
11 | 12 | use Drupal\Core\Entity\RevisionableInterface; |
@@ -102,13 +103,17 @@ protected function removeUnusedForEntityOnSave(EntityInterface $entity) { |
102 | 103 | * |
103 | 104 | * @param \Drupal\Core\Entity\EntityInterface $entity |
104 | 105 | * The parent entity. |
| 106 | + * |
| 107 | + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
| 108 | + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
| 109 | + * @throws \Drupal\Core\Entity\EntityStorageException |
105 | 110 | */ |
106 | 111 | public function handleEntityDelete(EntityInterface $entity) { |
107 | 112 | if ($this->isStorageAvailable() && $this->isLayoutCompatibleEntity($entity)) { |
108 | | - $entity_type = $this->entityTypeManager->getDefinition($entity->getEntityTypeId()); |
109 | | - if (!$entity_type->getDataTable()) { |
110 | | - // If the entity type does not have a data table we cannot find unused |
111 | | - // blocks on cron. |
| 113 | + if (!$this->isUsingDataTables($entity->getEntityTypeId())) { |
| 114 | + // If either entity type does not have a data table we cannot find |
| 115 | + // unused blocks in '::removeUnused()'. |
| 116 | + // @see ::getUnusedBlockIdsForEntityWithDataTable |
112 | 117 | $block_storage = $this->entityTypeManager->getStorage('block_content'); |
113 | 118 | $query = $block_storage->getQuery(); |
114 | 119 | $query->condition('parent_entity_id', $entity->id()); |
@@ -278,6 +283,8 @@ protected function deleteBlocks(array $block_content_ids) { |
278 | 283 | * @param int $limit |
279 | 284 | * The maximum number of block content entities to remove. |
280 | 285 | * |
| 286 | + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
| 287 | + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
281 | 288 | * @throws \Drupal\Core\Entity\EntityStorageException |
282 | 289 | */ |
283 | 290 | public function removeUnused($limit = 100) { |
@@ -347,47 +354,86 @@ protected function getBlockIdsForRevisionIds(array $revision_ids) { |
347 | 354 | * |
348 | 355 | * @return int[] |
349 | 356 | * The block IDs. |
| 357 | + * |
| 358 | + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException |
| 359 | + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException |
350 | 360 | */ |
351 | 361 | protected function getUnused($limit) { |
352 | | - $block_type_definition = $this->entityTypeManager->getDefinition('block_content'); |
353 | | - $data_table = $block_type_definition->getDataTable(); |
354 | | - $query = Database::getConnection()->select($data_table); |
355 | | - $query->distinct(TRUE); |
356 | | - $query->isNotNull('parent_entity_type'); |
357 | | - $query->fields($data_table, ['parent_entity_type']); |
358 | | - $parent_entity_types = $query->execute()->fetchCol(); |
359 | | - $block_id_key = $block_type_definition->getKey('id'); |
360 | 362 | $block_ids = []; |
361 | | - foreach ($parent_entity_types as $parent_entity_type) { |
362 | | - $parent_type_definition = $this->entityTypeManager->getDefinition($parent_entity_type); |
363 | | - if ($parent_data_table = $parent_type_definition->getDataTable()) { |
364 | | - $sub_query = Database::getConnection()->select($parent_data_table, 'parent'); |
365 | | - $parent_id_key = $parent_type_definition->getKey('id'); |
366 | | - $sub_query->fields('parent', [$parent_id_key]); |
367 | | - $sub_query->where("blocks.parent_entity_id = parent.$parent_id_key"); |
368 | | - |
369 | | - $query = Database::getConnection()->select($data_table, 'blocks'); |
370 | | - $query->fields('blocks', [$block_id_key]); |
371 | | - $query->isNotNull('parent_entity_id'); |
372 | | - $query->condition('parent_entity_type', $parent_entity_type); |
373 | | - $query->notExists($sub_query); |
374 | | - $query->range(0, $limit - count($block_ids)); |
375 | | - $new_block_ids = $query->execute()->fetchCol(); |
376 | | - } |
377 | | - else { |
378 | | - // @todo Handle parent types with no data table. |
379 | | - $block_query = $this->entityTypeManager->getStorage('block_content')->getQuery(); |
380 | | - $block_query->condition('parent_entity_type', $parent_entity_type); |
381 | | - $block_query->notExists('parent_entity_id'); |
382 | | - $block_query->range(0, $limit - count($block_ids)); |
383 | | - $new_block_ids = $block_query->execute(); |
384 | | - } |
385 | | - $block_ids = array_merge($block_ids, $new_block_ids); |
386 | | - if (count($block_ids) > 50) { |
387 | | - break; |
| 363 | + foreach ($this->entityTypeManager->getDefinitions() as $definition) { |
| 364 | + if ($this->entityTypeSupportsLayouts($definition)) { |
| 365 | + if ($this->isUsingDataTables($definition->id())) { |
| 366 | + $new_block_ids = $this->getUnusedBlockIdsForEntityWithDataTable($limit - count($block_ids), $definition); |
| 367 | + } |
| 368 | + else { |
| 369 | + $block_query = $this->entityTypeManager->getStorage('block_content')->getQuery(); |
| 370 | + $block_query->condition('parent_entity_type', $definition->id()); |
| 371 | + $block_query->notExists('parent_entity_id'); |
| 372 | + $block_query->range(0, $limit - count($block_ids)); |
| 373 | + $new_block_ids = $block_query->execute(); |
| 374 | + } |
| 375 | + $block_ids = array_merge($block_ids, $new_block_ids); |
| 376 | + if (count($block_ids) >= $limit) { |
| 377 | + break; |
| 378 | + } |
388 | 379 | } |
| 380 | + |
389 | 381 | } |
390 | 382 | return $block_ids; |
391 | 383 | } |
392 | 384 |
|
| 385 | + /** |
| 386 | + * Gets the unused block IDs for an entity type using a datatable. |
| 387 | + * |
| 388 | + * @param int $limit |
| 389 | + * The limit of number of block IDs to retrieve. |
| 390 | + * @param \Drupal\Core\Entity\EntityTypeInterface $parent_type_definition |
| 391 | + * The parent entity type definition. |
| 392 | + * |
| 393 | + * @return int[] |
| 394 | + * The block IDs. |
| 395 | + */ |
| 396 | + protected function getUnusedBlockIdsForEntityWithDataTable($limit, EntityTypeInterface $parent_type_definition) { |
| 397 | + $block_type_definition = $this->entityTypeManager->getDefinition('block_content'); |
| 398 | + $sub_query = Database::getConnection() |
| 399 | + ->select($parent_type_definition->getDataTable(), 'parent'); |
| 400 | + $parent_id_key = $parent_type_definition->getKey('id'); |
| 401 | + $sub_query->fields('parent', [$parent_id_key]); |
| 402 | + $sub_query->where("blocks.parent_entity_id = parent.$parent_id_key"); |
| 403 | + |
| 404 | + $query = Database::getConnection()->select($block_type_definition->getDataTable(), 'blocks'); |
| 405 | + $query->fields('blocks', [$block_type_definition->getKey('id')]); |
| 406 | + $query->isNotNull('parent_entity_id'); |
| 407 | + $query->condition('parent_entity_type', $parent_type_definition->id()); |
| 408 | + $query->notExists($sub_query); |
| 409 | + $query->range(0, $limit); |
| 410 | + return $query->execute()->fetchCol(); |
| 411 | + } |
| 412 | + |
| 413 | + /** |
| 414 | + * Determines if parent entity and 'block_content' type are using datatables. |
| 415 | + * |
| 416 | + * @param string $parent_entity_type_id |
| 417 | + * The parent entity type. |
| 418 | + * |
| 419 | + * @return bool |
| 420 | + * TRUE if the parent entity and 'block_content' are using datatables. |
| 421 | + */ |
| 422 | + protected function isUsingDataTables($parent_entity_type_id) { |
| 423 | + return $this->entityTypeManager->getDefinition($parent_entity_type_id)->getDataTable() && $this->entityTypeManager->getDefinition('block_content')->getDataTable(); |
| 424 | + } |
| 425 | + |
| 426 | + /** |
| 427 | + * Checks if the entity type supports layouts. |
| 428 | + * |
| 429 | + * @param \Drupal\Core\Entity\EntityTypeInterface $definition |
| 430 | + * The entity type definition. |
| 431 | + * |
| 432 | + * @return bool |
| 433 | + * TRUE if the entity type supports layouts. |
| 434 | + */ |
| 435 | + protected function entityTypeSupportsLayouts(EntityTypeInterface $definition) { |
| 436 | + return $definition->id() === 'entity_view_display' || array_search(FieldableEntityInterface::class, class_implements($definition->getClass())) !== FALSE; |
| 437 | + } |
| 438 | + |
393 | 439 | } |
0 commit comments