image_to_media_swapper-2.x-dev/src/BatchHandler.php

src/BatchHandler.php
<?php

declare(strict_types=1);

namespace Drupal\image_to_media_swapper;

/**
 * Handles batch processing for converting image fields to media.
 */
class BatchHandler {

  /**
   * Processes a chunk of entities to convert image fields to media.
   *
   * @throws \Drupal\Core\Entity\EntityStorageException
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   */
  public static function processChunk(string $fieldSelector, array $entity_ids, string $category, array &$context): void {
    /** @var \Drupal\image_to_media_swapper\BatchProcessorService $processor */
    $processor = \Drupal::service('image_to_media_swapper.batch_processor_service');
    $entity_type_id = explode('.', $fieldSelector)[0];
    $storage = \Drupal::entityTypeManager()->getStorage($entity_type_id);
    /** @var \Drupal\Core\Entity\FieldableEntityInterface[] $entities */
    $entities = $storage->loadMultiple($entity_ids);

    // Store all attempted entities before processing.
    $allAttemptedEntities = $entities;

    $converted = $processor->processContentByCategory($fieldSelector, $entities, $category);

    // Identify failed entities by comparing attempted vs successful.
    $convertedIds = array_map(fn($entity) => $entity->id(), $converted);
    $failedEntities = array_filter($allAttemptedEntities, fn($entity) => !in_array($entity->id(), $convertedIds));

    if (!isset($context['results']['processed'])) {
      $context['results']['processed'] = 0;
      $context['results']['updated_entities'] = [];
      $context['results']['failed_entities'] = [];
      $context['results']['group'] = $category;
    }

    foreach ($converted as $entity) {
      $context['results']['processed']++;
      $context['results']['updated_entities'][] = [
        'entity_type' => $entity->getEntityTypeId(),
        'bundle' => $entity->bundle(),
        'id' => $entity->id(),
      ];
    }

    // Track failed entities that weren't successfully converted.
    foreach ($failedEntities as $failedEntity) {
      $context['results']['failed_entities'][] = [
        'entity_type' => $failedEntity->getEntityTypeId(),
        'bundle' => $failedEntity->bundle(),
        'id' => $failedEntity->id(),
      ];

      // Create failed swap record.
      $processor->createSwapRecord($fieldSelector, $failedEntity, $category, 'failed', [
        'error_message' => 'Failed to convert file to media entity.',
      ]);
    }

    $totalProcessed = count($converted) + count($failedEntities);
    $context['message'] = t('Processed chunk of @total entities (@converted converted, @failed failed).', [
      '@total' => $totalProcessed,
      '@converted' => count($converted),
      '@failed' => count($failedEntities),
    ]);
  }

  /**
   * Processes a single MediaSwapRecord entity.
   *
   * @param int $record_id
   *   The ID of the MediaSwapRecord to process.
   * @param array &$context
   *   The batch context.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public static function processRecord(int $record_id, array &$context): void {
    /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entityTypeManager */
    $entityTypeManager = \Drupal::service('entity_type.manager');
    /** @var \Drupal\image_to_media_swapper\BatchProcessorService $processor */
    $processor = \Drupal::service('image_to_media_swapper.batch_processor_service');

    // Initialize results if needed.
    if (!isset($context['results']['processed'])) {
      $context['results']['processed'] = 0;
      $context['results']['successful'] = 0;
      $context['results']['failed'] = 0;
      $context['results']['skipped'] = 0;
    }

    try {
      // Load the MediaSwapRecord.
      $storage = $entityTypeManager->getStorage('media_swap_record');
      /** @var \Drupal\image_to_media_swapper\Entity\MediaSwapRecordInterface $record */
      $record = $storage->load($record_id);

      if (!$record) {
        $context['results']['failed']++;
        $context['message'] = t('Record with ID @id not found.', ['@id' => $record_id]);
        return;
      }

      // Skip if the record is not pending.
      if ($record->getStatus() !== 'pending') {
        $context['results']['skipped']++;
        $context['message'] = t('Skipped record @id (status: @status).', [
          '@id' => $record_id,
          '@status' => $record->getStatus(),
        ]);
        return;
      }

      // Get the target entity.
      $entityTypeId = $record->getTargetEntityType();
      $entityId = $record->getTargetEntityId();
      $entity = $entityTypeManager->getStorage($entityTypeId)->load($entityId);

      if (!$entity) {
        $record->setProcessingStatus('failed');
        $record->setErrorMessage('Target entity no longer exists.');
        $record->save();

        $context['results']['failed']++;
        $context['message'] = t('Failed to process record @id: Target entity not found.', ['@id' => $record_id]);
        return;
      }

      // Process the entity.
      $fieldSelector = $record->getFieldSelector();
      $category = $record->getBatchCategory();
      $entities = [$entity->id() => $entity];

      $result = $processor->processContentByCategory($fieldSelector, $entities, $category);

      if (!empty($result)) {
        $record->setProcessingStatus('completed');
        $record->save();

        $context['results']['successful']++;
        $context['results']['processed']++;
        $context['message'] = t('Successfully processed record @id.', ['@id' => $record_id]);
      }
      else {
        $record->setProcessingStatus('failed');
        $record->setErrorMessage('No changes were made to the content.');
        $record->save();

        $context['results']['failed']++;
        $context['message'] = t('Failed to process record @id: No changes made.', ['@id' => $record_id]);
      }
    }
    catch (\Exception $e) {
      // Handle any exceptions.
      if (isset($record)) {
        $record->setProcessingStatus('failed');
        $record->setErrorMessage($e->getMessage());
        $record->save();
      }

      $context['results']['failed']++;
      $context['message'] = t('Error processing record @id: @message', [
        '@id' => $record_id,
        '@message' => $e->getMessage(),
      ]);

      // Log the error.
      \Drupal::logger('image_to_media_swapper')->error('Error processing record @id: @message', [
        '@id' => $record_id,
        '@message' => $e->getMessage(),
      ]);
    }
  }

  /**
   * Handles the completion of the batch process.
   *
   * @param bool $success
   *   The success status of the batch operation.
   * @param array $results
   *   The results of the batch operation.
   * @param array $operations
   *   The operations that were performed during the batch.
   */
  public static function batchFinished(bool $success, array $results, array $operations): void {
    $messenger = \Drupal::messenger();
    if ($success) {
      $convertedCount = $results['processed'] ?? 0;
      $failedCount = count($results['failed_entities'] ?? []);
      $totalCount = $convertedCount + $failedCount;

      if (empty($totalCount)) {
        $messenger->addError(t('No operations were performed.'));
        return;
      }

      if ($failedCount > 0) {
        $messenger->addStatus(t('Successfully processed @converted items. @failed items failed processing.', [
          '@converted' => $convertedCount,
          '@failed' => $failedCount,
        ]));
        $messenger->addWarning(t('@failed entities could not be converted. Check the media swap records for details.', [
          '@failed' => $failedCount,
        ]));
      }
      else {
        $messenger->addStatus(t('Successfully processed @count items.', ['@count' => $convertedCount]));
      }

      // Handle results from processRecord method.
      if (isset($results['successful']) || isset($results['failed']) || isset($results['skipped'])) {
        $successful = $results['successful'] ?? 0;
        $failed = $results['failed'] ?? 0;
        $skipped = $results['skipped'] ?? 0;

        if ($successful > 0 || $failed > 0 || $skipped > 0) {
          $messenger->addStatus(t('Record processing complete: @successful successful, @failed failed, @skipped skipped.', [
            '@successful' => $successful,
            '@failed' => $failed,
            '@skipped' => $skipped,
          ]));
        }
      }
    }
    else {
      $messenger->addError(t('The batch process encountered an error.'));
    }
  }

}

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

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