diff --git a/src/UpstreamPluginBase.php b/src/UpstreamPluginBase.php index 3c26109..2182f93 100644 --- a/src/UpstreamPluginBase.php +++ b/src/UpstreamPluginBase.php @@ -48,7 +48,6 @@ abstract class UpstreamPluginBase extends PluginBase implements UpstreamPluginIn public function isRemote() { return $this->getPluginDefinition()['remote']; } - /** * {@inheritdoc} */ diff --git a/tests/modules/workspace_remote_test/config/install/rest.resource.replication.yml b/tests/modules/workspace_remote_test/config/install/rest.resource.replication.yml new file mode 100644 index 0000000..098f716 --- /dev/null +++ b/tests/modules/workspace_remote_test/config/install/rest.resource.replication.yml @@ -0,0 +1,16 @@ +langcode: en +status: true +dependencies: + module: + - basic_auth + - workspace +id: replication +plugin_id: replication +granularity: resource +configuration: + methods: + - POST + formats: + - json + authentication: + - basic_auth diff --git a/tests/modules/workspace_remote_test/src/Plugin/Upstream/RemoteWorkspaceUpstream.php b/tests/modules/workspace_remote_test/src/Plugin/Upstream/RemoteWorkspaceUpstream.php new file mode 100644 index 0000000..2e1aadb --- /dev/null +++ b/tests/modules/workspace_remote_test/src/Plugin/Upstream/RemoteWorkspaceUpstream.php @@ -0,0 +1,23 @@ +entityTypeManager = $entity_type_manager; + $this->workspaceManager = $workspace_manager; + $this->serializer = $serializer; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { + return new static( + $configuration, + $plugin_id, + $plugin_definition, + $container->getParameter('serializer.formats'), + $container->get('logger.factory')->get('rest'), + $container->get('entity_type.manager'), + $container->get('workspace.manager'), + $container->get('serializer') + ); + } + + /** + * {@inheritdoc} + */ + public function post($workspace_id, $revisions) { + $workspace = Workspace::load($workspace_id); + $this->workspaceManager->setActiveWorkspace($workspace); + foreach ($revisions as $entity_type_id => $entity_revisions) { + $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); + $class = $entity_type->getClass(); + foreach ($entity_revisions as $revision_id => $revision) { + /** @var \Drupal\Core\Entity\Entity $entity */ + $entity = $this->serializer->deserialize(json_encode($revision), $class, 'json'); + if (WorkspaceManager::DEFAULT_WORKSPACE == $workspace_id) { + $loaded_revision = $this->entityTypeManager->getStorage($entity_type_id)->loadRevision($entity->getRevisionId()); + $loaded_revision->_isReplicating = TRUE; + $loaded_revision->isDefaultRevision(TRUE); + $loaded_revision->save(); + } + } + } + return new ResourceResponse(TRUE); + } + +} diff --git a/tests/modules/workspace_remote_test/src/RemoteReplicator.php b/tests/modules/workspace_remote_test/src/RemoteReplicator.php new file mode 100644 index 0000000..ef4ea7d --- /dev/null +++ b/tests/modules/workspace_remote_test/src/RemoteReplicator.php @@ -0,0 +1,103 @@ +entityTypeManager = $entity_type_manager; + $this->database = $database; + $this->serializer = $serializer; + $this->client = $client; + } + + /** + * {@inheritdoc} + */ + public function applies(UpstreamPluginInterface $source, UpstreamPluginInterface $target) { + if ($target->getBaseId() === 'remote_workspace') { + return TRUE; + } + return FALSE; + } + + /** + * {@inheritdoc} + */ + public function replicate(UpstreamPluginInterface $source, UpstreamPluginInterface $target) { + $source_workspace = Workspace::load($source->getDerivativeId()); + $select = $this->database->select('content_workspace_revision', 'cwr')->fields('cwr', ['content_entity_type_id', 'content_entity_revision_id']); + $select->condition('workspace', $source_workspace->id()); + $revision_ids = $select->execute()->fetchAllKeyed(1, 0); + $revisions = []; + foreach ($revision_ids as $revision_id => $entity_type_id) { + $revisions[$entity_type_id][$revision_id] = $this->entityTypeManager->getStorage($entity_type_id)->loadRevision($revision_id); + } + $serialized_revisions = $this->serializer->serialize($revisions, 'json'); + $base_url = \Drupal::request()->getSchemeAndHttpHost(); + $token = $this->client->get($base_url . '/rest/session/token')->getBody(); + $this->client->post($base_url . '/admin/config/workflow/workspace/live/replication', [ + 'auth' => [ + \Drupal::state()->get('remote_replicator_auth_user'), + \Drupal::state()->get('remote_replicator_auth_pass'), + ], + 'body' => $serialized_revisions, + 'headers' => [ + 'Content-Type' => 'application/json', + 'X-CSRF-Token' => $token, + ], + ]); + } + +} diff --git a/tests/modules/workspace_remote_test/workspace_remote_test.info.yml b/tests/modules/workspace_remote_test/workspace_remote_test.info.yml new file mode 100644 index 0000000..7d34356 --- /dev/null +++ b/tests/modules/workspace_remote_test/workspace_remote_test.info.yml @@ -0,0 +1,10 @@ +name: 'Workspace Remote Test' +type: module +description: 'Provides remote replication for testing.' +package: Testing +version: VERSION +core: 8.x +dependencies: + - workspace + - rest + - basic_auth diff --git a/tests/modules/workspace_remote_test/workspace_remote_test.services.yml b/tests/modules/workspace_remote_test/workspace_remote_test.services.yml new file mode 100644 index 0000000..d733782 --- /dev/null +++ b/tests/modules/workspace_remote_test/workspace_remote_test.services.yml @@ -0,0 +1,6 @@ +services: + workspace.remote_replicator: + class: Drupal\workspace_remote_test\RemoteReplicator + arguments: ['@entity_type.manager', '@database', '@serializer', '@http_client'] + tags: + - { name: workspace_replicator, priority: 0 } diff --git a/tests/src/Functional/RemoteReplicationTest.php b/tests/src/Functional/RemoteReplicationTest.php new file mode 100644 index 0000000..c03e19f --- /dev/null +++ b/tests/src/Functional/RemoteReplicationTest.php @@ -0,0 +1,106 @@ +createContentType(['type' => 'page']); + + $permissions = [ + 'create page content', + 'create workspace', + 'edit any workspace', + 'view any workspace', + 'restful post replication', + ]; + $this->account = $this->createUser($permissions); + $this->setCurrentUser($this->account); + } + + /** + * Test replication to a remote workspace. + */ + public function testRemoteReplication() { + $workspace_manager = \Drupal::service('workspace.manager'); + + // Create three nodes on the stage workspace. + $workspace_manager->setActiveWorkspace(Workspace::load('stage')); + $node1 = $this->createNode(); + $node2 = $this->createNode(); + $node3 = $this->createNode(); + + // All three nodes should return a 404 when accessed on live. + $workspace_manager->setActiveWorkspace(Workspace::load('live')); + $this->drupalGet($node1->toUrl()->toString()); + $assert_session = $this->assertSession(); + $assert_session->statusCodeEquals(403); + $this->drupalGet($node2->toUrl()->toString()); + $assert_session->statusCodeEquals(403); + $this->drupalGet($node3->toUrl()->toString()); + $assert_session->statusCodeEquals(403); + + // Store username and password to be used for replication. + \Drupal::state()->set('remote_replicator_auth_user', $this->account->getUsername()); + \Drupal::state()->set('remote_replicator_auth_pass', $this->account->pass_raw); + + // Replicate from state to remote (live). + \Drupal::service('workspace.replication_manager')->replicate( + \Drupal::service('plugin.manager.workspace.upstream')->createInstance('local_workspace:stage'), + \Drupal::service('plugin.manager.workspace.upstream')->createInstance('remote_workspace') + ); + + // Nodes should now be accessible on live. + $this->drupalGet($node1->toUrl()->toString()); + $assert_session = $this->assertSession(); + $assert_session->statusCodeEquals(200); + $this->drupalGet($node2->toUrl()->toString()); + $assert_session->statusCodeEquals(200); + $this->drupalGet($node3->toUrl()->toString()); + $assert_session->statusCodeEquals(200); + } + +}