Skip to content
Snippets Groups Projects
Commit d78d49d6 authored by catch's avatar catch
Browse files

Issue #3307519 by amateescu, Darren Oh, s_leu, catch: The toolbar workspace...

Issue #3307519 by amateescu, Darren Oh, s_leu, catch: The toolbar workspace switcher is not redirecting to the current page
parent 03f20224
No related branches found
No related tags found
No related merge requests found
<?php
declare(strict_types=1);
namespace Drupal\workspaces;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Render\ElementInfoManagerInterface;
use Drupal\Core\Security\TrustedCallbackInterface;
use Drupal\Core\StringTranslation\StringTranslationTrait;
use Drupal\Core\Url;
/**
* Defines a service for workspaces #lazy_builder callbacks.
*
* @internal
*/
final class WorkspacesLazyBuilders implements TrustedCallbackInterface {
use StringTranslationTrait;
public function __construct(
protected readonly WorkspaceManagerInterface $workspaceManager,
protected readonly ElementInfoManagerInterface $elementInfo,
) {}
/**
* Lazy builder callback for rendering the workspace toolbar tab.
*
* @return array
* A render array.
*/
public function renderToolbarTab(): array {
$active_workspace = $this->workspaceManager->getActiveWorkspace();
$build = [
'#type' => 'link',
'#title' => $active_workspace ? $active_workspace->label() : $this->t('Live'),
'#url' => Url::fromRoute('entity.workspace.collection', [], ['query' => \Drupal::destination()->getAsArray()]),
'#attributes' => [
'title' => t('Switch workspace'),
'class' => [
'toolbar-item',
'toolbar-icon',
'toolbar-icon-workspace',
'use-ajax',
],
'data-dialog-type' => 'dialog',
'data-dialog-renderer' => 'off_canvas_top',
'data-dialog-options' => Json::encode([
'height' => 161,
'classes' => [
'ui-dialog' => 'workspaces-dialog',
],
]),
],
'#attached' => [
'library' => ['workspaces/drupal.workspaces.toolbar'],
],
'#cache' => [
'max-age' => 0,
],
];
// The renderer has already added element defaults by the time the lazy
// builder is run.
// @see https://www.drupal.org/project/drupal/issues/2609250
$build += $this->elementInfo->getInfo('link');
return $build;
}
/**
* Render callback for the workspace toolbar tab.
*/
public static function removeTabAttributes(array $element): array {
unset($element['tab']['#attributes']);
return $element;
}
/**
* {@inheritdoc}
*/
public static function trustedCallbacks(): array {
return ['removeTabAttributes', 'renderToolbarTab'];
}
}
......@@ -4,6 +4,8 @@
namespace Drupal\Tests\workspaces\Functional;
use Drupal\Core\Url;
use Drupal\dynamic_page_cache\EventSubscriber\DynamicPageCacheSubscriber;
use Drupal\Tests\BrowserTestBase;
use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait;
......@@ -20,7 +22,12 @@ class WorkspaceSwitcherTest extends BrowserTestBase {
/**
* {@inheritdoc}
*/
protected static $modules = ['block', 'workspaces'];
protected static $modules = [
'block',
'dynamic_page_cache',
'toolbar',
'workspaces',
];
/**
* {@inheritdoc}
......@@ -93,4 +100,20 @@ public function testQueryParameterNegotiator() {
$this->assertCacheContext('session');
}
/**
* Tests that the toolbar workspace switcher doesn't disable the page cache.
*/
public function testToolbarSwitcherDynamicPageCache() {
$this->drupalLogin($this->drupalCreateUser([
'access toolbar',
'view any workspace',
]));
// Front-page is visited right after login.
$this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'MISS');
// Reload the page, it should be cached now.
$this->drupalGet(Url::fromRoute('<front>'));
$this->assertSession()->elementExists('css', '.workspaces-toolbar-tab');
$this->assertSession()->responseHeaderEquals(DynamicPageCacheSubscriber::HEADER, 'HIT');
}
}
......@@ -5,7 +5,6 @@
* Provides full-site preview functionality for content staging.
*/
use Drupal\Component\Serialization\Json;
use Drupal\Core\Cache\Cache;
use Drupal\Core\Entity\EntityFormInterface;
use Drupal\Core\Entity\EntityInterface;
......@@ -266,29 +265,20 @@ function workspaces_toolbar() {
$items['workspace'] += [
'#type' => 'toolbar_item',
'tab' => [
'#type' => 'link',
'#title' => $active_workspace ? $active_workspace->label() : t('Live'),
'#url' => Url::fromRoute('entity.workspace.collection', [], ['query' => \Drupal::destination()->getAsArray()]),
'#attributes' => [
'title' => t('Switch workspace'),
'class' => ['use-ajax', 'toolbar-icon', 'toolbar-icon-workspace'],
'data-dialog-type' => 'dialog',
'data-dialog-renderer' => 'off_canvas_top',
'data-dialog-options' => Json::encode([
'height' => 161,
'classes' => [
'ui-dialog' => 'workspaces-dialog',
],
]),
'#lazy_builder' => ['workspaces.lazy_builders:renderToolbarTab', []],
'#create_placeholder' => TRUE,
'#lazy_builder_preview' => [
'#type' => 'link',
'#title' => $active_workspace ? $active_workspace->label() : t('Live'),
'#url' => Url::fromRoute('entity.workspace.collection'),
'#attributes' => [
'class' => ['toolbar-tray-lazy-placeholder-link'],
],
],
'#cache' => ['tags' => $active_workspace ? $active_workspace->getCacheTags() : []],
],
'#wrapper_attributes' => [
'class' => ['workspaces-toolbar-tab'],
],
'#attached' => [
'library' => ['workspaces/drupal.workspaces.toolbar'],
],
'#weight' => 500,
];
......@@ -298,5 +288,13 @@ function workspaces_toolbar() {
$items['workspace']['#wrapper_attributes']['class'][] = 'workspaces-toolbar-tab--is-default';
}
// \Drupal\toolbar\Element\ToolbarItem::preRenderToolbarItem adds an
// #attributes property to each toolbar item's tab child automatically.
// Lazy builders don't support an #attributes property so we need to
// add another render callback to remove the #attributes property. We start by
// adding the defaults, and then we append our own pre render callback.
$items['workspace'] += \Drupal::service('plugin.manager.element_info')->getInfo('toolbar_item');
$items['workspace']['#pre_render'][] = 'workspaces.lazy_builders:removeTabAttributes';
return $items;
}
......@@ -59,6 +59,11 @@ services:
parent: logger.channel_base
arguments: ['workspaces']
workspaces.lazy_builders:
class: Drupal\workspaces\WorkspacesLazyBuilders
arguments: [ '@workspaces.manager', '@plugin.manager.element_info' ]
Drupal\workspaces\WorkspacesLazyBuilders: '@workspaces.lazy_builders'
workspaces.entity.query.sql:
decorates: entity.query.sql
class: Drupal\workspaces\EntityQuery\QueryFactory
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment