From 50d6f37c1224fbc599b93047e93921102ada1092 Mon Sep 17 00:00:00 2001
From: ajstanley <alanjarlathstanley@gmail.com>
Date: Wed, 19 Mar 2025 13:59:00 +0000
Subject: [PATCH] batched

---
 src/Form/CreateMediaFromFileForm.php |   3 +-
 src/Utils.php                        | 157 +++++++++++++--------------
 2 files changed, 75 insertions(+), 85 deletions(-)

diff --git a/src/Form/CreateMediaFromFileForm.php b/src/Form/CreateMediaFromFileForm.php
index 48577e9..af6d221 100644
--- a/src/Form/CreateMediaFromFileForm.php
+++ b/src/Form/CreateMediaFromFileForm.php
@@ -142,7 +142,8 @@ final class CreateMediaFromFileForm extends FormBase {
     $destination = "{$file_system}{$directory}";
     $media_type = $form_state->getValue('media_type');
     $media_use = $form_state->getValue('media_use');
-    $results = $this->mediaUtils->buildMedia($source_path, $destination, $media_type, $media_use);
+    // $results = $this->mediaUtils->buildMedia($source_path, $destination, $media_type, $media_use);
+    $results = $this->mediaUtils->buildMediaBatch($source_path, $destination, $media_type, $media_use);
     $this->messenger()->addStatus($this->t('Media files have been processed from %source to %destination.', [
       '%source' => $source_path,
       '%destination' => $destination,
diff --git a/src/Utils.php b/src/Utils.php
index dc59149..4281d74 100644
--- a/src/Utils.php
+++ b/src/Utils.php
@@ -4,117 +4,106 @@ declare(strict_types=1);
 
 namespace Drupal\islandora_inplace_media;
 
-use Drupal\Core\Entity\EntityTypeManagerInterface;
 use Drupal\Core\File\FileSystemInterface;
-use Drupal\Core\Logger\LoggerChannelFactoryInterface;
-use Drupal\Core\Entity\EntityFieldManagerInterface;
 use Drupal\file\Entity\File;
 use Drupal\media\Entity\Media;
-use Drupal\media\Entity\MediaType;
 
 /**
  * Utility class for managing media file operations in Islandora.
  */
-final class Utils {
+class Utils {
 
   /**
-   * Constructs a Utils object.
+   * Processes individual file.
    */
-  public function __construct(
-    private readonly EntityTypeManagerInterface $entityTypeManager,
-    private readonly FileSystemInterface $fileSystem,
-    private readonly LoggerChannelFactoryInterface $loggerFactory,
-    private readonly EntityFieldManagerInterface $entityFieldManager,
-  ) {}
+  public static function processMediaBatch($file_name, $dir, $dest, $media_type, $media_use_tid, &$context) {
+    if (!isset($context['results'])) {
+      $context['results'] = [];
+    }
+
+    $logger = \Drupal::logger('islandora_inplace_media');
+    $fileSystem = \Drupal::service('file_system');
+
+    $source_path = $dir . '/' . $file_name;
+    $destination_path = $dest . '/' . $file_name;
+
+    if (!file_exists($source_path)) {
+      $logger->warning('File does not exist: @file', ['@file' => $source_path]);
+      return;
+    }
+
+    $moved_file = $fileSystem->move($source_path, $destination_path, FileSystemInterface::EXISTS_RENAME);
+    $new_file = File::create([
+      'uri' => $moved_file,
+      'status' => 1,
+    ]);
+    $new_file->save();
+    $context['results'][$new_file->id()] = $moved_file;
+
+    if (preg_match('/^(\d+)_/', $file_name, $matches)) {
+      $nid = $matches[1] ?? NULL;
+    }
+    unlink($source_path);
+
+    if ($nid) {
+      $media = Media::create([
+        "bundle" => $media_type,
+        "name" => $file_name,
+        "field_media_file" => [
+          "target_id" => $new_file->id(),
+        ],
+        'field_media_use' => [
+          "target_id" => $media_use_tid,
+        ],
+        "field_media_of" => $nid,
+      ]);
+      $media->save();
+    }
+  }
 
   /**
-   * Moves files from staging to a managed folder and creates media entities.
-   *
-   * @param string $dir
-   *   The source directory containing files.
-   * @param string $dest
-   *   The destination directory (e.g., 'public://media' or 'private://media').
-   * @param string $media_type
-   *   The media type to be created.
-   * @param string $media_use_tid
-   *   The terms id for new media.
+   * Builds batch from input directory.
    */
-  public function buildMedia(string $dir, string $dest, string $media_type, string $media_use_tid): array {
-    $results = [];
+  public static function buildMediaBatch(string $dir, string $dest, string $media_type, string $media_use_tid) {
     if (!is_dir($dir)) {
-      $this->loggerFactory->get('islandora_inplace_media')->error('Source directory does not exist: @dir', ['@dir' => $dir]);
-      return $results;
+      \Drupal::logger('islandora_inplace_media')->error('Source directory does not exist: @dir', ['@dir' => $dir]);
+      return;
     }
-    $default_file_field = $this->getDefaultFileField($media_type);
-    $this->fileSystem->prepareDirectory($dest, FileSystemInterface::CREATE_DIRECTORY);
+
+    // Use a service within the function, not in the batch context.
+    $fileSystem = \Drupal::service('file_system');
+    $fileSystem->prepareDirectory($dest, FileSystemInterface::CREATE_DIRECTORY);
 
     $files = scandir($dir);
     $files = array_diff($files, ['.', '..']);
 
-    foreach ($files as $file_name) {
-      $source_path = $dir . '/' . $file_name;
-      $destination_path = $dest . '/' . $file_name;
+    $batch = [
+      'title' => t('Processing media files...'),
+      'operations' => [],
+    // Static method reference.
+      'finished' => [self::class, 'finishMediaBatch'],
+    ];
 
-      $moved_file = $this->fileSystem->move($source_path, $destination_path, FileSystemInterface::EXISTS_RENAME);
-      $new_file = File::create([
-        'uri' => $moved_file,
-        'status' => 1,
-      ]);
-      $new_file->save();
-      $results[$new_file->id()] = $moved_file;
-      if (preg_match('/n(\d+)_/', $file_name, $matches)) {
-        $nid = $matches[1] ?? NULL;
-      }
-      unlink($source_path);
-      if ($nid) {
-        $media = Media::create([
-          "bundle" => $media_type,
-          "name" => $file_name,
-          $default_file_field => [
-            "target_id" => $new_file->id(),
-          ],
-          'field_media_use' => [
-            "target_id" => $media_use_tid,
-          ],
-          "field_media_of" => $nid,
-        ]);
-        $media->save();
-      }
+    foreach ($files as $file_name) {
+      $batch['operations'][] = [
+        [self::class, 'processMediaBatch'],
+        [$file_name, $dir, $dest, $media_type, $media_use_tid],
+      ];
     }
-    return $results;
+
+    batch_set($batch);
   }
 
   /**
-   * Get the default file field from a media type.
-   *
-   * @param string $media_type_id
-   *   The media type ID.
-   *
-   * @return string|null
-   *   The field name of the default file field, or NULL if none is found.
+   * Display results.
    */
-  public function getDefaultFileField(string $media_type_id): ?string {
-    // Load the media type.
-    $media_type = MediaType::load($media_type_id);
-    if (!$media_type) {
-      $this->loggerFactory->get('islandora_inplace_media')->error('Media type @type not found.', ['@type' => $media_type_id]);
-      return NULL;
+  public static function finishMediaBatch($success, $results, $operations) {
+    if ($success) {
+      \Drupal::logger('islandora_inplace_media')->notice('Successfully processed media files.');
     }
-
-    // Get all field definitions for the media entity type.
-    $field_definitions = $this->entityFieldManager->getFieldDefinitions('media', $media_type_id);
-
-    // Look for the first file-based field (file or image).
-    foreach ($field_definitions as $field_name => $field_definition) {
-      $storage_type = $field_definition->getType();
-      if (in_array($storage_type, ['file', 'image'])) {
-        if ($field_name != 'thumbnail') {
-          return $field_name;
-        }
-      }
+    else {
+      \Drupal::logger('islandora_inplace_media')->error('There were errors processing media files.');
     }
-
-    return NULL;
   }
 
 }