Chris@17: entityTypeManager = $entity_type_manager; Chris@17: $this->database = $database; Chris@17: $this->workspaceAssociationStorage = $entity_type_manager->getStorage('workspace_association'); Chris@18: $this->workspaceManager = $workspace_manager; Chris@17: $this->sourceWorkspace = $source; Chris@17: $this->targetWorkspace = $this->entityTypeManager->getStorage('workspace')->load(WorkspaceInterface::DEFAULT_WORKSPACE); Chris@17: } Chris@17: Chris@17: /** Chris@17: * {@inheritdoc} Chris@17: */ Chris@17: public function publish() { Chris@17: if ($this->checkConflictsOnTarget()) { Chris@17: throw new WorkspaceConflictException(); Chris@17: } Chris@17: Chris@17: $transaction = $this->database->startTransaction(); Chris@17: try { Chris@17: // @todo Handle the publishing of a workspace with a batch operation in Chris@17: // https://www.drupal.org/node/2958752. Chris@18: $this->workspaceManager->executeInWorkspace($this->targetWorkspace->id(), function () { Chris@18: foreach ($this->getDifferringRevisionIdsOnSource() as $entity_type_id => $revision_difference) { Chris@18: Chris@18: $entity_revisions = $this->entityTypeManager->getStorage($entity_type_id) Chris@18: ->loadMultipleRevisions(array_keys($revision_difference)); Chris@18: $default_revisions = $this->entityTypeManager->getStorage($entity_type_id) Chris@18: ->loadMultiple(array_values($revision_difference)); Chris@18: Chris@18: /** @var \Drupal\Core\Entity\ContentEntityInterface $entity */ Chris@18: foreach ($entity_revisions as $entity) { Chris@18: // When pushing workspace-specific revisions to the default Chris@18: // workspace (Live), we simply need to mark them as default Chris@18: // revisions. Chris@18: $entity->setSyncing(TRUE); Chris@18: $entity->isDefaultRevision(TRUE); Chris@18: $entity->original = $default_revisions[$entity->id()]; Chris@18: $entity->save(); Chris@18: } Chris@17: } Chris@18: }); Chris@17: } Chris@17: catch (\Exception $e) { Chris@17: $transaction->rollBack(); Chris@17: watchdog_exception('workspaces', $e); Chris@17: throw $e; Chris@17: } Chris@17: Chris@17: // Notify the workspace association storage that a workspace has been Chris@17: // pushed. Chris@17: $this->workspaceAssociationStorage->postPush($this->sourceWorkspace); Chris@17: } Chris@17: Chris@17: /** Chris@17: * {@inheritdoc} Chris@17: */ Chris@17: public function getSourceLabel() { Chris@17: return $this->sourceWorkspace->label(); Chris@17: } Chris@17: Chris@17: /** Chris@17: * {@inheritdoc} Chris@17: */ Chris@17: public function getTargetLabel() { Chris@17: return $this->targetWorkspace->label(); Chris@17: } Chris@17: Chris@17: /** Chris@17: * {@inheritdoc} Chris@17: */ Chris@17: public function checkConflictsOnTarget() { Chris@17: // Nothing to do for now, we can not get to a conflicting state because an Chris@17: // entity which is being edited in a workspace can not be edited in any Chris@17: // other workspace. Chris@17: } Chris@17: Chris@17: /** Chris@17: * {@inheritdoc} Chris@17: */ Chris@17: public function getDifferringRevisionIdsOnTarget() { Chris@17: $target_revision_difference = []; Chris@17: Chris@17: $tracked_entities = $this->workspaceAssociationStorage->getTrackedEntities($this->sourceWorkspace->id()); Chris@17: foreach ($tracked_entities as $entity_type_id => $tracked_revisions) { Chris@17: $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); Chris@17: Chris@17: // Get the latest revision IDs for all the entities that are tracked by Chris@17: // the source workspace. Chris@17: $query = $this->entityTypeManager Chris@17: ->getStorage($entity_type_id) Chris@17: ->getQuery() Chris@17: ->condition($entity_type->getKey('id'), $tracked_revisions, 'IN') Chris@17: ->latestRevision(); Chris@17: $result = $query->execute(); Chris@17: Chris@17: // Now we compare the revision IDs which are tracked by the source Chris@17: // workspace to the latest revision IDs of those entities and the Chris@17: // difference between these two arrays gives us all the entities which Chris@17: // have been modified on the target. Chris@17: if ($revision_difference = array_diff_key($result, $tracked_revisions)) { Chris@17: $target_revision_difference[$entity_type_id] = $revision_difference; Chris@17: } Chris@17: } Chris@17: Chris@17: return $target_revision_difference; Chris@17: } Chris@17: Chris@17: /** Chris@17: * {@inheritdoc} Chris@17: */ Chris@17: public function getDifferringRevisionIdsOnSource() { Chris@17: // Get the Workspace association revisions which haven't been pushed yet. Chris@17: return $this->workspaceAssociationStorage->getTrackedEntities($this->sourceWorkspace->id()); Chris@17: } Chris@17: Chris@17: /** Chris@17: * {@inheritdoc} Chris@17: */ Chris@17: public function getNumberOfChangesOnTarget() { Chris@17: $total_changes = $this->getDifferringRevisionIdsOnTarget(); Chris@17: return count($total_changes, COUNT_RECURSIVE) - count($total_changes); Chris@17: } Chris@17: Chris@17: /** Chris@17: * {@inheritdoc} Chris@17: */ Chris@17: public function getNumberOfChangesOnSource() { Chris@17: $total_changes = $this->getDifferringRevisionIdsOnSource(); Chris@17: return count($total_changes, COUNT_RECURSIVE) - count($total_changes); Chris@17: } Chris@17: Chris@17: }