epub_reader_framework-2.0.0-alpha2/src/Batch/ReaderChapterExtractorBatchProcessor.php

src/Batch/ReaderChapterExtractorBatchProcessor.php
<?php

namespace Drupal\epub_reader_framework\Batch;

use Drupal\Core\Url;
use Drupal\node\Entity\Node;
use Symfony\Component\HttpFoundation\RedirectResponse;

/**
 * Handle the batch processing of the epub extraction process.
 *
 * @package Drupal\epub_reader_framework\Batch
 */
class ReaderChapterExtractorBatchProcessor {

  /**
   * Batch set operation callback.
   *
   * @param int $reader_publication_id
   *   Node ID of the parent reader_publication entity.
   * @param array $context
   *   Batch context.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\Archiver\ArchiverException
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public static function operationCallback($reader_publication_id, array &$context) {
    if (empty($context['sandbox'])) {
      self::initialiseSandbox($reader_publication_id, $context);
    }

    // Nothing to process.
    if (!$context['sandbox']['max']) {
      $context['finished'] = 1;
      return;
    }

    // If we haven't yet processed all.
    if ($context['sandbox']['progress'] < $context['sandbox']['max']) {
      if (isset($context['sandbox']['spine'][$context['sandbox']['progress']])) {
        $chapter = $context['sandbox']['spine'][$context['sandbox']['progress']];
        if (isset($chapter['uri'])) {
          if ($reader_publication = Node::load($context['sandbox']['reader_publication_id'])) {
            /** @var \Drupal\node\NodeInterface $reader_publication */
            /** @var \Drupal\epub_reader_framework\Epub\ReaderEpubXhtmlConverter $epub_xhtml_converter */
            $epub_xhtml_converter = \Drupal::service('epub_reader_framework.reader_epub_xhtml_converter');

            try {
              $context['sandbox']['chapter_nids'][] = $epub_xhtml_converter->convertXhtmlToChapter(
                $reader_publication,
                $chapter['uri'],
                $chapter['@id']
              );
            }
            catch (Exception $e) {
              \Drupal::messenger()->addWarning($e->getMessage());
            }

            // Store chapter in results. This is used both in the finish
            // callback as well as the orphaned chapter cleanup.
            $context['results']['chapters'][] = $chapter['@id'];
          }
        }
      }

      $context['sandbox']['progress']++;
    }

    // Mark reader EPUB as processed:
    if ($reader_publication = Node::load($context['sandbox']['reader_publication_id'])) {
      if ($reader_publication->hasField('field_reader_file_processed') && !$reader_publication->field_reader_file_processed->value) {
        $reader_publication->set('field_reader_file_processed', TRUE);
        $reader_publication->setNewRevision(TRUE);
        $reader_publication->save();
      }
    }

    // Extra step added for post-processing.
    // @see self::extractEpub().
    if ($context['sandbox']['progress'] == $context['sandbox']['max']) {
      if ($context['results']['chapters'] && $reader_publication = Node::load($context['sandbox']['reader_publication_id'])) {
        /** @var \Drupal\node\NodeInterface $reader_publication */
        /** @var \Drupal\epub_reader_framework\Epub\ReaderEpubCompletedCleanup $epub_xhtml_converter */
        $epub_xhtml_converter = \Drupal::service('epub_reader_framework.reader_epub_completed_cleanup');
        $epub_xhtml_converter->cleanupChapters($reader_publication,
          $context['results']['chapters']);

        if ($context['sandbox']['chapter_nids']) {

          /** @var \Drupal\epub_reader_framework\Entity\ReaderEntityCrossReference $reader_entity_cross_reference */
          $reader_entity_cross_reference = \Drupal::service('epub_reader_framework.reader_entity_cross_reference');
          $reader_entity_cross_reference->crossReferenceChaptersFromPublicationExtraction(
            $reader_publication,
            $context['sandbox']['chapter_nids']
          );
        }
      }

      $context['sandbox']['progress']++;
    }

    // When progress equals max, finished is '1' which means completed. Any
    // decimal between '0' and '1' is used to determine the percentage of
    // the progress bar.
    $context['finished'] = $context['sandbox']['progress'] / $context['sandbox']['max'];
  }

  /**
   * Intialise sandbox on first operation callback.
   *
   * @param int $reader_publication_id
   *   Node ID of the parent reader_publication entity.
   * @param array $context
   *   Batch context.
   *
   * @throws \Drupal\Core\Archiver\ArchiverException
   */
  protected static function initialiseSandbox(
    $reader_publication_id,
    array &$context
  ) {
    $context['sandbox']['progress'] = 0;
    $context['sandbox']['max'] = 0;
    $context['sandbox']['reader_publication_id'] = $reader_publication_id;
    $context['sandbox']['chapter_nids'] = [];
    $context['results'] = [];
    $context['results']['chapters'] = [];
    $context['results']['reader_publication_id'] = $reader_publication_id;
    self::extractEpub($context);
  }

  /**
   * Context to load per operation.
   *
   * Full context sandbox is stored and passed between each batch opeation
   * callback occurrence. It is possible the publication epub content is too
   * large for that storage so load on demand per run instead.
   *
   * @param array $context
   *   The batch processing context.
   *
   * @throws \Drupal\Core\Archiver\ArchiverException
   */
  protected static function extractEpub(array &$context) {
    if (isset($context['sandbox']['reader_publication_id']) && $context['sandbox']['reader_publication_id']) {
      if ($reader_publication = Node::load($context['sandbox']['reader_publication_id'])) {
        /** @var \Drupal\node\NodeInterface $reader_publication */
        /** @var \Drupal\epub_reader_framework\Epub\ReaderEpubZipExtractor $epub_zip_extractor */
        $epub_zip_extractor = \Drupal::service('epub_reader_framework.reader_epub_zip_extractor');
        $epub_zip_extractor->extractEpubFiles($reader_publication);
        $context['sandbox']['extracted_files'] = $epub_zip_extractor->getExtractedFiles($reader_publication);
        $context['sandbox']['spine'] = $epub_zip_extractor->getSpineContents($reader_publication);
        $context['sandbox']['max'] = (is_array($context['sandbox']['spine']) ? count($context['sandbox']['spine']) : 0);

        // If we have chapters, add 1 post-processing step.
        if ($context['sandbox']['max']) {
          $context['sandbox']['max']++;
        }
      }
    }
  }

  /**
   * Batch finished callback.
   *
   * @param bool $success
   *   Batch encountered errors or not.
   * @param array $results
   *   The processed chapters.
   * @param array $operations
   *   The different batches that were run.
   */
  public static function finishedCallback($success, array $results, array $operations) {
    if ($success) {

      // The 'success' parameter means no fatal PHP errors were detected.
      $message = t('@count chapters were extracted successfully.', [
        '@count' => (isset($results['chapters']) ? count($results['chapters']) : 0),
      ]);
      \Drupal::messenger()->addStatus($message);
    }
    else {

      // A fatal error occurred.
      $message = t('Finished with an error.');
      \Drupal::messenger()->addWarning($message);
    }

    if (isset($results['reader_publication_id'])) {

      // Redirect to adding a publication.
      $url = Url::fromRoute('entity.node.edit_form', [
        'node' => $results['reader_publication_id'],
      ])->toString();
      $response = new RedirectResponse($url);
      $response->send();
    }
  }

}

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

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