comparison core/modules/workspaces/src/WorkspacePublisher.php @ 17:129ea1e6d783

Update, including to Drupal core 8.6.10
author Chris Cannam
date Thu, 28 Feb 2019 13:21:36 +0000
parents
children af1871eacc83
comparison
equal deleted inserted replaced
16:c2387f117808 17:129ea1e6d783
1 <?php
2
3 namespace Drupal\workspaces;
4
5 use Drupal\Core\Database\Connection;
6 use Drupal\Core\Entity\EntityTypeManagerInterface;
7
8 /**
9 * Default implementation of the workspace publisher.
10 *
11 * @internal
12 */
13 class WorkspacePublisher implements WorkspacePublisherInterface {
14
15 /**
16 * The source workspace entity.
17 *
18 * @var \Drupal\workspaces\WorkspaceInterface
19 */
20 protected $sourceWorkspace;
21
22 /**
23 * The target workspace entity.
24 *
25 * @var \Drupal\workspaces\WorkspaceInterface
26 */
27 protected $targetWorkspace;
28
29 /**
30 * The entity type manager.
31 *
32 * @var \Drupal\Core\Entity\EntityTypeManagerInterface
33 */
34 protected $entityTypeManager;
35
36 /**
37 * The database connection.
38 *
39 * @var \Drupal\Core\Database\Connection
40 */
41 protected $database;
42
43 /**
44 * The workspace association storage.
45 *
46 * @var \Drupal\workspaces\WorkspaceAssociationStorageInterface
47 */
48 protected $workspaceAssociationStorage;
49
50 /**
51 * Constructs a new WorkspacePublisher.
52 *
53 * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
54 * The entity type manager.
55 * @param \Drupal\Core\Database\Connection $database
56 * Database connection.
57 */
58 public function __construct(EntityTypeManagerInterface $entity_type_manager, Connection $database, WorkspaceInterface $source) {
59 $this->entityTypeManager = $entity_type_manager;
60 $this->database = $database;
61 $this->workspaceAssociationStorage = $entity_type_manager->getStorage('workspace_association');
62 $this->sourceWorkspace = $source;
63 $this->targetWorkspace = $this->entityTypeManager->getStorage('workspace')->load(WorkspaceInterface::DEFAULT_WORKSPACE);
64 }
65
66 /**
67 * {@inheritdoc}
68 */
69 public function publish() {
70 if ($this->checkConflictsOnTarget()) {
71 throw new WorkspaceConflictException();
72 }
73
74 $transaction = $this->database->startTransaction();
75 try {
76 // @todo Handle the publishing of a workspace with a batch operation in
77 // https://www.drupal.org/node/2958752.
78 foreach ($this->getDifferringRevisionIdsOnSource() as $entity_type_id => $revision_difference) {
79 $entity_revisions = $this->entityTypeManager->getStorage($entity_type_id)
80 ->loadMultipleRevisions(array_keys($revision_difference));
81 /** @var \Drupal\Core\Entity\EntityInterface|\Drupal\Core\Entity\RevisionableInterface $entity */
82 foreach ($entity_revisions as $entity) {
83 // When pushing workspace-specific revisions to the default workspace
84 // (Live), we simply need to mark them as default revisions.
85 // @todo Remove this dynamic property once we have an API for
86 // associating temporary data with an entity:
87 // https://www.drupal.org/node/2896474.
88 $entity->_isReplicating = TRUE;
89 $entity->isDefaultRevision(TRUE);
90 $entity->save();
91 }
92 }
93 }
94 catch (\Exception $e) {
95 $transaction->rollBack();
96 watchdog_exception('workspaces', $e);
97 throw $e;
98 }
99
100 // Notify the workspace association storage that a workspace has been
101 // pushed.
102 $this->workspaceAssociationStorage->postPush($this->sourceWorkspace);
103 }
104
105 /**
106 * {@inheritdoc}
107 */
108 public function getSourceLabel() {
109 return $this->sourceWorkspace->label();
110 }
111
112 /**
113 * {@inheritdoc}
114 */
115 public function getTargetLabel() {
116 return $this->targetWorkspace->label();
117 }
118
119 /**
120 * {@inheritdoc}
121 */
122 public function checkConflictsOnTarget() {
123 // Nothing to do for now, we can not get to a conflicting state because an
124 // entity which is being edited in a workspace can not be edited in any
125 // other workspace.
126 }
127
128 /**
129 * {@inheritdoc}
130 */
131 public function getDifferringRevisionIdsOnTarget() {
132 $target_revision_difference = [];
133
134 $tracked_entities = $this->workspaceAssociationStorage->getTrackedEntities($this->sourceWorkspace->id());
135 foreach ($tracked_entities as $entity_type_id => $tracked_revisions) {
136 $entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
137
138 // Get the latest revision IDs for all the entities that are tracked by
139 // the source workspace.
140 $query = $this->entityTypeManager
141 ->getStorage($entity_type_id)
142 ->getQuery()
143 ->condition($entity_type->getKey('id'), $tracked_revisions, 'IN')
144 ->latestRevision();
145 $result = $query->execute();
146
147 // Now we compare the revision IDs which are tracked by the source
148 // workspace to the latest revision IDs of those entities and the
149 // difference between these two arrays gives us all the entities which
150 // have been modified on the target.
151 if ($revision_difference = array_diff_key($result, $tracked_revisions)) {
152 $target_revision_difference[$entity_type_id] = $revision_difference;
153 }
154 }
155
156 return $target_revision_difference;
157 }
158
159 /**
160 * {@inheritdoc}
161 */
162 public function getDifferringRevisionIdsOnSource() {
163 // Get the Workspace association revisions which haven't been pushed yet.
164 return $this->workspaceAssociationStorage->getTrackedEntities($this->sourceWorkspace->id());
165 }
166
167 /**
168 * {@inheritdoc}
169 */
170 public function getNumberOfChangesOnTarget() {
171 $total_changes = $this->getDifferringRevisionIdsOnTarget();
172 return count($total_changes, COUNT_RECURSIVE) - count($total_changes);
173 }
174
175 /**
176 * {@inheritdoc}
177 */
178 public function getNumberOfChangesOnSource() {
179 $total_changes = $this->getDifferringRevisionIdsOnSource();
180 return count($total_changes, COUNT_RECURSIVE) - count($total_changes);
181 }
182
183 }