From 7efc1f1e7f0ebe8d09c82247c0411739d896240b Mon Sep 17 00:00:00 2001 From: Mike Decker Date: Thu, 30 Nov 2023 11:31:16 -0800 Subject: [PATCH] Entity Cleanup Cron Queue --- .../hs_field_helpers/drush.services.yml | 6 ++ .../hs_field_helpers/hs_field_helpers.module | 78 ------------------- .../src/Commands/HsFieldHelpersCommands.php | 67 ++++++++++++++++ .../QueueWorker/EntityCleanupQueueWorker.php | 57 ++++++++++++++ 4 files changed, 130 insertions(+), 78 deletions(-) create mode 100644 docroot/modules/humsci/hs_field_helpers/drush.services.yml create mode 100644 docroot/modules/humsci/hs_field_helpers/src/Commands/HsFieldHelpersCommands.php create mode 100644 docroot/modules/humsci/hs_field_helpers/src/Plugin/QueueWorker/EntityCleanupQueueWorker.php diff --git a/docroot/modules/humsci/hs_field_helpers/drush.services.yml b/docroot/modules/humsci/hs_field_helpers/drush.services.yml new file mode 100644 index 0000000000..88cc8131d6 --- /dev/null +++ b/docroot/modules/humsci/hs_field_helpers/drush.services.yml @@ -0,0 +1,6 @@ +services: + hs_field_helpers.commands: + class: \Drupal\hs_field_helpers\Commands\HsFieldHelpersCommands + arguments: ['@queue', '@entity_type.manager'] + tags: + - { name: drush.command } diff --git a/docroot/modules/humsci/hs_field_helpers/hs_field_helpers.module b/docroot/modules/humsci/hs_field_helpers/hs_field_helpers.module index 0350c0c9b4..a89e261f79 100644 --- a/docroot/modules/humsci/hs_field_helpers/hs_field_helpers.module +++ b/docroot/modules/humsci/hs_field_helpers/hs_field_helpers.module @@ -570,84 +570,6 @@ function _hs_field_helpers_get_view_mode_component(FieldableEntityInterface $ent } } -/** - * Implements hook_cron(). - */ -function hs_field_helpers_cron() { - if (!Settings::get('hs_field_helpers_cron', FALSE)) { - return; - } - $deleted = _he_field_helpers_clean_eck(); - $logger = \Drupal::logger('hs_field_helpers'); - foreach ($deleted as $entity_type => $ids) { - $logger->info(t('Deleted %count entities due to no usages. %type: %ids'), [ - '%count' => count($ids), - '%type' => $entity_type, - '%ids' => implode(', ', $ids), - ]); - } -} - -/** - * Deletes any ECK entities that don't have any usage of them anywhere. - * - * With entity reference fields, entity_usage module tracks the use of ECK - * entities. Because of that we can safely delete these entities that have no - * usage statitistics of them. Mostly this is from doing a migration rollback. - * Deleting a node manually seems to clean the ECK entities. - * - * @return array - * Keyed array of entity type to entity ids that were deleted. - */ -function _he_field_helpers_clean_eck() { - /** @var \Drupal\entity_usage\EntityUsage $entity_usage */ - $entity_usage = \Drupal::service('entity_usage.usage'); - $deleted = []; - foreach (_hs_field_helpers_get_cleanup_entity_types() as $entity_type) { - $entity_storage = \Drupal::entityTypeManager() - ->getStorage($entity_type); - $entity_ids = $entity_storage->getQuery() - ->accessCheck(FALSE) - ->execute(); - - // Chunk it up so that we don't try to load every single entity at once. - $chuncked_ids = array_chunk($entity_ids, 100); - - foreach ($chuncked_ids as $entity_ids) { - $entities = $entity_storage->loadMultiple($entity_ids); - - // Delete all ECK entities that aren't being used. Some ECK's don't get - // deleted if they were imported by a migration. - foreach ($entities as $entity) { - if (empty($entity_usage->listSources($entity))) { - $deleted[$entity_type][] = $entity->id(); - $entity->delete(); - } - } - } - } - return $deleted; -} - -/** - * Get the entity types to clean if there are no usages. - * - * @return string[] - * Entity type ids. - */ -function _hs_field_helpers_get_cleanup_entity_types(): array { - $cleanup_types = ['paragraph']; - $definitions = \Drupal::entityTypeManager()->getDefinitions(); - /** @var \Drupal\Core\Entity\ContentEntityType $entity_type */ - foreach ($definitions as $entity_type_id => $entity_type) { - // Find all the entity types ECK has available. - if ($entity_type->getOriginalClass() == EckEntity::class) { - $cleanup_types[] = $entity_type_id; - } - } - return $cleanup_types; -} - /** * Implements hook_ENTITY_TYPE_presave(). */ diff --git a/docroot/modules/humsci/hs_field_helpers/src/Commands/HsFieldHelpersCommands.php b/docroot/modules/humsci/hs_field_helpers/src/Commands/HsFieldHelpersCommands.php new file mode 100644 index 0000000000..fe358e61ae --- /dev/null +++ b/docroot/modules/humsci/hs_field_helpers/src/Commands/HsFieldHelpersCommands.php @@ -0,0 +1,67 @@ +queueFactory->get('entity_cleanup'); + + foreach ($this->getEntityTypes() as $entity_type) { + $entity_storage = $this->entityTypeManager->getStorage($entity_type); + + $entity_ids = $entity_storage->getQuery() + ->accessCheck(FALSE) + ->execute(); + + foreach ($entity_ids as $id) { + $queue->createItem([ + 'entity_type' => $entity_type, + 'id' => $id, + ]); + } + } + } + + /** + * Get the entity types to clean if there are no usages. + * + * @return string[] + * Entity type ids. + */ + function getEntityTypes(): array { + $cleanup_types = ['paragraph', 'hs_entity']; + $definitions = $this->entityTypeManager->getDefinitions(); + + /** @var \Drupal\Core\Entity\ContentEntityType $entity_type */ + foreach ($definitions as $entity_type_id => $entity_type) { + // Find all the entity types ECK has available. + if ($entity_type->getOriginalClass() == 'Drupal\eck\Entity\EckEntity') { + $cleanup_types[] = $entity_type_id; + } + } + return $cleanup_types; + } +} diff --git a/docroot/modules/humsci/hs_field_helpers/src/Plugin/QueueWorker/EntityCleanupQueueWorker.php b/docroot/modules/humsci/hs_field_helpers/src/Plugin/QueueWorker/EntityCleanupQueueWorker.php new file mode 100644 index 0000000000..765672fbce --- /dev/null +++ b/docroot/modules/humsci/hs_field_helpers/src/Plugin/QueueWorker/EntityCleanupQueueWorker.php @@ -0,0 +1,57 @@ +get('entity_type.manager'), + $container->get('entity_usage.usage') + ); + } + + /** + * {@inheritDoc} + */ + public function __construct(array $configuration, $plugin_id, $plugin_definition, protected EntityTypeManagerInterface $entityTypeManager, protected EntityUsageInterface $entityUsage) { + parent::__construct($configuration, $plugin_id, $plugin_definition); + } + + /** + * {@inheritDoc} + */ + public function processItem($data) { + if (!$this->entityTypeManager->hasDefinition($data['entity_type'])) { + return; + } + $entity_storage = $this->entityTypeManager->getStorage($data['entity_type']); + $entity = $entity_storage->load($data['id']); + + if ($entity && empty($this->entityUsage->listSources($entity))) { + $entity->delete(); + } + } + +}