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);
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc