wse-1.0.x-dev/src/WorkspaceReverter.php

src/WorkspaceReverter.php
<?php

namespace Drupal\wse;

use Drupal\Component\Utility\Environment;
use Drupal\Core\Database\Connection;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Logger\LoggerChannelTrait;
use Drupal\Core\Utility\Error;
use Drupal\workspaces\WorkspaceAssociationInterface;
use Drupal\workspaces\WorkspaceInterface;
use Drupal\workspaces\WorkspaceManagerInterface;
use Drupal\wse\Event\WorkspaceEvents;
use Drupal\wse\Event\WorkspaceRevertEvent;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;

/**
 * Defines a service for reverting workspace contents.
 */
class WorkspaceReverter {

  use LoggerChannelTrait;

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

  /**
   * The database connection.
   *
   * @var \Drupal\Core\Database\Connection
   */
  protected $database;

  /**
   * The workspace manager.
   *
   * @var \Drupal\workspaces\WorkspaceManagerInterface
   */
  protected $workspaceManager;

  /**
   * The workspace association service.
   *
   * @var \Drupal\workspaces\WorkspaceAssociationInterface
   */
  protected $workspaceAssociation;

  /**
   * The published revision storage service.
   *
   * @var \Drupal\wse\PublishedRevisionStorage
   */
  protected $publishedRevisionStorage;

  /**
   * The event dispatcher.
   *
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
   */
  protected $eventDispatcher;

  /**
   * Constructs a new WorkspaceReverter instance.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
   *   The entity type manager service.
   * @param \Drupal\Core\Database\Connection $database
   *   Database connection.
   * @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
   *   The workspace manager.
   * @param \Drupal\workspaces\WorkspaceAssociationInterface $workspace_association
   *   The workspace association service.
   * @param \Drupal\wse\PublishedRevisionStorage $published_revision_storage
   *   The published revision storage.
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
   *   The event dispatcher.
   */
  public function __construct(EntityTypeManagerInterface $entity_type_manager, Connection $database, WorkspaceManagerInterface $workspace_manager, WorkspaceAssociationInterface $workspace_association, PublishedRevisionStorage $published_revision_storage, EventDispatcherInterface $event_dispatcher) {
    $this->entityTypeManager = $entity_type_manager;
    $this->database = $database;
    $this->workspaceManager = $workspace_manager;
    $this->workspaceAssociation = $workspace_association;
    $this->publishedRevisionStorage = $published_revision_storage;
    $this->eventDispatcher = $event_dispatcher;
  }

  /**
   * Reverts the revisions published by a workspace.
   */
  public function revert(WorkspaceInterface $workspace) {
    $revert_to_revisions = $this->publishedRevisionStorage->getRevertRevisions($workspace->id());
    $revert_from_revisions = $this->publishedRevisionStorage->getPublishedRevisions($workspace->id());
    $this->eventDispatcher->dispatch(new WorkspaceRevertEvent($workspace, $revert_to_revisions, $revert_from_revisions), WorkspaceEvents::WORKSPACE_PRE_REVERT);

    $transaction = $this->database->startTransaction();
    try {
      // Roll back the revisions of this workspace.
      $this->workspaceManager->executeOutsideWorkspace(function () use ($revert_to_revisions) {
        foreach ($revert_to_revisions as $entity_type_id => $revert_revision_ids) {
          // Split the revisions into chunks to avoid loading too many entities.
          $revert_revision_chunks = array_chunk($revert_revision_ids, 100, TRUE);

          foreach ($revert_revision_chunks as $revert_revision_chunk) {
            $revisions = $this->entityTypeManager->getStorage($entity_type_id)
              ->loadMultipleRevisions(array_keys($revert_revision_chunk));

            foreach ($revisions as $revision) {
              if (method_exists($revision, 'setOriginal')) {
                $revision->setOriginal(clone $revision);
              }
              else {
                $revision->original = clone $revision;
              }
              $revision->setSyncing(TRUE);
              $revision->isDefaultRevision(TRUE);
              $revision->save();

              // Extend the execution time after each entity save, so we give
              // ample time for e.g. cascading operations.
              Environment::setTimeLimit(30);
            }
          }
        }
      });

      // Re-associate the published revisions to the workspace that is being
      // reverted.
      foreach ($revert_from_revisions as $entity_type_id => $revision_ids) {
        // Split the revisions into chunks to avoid loading too many entities.
        $revert_from_revision_chunks = array_chunk($revision_ids, 100, TRUE);

        foreach ($revert_from_revision_chunks as $revert_from_revision_chunk) {
          $revisions = $this->entityTypeManager->getStorage($entity_type_id)
            ->loadMultipleRevisions(array_keys($revert_from_revision_chunk));

          foreach ($revisions as $revision) {
            $revision->setSyncing(TRUE);
            $revision->isDefaultRevision(FALSE);

            // Track this revision in its previous workspace.
            $workspace_key = $revision->getEntityType()->getRevisionMetadataKey('workspace');
            $revision->set($workspace_key, $workspace->id());
            $this->workspaceAssociation->trackEntity($revision, $workspace);

            // Unset the 'was default revision' flag.
            $revision_default_key = $revision->getEntityType()->getRevisionMetadataKey('revision_default');
            $revision->set($revision_default_key, FALSE);

            $revision->save();

            // Extend the execution time after each entity save, so we give
            // ample time for e.g. cascading operations.
            Environment::setTimeLimit(30);
          }
        }
      }

      // Delete the published revisions record for this workspace.
      $this->publishedRevisionStorage->deleteRecord($workspace->id());

      // Move the workspace back to the 'open' status.
      $workspace->set('status', WSE_STATUS_OPEN)->save();
    }
    catch (\Exception $e) {
      $transaction->rollBack();
      Error::logException($this->getLogger('workspaces'), $e);
      throw $e;
    }

    $this->eventDispatcher->dispatch(new WorkspaceRevertEvent($workspace, $revert_to_revisions, $revert_from_revisions), WorkspaceEvents::WORKSPACE_POST_REVERT);
  }

}

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

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