diff --git a/core/modules/workspace/src/Entity/ReplicationLog.php b/core/modules/workspace/src/Entity/ReplicationLog.php index 5eb2196..ba640eb 100644 --- a/core/modules/workspace/src/Entity/ReplicationLog.php +++ b/core/modules/workspace/src/Entity/ReplicationLog.php @@ -87,7 +87,7 @@ public function setSourceLastSequence($source_last_sequence) { */ public static function loadOrCreate($id) { $entity = static::load($id); - if ($entity === FALSE) { + if (!$entity) { $entity = static::create(['id' => $id]); } diff --git a/core/modules/workspace/src/Entity/Workspace.php b/core/modules/workspace/src/Entity/Workspace.php index 77ad66f..7e1b914 100644 --- a/core/modules/workspace/src/Entity/Workspace.php +++ b/core/modules/workspace/src/Entity/Workspace.php @@ -10,6 +10,7 @@ use Drupal\user\UserInterface; use Drupal\workspace\RepositoryHandlerInterface; use Drupal\workspace\WorkspaceInterface; +use Drupal\workspace\WorkspaceManager; /** * The workspace entity class. @@ -141,6 +142,13 @@ public function getLocalRepositoryHandlerPlugin() { /** * {@inheritdoc} */ + public function isDefaultWorkspace() { + return $this->id() === WorkspaceManager::DEFAULT_WORKSPACE; + } + + /** + * {@inheritdoc} + */ public function setCreatedTime($created) { $this->set('created', (int) $created); return $this; diff --git a/core/modules/workspace/src/EntityAccess.php b/core/modules/workspace/src/EntityAccess.php index 4d3966d..2ba84f2 100644 --- a/core/modules/workspace/src/EntityAccess.php +++ b/core/modules/workspace/src/EntityAccess.php @@ -120,7 +120,7 @@ protected function bypassAccessResult(AccountInterface $account) { // This approach assumes that the current "global" active workspace is // correct, ie, if you're "in" a given workspace then you get ALL THE PERMS // to ALL THE THINGS! That's why this is a dangerous permission. - $active_workspace = $this->workspaceManager->getActiveWorkspace(TRUE); + $active_workspace = $this->workspaceManager->getActiveWorkspace(); return AccessResult::allowedIfHasPermission($account, 'bypass entity access workspace ' . $active_workspace->id()) ->orIf( diff --git a/core/modules/workspace/src/EntityQuery/Query.php b/core/modules/workspace/src/EntityQuery/Query.php index c3aa4e0..0e309a5 100644 --- a/core/modules/workspace/src/EntityQuery/Query.php +++ b/core/modules/workspace/src/EntityQuery/Query.php @@ -33,7 +33,7 @@ public function prepare() { // If the prepare() method from the trait decided that we need to alter this // query, we need to re-define the the key fields for fetchAllKeyed() as SQL // expressions. - if ($active_workspace = $this->sqlQuery->getMetaData('active_workspace')) { + if ($this->sqlQuery->getMetaData('active_workspace_id')) { $id_field = $this->entityType->getKey('id'); $revision_field = $this->entityType->getKey('revision'); diff --git a/core/modules/workspace/src/EntityQuery/QueryTrait.php b/core/modules/workspace/src/EntityQuery/QueryTrait.php index f86f788..c3b50a9 100644 --- a/core/modules/workspace/src/EntityQuery/QueryTrait.php +++ b/core/modules/workspace/src/EntityQuery/QueryTrait.php @@ -4,7 +4,6 @@ use Drupal\Core\Database\Connection; use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\workspace\WorkspaceManager; use Drupal\workspace\WorkspaceManagerInterface; /** @@ -56,15 +55,15 @@ public function prepare() { // Only alter the query if the active workspace is not the default one and // the entity type is supported. $active_workspace = $this->workspaceManager->getActiveWorkspace(); - if ($active_workspace !== WorkspaceManager::DEFAULT_WORKSPACE && $this->workspaceManager->entityTypeCanBelongToWorkspaces($this->entityType)) { - $this->sqlQuery->addMetaData('active_workspace', $active_workspace); + if (!$active_workspace->isDefaultWorkspace() && $this->workspaceManager->entityTypeCanBelongToWorkspaces($this->entityType)) { + $this->sqlQuery->addMetaData('active_workspace_id', $active_workspace->id()); $this->sqlQuery->addMetaData('simple_query', FALSE); // LEFT JOIN 'content_workspace' to the base table of the query so we can // properly include live content along with a possible workspace-specific // revision. $id_field = $this->entityType->getKey('id'); - $this->sqlQuery->leftJoin('content_workspace', 'content_workspace', "%alias.content_entity_type_id = '{$this->entityTypeId}' AND %alias.content_entity_id = base_table.$id_field AND %alias.workspace = '$active_workspace'"); + $this->sqlQuery->leftJoin('content_workspace', 'content_workspace', "%alias.content_entity_type_id = '{$this->entityTypeId}' AND %alias.content_entity_id = base_table.$id_field AND %alias.workspace = '{$active_workspace->id()}'"); } return $this; diff --git a/core/modules/workspace/src/EntityQuery/Tables.php b/core/modules/workspace/src/EntityQuery/Tables.php index 71a176a..eb7c607 100644 --- a/core/modules/workspace/src/EntityQuery/Tables.php +++ b/core/modules/workspace/src/EntityQuery/Tables.php @@ -47,7 +47,7 @@ public function __construct(SelectInterface $sql_query) { // The join between the first 'content_workspace' table and base table of // the query is done \Drupal\workspace\EntityQuery\QueryTrait::prepare(), so // we need to initialize its entry manually. - if ($active_workspace = $this->sqlQuery->getMetaData('active_workspace')) { + if ($this->sqlQuery->getMetaData('active_workspace_id')) { $this->contentWorkspaceTables['base_table'] = 'content_workspace'; $this->baseTablesEntityType['base_table'] = $this->sqlQuery->getMetaData('entity_type'); } @@ -62,7 +62,7 @@ public function addField($field, $type, $langcode) { // looking for workspace-specific revisions, we have to force the parent // method to always pick the revision tables if the field being queried is // revisionable. - if ($active_workspace = $this->sqlQuery->getMetaData('active_workspace')) { + if ($active_workspace_id = $this->sqlQuery->getMetaData('active_workspace_id')) { $this->sqlQuery->addMetaData('all_revisions', TRUE); } @@ -70,7 +70,7 @@ public function addField($field, $type, $langcode) { // Restore the 'all_revisions' metadata because we don't want to interfere // with the rest of the query. - if ($active_workspace) { + if ($active_workspace_id) { $this->sqlQuery->addMetaData('all_revisions', FALSE); } @@ -81,7 +81,7 @@ public function addField($field, $type, $langcode) { * {@inheritdoc} */ protected function addJoin($type, $table, $join_condition, $langcode, $delta = NULL) { - if ($active_workspace = $this->sqlQuery->getMetaData('active_workspace')) { + if ($this->sqlQuery->getMetaData('active_workspace_id')) { // The join condition for a shared or dedicated field table is in the form // of "%alias.$id_field = $base_table.$id_field". Whenever we join a field // table we have to check: @@ -113,9 +113,9 @@ protected function addJoin($type, $table, $join_condition, $langcode, $delta = N protected function addNextBaseTable(EntityType $entity_type, $table, $sql_column, FieldStorageDefinitionInterface $field_storage) { $next_base_table_alias = parent::addNextBaseTable($entity_type, $table, $sql_column, $field_storage); - $active_workspace = $this->sqlQuery->getMetaData('active_workspace'); - if ($active_workspace && $this->workspaceManager->entityTypeCanBelongToWorkspaces($entity_type)) { - $this->addContentWorkspaceJoin($entity_type->id(), $next_base_table_alias, $active_workspace); + $active_workspace_id = $this->sqlQuery->getMetaData('active_workspace_id'); + if ($active_workspace_id && $this->workspaceManager->entityTypeCanBelongToWorkspaces($entity_type)) { + $this->addContentWorkspaceJoin($entity_type->id(), $next_base_table_alias, $active_workspace_id); } return $next_base_table_alias; @@ -131,20 +131,20 @@ protected function addNextBaseTable(EntityType $entity_type, $table, $sql_column * The ID of the entity type whose base table we are joining. * @param string $base_table_alias * The alias of the entity type's base table. - * @param string $active_workspace - * The active workspace. + * @param string $active_workspace_id + * The ID of the active workspace. * * @return string * The alias of the joined table. */ - public function addContentWorkspaceJoin($entity_type_id, $base_table_alias, $active_workspace) { + public function addContentWorkspaceJoin($entity_type_id, $base_table_alias, $active_workspace_id) { if (!isset($this->contentWorkspaceTables[$base_table_alias])) { $entity_type = $this->entityManager->getDefinition($entity_type_id); $id_field = $entity_type->getKey('id'); // LEFT join the Content Workspace entity's table so we can properly // include live content along with a possible workspace-specific revision. - $this->contentWorkspaceTables[$base_table_alias] = $this->sqlQuery->leftJoin('content_workspace', NULL, "%alias.content_entity_type_id = '$entity_type_id' AND %alias.content_entity_id = $base_table_alias.$id_field AND %alias.workspace = '$active_workspace'"); + $this->contentWorkspaceTables[$base_table_alias] = $this->sqlQuery->leftJoin('content_workspace', NULL, "%alias.content_entity_type_id = '$entity_type_id' AND %alias.content_entity_id = $base_table_alias.$id_field AND %alias.workspace = '$active_workspace_id'"); $this->baseTablesEntityType[$base_table_alias] = $entity_type->id(); } diff --git a/core/modules/workspace/src/Form/WorkspaceSwitcherForm.php b/core/modules/workspace/src/Form/WorkspaceSwitcherForm.php index 51fc22e..8e7cf64 100644 --- a/core/modules/workspace/src/Form/WorkspaceSwitcherForm.php +++ b/core/modules/workspace/src/Form/WorkspaceSwitcherForm.php @@ -79,7 +79,7 @@ public function buildForm(array $form, FormStateInterface $form_state) { $workspace_labels[$workspace->id()] = $workspace->label(); } - $active_workspace = $this->workspaceManager->getActiveWorkspace(TRUE); + $active_workspace = $this->workspaceManager->getActiveWorkspace(); unset($workspace_labels[$active_workspace->id()]); $form['current'] = [ diff --git a/core/modules/workspace/src/Negotiator/DefaultWorkspaceNegotiator.php b/core/modules/workspace/src/Negotiator/DefaultWorkspaceNegotiator.php index 72b8a6c..6ab1349 100644 --- a/core/modules/workspace/src/Negotiator/DefaultWorkspaceNegotiator.php +++ b/core/modules/workspace/src/Negotiator/DefaultWorkspaceNegotiator.php @@ -2,6 +2,8 @@ namespace Drupal\workspace\Negotiator; +use Drupal\Component\Utility\Unicode; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\workspace\WorkspaceInterface; use Drupal\workspace\WorkspaceManager; use Symfony\Component\HttpFoundation\Request; @@ -12,6 +14,30 @@ class DefaultWorkspaceNegotiator implements WorkspaceNegotiatorInterface { /** + * The workspace storage handler. + * + * @var \Drupal\Core\Entity\EntityStorageInterface + */ + protected $workspaceStorage; + + /** + * The default workspace entity. + * + * @var \Drupal\workspace\WorkspaceInterface + */ + protected $defaultWorkspace; + + /** + * Constructor. + * + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. + */ + public function __construct(EntityTypeManagerInterface $entity_type_manager) { + $this->workspaceStorage = $entity_type_manager->getStorage('workspace'); + } + + /** * {@inheritdoc} */ public function applies(Request $request) { @@ -21,8 +47,18 @@ public function applies(Request $request) { /** * {@inheritdoc} */ - public function getWorkspaceId(Request $request) { - return WorkspaceManager::DEFAULT_WORKSPACE; + public function getWorkspace(Request $request) { + if (!$this->defaultWorkspace) { + $default_workspace = $this->workspaceStorage->create([ + 'id' => WorkspaceManager::DEFAULT_WORKSPACE, + 'label' => Unicode::ucwords(WorkspaceManager::DEFAULT_WORKSPACE), + ]); + $default_workspace->enforceIsNew(FALSE); + + $this->defaultWorkspace = $default_workspace; + } + + return $this->defaultWorkspace; } /** diff --git a/core/modules/workspace/src/Negotiator/SessionWorkspaceNegotiator.php b/core/modules/workspace/src/Negotiator/SessionWorkspaceNegotiator.php index 3771995..1514ac0 100644 --- a/core/modules/workspace/src/Negotiator/SessionWorkspaceNegotiator.php +++ b/core/modules/workspace/src/Negotiator/SessionWorkspaceNegotiator.php @@ -2,10 +2,10 @@ namespace Drupal\workspace\Negotiator; +use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Session\AccountInterface; use Drupal\workspace\WorkspaceInterface; use Drupal\user\PrivateTempStoreFactory; -use Drupal\workspace\WorkspaceManager; use Symfony\Component\HttpFoundation\Request; /** @@ -28,11 +28,11 @@ class SessionWorkspaceNegotiator implements WorkspaceNegotiatorInterface { protected $tempstore; /** - * The default workspace ID. + * The workspace storage handler. * - * @var string + * @var \Drupal\Core\Entity\EntityStorageInterface */ - protected $defaultWorkspaceId; + protected $workspaceStorage; /** * Constructor. @@ -41,10 +41,13 @@ class SessionWorkspaceNegotiator implements WorkspaceNegotiatorInterface { * The current user. * @param \Drupal\user\PrivateTempStoreFactory $tempstore_factory * The tempstore factory. + * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager + * The entity type manager. */ - public function __construct(AccountInterface $current_user, PrivateTempStoreFactory $tempstore_factory) { + public function __construct(AccountInterface $current_user, PrivateTempStoreFactory $tempstore_factory, EntityTypeManagerInterface $entity_type_manager) { $this->currentUser = $current_user; $this->tempstore = $tempstore_factory->get('workspace.negotiator.session'); + $this->workspaceStorage = $entity_type_manager->getStorage('workspace'); } /** @@ -59,9 +62,14 @@ public function applies(Request $request) { /** * {@inheritdoc} */ - public function getWorkspaceId(Request $request) { + public function getWorkspace(Request $request) { $workspace_id = $this->tempstore->get('active_workspace_id'); - return $workspace_id ?: WorkspaceManager::DEFAULT_WORKSPACE; + + if ($workspace_id && ($workspace = $this->workspaceStorage->load($workspace_id))) { + return $workspace; + } + + return NULL; } /** diff --git a/core/modules/workspace/src/Negotiator/WorkspaceNegotiatorInterface.php b/core/modules/workspace/src/Negotiator/WorkspaceNegotiatorInterface.php index 615dd1f..4ccee6a 100644 --- a/core/modules/workspace/src/Negotiator/WorkspaceNegotiatorInterface.php +++ b/core/modules/workspace/src/Negotiator/WorkspaceNegotiatorInterface.php @@ -8,12 +8,13 @@ /** * Workspace negotiators provide a way to get the active workspace. * - * WorkspaceManager acts as the service collector for Workspace negotiators. + * \Drupal\workspace\WorkspaceManager acts as the service collector for + * Workspace negotiators. */ interface WorkspaceNegotiatorInterface { /** - * Checks whether the negotiator applies or not. + * Checks whether the negotiator applies to the current request or not. * * @param \Symfony\Component\HttpFoundation\Request $request * The HTTP request. @@ -24,18 +25,22 @@ public function applies(Request $request); /** - * Gets the ID of the active workspace. + * Gets the negotiated workspace, if any. + * + * Note that it is the responsibility of each implementation to check whether + * the negotiated workspace actually exists in the storage. * * @param \Symfony\Component\HttpFoundation\Request $request * The HTTP request. * - * @return string - * The workspace ID. + * @return \Drupal\workspace\WorkspaceInterface|null + * The negotiated workspace or NULL if the negotiator could not determine a + * valid workspace. */ - public function getWorkspaceId(Request $request); + public function getWorkspace(Request $request); /** - * Sets the active workspace. + * Sets the negotiated workspace. * * @param \Drupal\workspace\WorkspaceInterface $workspace * The workspace entity. diff --git a/core/modules/workspace/src/Plugin/Field/FieldWidget/WorkspaceUpstreamWidget.php b/core/modules/workspace/src/Plugin/Field/FieldWidget/WorkspaceUpstreamWidget.php index 37110c6..3c2dae6 100644 --- a/core/modules/workspace/src/Plugin/Field/FieldWidget/WorkspaceUpstreamWidget.php +++ b/core/modules/workspace/src/Plugin/Field/FieldWidget/WorkspaceUpstreamWidget.php @@ -73,12 +73,15 @@ public static function create(ContainerInterface $container, array $configuratio * {@inheritdoc} */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { + /** @var \Drupal\workspace\WorkspaceInterface $workspace */ + $workspace = $items->getEntity(); + // Gather the list of upstreams grouped by category. $upstream_options = []; foreach ($this->upstreamPluginManager->getGroupedDefinitions() as $category => $upstream_plugin_definitions) { foreach ($upstream_plugin_definitions as $plugin_id => $plugin_definition) { // Do not include the local workspace itself as an option. - if ($plugin_id !== 'local_workspace' . PluginBase::DERIVATIVE_SEPARATOR . $items->getEntity()->id()) { + if ($plugin_id !== 'local_workspace' . PluginBase::DERIVATIVE_SEPARATOR . $workspace->id()) { $upstream_options[$category][$plugin_id] = $plugin_definition['label']; } } @@ -87,7 +90,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen // The default ('Live') workspace can not have another local workspace as an // upstream value, so we need to remove all options from the // 'Local workspace' category. - if ($items->getEntity()->id() === WorkspaceManager::DEFAULT_WORKSPACE) { + if ($workspace->isDefaultWorkspace()) { unset($upstream_options['Local workspace']); } diff --git a/core/modules/workspace/src/Plugin/RepositoryHandler/LocalWorkspaceRepositoryHandler.php b/core/modules/workspace/src/Plugin/RepositoryHandler/LocalWorkspaceRepositoryHandler.php index 2699219..3e932a8 100644 --- a/core/modules/workspace/src/Plugin/RepositoryHandler/LocalWorkspaceRepositoryHandler.php +++ b/core/modules/workspace/src/Plugin/RepositoryHandler/LocalWorkspaceRepositoryHandler.php @@ -119,8 +119,11 @@ public function replicate(RepositoryHandlerInterface $source, RepositoryHandlerI // Replicating content from one workspace to another on the same site // roughly follows the CouchDB replication protocol. // @see http://docs.couchdb.org/en/2.1.0/replication/protocol.html + /** @var \Drupal\workspace\WorkspaceInterface $source_workspace */ $source_workspace = $this->entityTypeManager->getStorage('workspace')->load($source->getDerivativeId()); + /** @var \Drupal\workspace\WorkspaceInterface $target_workspace */ $target_workspace = $this->entityTypeManager->getStorage('workspace')->load($target->getDerivativeId()); + $start_time = new \DateTime(); $session_id = \md5((\microtime(TRUE) * 1000000)); // @todo Figure out if we want to include more information in the @@ -133,7 +136,7 @@ public function replicate(RepositoryHandlerInterface $source, RepositoryHandlerI // Get the current active workspace, so we can set it back as the active // after the replication has completed. - $current_active = $this->workspaceManager->getActiveWorkspace(TRUE); + $current_active = $this->workspaceManager->getActiveWorkspace(); // Set the source as the active workspace, so we can fetch all the entities // relative to the source workspace. @@ -175,9 +178,9 @@ public function replicate(RepositoryHandlerInterface $source, RepositoryHandlerI // workspace. /** @var \Drupal\Core\Entity\ContentEntityInterface $content_workspace */ $content_workspace = $this->entityTypeManager->getStorage('content_workspace')->loadRevision($revision_id); - if (WorkspaceManager::DEFAULT_WORKSPACE === $target_workspace->id()) { - // If the target workspace is the default workspace (generally 'live') - // the revision needs to be set to the default revision. + if ($target_workspace->isDefaultWorkspace()) { + // If the target workspace is the default workspace, the revision + // needs to be set to the default revision. /** @var \Drupal\Core\Entity\ContentEntityInterface|\Drupal\Core\Entity\RevisionableInterface $entity */ $entity = $this->entityTypeManager ->getStorage($content_workspace->content_entity_type_id->value) diff --git a/core/modules/workspace/src/WorkspaceAccessControlHandler.php b/core/modules/workspace/src/WorkspaceAccessControlHandler.php index dfbfc39..7b4fb35 100644 --- a/core/modules/workspace/src/WorkspaceAccessControlHandler.php +++ b/core/modules/workspace/src/WorkspaceAccessControlHandler.php @@ -31,7 +31,7 @@ protected function checkAccess(EntityInterface $entity, $operation, AccountInter $permission_operation = $operation === 'update' ? 'edit' : 'view'; // The default workspace is always viewable, no matter what. - return AccessResult::allowedIf($operation == 'view' && $entity->id() == WorkspaceManager::DEFAULT_WORKSPACE)->addCacheableDependency($entity) + return AccessResult::allowedIf($operation == 'view' && $entity->isDefaultWorkspace())->addCacheableDependency($entity) // Or if the user has permission to access any workspace at all. ->orIf(AccessResult::allowedIfHasPermission($account, $operations[$operation]['any'])) // Or if it's their own workspace, and they have permission to access diff --git a/core/modules/workspace/src/WorkspaceCacheContext.php b/core/modules/workspace/src/WorkspaceCacheContext.php index d7d010b..14ce019 100644 --- a/core/modules/workspace/src/WorkspaceCacheContext.php +++ b/core/modules/workspace/src/WorkspaceCacheContext.php @@ -40,7 +40,7 @@ public static function getLabel() { * {@inheritdoc} */ public function getContext() { - return $this->workspaceManager->getActiveWorkspace(); + return $this->workspaceManager->getActiveWorkspace()->id(); } /** diff --git a/core/modules/workspace/src/WorkspaceInterface.php b/core/modules/workspace/src/WorkspaceInterface.php index 8b7a0c4..91c140d 100644 --- a/core/modules/workspace/src/WorkspaceInterface.php +++ b/core/modules/workspace/src/WorkspaceInterface.php @@ -30,6 +30,14 @@ public function getRepositoryHandlerPlugin(); public function getLocalRepositoryHandlerPlugin(); /** + * Determines whether the workspace is the default one or not. + * + * @return bool + * TRUE if this workspace is the default one (e.g 'Live'), FALSE otherwise. + */ + public function isDefaultWorkspace(); + + /** * Sets the workspace creation timestamp. * * @param int $timestamp diff --git a/core/modules/workspace/src/WorkspaceListBuilder.php b/core/modules/workspace/src/WorkspaceListBuilder.php index d075e30..fc4ef14 100644 --- a/core/modules/workspace/src/WorkspaceListBuilder.php +++ b/core/modules/workspace/src/WorkspaceListBuilder.php @@ -66,7 +66,7 @@ public function buildRow(EntityInterface $entity) { /** @var \Drupal\workspace\WorkspaceInterface $entity */ $row['label'] = $entity->label() . ' (' . $entity->id() . ')'; $row['owner'] = $entity->getOwner()->getDisplayname(); - $active_workspace = $this->workspaceManager->getActiveWorkspace(); + $active_workspace = $this->workspaceManager->getActiveWorkspace()->id(); $row['status'] = $active_workspace == $entity->id() ? $this->t('Active') : $this->t('Inactive'); return $row + parent::buildRow($entity); @@ -83,7 +83,7 @@ public function getDefaultOperations(EntityInterface $entity) { } $active_workspace = $this->workspaceManager->getActiveWorkspace(); - if ($entity->id() != $active_workspace) { + if ($entity->id() != $active_workspace->id()) { $operations['activate'] = [ 'title' => $this->t('Set Active'), 'weight' => 20, diff --git a/core/modules/workspace/src/WorkspaceManager.php b/core/modules/workspace/src/WorkspaceManager.php index c20bb51..fbce585 100644 --- a/core/modules/workspace/src/WorkspaceManager.php +++ b/core/modules/workspace/src/WorkspaceManager.php @@ -148,24 +148,20 @@ public function getSupportedEntityTypes() { /** * {@inheritdoc} - * - * @todo {@link https://www.drupal.org/node/2600382 Access check.} */ - public function getActiveWorkspace($object = FALSE) { + public function getActiveWorkspace() { $request = $this->requestStack->getCurrentRequest(); foreach ($this->negotiatorIds as $negotiator_id) { $negotiator = $this->classResolver->getInstanceFromDefinition($negotiator_id); if ($negotiator->applies($request)) { - if ($workspace_id = $negotiator->getWorkspaceId($request)) { - if ($object) { - return $this->entityTypeManager->getStorage('workspace')->load($workspace_id); - } - else { - return $workspace_id; - } + if ($active_workspace = $negotiator->getWorkspace($request)) { + break; } } } + + // The default workspace negotiator always returns a valid workspace. + return $active_workspace; } /** @@ -174,8 +170,7 @@ public function getActiveWorkspace($object = FALSE) { public function setActiveWorkspace(WorkspaceInterface $workspace) { // If the current user doesn't have access to view the workspace, they // shouldn't be allowed to switch to it. - // @todo Could this be handled better? - if (!$workspace->access('view') && ($workspace->id() != static::DEFAULT_WORKSPACE)) { + if (!$workspace->access('view') && !$workspace->isDefaultWorkspace()) { $this->logger->error('Denied access to view workspace {workspace}', ['workspace' => $workspace->label()]); throw new WorkspaceAccessException('The user does not have permission to view that workspace.'); } @@ -230,7 +225,7 @@ public function updateOrCreateFromEntity(EntityInterface $entity) { // Add the revision ID and the workspace ID. $content_workspace->set('content_entity_revision_id', $entity->getRevisionId()); - $content_workspace->set('workspace', $this->getActiveWorkspace()); + $content_workspace->set('workspace', $this->getActiveWorkspace()->id()); // Save without updating the content entity. $content_workspace->save(); diff --git a/core/modules/workspace/src/WorkspaceManagerInterface.php b/core/modules/workspace/src/WorkspaceManagerInterface.php index 89fb309..6feadb0 100644 --- a/core/modules/workspace/src/WorkspaceManagerInterface.php +++ b/core/modules/workspace/src/WorkspaceManagerInterface.php @@ -32,15 +32,10 @@ public function getSupportedEntityTypes(); /** * Gets the active workspace. * - * @param bool $object - * TRUE for the active workspace to be returned as an object, FALSE - * otherwise. - * - * @return \Drupal\workspace\WorkspaceInterface|string - * The active workspace entity object or workspace ID, depending on the - * $object parameter. + * @return \Drupal\workspace\WorkspaceInterface + * The active workspace entity object. */ - public function getActiveWorkspace($object = FALSE); + public function getActiveWorkspace(); /** * Sets the active workspace via the workspace negotiators. diff --git a/core/modules/workspace/tests/src/Functional/WorkspaceTestUtilities.php b/core/modules/workspace/tests/src/Functional/WorkspaceTestUtilities.php index 14475fb..328a51b 100644 --- a/core/modules/workspace/tests/src/Functional/WorkspaceTestUtilities.php +++ b/core/modules/workspace/tests/src/Functional/WorkspaceTestUtilities.php @@ -99,7 +99,7 @@ protected function setupWorkspaceSwitcherBlock() { protected function switchToWorkspace(WorkspaceInterface $workspace) { /** @var \Drupal\workspace\WorkspaceManager $workspace_manager */ $workspace_manager = \Drupal::service('workspace.manager'); - if ($workspace_manager->getActiveWorkspace() !== $workspace->id()) { + if ($workspace_manager->getActiveWorkspace()->id() !== $workspace->id()) { // Switch the system under test to the specified workspace. /** @var \Drupal\Tests\WebAssert $session */ $session = $this->assertSession(); diff --git a/core/modules/workspace/tests/src/Kernel/WorkspaceIntegrationTest.php b/core/modules/workspace/tests/src/Kernel/WorkspaceIntegrationTest.php index 06a2d24..bb50147 100644 --- a/core/modules/workspace/tests/src/Kernel/WorkspaceIntegrationTest.php +++ b/core/modules/workspace/tests/src/Kernel/WorkspaceIntegrationTest.php @@ -596,7 +596,7 @@ protected function assertEntityQuery(array $expected_values, $entity_type_id) { protected function switchToWorkspace($workspace_id) { /** @var \Drupal\workspace\WorkspaceManager $workspace_manager */ $workspace_manager = \Drupal::service('workspace.manager'); - if ($workspace_manager->getActiveWorkspace() !== $workspace_id) { + if ($workspace_manager->getActiveWorkspace()->id() !== $workspace_id) { // Switch the test runner's context to the specified workspace. $workspace = $this->entityTypeManager->getStorage('workspace')->load($workspace_id); \Drupal::service('workspace.manager')->setActiveWorkspace($workspace); diff --git a/core/modules/workspace/workspace.module b/core/modules/workspace/workspace.module index b28590f..3b3118e 100644 --- a/core/modules/workspace/workspace.module +++ b/core/modules/workspace/workspace.module @@ -16,7 +16,6 @@ use Drupal\views\Plugin\views\query\Sql; use Drupal\views\ViewExecutable; use Drupal\workspace\EntityAccess; -use Drupal\workspace\WorkspaceManager; /** * Implements hook_help(). @@ -48,7 +47,7 @@ function workspace_entity_load(array &$entities, $entity_type_id) { // Don't alter the loaded entities if the active workspace is the default one. $active_workspace = $workspace_manager->getActiveWorkspace(); - if ($active_workspace == WorkspaceManager::DEFAULT_WORKSPACE) { + if ($active_workspace->isDefaultWorkspace()) { return; } @@ -65,7 +64,7 @@ function workspace_entity_load(array &$entities, $entity_type_id) { ->groupBy('content_entity_id') ->condition('content_entity_type_id', $entity_type_id) ->condition('content_entity_id', $entity_ids, 'IN') - ->condition('workspace', $active_workspace, '=') + ->condition('workspace', $active_workspace->id(), '=') ->execute(); // Since hook_entity_load() is called on both regular entity load as well as @@ -106,7 +105,7 @@ function workspace_entity_presave(EntityInterface $entity) { // Only run if the entity type can belong to a workspace and we are in a // non-default workspace. if (!$workspace_manager->entityTypeCanBelongToWorkspaces($entity->getEntityType()) - || $workspace_manager->getActiveWorkspace() === WorkspaceManager::DEFAULT_WORKSPACE) { + || $workspace_manager->getActiveWorkspace()->isDefaultWorkspace()) { return; } @@ -146,7 +145,7 @@ function workspace_entity_insert(EntityInterface $entity) { // Only run if the entity type can belong to a workspace and we are in a // non-default workspace. if (!$workspace_manager->entityTypeCanBelongToWorkspaces($entity->getEntityType()) - || $workspace_manager->getActiveWorkspace() === WorkspaceManager::DEFAULT_WORKSPACE) { + || $workspace_manager->getActiveWorkspace()->isDefaultWorkspace()) { return; } @@ -175,7 +174,7 @@ function workspace_entity_update(EntityInterface $entity) { // Only run if the entity type can belong to a workspace and we are in a // non-default workspace. if (!$workspace_manager->entityTypeCanBelongToWorkspaces($entity->getEntityType()) - || $workspace_manager->getActiveWorkspace() === WorkspaceManager::DEFAULT_WORKSPACE) { + || $workspace_manager->getActiveWorkspace()->isDefaultWorkspace()) { return; } @@ -213,7 +212,7 @@ function workspace_views_query_alter(ViewExecutable $view, QueryPluginBase $quer // Don't alter any views queries if we're in the default workspace. $active_workspace = $workspace_manager->getActiveWorkspace(); - if ($active_workspace == WorkspaceManager::DEFAULT_WORKSPACE) { + if ($active_workspace->isDefaultWorkspace()) { return; } @@ -414,7 +413,7 @@ function _workspace_ensure_content_workspace_table($entity_type_id, Sql $query, ], [ 'field' => 'workspace', - 'value' => \Drupal::service('workspace.manager')->getActiveWorkspace(), + 'value' => \Drupal::service('workspace.manager')->getActiveWorkspace()->id(), ], ], 'type' => 'LEFT', @@ -558,15 +557,6 @@ function workspace_rest_resource_alter(&$definitions) { */ function workspace_toolbar() { $items = []; - - /** @var \Drupal\workspace\WorkspaceInterface $active_workspace */ - $active_workspace = \Drupal::service('workspace.manager')->getActiveWorkspace(TRUE); - - // When the module is uninstalled, there is no active workspace anymore. - if (!$active_workspace) { - return $items; - } - $items['workspace'] = [ '#cache' => [ 'contexts' => [ @@ -582,6 +572,9 @@ function workspace_toolbar() { return $items; } + /** @var \Drupal\workspace\WorkspaceInterface $active_workspace */ + $active_workspace = \Drupal::service('workspace.manager')->getActiveWorkspace(); + $configure_link = NULL; if ($current_user->hasPermission('administer workspaces')) { $configure_link = [ @@ -619,7 +612,7 @@ function workspace_toolbar() { // Add a special class to the wrapper if we are in the default workspace so we // can highlight it with a different color. - if ($active_workspace->id() === WorkspaceManager::DEFAULT_WORKSPACE) { + if ($active_workspace->isDefaultWorkspace()) { $items['workspace']['#wrapper_attributes']['class'][] = 'is-live'; } @@ -637,7 +630,7 @@ function workspace_renderable_links() { /** @var \Drupal\Core\Entity\EntityRepositoryInterface $entity_repository */ $entity_repository = \Drupal::service('entity.repository'); /** @var \Drupal\workspace\WorkspaceInterface $active_workspace */ - $active_workspace = \Drupal::service('workspace.manager')->getActiveWorkspace(TRUE); + $active_workspace = \Drupal::service('workspace.manager')->getActiveWorkspace(); $links = $cache_tags = []; foreach ($entity_type_manager->getStorage('workspace')->loadMultiple() as $workspace) { diff --git a/core/modules/workspace/workspace.services.yml b/core/modules/workspace/workspace.services.yml index 3118ee4..ed83dbe 100644 --- a/core/modules/workspace/workspace.services.yml +++ b/core/modules/workspace/workspace.services.yml @@ -9,11 +9,12 @@ services: parent: default_plugin_manager workspace.negotiator.default: class: Drupal\workspace\Negotiator\DefaultWorkspaceNegotiator + arguments: ['@entity_type.manager'] tags: - { name: workspace_negotiator, priority: 0 } workspace.negotiator.session: class: Drupal\workspace\Negotiator\SessionWorkspaceNegotiator - arguments: ['@current_user', '@user.private_tempstore'] + arguments: ['@current_user', '@user.private_tempstore', '@entity_type.manager'] tags: - { name: workspace_negotiator, priority: 100 } cache_context.workspace: