pdf_to_imagefield-1.0.x-dev/src/PDFToImageManager.php

src/PDFToImageManager.php
<?php

namespace Drupal\pdf_to_imagefield;

use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityDisplayRepositoryInterface;
use Drupal\Core\Entity\EntityFieldManager;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelInterface;
use Drupal\Core\StreamWrapper\StreamWrapperInterface;
use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\file\FileInterface;
use Spatie\PdfToImage\Pdf;

/**
 * Provides helper class of PDFToImageManager.
 */
class PDFToImageManager implements PDFToImageManagerInterface {

  use StringTranslationTrait;

  /**
   * The entity field manager.
   *
   * @var \Drupal\Core\Entity\EntityFieldManager
   */
  protected EntityFieldManager $entityFieldManager;

  /**
   * The entity display repository.
   *
   * @var \Drupal\Core\Entity\EntityDisplayRepositoryInterface
   */
  protected EntityDisplayRepositoryInterface $entityDisplayRepository;

  /**
   * The entity type manager.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  protected EntityTypeManagerInterface $entityTypeManager;

  /**
   * The stream wrapper manager.
   *
   * @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
   */
  protected StreamWrapperManagerInterface $streamWrapperManager;

  /**
   * The module logger.
   *
   * @var \Drupal\Core\Logger\LoggerChannelInterface
   */
  private LoggerChannelInterface $logger;

  /**
   * Construct PDFToImageManager.
   */
  public function __construct(
    EntityFieldManager $entityFieldManager,
    EntityDisplayRepositoryInterface $entityDisplayRepository,
    EntityTypeManagerInterface $entityTypeManager,
    StreamWrapperManagerInterface $streamWrapperManager,
    LoggerChannelInterface $logger,
  ) {
    $this->logger = $logger;
    $this->streamWrapperManager = $streamWrapperManager;
    $this->entityTypeManager = $entityTypeManager;
    $this->entityDisplayRepository = $entityDisplayRepository;
    $this->entityFieldManager = $entityFieldManager;
  }

  /**
   * {@inheritDoc}
   */
  public function getImageTargetFields(string $entity_type_id, string $bundle): array {
    $fields = $this->entityFieldManager->getFieldDefinitions($entity_type_id, $bundle);

    $field_options = [];
    foreach ($fields as $field_name => $field_definition) {
      if (in_array($field_definition->getType(), ['file', 'image'])) {
        $field_options[$field_name] = $field_definition->getLabel();
      }
    }
    return $field_options;
  }

  /**
   * {@inheritDoc}
   */
  public function getPdfToImageSourceFields(string $entity_type_id, string $bundle): array {
    $fields = $this->entityDisplayRepository->getFormDisplay($entity_type_id, $bundle)->getComponents();

    $source_fields = [];
    foreach ($fields as $field_name => $field) {
      if (isset($field['type']) && $field['type'] === 'pdf_to_imagefield') {
        $source_fields[$field_name] = $field;
      }
    }
    return $source_fields;
  }

  /**
   * {@inheritDoc}
   */
  public function initConversion(ContentEntityInterface $entity, string $field_id, array $field): void {
    $settings = $field['settings'];
    /** @var \Drupal\file\Plugin\Field\FieldType\FileFieldItemList $file_field */
    $file_field = $entity->get($field_id);
    /** @var \Drupal\file\FileInterface[] $files */
    $files = $file_field->referencedEntities();
    if (!($target_field = $settings['target_field'] ?? NULL)) {
      return;
    }
    if (empty($files)) {
      // Updating entity object to be sure that the target field is empty
      // before batch work.
      /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */
      $entity = $this->entityTypeManager->getStorage($entity->getEntityTypeId())->load($entity->id());
      $entity->set($target_field, []);
      $entity->save();
      return;
    }

    $operations = [];
    $other_files = [];
    $pdf_files = [];
    $limit = $settings['batch_limit'];
    $base_batch_data = [
      'entity' => $entity,
      'image'  => [
        'field' => $this->entityTypeManager->getStorage('field_storage_config')->loadByProperties([
          'entity_type' => $entity->getEntityTypeId(),
          'field_name' => $target_field,
        ]),
        'instance' => $this->entityTypeManager->getStorage('field_config')->loadByProperties([
          'entity_type' => $entity->getEntityTypeId(),
          'bundle' => $entity->bundle(),
          'field_name' => $target_field,
        ]),
      ],
      'pdf_settings' => $settings,
    ];
    foreach ($files as $file) {
      if ($file->getMimeType() !== 'application/pdf') {
        if (!$settings['only_pdf']) {
          $other_files[] = $file;
        }
        continue;
      }

      // Check if PDF has been already converted.
      if ($pdf_pages = $this->getPdfPages($file)) {
        $other_files = array_merge($other_files, $pdf_pages);
        continue;
      }

      // Prepare data for PDF conversion.
      $uri = $file->getFileUri();
      if ($uri === NULL) {
        continue;
      }
      $stream_wrapper = $this->streamWrapperManager->getViaUri($uri);
      if (!$stream_wrapper instanceof StreamWrapperInterface) {
        continue;
      }
      $full_path = $stream_wrapper->realpath();
      if (!file_exists($full_path)) {
        $this->logger->error('Invalid file given to convert. Could not read %file (%source_file)',
          [
            '%file' => $file->getFileUri(),
            '%source_file' => $full_path,
          ]);
        continue;
      }
      $pdf = new Pdf($full_path);
      $count = $pdf->getNumberOfPages();

      // Skip PDF if it doesn't have any pages.
      if (!$count) {
        continue;
      }

      // Prepare PDF settings.
      $pdf->setOutputFormat($settings['image_format'] ?? 'png');
      $pdf->setResolution($settings['resolution'] ?? 144);
      $pdf->setCompressionQuality($settings['compression'] ?? 100);

      // Prepare batch operations according to page limit per operation.
      $start_page = 1;
      do {
        $pdf_files[] = [
          $file,
          $pdf,
          $start_page,
          min($start_page + $limit, $count),
        ];
        $start_page += $limit + 1;
      } while ($start_page < $count);
    }

    if ($other_files) {
      $operations[] = [self::HELPER_CLASS . '::moveNonPdfFiles',
        [$base_batch_data, $other_files],
      ];
    }
    if ($pdf_files) {
      foreach ($pdf_files as $pdf_file) {
        $operations[] = [self::HELPER_CLASS . '::generateProcessPage',
          [$base_batch_data, ...$pdf_file],
        ];
      }
    }

    if (!$operations) {
      $this->logger->info('There are no files to process.');
    }

    $this->logger->info('Starting a process to convert attached PDF to image previews');
    // Inits batch.
    $batch = [
      'title' => $this->t('Processing PDF to Image.'),
      'operations' => $operations,
      'finished' => self::HELPER_CLASS . '::generateProcessAttach',
      'progress_message' => $this->t('Processed @current out of @total.'),
    ];
    batch_set($batch);
    $this->logger->notice('Batch operations end.');
    $this->logger->info('Update batch operations end.');
  }

  /**
   * Get PDF pages that have been already converted.
   *
   * @param \Drupal\file\FileInterface $file
   *   PDF file.
   *
   * @return \Drupal\file\FileInterface[]
   *   PDF pages.
   */
  protected function getPdfPages(FileInterface $file): array {
    $file_storage = $this->entityTypeManager->getStorage('file');
    $pdf_pages = $file_storage->getQuery()
      ->accessCheck(FALSE)
      ->condition('filename', $file->id(), 'STARTS_WITH')
      ->execute();
    if ($pdf_pages) {
      return $file_storage->loadMultiple($pdf_pages);
    }
    return [];
  }

}

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

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