diff --git a/core/modules/workspace/src/Annotation/RepositoryHandler.php b/core/modules/workspace/src/Annotation/RepositoryHandler.php deleted file mode 100644 index 89f7010a6a3bbd68594d4c829600109a170cd303..0000000000000000000000000000000000000000 --- a/core/modules/workspace/src/Annotation/RepositoryHandler.php +++ /dev/null @@ -1,53 +0,0 @@ -setLabel(new TranslatableMarkup('Created')) ->setDescription(new TranslatableMarkup('The time that the workspaces was created.')); - $fields['target'] = BaseFieldDefinition::create('string') - ->setLabel(new TranslatableMarkup('Target workspace')) - ->setDescription(new TranslatableMarkup('The workspace to push to and pull from.')) - ->setRevisionable(TRUE) - ->setRequired(TRUE) - ->setDefaultValue('live'); - return $fields; } /** * {@inheritdoc} */ - public function push() { - return $this->getRepositoryHandler()->push(); - } - - /** - * {@inheritdoc} - */ - public function pull() { - return $this->getRepositoryHandler()->pull(); - } - - /** - * {@inheritdoc} - */ - public function getRepositoryHandler() { - return \Drupal::service('plugin.manager.workspace.repository_handler')->createFromWorkspace($this); + public function publish() { + return \Drupal::service('workspace.operation_factory')->getPublisher($this)->publish(); } /** diff --git a/core/modules/workspace/src/Form/WorkspaceDeleteForm.php b/core/modules/workspace/src/Form/WorkspaceDeleteForm.php index 4a14bc60234dc3f8eecc34bc83eab4b4325fca31..9c2113b96c7a843b8ad134b370c7678db39d6b10 100644 --- a/core/modules/workspace/src/Form/WorkspaceDeleteForm.php +++ b/core/modules/workspace/src/Form/WorkspaceDeleteForm.php @@ -24,7 +24,7 @@ class WorkspaceDeleteForm extends ContentEntityDeleteForm { */ public function buildForm(array $form, FormStateInterface $form_state) { $form = parent::buildForm($form, $form_state); - $source_rev_diff = $this->entity->getRepositoryHandler()->getDifferringRevisionIdsOnSource(); + $source_rev_diff = $this->entityTypeManager->getStorage('workspace_association')->getTrackedEntities($this->entity->id()); $items = []; foreach ($source_rev_diff as $entity_type_id => $revision_ids) { $label = $this->entityTypeManager->getDefinition($entity_type_id)->getLabel(); diff --git a/core/modules/workspace/src/Form/WorkspaceDeployForm.php b/core/modules/workspace/src/Form/WorkspaceDeployForm.php index 2abd3958be60a4d88f6b2adbf6b917b51780c631..bc24e2049c5d7f881da5481270d6ba1b184c3259 100644 --- a/core/modules/workspace/src/Form/WorkspaceDeployForm.php +++ b/core/modules/workspace/src/Form/WorkspaceDeployForm.php @@ -8,6 +8,7 @@ use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Messenger\MessengerInterface; +use Drupal\workspace\WorkspaceOperationFactory; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -29,21 +30,31 @@ class WorkspaceDeployForm extends ContentEntityForm { */ protected $messenger; + /** + * The workspace operation factory. + * + * @var \Drupal\workspace\WorkspaceOperationFactory + */ + protected $workspaceOperationFactory; + /** * Constructs a new WorkspaceDeployForm. * * @param \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository * The entity repository service. - * @param \Drupal\Core\Messenger\MessengerInterface $messenger - * The messenger service. * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info * The entity type bundle service. * @param \Drupal\Component\Datetime\TimeInterface $time * The time service. + * @param \Drupal\Core\Messenger\MessengerInterface $messenger + * The messenger service. + * @param \Drupal\workspace\WorkspaceOperationFactory $workspace_operation_factory + * The workspace operation factory service. */ - public function __construct(EntityRepositoryInterface $entity_repository, MessengerInterface $messenger, EntityTypeBundleInfoInterface $entity_type_bundle_info = NULL, TimeInterface $time = NULL) { + public function __construct(EntityRepositoryInterface $entity_repository, EntityTypeBundleInfoInterface $entity_type_bundle_info, TimeInterface $time, MessengerInterface $messenger, WorkspaceOperationFactory $workspace_operation_factory) { parent::__construct($entity_repository, $entity_type_bundle_info, $time); $this->messenger = $messenger; + $this->workspaceOperationFactory = $workspace_operation_factory; } /** @@ -52,9 +63,10 @@ public function __construct(EntityRepositoryInterface $entity_repository, Messen public static function create(ContainerInterface $container) { return new static( $container->get('entity.repository'), - $container->get('messenger'), $container->get('entity_type.bundle.info'), - $container->get('datetime.time') + $container->get('datetime.time'), + $container->get('messenger'), + $container->get('workspace.operation_factory') ); } @@ -64,17 +76,17 @@ public static function create(ContainerInterface $container) { public function form(array $form, FormStateInterface $form_state) { $form = parent::form($form, $form_state); - $repository_handler = $this->entity->getRepositoryHandler(); + $workspace_publisher = $this->workspaceOperationFactory->getPublisher($this->entity); $args = [ '%source_label' => $this->entity->label(), - '%target_label' => $repository_handler->getLabel(), + '%target_label' => $workspace_publisher->getTargetLabel(), ]; $form['#title'] = $this->t('Deploy %source_label workspace', $args); // List the changes that can be pushed. - if ($source_rev_diff = $repository_handler->getDifferringRevisionIdsOnSource()) { - $total_count = $repository_handler->getNumberOfChangesOnSource(); + if ($source_rev_diff = $workspace_publisher->getDifferringRevisionIdsOnSource()) { + $total_count = $workspace_publisher->getNumberOfChangesOnSource(); $form['deploy'] = [ '#theme' => 'item_list', '#title' => $this->formatPlural($total_count, 'There is @count item that can be deployed from %source_label to %target_label', 'There are @count items that can be deployed from %source_label to %target_label', $args), @@ -86,20 +98,6 @@ public function form(array $form, FormStateInterface $form_state) { } } - // List the changes that can be pulled. - if ($target_rev_diff = $repository_handler->getDifferringRevisionIdsOnTarget()) { - $total_count = $repository_handler->getNumberOfChangesOnTarget(); - $form['refresh'] = [ - '#theme' => 'item_list', - '#title' => $this->formatPlural($total_count, 'There is @count item that can be refreshed from %target_label to %source_label', 'There are @count items that can be refreshed from %target_label to %source_label', $args), - '#items' => [], - '#total_count' => $total_count, - ]; - foreach ($target_rev_diff as $entity_type_id => $revision_difference) { - $form['deploy']['#items'][$entity_type_id] = $this->entityTypeManager->getDefinition($entity_type_id)->getCountLabel(count($revision_difference)); - } - } - // If there are no changes to push or pull, show an informational message. if (!isset($form['deploy']) && !isset($form['refresh'])) { $form['help'] = [ @@ -117,11 +115,11 @@ public function actions(array $form, FormStateInterface $form_state) { $elements = parent::actions($form, $form_state); unset($elements['delete']); - $repository_handler = $this->entity->getRepositoryHandler(); + $workspace_publisher = $this->workspaceOperationFactory->getPublisher($this->entity); if (isset($form['deploy'])) { $total_count = $form['deploy']['#total_count']; - $elements['submit']['#value'] = $this->formatPlural($total_count, 'Deploy @count item to @target', 'Deploy @count items to @target', ['@target' => $repository_handler->getLabel()]); + $elements['submit']['#value'] = $this->formatPlural($total_count, 'Deploy @count item to @target', 'Deploy @count items to @target', ['@target' => $workspace_publisher->getTargetLabel()]); $elements['submit']['#submit'] = ['::submitForm', '::deploy']; } else { @@ -130,16 +128,6 @@ public function actions(array $form, FormStateInterface $form_state) { $elements['submit']['#disabled'] = TRUE; } - // Only show the 'Refresh' operation if there's something to pull. - if (isset($form['refresh'])) { - $total_count = $form['refresh']['#total_count']; - $elements['refresh'] = [ - '#type' => 'submit', - '#value' => $this->formatPlural($total_count, 'Refresh @count item from @target', 'Refresh @count items from @target', ['@target' => $repository_handler->getLabel()]), - '#submit' => ['::submitForm', '::refresh'], - ]; - } - $elements['cancel'] = [ '#type' => 'link', '#title' => $this->t('Cancel'), @@ -162,7 +150,7 @@ public function deploy(array &$form, FormStateInterface $form_state) { $workspace = $this->entity; try { - $workspace->push(); + $workspace->publish(); $this->messenger->addMessage($this->t('Successful deployment.')); } catch (\Exception $e) { @@ -170,24 +158,4 @@ public function deploy(array &$form, FormStateInterface $form_state) { } } - /** - * Form submission handler; pulls the target's content into a workspace. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. - */ - public function refresh(array &$form, FormStateInterface $form_state) { - $workspace = $this->entity; - - try { - $workspace->pull(); - $this->messenger->addMessage($this->t('Refresh successful.')); - } - catch (\Exception $e) { - $this->messenger->addMessage($this->t('Refresh failed. All errors have been logged.'), 'error'); - } - } - } diff --git a/core/modules/workspace/src/Negotiator/DefaultWorkspaceNegotiator.php b/core/modules/workspace/src/Negotiator/DefaultWorkspaceNegotiator.php index d4310db11dc7a58e3e8f3b48e45c8be964c47505..fe8f2a77f66633071a3acbff1304cfe2dc35b934 100644 --- a/core/modules/workspace/src/Negotiator/DefaultWorkspaceNegotiator.php +++ b/core/modules/workspace/src/Negotiator/DefaultWorkspaceNegotiator.php @@ -51,7 +51,6 @@ public function getActiveWorkspace(Request $request) { $default_workspace = $this->workspaceStorage->create([ 'id' => WorkspaceInterface::DEFAULT_WORKSPACE, 'label' => Unicode::ucwords(WorkspaceInterface::DEFAULT_WORKSPACE), - 'target' => '', ]); $default_workspace->enforceIsNew(FALSE); diff --git a/core/modules/workspace/src/Plugin/RepositoryHandler/NullRepositoryHandler.php b/core/modules/workspace/src/Plugin/RepositoryHandler/NullRepositoryHandler.php deleted file mode 100644 index ce2d515b409c8d8d4049ba724f232afd6c97daa4..0000000000000000000000000000000000000000 --- a/core/modules/workspace/src/Plugin/RepositoryHandler/NullRepositoryHandler.php +++ /dev/null @@ -1,82 +0,0 @@ -getPluginDefinition()['label']; - } - - /** - * {@inheritdoc} - */ - public function getDescription() { - return $this->getPluginDefinition()['description']; - } - -} diff --git a/core/modules/workspace/src/RepositoryHandlerBase.php b/core/modules/workspace/src/RepositoryHandlerBase.php deleted file mode 100644 index 636fc2856d8912fe6c9c7551efd43c383383360e..0000000000000000000000000000000000000000 --- a/core/modules/workspace/src/RepositoryHandlerBase.php +++ /dev/null @@ -1,72 +0,0 @@ -source = $configuration['source']; - $this->target = $configuration['target']; - } - - /** - * {@inheritdoc} - */ - public function getLabel() { - return $this->getPluginDefinition()['label']; - } - - /** - * {@inheritdoc} - */ - public function getDescription() { - return $this->getPluginDefinition()['description']; - } - - /** - * {@inheritdoc} - */ - public function calculateDependencies() { - return []; - } - -} diff --git a/core/modules/workspace/src/RepositoryHandlerInterface.php b/core/modules/workspace/src/RepositoryHandlerInterface.php deleted file mode 100644 index 660ab626d8258c9ba93e4539c84b55654f58b1ff..0000000000000000000000000000000000000000 --- a/core/modules/workspace/src/RepositoryHandlerInterface.php +++ /dev/null @@ -1,127 +0,0 @@ -alterInfo('workspace_repository_handler_info'); - $this->setCacheBackend($cache_backend, 'workspace_repository_handler'); - } - - /** - * {@inheritdoc} - */ - public function processDefinition(&$definition, $plugin_id) { - parent::processDefinition($definition, $plugin_id); - $this->processDefinitionCategory($definition); - } - - /** - * {@inheritdoc} - */ - public function createFromWorkspace(WorkspaceInterface $workspace) { - $target = $workspace->target->value; - $configuration = [ - 'source' => $workspace->id(), - 'target' => $target, - ]; - return $this->createInstance($target, $configuration); - } - - /** - * {@inheritdoc} - */ - public function getFallbackPluginId($plugin_id, array $configuration = []) { - return 'null'; - } - -} diff --git a/core/modules/workspace/src/RepositoryHandlerManagerInterface.php b/core/modules/workspace/src/RepositoryHandlerManagerInterface.php deleted file mode 100644 index ae04e907fcbefee1f002216088e353a203b61a0b..0000000000000000000000000000000000000000 --- a/core/modules/workspace/src/RepositoryHandlerManagerInterface.php +++ /dev/null @@ -1,23 +0,0 @@ -getRepositoryHandler() instanceof NullRepositoryHandler) { + if (!$entity->isDefaultWorkspace()) { $operations['deploy'] = [ 'title' => $this->t('Deploy content'), // The 'Deploy' operation should be the default one for the currently diff --git a/core/modules/workspace/src/WorkspaceOperationFactory.php b/core/modules/workspace/src/WorkspaceOperationFactory.php new file mode 100644 index 0000000000000000000000000000000000000000..f4cd119ac9d08b92afed8873d1a5c94e649f6094 --- /dev/null +++ b/core/modules/workspace/src/WorkspaceOperationFactory.php @@ -0,0 +1,58 @@ +entityTypeManager = $entity_type_manager; + $this->database = $database; + } + + /** + * Gets the workspace publisher. + * + * @param \Drupal\workspace\WorkspaceInterface $source + * A workspace entity. + * + * @return \Drupal\workspace\WorkspacePublisherInterface + * A workspace publisher object. + */ + public function getPublisher(WorkspaceInterface $source) { + return new WorkspacePublisher($this->entityTypeManager, $this->database, $source); + } + +} diff --git a/core/modules/workspace/src/WorkspaceOperationInterface.php b/core/modules/workspace/src/WorkspaceOperationInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..76bb2b838867def3a9f39b5f797cf831a32b94c5 --- /dev/null +++ b/core/modules/workspace/src/WorkspaceOperationInterface.php @@ -0,0 +1,82 @@ +entityTypeManager = $entity_type_manager; $this->database = $database; $this->workspaceAssociationStorage = $entity_type_manager->getStorage('workspace_association'); - $this->sourceWorkspace = $this->entityTypeManager->getStorage('workspace')->load($this->source); - $this->targetWorkspace = $this->entityTypeManager->getStorage('workspace')->load($this->target); + $this->sourceWorkspace = $source; + $this->targetWorkspace = $this->entityTypeManager->getStorage('workspace')->load(WorkspaceInterface::DEFAULT_WORKSPACE); } /** * {@inheritdoc} */ - public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('entity_type.manager'), - $container->get('database') - ); - } - - /** - * {@inheritdoc} - */ - public function calculateDependencies() { - $this->dependencies = parent::calculateDependencies(); - $this->addDependency($this->sourceWorkspace->getConfigDependencyKey(), $this->sourceWorkspace->getConfigDependencyName()); - - return $this->dependencies; - } - - /** - * {@inheritdoc} - */ - public function push() { + public function publish() { if ($this->checkConflictsOnTarget()) { throw new WorkspaceConflictException(); } @@ -145,9 +105,15 @@ public function push() { /** * {@inheritdoc} */ - public function pull() { - // Nothing to do for now, pulling in changes can only be implemented when we - // are able to resolve conflicts. + public function getSourceLabel() { + return $this->sourceWorkspace->label(); + } + + /** + * {@inheritdoc} + */ + public function getTargetLabel() { + return $this->targetWorkspace->label(); } /** @@ -165,7 +131,7 @@ public function checkConflictsOnTarget() { public function getDifferringRevisionIdsOnTarget() { $target_revision_difference = []; - $tracked_entities = $this->workspaceAssociationStorage->getTrackedEntities($this->source); + $tracked_entities = $this->workspaceAssociationStorage->getTrackedEntities($this->sourceWorkspace->id()); foreach ($tracked_entities as $entity_type_id => $tracked_revisions) { $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); @@ -195,7 +161,7 @@ public function getDifferringRevisionIdsOnTarget() { */ public function getDifferringRevisionIdsOnSource() { // Get the Workspace association revisions which haven't been pushed yet. - return $this->workspaceAssociationStorage->getTrackedEntities($this->source); + return $this->workspaceAssociationStorage->getTrackedEntities($this->sourceWorkspace->id()); } /** diff --git a/core/modules/workspace/src/WorkspacePublisherInterface.php b/core/modules/workspace/src/WorkspacePublisherInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..c5a4366d525bb013d3497b37a4ec2bcd41df92f0 --- /dev/null +++ b/core/modules/workspace/src/WorkspacePublisherInterface.php @@ -0,0 +1,17 @@ + 'layla', 'label' => 'Layla', - 'target' => 'live', ]); $workspace->save(); return $workspace; @@ -120,11 +119,6 @@ protected function getExpectedNormalizedEntity() { 'url' => base_path() . 'user/' . $author->id(), ], ], - 'target' => [ - [ - 'value' => 'live', - ], - ], 'uuid' => [ [ 'value' => $this->entity->uuid(), @@ -148,11 +142,6 @@ protected function getNormalizedPostEntity() { 'value' => 'Running on faith', ], ], - 'target' => [ - [ - 'value' => 'local_workspace:stage', - ], - ], ]; } @@ -176,11 +165,6 @@ protected function getNormalizedPatchEntity() { 'value' => 'Running on faith', ], ], - 'target' => [ - [ - 'value' => 'local_workspace:stage', - ], - ], ]; } diff --git a/core/modules/workspace/tests/src/Functional/WorkspaceConcurrentEditingTest.php b/core/modules/workspace/tests/src/Functional/WorkspaceConcurrentEditingTest.php index 1662eb6517998d2ecd5532ca4724793b47cf3ea9..bced173857ae29ae21b74ad1ed47072ec3f8d97c 100644 --- a/core/modules/workspace/tests/src/Functional/WorkspaceConcurrentEditingTest.php +++ b/core/modules/workspace/tests/src/Functional/WorkspaceConcurrentEditingTest.php @@ -87,7 +87,7 @@ public function testSwitchingWorkspaces() { // Deploy the changes from the 'Vultures' workspace and check that the node // can be edited again in other workspaces. - $vultures->getRepositoryHandler()->push(); + $vultures->publish(); $this->switchToWorkspace($gravity); $this->drupalGet('/node/' . $test_node->id() . '/edit'); $page = $this->getSession()->getPage(); diff --git a/core/modules/workspace/tests/src/Kernel/WorkspaceIntegrationTest.php b/core/modules/workspace/tests/src/Kernel/WorkspaceIntegrationTest.php index dd34274e0715fe83d6642316316dd8227efe847a..cbf2b74511a0d887fae8724f6c791860bbda04ee 100644 --- a/core/modules/workspace/tests/src/Kernel/WorkspaceIntegrationTest.php +++ b/core/modules/workspace/tests/src/Kernel/WorkspaceIntegrationTest.php @@ -104,7 +104,7 @@ protected function initializeWorkspaceModule() { // Create two workspaces by default, 'live' and 'stage'. $this->workspaces['live'] = Workspace::create(['id' => 'live']); $this->workspaces['live']->save(); - $this->workspaces['stage'] = Workspace::create(['id' => 'stage', 'target' => 'live']); + $this->workspaces['stage'] = Workspace::create(['id' => 'stage']); $this->workspaces['stage']->save(); $permissions = [ @@ -345,7 +345,8 @@ public function testWorkspaces() { $this->assertWorkspaceAssociation($expected_workspace_association['add_published_node_in_stage'], 'node'); // Deploy 'stage' to 'live'. - $stage_repository_handler = $this->workspaces['stage']->getRepositoryHandler(); + /** @var \Drupal\workspace\WorkspacePublisher $workspace_publisher */ + $workspace_publisher = \Drupal::service('workspace.operation_factory')->getPublisher($this->workspaces['stage']); // Check which revisions need to be pushed. $expected = [ @@ -356,14 +357,14 @@ public function testWorkspaces() { 7 => 4, ], ]; - $this->assertEquals($expected, $stage_repository_handler->getDifferringRevisionIdsOnSource()); + $this->assertEquals($expected, $workspace_publisher->getDifferringRevisionIdsOnSource()); - $stage_repository_handler->push(); + $this->workspaces['stage']->publish(); $this->assertWorkspaceStatus($test_scenarios['push_stage_to_live'], 'node'); $this->assertWorkspaceAssociation($expected_workspace_association['push_stage_to_live'], 'node'); // Check that there are no more revisions to push. - $this->assertEmpty($stage_repository_handler->getDifferringRevisionIdsOnSource()); + $this->assertEmpty($workspace_publisher->getDifferringRevisionIdsOnSource()); } /** diff --git a/core/modules/workspace/workspace.install b/core/modules/workspace/workspace.install index e9af7dfa69bb604f2f448ca207b711cfb734ec9a..e748fc63bfa6a266dcaf865a0efef0738bcf367a 100644 --- a/core/modules/workspace/workspace.install +++ b/core/modules/workspace/workspace.install @@ -48,14 +48,12 @@ function workspace_install() { Workspace::create([ 'id' => 'live', 'label' => 'Live', - 'target' => '', 'uid' => $owner_id, ])->save(); Workspace::create([ 'id' => 'stage', 'label' => 'Stage', - 'target' => 'live', 'uid' => $owner_id, ])->save(); } diff --git a/core/modules/workspace/workspace.services.yml b/core/modules/workspace/workspace.services.yml index cd2b9ea51de09d251ae0b6d2693b1f68ac024682..e147017298c7ba2ac5a878536592370c035f0e40 100644 --- a/core/modules/workspace/workspace.services.yml +++ b/core/modules/workspace/workspace.services.yml @@ -4,9 +4,10 @@ services: arguments: ['@request_stack', '@entity_type.manager', '@current_user', '@state', '@logger.channel.workspace', '@class_resolver'] tags: - { name: service_id_collector, tag: workspace_negotiator } - plugin.manager.workspace.repository_handler: - class: Drupal\workspace\RepositoryHandlerManager - parent: default_plugin_manager + workspace.operation_factory: + class: Drupal\workspace\WorkspaceOperationFactory + arguments: ['@entity_type.manager', '@database'] + workspace.negotiator.default: class: Drupal\workspace\Negotiator\DefaultWorkspaceNegotiator arguments: ['@entity_type.manager'] @@ -22,6 +23,7 @@ services: parent: workspace.negotiator.session tags: - { name: workspace_negotiator, priority: 100 } + cache_context.workspace: class: Drupal\workspace\WorkspaceCacheContext arguments: ['@workspace.manager'] @@ -30,8 +32,9 @@ services: logger.channel.workspace: parent: logger.channel_base arguments: ['workspace'] + workspace.entity.query.sql: - decorates: 'entity.query.sql' + decorates: entity.query.sql class: Drupal\workspace\EntityQuery\QueryFactory arguments: ['@database', '@workspace.manager'] public: false @@ -39,7 +42,7 @@ services: tags: - { name: backend_overridable } pgsql.workspace.entity.query.sql: - decorates: 'pgsql.entity.query.sql' + decorates: pgsql.entity.query.sql class: Drupal\workspace\EntityQuery\PgsqlQueryFactory arguments: ['@database', '@workspace.manager'] public: false