contacts_events-8.x-1.x-dev/src/EventSubscriber/CloneEventDependentEntitySubscriberBase.php
src/EventSubscriber/CloneEventDependentEntitySubscriberBase.php
<?php
namespace Drupal\contacts_events\EventSubscriber;
use Drupal\contacts_events\Entity\EventInterface;
use Drupal\contacts_events\Event\CloneEvent;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Entity\Query\QueryInterface;
use Drupal\Core\Site\Settings;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Trait for clone event subscribers duplicating dependent entities.
*/
abstract class CloneEventDependentEntitySubscriberBase implements EventSubscriberInterface {
/**
* The entity type manager.
*
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
*/
protected $entityTypeManager;
/**
* The size of each batch.
*
* @var int
*/
protected $batchSize;
/**
* Constructs the event clone subscriber.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Site\Settings $settings
* The Drupal settings object.
*/
public function __construct(EntityTypeManagerInterface $entity_type_manager, Settings $settings) {
$this->entityTypeManager = $entity_type_manager;
$this->batchSize = $settings->get('entity_update_batch_size') ?? 50;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
CloneEvent::class => ['onClone'],
];
}
/**
* Respond to clone event by adding the operations to perform.
*
* ```php
* $event->addOperation(
* 'service_name',
* 'operationMethod',
* new TranslatableMarkup('Operation description'),
* );
* ```
*
* @param \Drupal\contacts_events\Event\CloneEvent $event
* The clone event.
*/
abstract protected function onClone(CloneEvent $event): void;
/**
* Clone operation for a dependant entity.
*
* @param string $entity_type_id
* The entity type ID for the dependant entity to clone.
* @param \Drupal\contacts_events\Entity\EventInterface $event
* The new event.
* @param \Drupal\contacts_events\Entity\EventInterface $source
* The source event.
* @param array $sandbox
* A sandbox for storing data that will be preserved between calls to this
* operation.
* @param string $event_field
* The event field on the dependant entity.
*
* @return int
* The progress percentage between 0 (not started) and 100 (complete).
*/
protected function cloneDependantEntityOperation(string $entity_type_id, EventInterface $event, EventInterface $source, array &$sandbox, string $event_field): int {
if (!isset($sandbox['last_id'])) {
$sandbox['last_id'] = 0;
$sandbox['max'] = $this->getCount($entity_type_id, $source->id(), $event_field);
if ($sandbox['max'] === 0) {
return 100;
}
}
$entities = $this->getBatch($entity_type_id, $source->id(), $sandbox['last_id'], $event_field);
foreach ($entities as $entity) {
$entity
->createDuplicate()
->set($event_field, $event)
->save();
$sandbox['progress']++;
$sandbox['last_id'] = $entity->id();
}
return (int) floor($sandbox['progress'] / $sandbox['max'] * 100);
}
/**
* Get the count of dependant entities.
*
* @param string $entity_type_id
* The entity type ID.
* @param int $event_id
* The source event ID.
* @param string $event_field
* The field on the entity referencing the event.
*
* @return int
* The count of dependant entities.
*/
protected function getCount(string $entity_type_id, int $event_id, string $event_field): int {
return (int) $this->getBaseQuery($entity_type_id, $event_id, $event_field)->count()->execute();
}
/**
* Get the next batch of dependant entities.
*
* @param string $entity_type_id
* The entity type ID.
* @param int $event_id
* The source event ID.
* @param int $last_id
* The last ID processed to filter the query.
* @param string $event_field
* The field on the entity referencing the event.
*
* @return \Drupal\Core\Entity\ContentEntityInterface[]
* The next batch of dependant entities.
*/
protected function getBatch(string $entity_type_id, int $event_id, int $last_id, string $event_field): array {
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
$id_field = $entity_type->getKey('id');
$ids = $this->getBaseQuery($entity_type_id, $event_id, $event_field)
->condition($id_field, $last_id, '>')
->sort($id_field, 'ASC')
->range(0, $this->batchSize)
->execute();
return $this->entityTypeManager
->getStorage($entity_type_id)
->loadMultiple($ids);
}
/**
* Get the base query.
*
* @param string $entity_type_id
* The entity type ID.
* @param int $event_id
* The source event ID.
* @param string $event_field
* The field on the entity referencing the event.
*
* @return \Drupal\Core\Entity\Query\QueryInterface
* The base query.
*/
protected function getBaseQuery(string $entity_type_id, int $event_id, string $event_field): QueryInterface {
return $this->entityTypeManager
->getStorage($entity_type_id)
->getQuery()
->accessCheck(TRUE)
->condition($event_field, $event_id);
}
}
