diff --git a/css/multiversion.toolbar.css b/css/multiversion.toolbar.css
index 8900815..ec41cc3 100644
--- a/css/multiversion.toolbar.css
+++ b/css/multiversion.toolbar.css
@@ -10,3 +10,33 @@
.toolbar .toolbar-bar .multiversion-toolbar-tab.toolbar-tab {
float: right;
}
+
+#toolbar-item-workspace-switcher-tray nav {
+ display: flex;
+ align-items: center;
+}
+
+#toolbar-item-workspace-switcher-tray.toolbar-tray-vertical nav {
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+}
+
+.toolbar #toolbar-item-workspace-switcher-tray input[type="submit"],
+.toolbar #toolbar-item-workspace-switcher-tray input[type="submit"]:hover {
+ background: transparent;
+ border: 0;
+ border-radius: 0;
+}
+
+.toolbar #toolbar-item-workspace-switcher-tray input[type="submit"]:hover {
+ text-decoration: underline;
+}
+
+.toolbar #toolbar-item-workspace-switcher-tray.toolbar-tray-horizontal a {
+ border-right: 1px solid darkgray;
+}
+
+.toolbar #toolbar-item-workspace-switcher-tray.toolbar-tray-vertical a {
+ border-bottom: 1px solid darkgray;
+}
diff --git a/multiversion.routing.yml b/multiversion.routing.yml
index 133cd95..e4657bb 100644
--- a/multiversion.routing.yml
+++ b/multiversion.routing.yml
@@ -8,6 +8,16 @@ entity.workspace.add:
requirements:
_permission: 'administer workspaces'
+entity.workspace.activate_form:
+ path: '/admin/structure/workspaces/{workspace}/activate'
+ defaults:
+ _title: 'Activate Workspace'
+ _form: '\Drupal\multiversion\Form\WorkspaceActivateForm'
+ options:
+ _admin_route: TRUE
+ requirements:
+ _permission: 'administer workspaces'
+
entity.workspace.add_form:
path: '/admin/structure/workspaces/add/{workspace_type}'
defaults:
diff --git a/multiversion.services.yml b/multiversion.services.yml
index a617103..be355d6 100644
--- a/multiversion.services.yml
+++ b/multiversion.services.yml
@@ -38,7 +38,7 @@ services:
- { name: cache.context }
multiversion.toolbar:
class: Drupal\multiversion\Toolbar
- arguments: ['@entity_type.manager', '@workspace.manager']
+ arguments: ['@entity_type.manager', '@workspace.manager', '@form_builder']
# @todo: {@link https://www.drupal.org/node/2597414 Simplify the container
diff --git a/multiversion_ui/css/multiversion.switcherform.css b/multiversion_ui/css/multiversion.switcherform.css
new file mode 100644
index 0000000..3fb9e69
--- /dev/null
+++ b/multiversion_ui/css/multiversion.switcherform.css
@@ -0,0 +1,4 @@
+form.multiversion-switcher-form {
+ display: inline;
+ border: 2px solid red;
+}
diff --git a/src/Entity/Workspace.php b/src/Entity/Workspace.php
index cb38769..308e838 100644
--- a/src/Entity/Workspace.php
+++ b/src/Entity/Workspace.php
@@ -35,6 +35,7 @@ use Drupal\user\UserInterface;
* },
* links = {
* "edit-form" = "/admin/structure/workspaces/{workspace}/edit",
+ * "activate-form" = "/admin/structure/workspaces/{workspace}/activate",
* "collection" = "/admin/structure/workspaces"
* },
* admin_permission = "administer workspaces",
diff --git a/src/Form/WorkspaceActivateForm.php b/src/Form/WorkspaceActivateForm.php
new file mode 100644
index 0000000..f73f3fb
--- /dev/null
+++ b/src/Form/WorkspaceActivateForm.php
@@ -0,0 +1,121 @@
+get('workspace.manager'),
+ $container->get('entity_type.manager')
+ );
+ }
+
+ /**
+ * Inject dependencies for activating a workspace.
+ *
+ * @param \Drupal\multiversion\Workspace\WorkspaceManagerInterface $workspace_manager
+ * The workspace manager.
+ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
+ * The entity type manager.
+ */
+ public function __construct(WorkspaceManagerInterface $workspace_manager, EntityTypeManagerInterface $entity_type_manager) {
+ $this->workspaceManager = $workspace_manager;
+ $this->entityTypeManager = $entity_type_manager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function buildForm(array $form, FormStateInterface $form_state, Workspace $workspace = NULL) {
+ $form['workspace_id'] = [
+ '#type' => 'hidden',
+ '#value' => $workspace->id(),
+ ];
+
+ $form['instruction'] = [
+ '#type' => 'markup',
+ '#prefix' => '
',
+ '#markup' => $this->t('Would you like to activate the %workspace workspace?', ['%workspace' => $workspace->label()]),
+ '#suffix' => '
',
+ ];
+
+ $form['submit'] = [
+ '#type' => 'submit',
+ '#value' => 'Activate',
+ ];
+
+ $form['#title'] = $this->t('Activate workspace %label', array('%label' => $workspace->label()));
+
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, FormStateInterface $form_state) {
+ $id = $form_state->getValue('workspace_id');
+
+ // Ensure we are given an ID.
+ if (!$id) {
+ $form_state->setErrorByName('workspace_id', 'The workspace ID is required.');
+ }
+
+ // Ensure the workspace by that id exists.
+ /** @var WorkspaceInterface $workspace */
+ $workspace = $this->entityTypeManager->getStorage('workspace')->load($id);
+ if (!$workspace) {
+ $form_state->setErrorByName('workspace_id', 'This workspace no longer exists.');
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $id = $form_state->getValue('workspace_id');
+ /** @var WorkspaceInterface $workspace */
+ $workspace = $this->entityTypeManager->getStorage('workspace')->load($id);
+
+ $this->workspaceManager->setActiveWorkspace($workspace);
+
+ drupal_set_message($this->t('Now viewing workspace %workspace', ['%workspace' => $workspace->label()]));
+ }
+
+}
diff --git a/src/Form/WorkspaceSwitcherForm.php b/src/Form/WorkspaceSwitcherForm.php
new file mode 100644
index 0000000..cc035b7
--- /dev/null
+++ b/src/Form/WorkspaceSwitcherForm.php
@@ -0,0 +1,121 @@
+get('workspace.manager'),
+ $container->get('entity_type.manager')
+ );
+ }
+
+ public function __construct(WorkspaceManagerInterface $workspace_manager, EntityTypeManagerInterface $entity_type_manager) {
+ $this->workspaceManager = $workspace_manager;
+ $this->entityTypeManager = $entity_type_manager;
+ }
+
+
+ /**
+ * @inheritDoc
+ */
+ public function getFormId() {
+ return 'workspace_switcher_form_' . static::$formCounter++;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function buildForm(array $form, FormStateInterface $form_state, WorkspaceInterface $workspace = NULL) {
+ // @todo this form is identical to WorkspaceActivateForm except for this method; can we consolidate forms?
+ $form['workspace_id'] = [
+ '#type' => 'hidden',
+ '#value' => $workspace->id(),
+ ];
+
+ $form['submit'] = [
+ '#type' => 'submit',
+ '#value' => $workspace->label(),
+ ];
+
+ // @todo This does not appear to have any effect. I am not sure yet why.
+ $form['#attached']['library'][] = 'multiversion/switcherform';
+
+ return $form;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function validateForm(array &$form, FormStateInterface $form_state) {
+ $id = $form_state->getValue('workspace_id');
+
+ // Ensure we are given an ID.
+ if (!$id) {
+ $form_state->setErrorByName('workspace_id', 'The workspace ID is required.');
+ }
+
+ // Ensure the workspace by that id exists.
+ /** @var WorkspaceInterface $workspace */
+ $workspace = $this->entityTypeManager->getStorage('workspace')->load($id);
+ if (!$workspace) {
+ $form_state->setErrorByName('workspace_id', 'This workspace no longer exists.');
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function submitForm(array &$form, FormStateInterface $form_state) {
+ $id = $form_state->getValue('workspace_id');
+ /** @var WorkspaceInterface $workspace */
+ $workspace = $this->entityTypeManager->getStorage('workspace')->load($id);
+
+ $this->workspaceManager->setActiveWorkspace($workspace);
+
+ drupal_set_message($this->t('Now viewing workspace %workspace', ['%workspace' => $workspace->label()]));
+ }
+
+}
diff --git a/src/Plugin/Block/WorkspaceBlock.php b/src/Plugin/Block/WorkspaceBlock.php
deleted file mode 100644
index 7f675bf..0000000
--- a/src/Plugin/Block/WorkspaceBlock.php
+++ /dev/null
@@ -1,80 +0,0 @@
-workspaceManager = $workspace_manager;
- $this->entityTypeManager = $entity_type_manager;
- }
-
- /**
- * {@inheritdoc}
- */
- public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
- return new static(
- $configuration,
- $plugin_id,
- $plugin_definition,
- $container->get('workspace.manager'),
- $container->get('entity_type.manager')
- );
- }
-
- /**
- * {@inheritdoc}
- */
- public function build() {
- $build = array();
- $route_name = \Drupal::service('path.matcher')->isFrontPage() ? '' : '';
- $links = $this->workspaceManager->getWorkspaceSwitchLinks(Url::fromRoute($route_name));
-
- if (isset($links)) {
- $build = array(
- '#theme' => 'links__workspace_block',
- '#links' => $links,
- '#attributes' => array(
- 'class' => array(
- 'workspace-switcher',
- ),
- ),
- '#set_active_class' => TRUE,
- // @todo: The caching need tests.
- '#cache' => [
- 'contexts' => $this->entityTypeManager->getDefinition('workspace')->getListCacheContexts(),
- 'tags' => $this->entityTypeManager->getDefinition('workspace')->getListCacheTags(),
- ],
- );
- }
- return $build;
- }
-
-}
diff --git a/src/Tests/Views/MultiversionTestBase.php b/src/Tests/Views/MultiversionTestBase.php
index 0ecfcd9..4e7bf1c 100644
--- a/src/Tests/Views/MultiversionTestBase.php
+++ b/src/Tests/Views/MultiversionTestBase.php
@@ -20,7 +20,7 @@ abstract class MultiversionTestBase extends ViewTestBase {
*
* @var array
*/
- public static $modules = ['multiversion_test_views'];
+ public static $modules = ['multiversion_test_views', 'toolbar'];
protected function setUp($import_test_views = TRUE) {
parent::setUp($import_test_views);
diff --git a/src/Tests/Views/WorkspaceTest.php b/src/Tests/Views/WorkspaceTest.php
index 1749665..054e118 100644
--- a/src/Tests/Views/WorkspaceTest.php
+++ b/src/Tests/Views/WorkspaceTest.php
@@ -8,6 +8,7 @@
namespace Drupal\multiversion\Tests\Views;
use Drupal\multiversion\Entity\Workspace;
+use Drupal\multiversion\Workspace\WorkspaceManagerInterface;
/**
* Tests the workspace and current_workspace field handlers.
@@ -20,45 +21,61 @@ class WorkspaceTest extends MultiversionTestBase {
protected $strictConfigSchema = FALSE;
/**
- * Views used by this test.
- *
- * @var array
+ * {@inheritdoc}
*/
- public static $testViews = ['test_current_workspace'];
+ protected function setUp() {
+ parent::setUp();
+
+ // Create Article node type.
+ if ($this->profile != 'standard') {
+ $this->drupalCreateContentType(['type' => 'article', 'name' => 'Article']);
+ }
+ }
/**
- * Tests the workspace filter.
+ * Test being able to switch between active workspaces.
*/
public function testWorkspace() {
- $admin_user = $this->drupalCreateUser(['bypass node access']);
+ $admin_user = $this->drupalCreateUser(['bypass node access', 'administer workspaces']);
$uid = $admin_user->id();
$this->drupalLogin($admin_user);
- // Create two nodes on 'default' workspace.
- $node1 = $this->drupalCreateNode(['uid' => $uid]);
- $node2 = $this->drupalCreateNode(['uid' => $uid]);
+ /** @var WorkspaceManagerInterface $workspace_manager */
+ $workspace_manager = $this->container->get('workspace.manager');
+
+ $initial_workspace = $workspace_manager->getActiveWorkspace();
+
+ // Create a node on 'default' workspace.
+ $this->drupalPostForm('node/add/article', [
+ 'title[0][value]' => 'Initial workspace article',
+ ], 'Save');
+ $node1_url = $this->drupalGetHeader('location', true);
// Create a new workspace and switch to it.
$new_workspace = Workspace::create(['machine_name' => 'new_workspace', 'label' => 'New Workspace', 'type' => 'basic']);
$new_workspace->save();
- \Drupal::service('workspace.manager')->setActiveWorkspace($new_workspace);
-
- // Create two nodes on 'new_workspace' workspace.
- $node3 = $this->drupalCreateNode(['uid' => $uid]);
- $node4 = $this->drupalCreateNode(['uid' => $uid]);
-
- // Test current_workspace filter.
- $this->drupalGet('test_current_workspace', ['query' => ['workspace' => $new_workspace->id()]]);
- $this->assertNoText($node1->label());
- $this->assertNoText($node2->label());
- $this->assertText($node3->label());
- $this->assertText($node4->label());
-
- $this->drupalGet('test_current_workspace', ['query' => ['workspace' => 1]]);
- $this->assertText($node1->label());
- $this->assertText($node2->label());
- $this->assertNoText($node3->label());
- $this->assertNoText($node4->label());
+ $this->drupalPostForm($new_workspace->url('activate-form'), [], 'Activate');
+
+ // Create a node on 'new_workspace' workspace.
+ $this->drupalPostForm('node/add/article', [
+ 'title[0][value]' => 'New workspace article',
+ ], 'Save');
+ $node2_url = $this->drupalGetHeader('location', true);
+
+ // Ensure you have access to only active workspace.
+ $this->drupalGet($node1_url);
+ $this->assertResponse(404, 'User cannot access content in an inactive workspace.');
+ $out = $this->drupalGet($node2_url);
+ $this->assertResponse(200, 'User can access content in the active workspace.');
+
+ // Switch back to the initial workspace.
+ $this->drupalPostForm($initial_workspace->url('activate-form'), [], 'Activate');
+
+ // Ensure you have access to only active workspace.
+ $this->drupalGet($node1_url);
+ $this->assertResponse(200, 'User can access content in the active workspace.');
+ $out = $this->drupalGet($node2_url);
+ $this->assertResponse(404, 'User cannot access content in an inactive workspace.');
}
}
diff --git a/src/Tests/WorkspaceBlockTest.php b/src/Tests/WorkspaceBlockTest.php
deleted file mode 100644
index fec3050..0000000
--- a/src/Tests/WorkspaceBlockTest.php
+++ /dev/null
@@ -1,91 +0,0 @@
-webUser = $this->drupalCreateUser([
- 'administer blocks',
- 'create article content',
- 'access administration pages',
- 'access content',
- ]);
- $this->drupalLogin($this->webUser);
- $this->drupalPlaceBlock('local_tasks_block');
- }
-
- public function testBlock() {
- $this->drupalPlaceBlock('multiversion_workspace_block', ['region' => 'sidebar_first', 'label' => 'Workspace switcher']);
- $this->drupalGet('');
-
- // Confirm that the block is being displayed.
- $this->assertText('Workspace switcher', t('Block successfully being displayed on the page.'));
- $front = Url::fromRoute('')->toString(TRUE)->getGeneratedUrl();
- $this->assertRaw('href="'. $front .'"', 'The id of the default workspace was displayed in the Workspace switcher block as a link.');
- $machine_name = $this->randomMachineName();
- $entity = Workspace::create(['machine_name' => $machine_name, 'label' => $machine_name, 'type' => 'basic']);
- $entity->save();
- $id = $entity->id();
- $node = Node::create(['type' => 'article', 'title' => 'Test article']);
- $node->save();
- $nid = $node->id();
- $this->drupalGet('');
- $this->assertText('Test article', 'The title of the test article was displayed on the front page.');
- $this->drupalGet("node/$nid");
- $this->assertText('Test article');
- $this->drupalGet('');
- $url = $front . "?workspace=$id";
- $this->assertRaw('href="'. $url .'"', 'The id of the new workspace was displayed in the Workspace switcher block as a link.');
- $this->drupalGet("/node/$nid", ['query' => ['workspace' => $id]]);
- $this->assertText('Page not found');
- $this->drupalGet('', ['query' =>['workspace' => 'default']]);
- $this->assertText('Test article', 'The title of the test article was displayed on the front page.');
- $this->drupalGet('', ['query' => ['workspace' => $id]]);
- $this->drupalGet('/node/add/article');
- $this->assertText('Create Article');
- $this->drupalGet('', ['query' => ['workspace' => $id]]);
- $this->assertNoText('Test article', 'The title of the test article was not displayed on the front page after switching the workspace.');
- $entity->delete();
- $this->drupalGet('');
- $this->assertNoText($machine_name, 'The name of the deleted workspace was not displayed in the Workspace switcher block.');
- }
-
-}
diff --git a/src/Tests/WorkspaceTest.php b/src/Tests/WorkspaceTest.php
index 58f905f..d9b6a35 100644
--- a/src/Tests/WorkspaceTest.php
+++ b/src/Tests/WorkspaceTest.php
@@ -14,6 +14,8 @@ use Drupal\multiversion\Entity\WorkspaceInterface;
/**
* Test the workspace entity.
*
+ * @todo refactor to test the form at /admin/structure/workspaces/{id}/activate
+ *
* @group multiversion
*/
class WorkspaceTest extends MultiversionWebTestBase {
diff --git a/src/Toolbar.php b/src/Toolbar.php
index e013d60..5ce2dfc 100644
--- a/src/Toolbar.php
+++ b/src/Toolbar.php
@@ -4,9 +4,12 @@
namespace Drupal\multiversion;
use Drupal\Core\Entity\EntityTypeManagerInterface;
+use Drupal\Core\Form\FormBuilderInterface;
+use Drupal\Core\Link;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
use Drupal\multiversion\Entity\WorkspaceInterface;
+use Drupal\multiversion\Form\WorkspaceSwitcherForm;
use Drupal\multiversion\Workspace\WorkspaceManagerInterface;
@@ -27,16 +30,25 @@ class Toolbar {
protected $workspaceManager;
/**
+ * @var \Drupal\Core\Form\FormBuilderInterface
+ */
+ protected $formBuilder;
+
+ /**
* Constructs a new Toolbar.
*
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager service.
* @param \Drupal\multiversion\Workspace\WorkspaceManagerInterface $workspace_manager
* The workspace manager service.
+ * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
+ * The form builder service.
*/
- public function __construct(EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager) {
+
+ public function __construct(EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager, FormBuilderInterface $form_builder) {
$this->entityTypeManager = $entity_type_manager;
$this->workspaceManager = $workspace_manager;
+ $this->formBuilder = $form_builder;
}
/**
@@ -67,28 +79,27 @@ class Toolbar {
$items['workspace_switcher']['tab'] = [
'#type' => 'link',
'#title' => $this->t('Workspaces (@active)', ['@active' => $active->label()]),
- // @todo This should likely be something else, but not sure what.
- '#url' => Url::fromRoute(''),
+ '#url' => Url::fromRoute('entity.workspace.collection'),
'#attributes' => [
'title' => $this->t('Switch workspaces'),
'class' => ['toolbar-icon', 'toolbar-icon-multiversion'],
],
];
+ $create_link = Link::createFromRoute($this->t('Create new workspace'), 'entity.workspace.add');
+
$items['workspace_switcher']['tray'] = [
'#heading' => $this->t('Switch to workspace'),
- 'workspace_links' => [
- '#pre_render' => ['multiversion.toolbar:preRenderWorkspaceLinks'],
- '#cache' => [
- 'contexts' => $this->entityTypeManager->getDefinition('workspace')->getListCacheContexts(),
- 'tags' => $this->entityTypeManager->getDefinition('workspace')->getListCacheTags(),
- ],
- '#theme' => 'links__toolbar_workspaces',
- // This will be filled in during pre-render.
- '#links' => [],
- '#attributes' => [
- 'class' => ['toolbar-menu'],
- ],
+ '#pre_render' => ['multiversion.toolbar:preRenderWorkspaceSwitcherForms'],
+ 'create_link' => $create_link->toRenderable(),
+ // This wil get filled in via pre-render.
+ 'workspace_forms' => [],
+ '#cache' => [
+ 'contexts' => $this->entityTypeManager->getDefinition('workspace')->getListCacheContexts(),
+ 'tags' => $this->entityTypeManager->getDefinition('workspace')->getListCacheTags(),
+ ],
+ '#attributes' => [
+ 'class' => ['toolbar-menu'],
],
];
@@ -96,48 +107,19 @@ class Toolbar {
}
/**
- * Prerender callback; Adds the workspace links to the render array.
+ * Prerender callback; Adds the workspace switcher forms to the render array.
*
* @param array $element
*
* @return array
* The modified $element.
*/
- public function preRenderWorkspaceLinks(array $element) {
- $element['#links'] = $this->workspaceLinks();
-
- return $element;
- }
-
- /**
- * Builds a render array of links to switch to all workspaces.
- *
- * Note: This is an expensive call so should only be made from within a
- * pre-render callback, so it gets cached.
- *
- * @return array
- * A render array of links to switch to each workspace.
- */
- protected function workspaceLinks() {
- $links = [];
-
- $links['add'] = [
- 'title' => $this->t('Create new workspace'),
- 'url' => Url::fromRoute('entity.workspace.add'),
- ];
-
- /** @var WorkspaceInterface $workspace */
+ public function preRenderWorkspaceSwitcherForms(array $element) {
foreach ($this->allWorkspaces() as $workspace) {
- $links['workspace_' . $workspace->getMachineName()] = [
- 'title' => $workspace->label(),
- 'url' => Url::fromRoute('', ['workspace' => $workspace->id()]),
- 'attributes' => [
- 'title' => t('Switch to %workspace workspace', ['%workspace' => $workspace->label()])
- ],
- ];
+ $element['workspace_forms']['workspace_' . $workspace->getMachineName()] = $this->formBuilder->getForm(WorkspaceSwitcherForm::class, $workspace);
}
- return $links;
+ return $element;
}
/**
diff --git a/src/Workspace/SessionWorkspaceNegotiator.php b/src/Workspace/SessionWorkspaceNegotiator.php
index e336438..70b5178 100644
--- a/src/Workspace/SessionWorkspaceNegotiator.php
+++ b/src/Workspace/SessionWorkspaceNegotiator.php
@@ -11,7 +11,7 @@ use Drupal\Core\Url;
use Drupal\multiversion\Entity\WorkspaceInterface;
use Symfony\Component\HttpFoundation\Request;
-class SessionWorkspaceNegotiator extends WorkspaceNegotiatorBase implements WorkspaceSwitcherInterface {
+class SessionWorkspaceNegotiator extends WorkspaceNegotiatorBase {
/**
* {@inheritdoc}
@@ -41,42 +41,4 @@ class SessionWorkspaceNegotiator extends WorkspaceNegotiatorBase implements Work
return TRUE;
}
- /**
- * {@inheritdoc}
- */
- public function getWorkspaceSwitchLinks(Request $request, Url $url) {
- $links = array();
- $active_workspace_id = $this->workspaceManager->getActiveWorkspace($request)->id();
- $query = array();
- parse_str($request->getQueryString(), $query);
-
- // If we have an error on the requested page, set links URL to be .
- if (!empty($query['_exception_statuscode'])) {
- if (isset($query['workspace'])) {
- $query = array(
- 'workspace' => $query['workspace'],
- );
- }
- $url = URL::fromRoute('');
- }
-
- $workspaces = $this->workspaceManager->loadMultiple();
- ksort($workspaces);
- foreach ($workspaces as $workspace) {
- // @todo {@link https://www.drupal.org/node/2600382 Access check.}
- $workspace_id = $workspace->id();
- $links[$workspace_id] = array(
- 'url' => $url,
- 'title' => $workspace->label(),
- 'query' => $query,
- );
- $links[$workspace_id]['query']['workspace'] = $workspace_id;
- if ($workspace_id == $active_workspace_id) {
- $links[$workspace_id]['attributes']['class'][] = 'session-active';
- }
- }
-
- return $links;
- }
-
}
diff --git a/src/Workspace/WorkspaceManager.php b/src/Workspace/WorkspaceManager.php
index 4570a47..c33e3ef 100644
--- a/src/Workspace/WorkspaceManager.php
+++ b/src/Workspace/WorkspaceManager.php
@@ -35,7 +35,8 @@ class WorkspaceManager implements WorkspaceManagerInterface {
protected $sortedNegotiators;
/**
- * @var \Drupal\multiversion\Entity\WorkspaceInterface
+ * @var \Drupal\multiversion\Entity\WorkspaceInterface $activeWorkspace
+ * Track the active workspace for performance gain.
*/
protected $activeWorkspace;
@@ -84,21 +85,24 @@ class WorkspaceManager implements WorkspaceManagerInterface {
* @todo {@link https://www.drupal.org/node/2600382 Access check.}
*/
public function getActiveWorkspace() {
- if (!isset($this->activeWorkspace)) {
- $request = $this->requestStack->getCurrentRequest();
- foreach ($this->getSortedNegotiators() as $negotiator) {
- if ($negotiator->applies($request)) {
- if ($workspace_id = $negotiator->getWorkspaceId($request)) {
- /** @var \Drupal\multiversion\Entity\WorkspaceInterface $workspace */
- if ($workspace = $this->entityManager->getStorage('workspace')->load($workspace_id)) {
- $negotiator->persist($workspace);
- $this->activeWorkspace = $workspace;
- break;
- }
+ // Return the cached value if it is set.
+ if (isset($this->activeWorkspace)) {
+ return $this->activeWorkspace;
+ }
+
+ $this->activeWorkspace = NULL;
+ $request = $this->requestStack->getCurrentRequest();
+ foreach ($this->getSortedNegotiators() as $negotiator) {
+ if ($negotiator->applies($request)) {
+ if ($workspace_id = $negotiator->getWorkspaceId($request)) {
+ if ($active_workspace = $this->load($workspace_id)) {
+ $this->activeWorkspace = $active_workspace;
+ break;
}
}
}
}
+
return $this->activeWorkspace;
}
@@ -106,22 +110,19 @@ class WorkspaceManager implements WorkspaceManagerInterface {
* {@inheritdoc}
*/
public function setActiveWorkspace(WorkspaceInterface $workspace) {
- $this->activeWorkspace = $workspace;
- return $this;
- }
+ // Unset the cached variable so it can re-populate on get.
+ unset($this->activeWorkspace);
- /**
- * {@inheritdoc}
- */
- public function getWorkspaceSwitchLinks(Url $url) {
+ // Set the workspace on the proper negotiator.
$request = $this->requestStack->getCurrentRequest();
foreach ($this->getSortedNegotiators() as $negotiator) {
- if ($negotiator instanceof WorkspaceSwitcherInterface && $negotiator->applies($request)) {
- if ($links = $negotiator->getWorkspaceSwitchLinks($request, $url)) {
- return $links;
- }
+ if ($negotiator->applies($request)) {
+ $negotiator->persist($workspace);
+ break;
}
}
+
+ return $this;
}
/**
diff --git a/src/Workspace/WorkspaceManagerInterface.php b/src/Workspace/WorkspaceManagerInterface.php
index 17eeb9b..9c75ca4 100644
--- a/src/Workspace/WorkspaceManagerInterface.php
+++ b/src/Workspace/WorkspaceManagerInterface.php
@@ -44,10 +44,4 @@ interface WorkspaceManagerInterface {
*/
public function setActiveWorkspace(WorkspaceInterface $workspace);
- /**
- * @param \Drupal\Core\Url $url
- * @return array
- */
- public function getWorkspaceSwitchLinks(Url $url);
-
}
diff --git a/src/Workspace/WorkspaceSwitcherInterface.php b/src/Workspace/WorkspaceSwitcherInterface.php
deleted file mode 100644
index b36c172..0000000
--- a/src/Workspace/WorkspaceSwitcherInterface.php
+++ /dev/null
@@ -1,22 +0,0 @@
-getOwner()->getDisplayname();
$type = $entity->get('type')->first()->entity;
$row['type'] = $type ? $type->label() : '';
+ $active_workspace = $entity->getActiveWorkspaceId();
+ $row['status'] = $active_workspace && $active_workspace[0] == $entity->id() ? 'Active' : 'Inactive';
return $row + parent::buildRow($entity);
}
@@ -46,6 +49,17 @@ class WorkspaceListBuilder extends EntityListBuilder {
if (isset($operations['edit'])) {
$operations['edit']['query']['destination'] = $entity->url('collection');
}
+
+ $active_workspace = $entity->getActiveWorkspaceId();
+ if (!$active_workspace || $entity->id() != $active_workspace[0]) {
+ $operations['activate'] = array(
+ 'title' => $this->t('Set Active'),
+ 'weight' => 20,
+ // @todo What is the better way to get the form submission to redirect back to the workspaces page?
+ 'url' => $entity->urlInfo('activate-form', ['query' => ['destination' => '/admin/structure/workspaces']]),
+ );
+ }
+
return $operations;
}
diff --git a/tests/src/Unit/SessionWorkspaceNegotiatorTest.php b/tests/src/Unit/SessionWorkspaceNegotiatorTest.php
index 8369fa5..1de3bf1 100644
--- a/tests/src/Unit/SessionWorkspaceNegotiatorTest.php
+++ b/tests/src/Unit/SessionWorkspaceNegotiatorTest.php
@@ -174,67 +174,4 @@ class SessionWorkspaceNegotiatorTest extends UnitTestCase {
$this->assertSame(1, $_SESSION['workspace']);
}
- /**
- * Tests the getWorkspaceSwitchLinks() method.
- */
- public function testGetWorkspaceSwitchLinks() {
- $second_machine_name = $this->values[1]['machine_name'];
- $url = Url::fromRoute($this->path);
- $expected_links = [
- 1 => [
- 'url' => $url,
- 'title' => $this->defaultMachineName,
- 'query' => ['workspace' => 1],
- 'attributes' => [
- 'class' => ['session-active'],
- ],
- ],
- 2 => [
- 'url' => $url,
- 'title' => $second_machine_name,
- 'query' => ['workspace' => 2],
- ],
- ];
-
- foreach ($this->values as $key => $value) {
- $this->entities[$key]->expects($this->any())
- ->method('id')
- ->will($this->returnValue($value['id']));
- $this->entities[$key]->expects($this->any())
- ->method('label')
- ->will($this->returnValue($value['label']));
- }
-
- $this->negotiator = $this->getMock('\Drupal\multiversion\Workspace\SessionWorkspaceNegotiator');
- $this->negotiator->expects($this->any())
- ->method('getActiveWorkspace')
- ->with($this->requestStack, $this->entityManager)
- ->will($this->returnValue($this->defaultMachineName));
-
- $storage = $this->getMock('\Drupal\Core\Entity\EntityStorageInterface');
- $storage->expects($this->any())
- ->method('loadMultiple')
- ->with()
- ->will($this->returnValue($this->entities));
-
- $this->entityManager->expects($this->any())
- ->method('getStorage')
- ->with('workspace')
- ->will($this->returnValue($storage));
-
- $this->workspaceManager->expects($this->any())
- ->method('loadMultiple')
- ->with()
- ->will($this->returnValue(array($this->entities)));
-
- $workspace_manager = new WorkspaceManager($this->requestStack, $this->entityManager, $this->cacheRender);
- $workspace_manager->addNegotiator($this->workspaceNegotiator, 1);
- $workspace_manager->setActiveWorkspace($this->entities[0]);
- $negotiator = new SessionWorkspaceNegotiator();
- $negotiator->setWorkspaceManager($workspace_manager);
-
- $links = $negotiator->getWorkspaceSwitchLinks($this->request, $url);
- $this->assertSame($expected_links, $links);
- }
-
}
diff --git a/tests/src/Unit/WorkspaceManagerTest.php b/tests/src/Unit/WorkspaceManagerTest.php
index e4b0eb1..c59863e 100644
--- a/tests/src/Unit/WorkspaceManagerTest.php
+++ b/tests/src/Unit/WorkspaceManagerTest.php
@@ -11,6 +11,7 @@ use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Url;
use Drupal\Tests\UnitTestCase;
use Drupal\multiversion\Workspace\WorkspaceManager;
+use Prophecy\Argument;
use Symfony\Component\HttpFoundation\Request;
/**
@@ -181,48 +182,72 @@ class WorkspaceManagerTest extends UnitTestCase {
}
/**
- * Tests the setActiveWorkspace() and getActiveWorkspace() methods.
+ * Tests that setActiveWorkspace() sets the workspace on the negotiator.
*/
public function testSetActiveWorkspace() {
+ // Create the request we will use.
+ $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
+ $this->requestStack->method('getCurrentRequest')->willReturn($request);
+
+ // Create the workspace that we will set.
+ $workspace = $this->getMockBuilder('Drupal\multiversion\Entity\Workspace')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ // Spy on the negotiator and stub the applies and persist methods.
+ $negotiator = $this->prophesize('Drupal\multiversion\Workspace\DefaultWorkspaceNegotiator');
+ $negotiator->applies(Argument::any())->willReturn(TRUE);
+ $negotiator->persist(Argument::any())->will(function(){ return $this; });
+
+ // Create the workspace manager.
$workspace_manager = new WorkspaceManager($this->requestStack, $this->entityManager, $this->cacheRender);
- $workspace_manager->setActiveWorkspace($this->entities[0]);
- $this->assertSame($this->entities[0], $workspace_manager->getActiveWorkspace());
+ $workspace_manager->addNegotiator($negotiator->reveal(), 1);
+
+ // Execute the code under test.
+ $workspace_manager->setActiveWorkspace($workspace);
+
+ // Ensure persist with the workspace was called on the negotiator.
+ $negotiator->persist($workspace)->shouldHaveBeenCalled();
}
/**
- * Tests the getWorkspaceSwitchLinks() method.
+ * Tests that getActiveWorkspace() gets from the negotiator.
*/
- public function testGetWorkspaceSwitchLinks() {
- $path = '';
- $request = Request::create($path);
- $query = array();
- $url = Url::fromRoute('');
- $expected_links = array(
- 1 => array(
- 'href' => $url,
- 'title' => null,
- 'query' => $query,
- ),
- );
-
- $this->requestStack->expects($this->once())
- ->method('getCurrentRequest')
- ->will($this->returnValue($request));
+ public function testGetActiveWorkspace() {
+ $workspace_id = '123';
+
+ // Create the request we will use.
+ $request = $this->getMock('Symfony\Component\HttpFoundation\Request');
+ $this->requestStack->method('getCurrentRequest')->willReturn($request);
+
+ // Create the workspace that we will get.
+ $workspace = $this->getMockBuilder('Drupal\multiversion\Entity\Workspace')
+ ->disableOriginalConstructor()
+ ->getMock();
+ // Create the negotiator and stub the applies and getWorkspaceId methods.
+ $negotiator = $this->getMock('Drupal\multiversion\Workspace\DefaultWorkspaceNegotiator');
+ $negotiator->method('applies')->willReturn(TRUE);
+ $negotiator->method('getWorkspaceId')->willReturn($workspace_id);
+
+ // Create the storage and stub the load method.
+ $storage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
+ $storage->method('load')->with($workspace_id)->willReturn($workspace);
+
+ // Stub the entity manager to return $storage.
+ $this->entityManager->method('getStorage')
+ ->with($this->entityTypeId)
+ ->willReturn($storage);
+
+ // Create the workspace manager with the negotiator.
$workspace_manager = new WorkspaceManager($this->requestStack, $this->entityManager, $this->cacheRender);
- $workspace_manager->addNegotiator($this->workspaceNegotiators[1][0], 1);
+ $workspace_manager->addNegotiator($negotiator, 1);
+
+ // Execute the code under test.
+ $active_workspace = $workspace_manager->getActiveWorkspace();
- $this->workspaceNegotiators[1][0]->expects($this->any())
- ->method('applies')
- ->with($request)
- ->will($this->returnValue(TRUE));
- $this->workspaceNegotiators[1][0]->expects($this->once())
- ->method('getWorkspaceSwitchLinks')
- ->with($request, $url)
- ->will($this->returnValue($expected_links));
-
- $result_links = $workspace_manager->getWorkspaceSwitchLinks($url);
- $this->assertSame($expected_links, $result_links);
+ // Ensure value is the workspace we stubbed.
+ $this->assertSame($workspace, $active_workspace);
}
/**