Issue #3101671 by amateescu, webdrips, smithmilner, s_leu, smustgrave: Add mechanism to have workspaces skip processing entity types
(cherry picked from commit 940a069060
)
merge-requests/6880/merge
parent
bd8960f835
commit
1fd6c15aef
|
@ -0,0 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workspaces\Entity\Handler;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* Provides a custom workspace handler for block_content entities.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class BlockContentWorkspaceHandler extends DefaultWorkspaceHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEntitySupported(EntityInterface $entity): bool {
|
||||
// Only reusable blocks can be tracked individually. Non-reusable or inline
|
||||
// blocks are tracked as part of the entity they are a composite of.
|
||||
/** @var \Drupal\block_content\BlockContentInterface $entity */
|
||||
return $entity->isReusable();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workspaces\Entity\Handler;
|
||||
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Common customizations for most entity types.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class DefaultWorkspaceHandler implements WorkspaceHandlerInterface, EntityHandlerInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEntitySupported(EntityInterface $entity): bool {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workspaces\Entity\Handler;
|
||||
|
||||
use Drupal\Core\Entity\EntityHandlerInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
* Defines a handler for entity types that are ignored by workspaces.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class IgnoredWorkspaceHandler implements WorkspaceHandlerInterface, EntityHandlerInterface {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
|
||||
return new static();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEntitySupported(EntityInterface $entity): bool {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workspaces\Entity\Handler;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
|
||||
/**
|
||||
* Defines workspace operations that need to vary by entity type.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
interface WorkspaceHandlerInterface {
|
||||
|
||||
/**
|
||||
* Determines if an entity should be tracked in a workspace.
|
||||
*
|
||||
* At the general level, workspace support is determined for the entire entity
|
||||
* type. If an entity type is supported, there may be further decisions each
|
||||
* entity type can make to evaluate if a given entity is appropriate to be
|
||||
* tracked in a workspace.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity we may be tracking.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if this entity should be tracked in a workspace, FALSE otherwise.
|
||||
*/
|
||||
public function isEntitySupported(EntityInterface $entity): bool;
|
||||
|
||||
}
|
|
@ -39,6 +39,7 @@ use Drupal\workspaces\WorkspaceInterface;
|
|||
* "delete" = "\Drupal\workspaces\Form\WorkspaceDeleteForm",
|
||||
* "activate" = "\Drupal\workspaces\Form\WorkspaceActivateForm",
|
||||
* },
|
||||
* "workspace" = "\Drupal\workspaces\Entity\Handler\IgnoredWorkspaceHandler",
|
||||
* },
|
||||
* admin_permission = "administer workspaces",
|
||||
* base_table = "workspace",
|
||||
|
|
|
@ -33,6 +33,13 @@ class EntityAccess implements ContainerInjectionInterface {
|
|||
*/
|
||||
protected $workspaceManager;
|
||||
|
||||
/**
|
||||
* The workspace information service.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceInformationInterface
|
||||
*/
|
||||
protected $workspaceInfo;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityAccess instance.
|
||||
*
|
||||
|
@ -40,10 +47,13 @@ class EntityAccess implements ContainerInjectionInterface {
|
|||
* The entity type manager service.
|
||||
* @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
|
||||
* The workspace manager service.
|
||||
* @param \Drupal\workspaces\WorkspaceInformationInterface $workspace_information
|
||||
* The workspace information service.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager) {
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager, WorkspaceInformationInterface $workspace_information) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
$this->workspaceInfo = $workspace_information;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,7 +62,8 @@ class EntityAccess implements ContainerInjectionInterface {
|
|||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('workspaces.manager')
|
||||
$container->get('workspaces.manager'),
|
||||
$container->get('workspaces.information')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -75,7 +86,7 @@ class EntityAccess implements ContainerInjectionInterface {
|
|||
// Workspaces themselves are handled by their own access handler and we
|
||||
// should not try to do any access checks for entity types that can not
|
||||
// belong to a workspace.
|
||||
if ($entity->getEntityTypeId() === 'workspace' || !$this->workspaceManager->isEntityTypeSupported($entity->getEntityType()) || !$this->workspaceManager->hasActiveWorkspace()) {
|
||||
if (!$this->workspaceInfo->isEntitySupported($entity) || !$this->workspaceManager->hasActiveWorkspace()) {
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
|
@ -102,7 +113,7 @@ class EntityAccess implements ContainerInjectionInterface {
|
|||
// should not try to do any access checks for entity types that can not
|
||||
// belong to a workspace.
|
||||
$entity_type = $this->entityTypeManager->getDefinition($context['entity_type_id']);
|
||||
if ($entity_type->id() === 'workspace' || !$this->workspaceManager->isEntityTypeSupported($entity_type) || !$this->workspaceManager->hasActiveWorkspace()) {
|
||||
if (!$this->workspaceInfo->isEntityTypeSupported($entity_type) || !$this->workspaceManager->hasActiveWorkspace()) {
|
||||
return AccessResult::neutral();
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ namespace Drupal\workspaces;
|
|||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Entity\RevisionableInterface;
|
||||
use Drupal\Core\Form\FormStateInterface;
|
||||
|
@ -42,6 +41,13 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
*/
|
||||
protected $workspaceAssociation;
|
||||
|
||||
/**
|
||||
* The workspace information service.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceInformationInterface
|
||||
*/
|
||||
protected $workspaceInfo;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityOperations instance.
|
||||
*
|
||||
|
@ -51,11 +57,14 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
* The workspace manager service.
|
||||
* @param \Drupal\workspaces\WorkspaceAssociationInterface $workspace_association
|
||||
* The workspace association service.
|
||||
* @param \Drupal\workspaces\WorkspaceInformationInterface $workspace_information
|
||||
* The workspace information service.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager, WorkspaceAssociationInterface $workspace_association) {
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager, WorkspaceAssociationInterface $workspace_association, WorkspaceInformationInterface $workspace_information) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
$this->workspaceAssociation = $workspace_association;
|
||||
$this->workspaceInfo = $workspace_information;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -65,7 +74,8 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
return new static(
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('workspaces.manager'),
|
||||
$container->get('workspaces.association')
|
||||
$container->get('workspaces.association'),
|
||||
$container->get('workspaces.information')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -77,9 +87,8 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
public function entityPreload(array $ids, $entity_type_id) {
|
||||
$entities = [];
|
||||
|
||||
// Only run if the entity type can belong to a workspace and we are in a
|
||||
// non-default workspace.
|
||||
if (!$this->workspaceManager->shouldAlterOperations($this->entityTypeManager->getDefinition($entity_type_id))) {
|
||||
$entity_type = $this->entityTypeManager->getDefinition($entity_type_id);
|
||||
if (!$this->workspaceInfo->isEntityTypeSupported($entity_type) || !$this->workspaceManager->hasActiveWorkspace()) {
|
||||
return $entities;
|
||||
}
|
||||
|
||||
|
@ -87,6 +96,11 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
// current active workspace. If an entity has multiple revisions set for a
|
||||
// workspace, only the one with the highest ID is returned.
|
||||
if ($tracked_entities = $this->workspaceAssociation->getTrackedEntities($this->workspaceManager->getActiveWorkspace()->id(), $entity_type_id, $ids)) {
|
||||
// Bail out early if there are no tracked entities of this type.
|
||||
if (!isset($tracked_entities[$entity_type_id])) {
|
||||
return $entities;
|
||||
}
|
||||
|
||||
/** @var \Drupal\Core\Entity\RevisionableStorageInterface $storage */
|
||||
$storage = $this->entityTypeManager->getStorage($entity_type_id);
|
||||
|
||||
|
@ -109,18 +123,13 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
* @see hook_entity_presave()
|
||||
*/
|
||||
public function entityPresave(EntityInterface $entity) {
|
||||
$entity_type = $entity->getEntityType();
|
||||
|
||||
// Only run if we are not dealing with an entity type provided by the
|
||||
// Workspaces module, an internal entity type or if we are in a non-default
|
||||
// workspace.
|
||||
if ($this->shouldSkipPreOperations($entity_type)) {
|
||||
if ($this->shouldSkipOperations($entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disallow any change to an unsupported entity when we are not in the
|
||||
// default workspace.
|
||||
if (!$this->workspaceManager->isEntityTypeSupported($entity_type)) {
|
||||
if (!$this->workspaceInfo->isEntitySupported($entity)) {
|
||||
throw new \RuntimeException('This entity can only be saved in the default workspace.');
|
||||
}
|
||||
|
||||
|
@ -140,7 +149,7 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
|
||||
// Track the workspaces in which the new revision was saved.
|
||||
if (!$entity->isSyncing()) {
|
||||
$field_name = $entity_type->getRevisionMetadataKey('workspace');
|
||||
$field_name = $entity->getEntityType()->getRevisionMetadataKey('workspace');
|
||||
$entity->{$field_name}->target_id = $this->workspaceManager->getActiveWorkspace()->id();
|
||||
}
|
||||
|
||||
|
@ -167,10 +176,7 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
* @see hook_entity_insert()
|
||||
*/
|
||||
public function entityInsert(EntityInterface $entity) {
|
||||
/** @var \Drupal\Core\Entity\RevisionableInterface|\Drupal\Core\Entity\EntityPublishedInterface $entity */
|
||||
// Only run if the entity type can belong to a workspace and we are in a
|
||||
// non-default workspace.
|
||||
if (!$this->workspaceManager->shouldAlterOperations($entity->getEntityType())) {
|
||||
if ($this->shouldSkipOperations($entity) || !$this->workspaceInfo->isEntitySupported($entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -202,9 +208,7 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
* @see hook_entity_update()
|
||||
*/
|
||||
public function entityUpdate(EntityInterface $entity) {
|
||||
// Only run if the entity type can belong to a workspace and we are in a
|
||||
// non-default workspace.
|
||||
if (!$this->workspaceManager->shouldAlterOperations($entity->getEntityType())) {
|
||||
if ($this->shouldSkipOperations($entity) || !$this->workspaceInfo->isEntitySupported($entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -224,18 +228,13 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
* @see hook_entity_predelete()
|
||||
*/
|
||||
public function entityPredelete(EntityInterface $entity) {
|
||||
$entity_type = $entity->getEntityType();
|
||||
|
||||
// Only run if we are not dealing with an entity type provided by the
|
||||
// Workspaces module, an internal entity type or if we are in a non-default
|
||||
// workspace.
|
||||
if ($this->shouldSkipPreOperations($entity_type)) {
|
||||
if ($this->shouldSkipOperations($entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Disallow any change to an unsupported entity when we are not in the
|
||||
// default workspace.
|
||||
if (!$this->workspaceManager->isEntityTypeSupported($entity_type)) {
|
||||
if (!$this->workspaceInfo->isEntitySupported($entity)) {
|
||||
throw new \RuntimeException('This entity can only be deleted in the default workspace.');
|
||||
}
|
||||
}
|
||||
|
@ -253,17 +252,21 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
* @see hook_form_alter()
|
||||
*/
|
||||
public function entityFormAlter(array &$form, FormStateInterface $form_state, $form_id) {
|
||||
/** @var \Drupal\Core\Entity\RevisionableInterface $entity */
|
||||
$entity = $form_state->getFormObject()->getEntity();
|
||||
if (!$this->workspaceManager->isEntityTypeSupported($entity->getEntityType())) {
|
||||
if (!$this->workspaceInfo->isEntitySupported($entity) && !$this->workspaceInfo->isEntityIgnored($entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For supported entity types, signal the fact that this form is safe to use
|
||||
// in a non-default workspace.
|
||||
// For supported and ignored entity types, signal the fact that this form is
|
||||
// safe to use in a workspace.
|
||||
// @see \Drupal\workspaces\FormOperations::validateForm()
|
||||
$form_state->set('workspace_safe', TRUE);
|
||||
|
||||
// There is nothing more to do for ignored entity types.
|
||||
if ($this->workspaceInfo->isEntityIgnored($entity)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Add an entity builder to the form which marks the edited entity object as
|
||||
// a pending revision. This is needed so validation constraints like
|
||||
// \Drupal\path\Plugin\Validation\Constraint\PathAliasConstraintValidator
|
||||
|
@ -295,23 +298,18 @@ class EntityOperations implements ContainerInjectionInterface {
|
|||
}
|
||||
|
||||
/**
|
||||
* Determines whether we need to react on pre-save or pre-delete operations.
|
||||
* Determines whether we need to react on entity operations.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type to check.
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity to check.
|
||||
*
|
||||
* @return bool
|
||||
* Returns TRUE if the pre-save or pre-delete entity operations should not
|
||||
* be altered in the current request, FALSE otherwise.
|
||||
* Returns TRUE if entity operations should not be altered, FALSE otherwise.
|
||||
*/
|
||||
protected function shouldSkipPreOperations(EntityTypeInterface $entity_type) {
|
||||
// We should not react on pre-save and pre-delete entity operations if one
|
||||
// of the following conditions are met:
|
||||
// - the entity type is provided by the Workspaces module;
|
||||
// - the entity type is internal, which means that it should not affect
|
||||
// anything in the default (Live) workspace;
|
||||
// - we are in the default workspace.
|
||||
return $entity_type->getProvider() === 'workspaces' || $entity_type->isInternal() || !$this->workspaceManager->hasActiveWorkspace();
|
||||
protected function shouldSkipOperations(EntityInterface $entity) {
|
||||
// We should not react on entity operations when the entity is ignored or
|
||||
// when we're not in a workspace context.
|
||||
return $this->workspaceInfo->isEntityIgnored($entity) || !$this->workspaceManager->hasActiveWorkspace();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,52 +2,11 @@
|
|||
|
||||
namespace Drupal\workspaces\EntityQuery;
|
||||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\Query\QueryBase;
|
||||
use Drupal\Core\Entity\Query\Sql\pgsql\QueryFactory as BaseQueryFactory;
|
||||
use Drupal\workspaces\WorkspaceManagerInterface;
|
||||
|
||||
/**
|
||||
* Workspaces PostgreSQL-specific entity query implementation.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class PgsqlQueryFactory extends BaseQueryFactory {
|
||||
|
||||
/**
|
||||
* The workspace manager.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceManagerInterface
|
||||
*/
|
||||
protected $workspaceManager;
|
||||
|
||||
/**
|
||||
* Constructs a PgsqlQueryFactory object.
|
||||
*
|
||||
* @param \Drupal\Core\Database\Connection $connection
|
||||
* The database connection used by the entity query.
|
||||
* @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
|
||||
* The workspace manager.
|
||||
*/
|
||||
public function __construct(Connection $connection, WorkspaceManagerInterface $workspace_manager) {
|
||||
$this->connection = $connection;
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
$this->namespaces = QueryBase::getNamespaces($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get(EntityTypeInterface $entity_type, $conjunction) {
|
||||
$class = QueryBase::getClass($this->namespaces, 'Query');
|
||||
return new $class($entity_type, $conjunction, $this->connection, $this->namespaces, $this->workspaceManager);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getAggregate(EntityTypeInterface $entity_type, $conjunction) {
|
||||
$class = QueryBase::getClass($this->namespaces, 'QueryAggregate');
|
||||
return new $class($entity_type, $conjunction, $this->connection, $this->namespaces, $this->workspaceManager);
|
||||
}
|
||||
class PgsqlQueryFactory extends QueryFactory {
|
||||
|
||||
}
|
||||
|
|
|
@ -6,34 +6,22 @@ use Drupal\Core\Database\Connection;
|
|||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\Query\QueryBase;
|
||||
use Drupal\Core\Entity\Query\Sql\QueryFactory as BaseQueryFactory;
|
||||
use Drupal\workspaces\WorkspaceInformationInterface;
|
||||
use Drupal\workspaces\WorkspaceManagerInterface;
|
||||
|
||||
/**
|
||||
* Workspaces-specific entity query implementation.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class QueryFactory extends BaseQueryFactory {
|
||||
|
||||
/**
|
||||
* The workspace manager.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceManagerInterface
|
||||
*/
|
||||
protected $workspaceManager;
|
||||
|
||||
/**
|
||||
* Constructs a QueryFactory object.
|
||||
*
|
||||
* Initializes the list of namespaces used to locate query
|
||||
* classes for different entity types.
|
||||
*
|
||||
* @param \Drupal\Core\Database\Connection $connection
|
||||
* The database connection used by the entity query.
|
||||
* @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
|
||||
* The workspace manager.
|
||||
*/
|
||||
public function __construct(Connection $connection, WorkspaceManagerInterface $workspace_manager) {
|
||||
public function __construct(
|
||||
Connection $connection,
|
||||
protected readonly WorkspaceManagerInterface $workspaceManager,
|
||||
protected readonly WorkspaceInformationInterface $workspaceInfo
|
||||
) {
|
||||
$this->connection = $connection;
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
$this->namespaces = QueryBase::getNamespaces($this);
|
||||
}
|
||||
|
||||
|
@ -42,7 +30,7 @@ class QueryFactory extends BaseQueryFactory {
|
|||
*/
|
||||
public function get(EntityTypeInterface $entity_type, $conjunction) {
|
||||
$class = QueryBase::getClass($this->namespaces, 'Query');
|
||||
return new $class($entity_type, $conjunction, $this->connection, $this->namespaces, $this->workspaceManager);
|
||||
return new $class($entity_type, $conjunction, $this->connection, $this->namespaces, $this->workspaceManager, $this->workspaceInfo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,7 +38,7 @@ class QueryFactory extends BaseQueryFactory {
|
|||
*/
|
||||
public function getAggregate(EntityTypeInterface $entity_type, $conjunction) {
|
||||
$class = QueryBase::getClass($this->namespaces, 'QueryAggregate');
|
||||
return new $class($entity_type, $conjunction, $this->connection, $this->namespaces, $this->workspaceManager);
|
||||
return new $class($entity_type, $conjunction, $this->connection, $this->namespaces, $this->workspaceManager, $this->workspaceInfo);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,10 +4,13 @@ namespace Drupal\workspaces\EntityQuery;
|
|||
|
||||
use Drupal\Core\Database\Connection;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\workspaces\WorkspaceInformationInterface;
|
||||
use Drupal\workspaces\WorkspaceManagerInterface;
|
||||
|
||||
/**
|
||||
* Provides workspaces-specific helpers for altering entity queries.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
trait QueryTrait {
|
||||
|
||||
|
@ -18,6 +21,13 @@ trait QueryTrait {
|
|||
*/
|
||||
protected $workspaceManager;
|
||||
|
||||
/**
|
||||
* The workspace information service.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceInformationInterface
|
||||
*/
|
||||
protected $workspaceInfo;
|
||||
|
||||
/**
|
||||
* Constructs a Query object.
|
||||
*
|
||||
|
@ -32,11 +42,14 @@ trait QueryTrait {
|
|||
* List of potential namespaces of the classes belonging to this query.
|
||||
* @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
|
||||
* The workspace manager.
|
||||
* @param \Drupal\workspaces\WorkspaceInformationInterface $workspace_information
|
||||
* The workspace information service.
|
||||
*/
|
||||
public function __construct(EntityTypeInterface $entity_type, $conjunction, Connection $connection, array $namespaces, WorkspaceManagerInterface $workspace_manager) {
|
||||
public function __construct(EntityTypeInterface $entity_type, $conjunction, Connection $connection, array $namespaces, WorkspaceManagerInterface $workspace_manager, WorkspaceInformationInterface $workspace_information) {
|
||||
parent::__construct($entity_type, $conjunction, $connection, $namespaces);
|
||||
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
$this->workspaceInfo = $workspace_information;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -54,7 +67,7 @@ trait QueryTrait {
|
|||
|
||||
// Only alter the query if the active workspace is not the default one and
|
||||
// the entity type is supported.
|
||||
if ($this->workspaceManager->isEntityTypeSupported($this->entityType) && $this->workspaceManager->hasActiveWorkspace()) {
|
||||
if ($this->workspaceInfo->isEntityTypeSupported($this->entityType) && $this->workspaceManager->hasActiveWorkspace()) {
|
||||
$active_workspace = $this->workspaceManager->getActiveWorkspace();
|
||||
$this->sqlQuery->addMetaData('active_workspace_id', $active_workspace->id());
|
||||
$this->sqlQuery->addMetaData('simple_query', FALSE);
|
||||
|
|
|
@ -13,11 +13,11 @@ use Drupal\Core\Field\FieldStorageDefinitionInterface;
|
|||
class Tables extends BaseTables {
|
||||
|
||||
/**
|
||||
* The workspace manager.
|
||||
* The workspace information service.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceManagerInterface
|
||||
* @var \Drupal\workspaces\WorkspaceInformationInterface
|
||||
*/
|
||||
protected $workspaceManager;
|
||||
protected $workspaceInfo;
|
||||
|
||||
/**
|
||||
* Workspace association table array, key is base table name, value is alias.
|
||||
|
@ -42,7 +42,7 @@ class Tables extends BaseTables {
|
|||
public function __construct(SelectInterface $sql_query) {
|
||||
parent::__construct($sql_query);
|
||||
|
||||
$this->workspaceManager = \Drupal::service('workspaces.manager');
|
||||
$this->workspaceInfo = \Drupal::service('workspaces.information');
|
||||
|
||||
// The join between the first 'workspace_association' table and base table
|
||||
// of the query is done in
|
||||
|
@ -117,7 +117,7 @@ class Tables extends BaseTables {
|
|||
$next_base_table_alias = parent::addNextBaseTable($entity_type, $table, $sql_column, $field_storage);
|
||||
|
||||
$active_workspace_id = $this->sqlQuery->getMetaData('active_workspace_id');
|
||||
if ($active_workspace_id && $this->workspaceManager->isEntityTypeSupported($entity_type)) {
|
||||
if ($active_workspace_id && $this->workspaceInfo->isEntityTypeSupported($entity_type)) {
|
||||
$this->addWorkspaceAssociationJoin($entity_type->id(), $next_base_table_alias, $active_workspace_id);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,10 +3,13 @@
|
|||
namespace Drupal\workspaces;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityPublishedInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\StringTranslation\TranslatableMarkup;
|
||||
use Drupal\workspaces\Entity\Handler\BlockContentWorkspaceHandler;
|
||||
use Drupal\workspaces\Entity\Handler\DefaultWorkspaceHandler;
|
||||
use Drupal\workspaces\Entity\Handler\IgnoredWorkspaceHandler;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
|
||||
/**
|
||||
|
@ -19,31 +22,9 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
|||
*/
|
||||
class EntityTypeInfo implements ContainerInjectionInterface {
|
||||
|
||||
/**
|
||||
* The entity type manager service.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The workspace manager service.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceManagerInterface
|
||||
*/
|
||||
protected $workspaceManager;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityTypeInfo instance.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
|
||||
* The entity type manager service.
|
||||
* @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
|
||||
* The workspace manager service.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, WorkspaceManagerInterface $workspace_manager) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
public function __construct(
|
||||
protected readonly WorkspaceInformationInterface $workspaceInfo
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,13 +32,12 @@ class EntityTypeInfo implements ContainerInjectionInterface {
|
|||
*/
|
||||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('workspaces.manager')
|
||||
$container->get('workspaces.information')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the "EntityWorkspaceConflict" constraint to eligible entity types.
|
||||
* Adds workspace support info to eligible entity types.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
|
||||
* An associative array of all entity type definitions, keyed by the entity
|
||||
|
@ -67,15 +47,31 @@ class EntityTypeInfo implements ContainerInjectionInterface {
|
|||
*/
|
||||
public function entityTypeBuild(array &$entity_types) {
|
||||
foreach ($entity_types as $entity_type) {
|
||||
if ($this->workspaceManager->isEntityTypeSupported($entity_type)) {
|
||||
$entity_type->addConstraint('EntityWorkspaceConflict');
|
||||
$entity_type->setRevisionMetadataKey('workspace', 'workspace');
|
||||
if ($entity_type->hasHandlerClass('workspace')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Revisionable and publishable entity types are always supported.
|
||||
if ($entity_type->entityClassImplements(EntityPublishedInterface::class) && $entity_type->isRevisionable()) {
|
||||
$entity_type->setHandlerClass('workspace', DefaultWorkspaceHandler::class);
|
||||
|
||||
// Support for custom blocks has to be determined on a per-entity
|
||||
// basis.
|
||||
if ($entity_type->id() === 'block_content') {
|
||||
$entity_type->setHandlerClass('workspace', BlockContentWorkspaceHandler::class);
|
||||
}
|
||||
}
|
||||
|
||||
// Internal entity types are allowed to perform CRUD operations inside a
|
||||
// workspace.
|
||||
if ($entity_type->isInternal()) {
|
||||
$entity_type->setHandlerClass('workspace', IgnoredWorkspaceHandler::class);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the 'latest-version' link template provided by Content Moderation.
|
||||
* Adds Workspace configuration to appropriate entity types.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface[] $entity_types
|
||||
* An array of entity types.
|
||||
|
@ -84,6 +80,16 @@ class EntityTypeInfo implements ContainerInjectionInterface {
|
|||
*/
|
||||
public function entityTypeAlter(array &$entity_types) {
|
||||
foreach ($entity_types as $entity_type) {
|
||||
if (!$this->workspaceInfo->isEntityTypeSupported($entity_type)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Workspace-support status has been declared in the "build" phase, now we
|
||||
// can use that information and add additional configuration in the
|
||||
// "alter" phase.
|
||||
$entity_type->addConstraint('EntityWorkspaceConflict');
|
||||
$entity_type->setRevisionMetadataKey('workspace', 'workspace');
|
||||
|
||||
// Non-default workspaces display the active revision on the canonical
|
||||
// route of an entity, so the latest version route is no longer needed.
|
||||
$link_templates = $entity_type->get('links');
|
||||
|
@ -123,7 +129,7 @@ class EntityTypeInfo implements ContainerInjectionInterface {
|
|||
* @see hook_entity_base_field_info()
|
||||
*/
|
||||
public function entityBaseFieldInfo(EntityTypeInterface $entity_type) {
|
||||
if ($this->workspaceManager->isEntityTypeSupported($entity_type)) {
|
||||
if ($this->workspaceInfo->isEntityTypeSupported($entity_type)) {
|
||||
$field_name = $entity_type->getRevisionMetadataKey('workspace');
|
||||
$fields[$field_name] = BaseFieldDefinition::create('entity_reference')
|
||||
->setLabel(new TranslatableMarkup('Workspace'))
|
||||
|
|
|
@ -9,7 +9,7 @@ use Drupal\Core\Entity\EntityTypeInterface;
|
|||
use Drupal\Core\Entity\EntityTypeListenerInterface;
|
||||
use Drupal\Core\Field\BaseFieldDefinition;
|
||||
use Drupal\Core\StringTranslation\StringTranslationTrait;
|
||||
use Drupal\workspaces\WorkspaceManagerInterface;
|
||||
use Drupal\workspaces\WorkspaceInformationInterface;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
/**
|
||||
|
@ -35,11 +35,11 @@ class EntitySchemaSubscriber implements EntityTypeListenerInterface, EventSubscr
|
|||
protected $entityLastInstalledSchemaRepository;
|
||||
|
||||
/**
|
||||
* The workspace manager.
|
||||
* The workspace information service.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceManagerInterface
|
||||
* @var \Drupal\workspaces\WorkspaceInformationInterface
|
||||
*/
|
||||
protected $workspaceManager;
|
||||
protected $workspaceInfo;
|
||||
|
||||
/**
|
||||
* Constructs a new EntitySchemaSubscriber.
|
||||
|
@ -48,13 +48,13 @@ class EntitySchemaSubscriber implements EntityTypeListenerInterface, EventSubscr
|
|||
* Definition update manager.
|
||||
* @param \Drupal\Core\Entity\EntityLastInstalledSchemaRepositoryInterface $entityLastInstalledSchemaRepository
|
||||
* Last definitions.
|
||||
* @param \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager
|
||||
* The workspace manager.
|
||||
* @param \Drupal\workspaces\WorkspaceInformationInterface $workspace_information
|
||||
* The workspace information service.
|
||||
*/
|
||||
public function __construct(EntityDefinitionUpdateManagerInterface $entityDefinitionUpdateManager, EntityLastInstalledSchemaRepositoryInterface $entityLastInstalledSchemaRepository, WorkspaceManagerInterface $workspace_manager) {
|
||||
public function __construct(EntityDefinitionUpdateManagerInterface $entityDefinitionUpdateManager, EntityLastInstalledSchemaRepositoryInterface $entityLastInstalledSchemaRepository, WorkspaceInformationInterface $workspace_information) {
|
||||
$this->entityDefinitionUpdateManager = $entityDefinitionUpdateManager;
|
||||
$this->entityLastInstalledSchemaRepository = $entityLastInstalledSchemaRepository;
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
$this->workspaceInfo = $workspace_information;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -70,7 +70,7 @@ class EntitySchemaSubscriber implements EntityTypeListenerInterface, EventSubscr
|
|||
public function onEntityTypeCreate(EntityTypeInterface $entity_type) {
|
||||
// If the entity type is supported by Workspaces, add the revision metadata
|
||||
// field.
|
||||
if ($this->workspaceManager->isEntityTypeSupported($entity_type)) {
|
||||
if ($this->workspaceInfo->isEntityTypeSupported($entity_type)) {
|
||||
$this->addRevisionMetadataField($entity_type);
|
||||
}
|
||||
}
|
||||
|
@ -88,13 +88,13 @@ class EntitySchemaSubscriber implements EntityTypeListenerInterface, EventSubscr
|
|||
public function onEntityTypeUpdate(EntityTypeInterface $entity_type, EntityTypeInterface $original) {
|
||||
// If the entity type is now supported by Workspaces, add the revision
|
||||
// metadata field.
|
||||
if ($this->workspaceManager->isEntityTypeSupported($entity_type) && !$this->workspaceManager->isEntityTypeSupported($original)) {
|
||||
if ($this->workspaceInfo->isEntityTypeSupported($entity_type) && !$this->workspaceInfo->isEntityTypeSupported($original)) {
|
||||
$this->addRevisionMetadataField($entity_type);
|
||||
}
|
||||
|
||||
// If the entity type is no longer supported by Workspaces, remove the
|
||||
// revision metadata field.
|
||||
if ($this->workspaceManager->isEntityTypeSupported($original) && !$this->workspaceManager->isEntityTypeSupported($entity_type)) {
|
||||
if ($this->workspaceInfo->isEntityTypeSupported($original) && !$this->workspaceInfo->isEntityTypeSupported($entity_type)) {
|
||||
$revision_metadata_keys = $original->get('revision_metadata_keys');
|
||||
$field_storage_definition = $this->entityLastInstalledSchemaRepository->getLastInstalledFieldStorageDefinitions($entity_type->id())[$revision_metadata_keys['workspace']];
|
||||
$this->entityDefinitionUpdateManager->uninstallFieldStorageDefinition($field_storage_definition);
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace Drupal\workspaces\Plugin\Validation\Constraint;
|
|||
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\workspaces\WorkspaceInformationInterface;
|
||||
use Drupal\workspaces\WorkspaceManagerInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\Validator\Constraint;
|
||||
|
@ -28,12 +29,20 @@ class EntityReferenceSupportedNewEntitiesConstraintValidator extends ConstraintV
|
|||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The workspace information service.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceInformationInterface
|
||||
*/
|
||||
protected $workspaceInfo;
|
||||
|
||||
/**
|
||||
* Creates a new EntityReferenceSupportedNewEntitiesConstraintValidator instance.
|
||||
*/
|
||||
public function __construct(WorkspaceManagerInterface $workspaceManager, EntityTypeManagerInterface $entityTypeManager) {
|
||||
public function __construct(WorkspaceManagerInterface $workspaceManager, EntityTypeManagerInterface $entityTypeManager, WorkspaceInformationInterface $workspace_information) {
|
||||
$this->workspaceManager = $workspaceManager;
|
||||
$this->entityTypeManager = $entityTypeManager;
|
||||
$this->workspaceInfo = $workspace_information;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,7 +51,8 @@ class EntityReferenceSupportedNewEntitiesConstraintValidator extends ConstraintV
|
|||
public static function create(ContainerInterface $container) {
|
||||
return new static(
|
||||
$container->get('workspaces.manager'),
|
||||
$container->get('entity_type.manager')
|
||||
$container->get('entity_type.manager'),
|
||||
$container->get('workspaces.information')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -58,7 +68,7 @@ class EntityReferenceSupportedNewEntitiesConstraintValidator extends ConstraintV
|
|||
$target_entity_type_id = $value->getFieldDefinition()->getFieldStorageDefinition()->getSetting('target_type');
|
||||
$target_entity_type = $this->entityTypeManager->getDefinition($target_entity_type_id);
|
||||
|
||||
if ($value->hasNewEntity() && !$this->workspaceManager->isEntityTypeSupported($target_entity_type)) {
|
||||
if ($value->hasNewEntity() && !$this->workspaceInfo->isEntityTypeSupported($target_entity_type)) {
|
||||
$this->context->addViolation($constraint->message, ['%collection_label' => $target_entity_type->getCollectionLabel()]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,13 @@ class ViewsQueryAlter implements ContainerInjectionInterface {
|
|||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The workspace information service.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceInformationInterface
|
||||
*/
|
||||
protected WorkspaceInformationInterface $workspaceInfo;
|
||||
|
||||
/**
|
||||
* An array of tables adjusted for workspace_association join.
|
||||
*
|
||||
|
@ -85,14 +92,17 @@ class ViewsQueryAlter implements ContainerInjectionInterface {
|
|||
* The views join plugin manager.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\workspaces\WorkspaceInformationInterface $workspace_information
|
||||
* The workspace information service.
|
||||
*/
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, WorkspaceManagerInterface $workspace_manager, ViewsData $views_data, ViewsHandlerManager $views_join_plugin_manager, LanguageManagerInterface $language_manager) {
|
||||
public function __construct(EntityTypeManagerInterface $entity_type_manager, EntityFieldManagerInterface $entity_field_manager, WorkspaceManagerInterface $workspace_manager, ViewsData $views_data, ViewsHandlerManager $views_join_plugin_manager, LanguageManagerInterface $language_manager, WorkspaceInformationInterface $workspace_information) {
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->entityFieldManager = $entity_field_manager;
|
||||
$this->workspaceManager = $workspace_manager;
|
||||
$this->viewsData = $views_data;
|
||||
$this->viewsJoinPluginManager = $views_join_plugin_manager;
|
||||
$this->languageManager = $language_manager;
|
||||
$this->workspaceInfo = $workspace_information;
|
||||
$this->adjustedTables = new \WeakMap();
|
||||
}
|
||||
|
||||
|
@ -106,7 +116,8 @@ class ViewsQueryAlter implements ContainerInjectionInterface {
|
|||
$container->get('workspaces.manager'),
|
||||
$container->get('views.views_data'),
|
||||
$container->get('plugin.manager.views.join'),
|
||||
$container->get('language_manager')
|
||||
$container->get('language_manager'),
|
||||
$container->get('workspaces.information')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -140,7 +151,7 @@ class ViewsQueryAlter implements ContainerInjectionInterface {
|
|||
|
||||
$entity_type_definitions = $this->entityTypeManager->getDefinitions();
|
||||
foreach ($entity_type_ids as $entity_type_id) {
|
||||
if ($this->workspaceManager->isEntityTypeSupported($entity_type_definitions[$entity_type_id])) {
|
||||
if ($this->workspaceInfo->isEntityTypeSupported($entity_type_definitions[$entity_type_id])) {
|
||||
$this->alterQueryForEntityType($query, $entity_type_definitions[$entity_type_id]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,111 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workspaces;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityPublishedInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\workspaces\Entity\Handler\IgnoredWorkspaceHandler;
|
||||
|
||||
/**
|
||||
* General service for workspace support information.
|
||||
*/
|
||||
class WorkspaceInformation implements WorkspaceInformationInterface {
|
||||
|
||||
/**
|
||||
* An array of workspace-support statuses, keyed by entity type ID.
|
||||
*
|
||||
* @var bool[]
|
||||
*/
|
||||
protected array $supported = [];
|
||||
|
||||
/**
|
||||
* An array of workspace-ignored statuses, keyed by entity type ID.
|
||||
*
|
||||
* @var bool[]
|
||||
*/
|
||||
protected array $ignored = [];
|
||||
|
||||
public function __construct(
|
||||
protected readonly EntityTypeManagerInterface $entityTypeManager
|
||||
) {}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEntitySupported(EntityInterface $entity): bool {
|
||||
$entity_type = $entity->getEntityType();
|
||||
|
||||
if (!$this->isEntityTypeSupported($entity_type)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
$handler = $this->entityTypeManager->getHandler($entity_type->id(), 'workspace');
|
||||
return $handler->isEntitySupported($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEntityTypeSupported(EntityTypeInterface $entity_type): bool {
|
||||
if (!isset($this->supported[$entity_type->id()])) {
|
||||
if ($entity_type->hasHandlerClass('workspace')) {
|
||||
$supported = !is_a($entity_type->getHandlerClass('workspace'), IgnoredWorkspaceHandler::class, TRUE);
|
||||
}
|
||||
else {
|
||||
// Fallback for cases when entity type info hasn't been altered yet, for
|
||||
// example when the Workspaces module is being installed.
|
||||
$supported = $entity_type->entityClassImplements(EntityPublishedInterface::class) && $entity_type->isRevisionable();
|
||||
}
|
||||
|
||||
$this->supported[$entity_type->id()] = $supported;
|
||||
}
|
||||
|
||||
return $this->supported[$entity_type->id()];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSupportedEntityTypes(): array {
|
||||
$entity_types = [];
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
|
||||
if ($this->isEntityTypeSupported($entity_type)) {
|
||||
$entity_types[$entity_type_id] = $entity_type;
|
||||
}
|
||||
}
|
||||
return $entity_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEntityIgnored(EntityInterface $entity): bool {
|
||||
$entity_type = $entity->getEntityType();
|
||||
|
||||
if ($this->isEntityTypeIgnored($entity_type)) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ($entity_type->hasHandlerClass('workspace')) {
|
||||
$handler = $this->entityTypeManager->getHandler($entity_type->id(), 'workspace');
|
||||
return !$handler->isEntitySupported($entity);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEntityTypeIgnored(EntityTypeInterface $entity_type): bool {
|
||||
if (!isset($this->ignored[$entity_type->id()])) {
|
||||
$this->ignored[$entity_type->id()] = $entity_type->hasHandlerClass('workspace')
|
||||
&& is_a($entity_type->getHandlerClass('workspace'), IgnoredWorkspaceHandler::class, TRUE);
|
||||
}
|
||||
|
||||
return $this->ignored[$entity_type->id()];
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workspaces;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
|
||||
/**
|
||||
* Provides an interface for workspace-support information.
|
||||
*/
|
||||
interface WorkspaceInformationInterface {
|
||||
|
||||
/**
|
||||
* Determines whether an entity can belong to a workspace.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the entity can belong to a workspace, FALSE otherwise.
|
||||
*/
|
||||
public function isEntitySupported(EntityInterface $entity): bool;
|
||||
|
||||
/**
|
||||
* Determines whether an entity type can belong to a workspace.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the entity type can belong to a workspace, FALSE otherwise.
|
||||
*/
|
||||
public function isEntityTypeSupported(EntityTypeInterface $entity_type): bool;
|
||||
|
||||
/**
|
||||
* Returns an array of entity types that can belong to workspaces.
|
||||
*
|
||||
* @return \Drupal\Core\Entity\EntityTypeInterface[]
|
||||
* An array of entity type definition objects.
|
||||
*/
|
||||
public function getSupportedEntityTypes(): array;
|
||||
|
||||
/**
|
||||
* Determines whether CRUD operations for an entity are allowed.
|
||||
*
|
||||
* CRUD operations for an ignored entity are allowed in a workspace, but their
|
||||
* revisions are not tracked.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityInterface $entity
|
||||
* The entity to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if CRUD operations of an entity type can safely be done inside a
|
||||
* workspace, without impacting the Live site, FALSE otherwise.
|
||||
*/
|
||||
public function isEntityIgnored(EntityInterface $entity): bool;
|
||||
|
||||
/**
|
||||
* Determines whether CRUD operations for an entity type are allowed.
|
||||
*
|
||||
* CRUD operations for an ignored entity type are allowed in a workspace, but
|
||||
* their revisions are not tracked.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
|
||||
* The entity type to check.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if CRUD operations of an entity type can safely be done inside a
|
||||
* workspace, without impacting the Live site, FALSE otherwise.
|
||||
*/
|
||||
public function isEntityTypeIgnored(EntityTypeInterface $entity_type): bool;
|
||||
|
||||
}
|
|
@ -4,7 +4,6 @@ namespace Drupal\workspaces;
|
|||
|
||||
use Drupal\Core\Cache\MemoryCache\MemoryCacheInterface;
|
||||
use Drupal\Core\DependencyInjection\ClassResolverInterface;
|
||||
use Drupal\Core\Entity\EntityPublishedInterface;
|
||||
use Drupal\Core\Entity\EntityTypeInterface;
|
||||
use Drupal\Core\Entity\EntityTypeManagerInterface;
|
||||
use Drupal\Core\Session\AccountProxyInterface;
|
||||
|
@ -21,15 +20,6 @@ class WorkspaceManager implements WorkspaceManagerInterface {
|
|||
|
||||
use StringTranslationTrait;
|
||||
|
||||
/**
|
||||
* An array of which entity types are supported.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $supported = [
|
||||
'workspace' => FALSE,
|
||||
];
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
*
|
||||
|
@ -86,6 +76,13 @@ class WorkspaceManager implements WorkspaceManagerInterface {
|
|||
*/
|
||||
protected $workspaceAssociation;
|
||||
|
||||
/**
|
||||
* The workspace information service.
|
||||
*
|
||||
* @var \Drupal\workspaces\WorkspaceInformationInterface
|
||||
*/
|
||||
protected WorkspaceInformationInterface $workspaceInfo;
|
||||
|
||||
/**
|
||||
* The workspace negotiator service IDs.
|
||||
*
|
||||
|
@ -119,10 +116,12 @@ class WorkspaceManager implements WorkspaceManagerInterface {
|
|||
* The class resolver.
|
||||
* @param \Drupal\workspaces\WorkspaceAssociationInterface $workspace_association
|
||||
* The workspace association service.
|
||||
* @param array $negotiator_ids
|
||||
* @param \Drupal\workspaces\WorkspaceInformationInterface|null $workspace_information
|
||||
* The workspace information service.
|
||||
* @param array|null $negotiator_ids
|
||||
* The workspace negotiator service IDs.
|
||||
*/
|
||||
public function __construct(RequestStack $request_stack, EntityTypeManagerInterface $entity_type_manager, MemoryCacheInterface $entity_memory_cache, AccountProxyInterface $current_user, StateInterface $state, LoggerInterface $logger, ClassResolverInterface $class_resolver, WorkspaceAssociationInterface $workspace_association, array $negotiator_ids) {
|
||||
public function __construct(RequestStack $request_stack, EntityTypeManagerInterface $entity_type_manager, MemoryCacheInterface $entity_memory_cache, AccountProxyInterface $current_user, StateInterface $state, LoggerInterface $logger, ClassResolverInterface $class_resolver, WorkspaceAssociationInterface $workspace_association, protected ?WorkspaceInformationInterface $workspace_information = NULL, array $negotiator_ids = NULL) {
|
||||
$this->requestStack = $request_stack;
|
||||
$this->entityTypeManager = $entity_type_manager;
|
||||
$this->entityMemoryCache = $entity_memory_cache;
|
||||
|
@ -131,33 +130,34 @@ class WorkspaceManager implements WorkspaceManagerInterface {
|
|||
$this->logger = $logger;
|
||||
$this->classResolver = $class_resolver;
|
||||
$this->workspaceAssociation = $workspace_association;
|
||||
$this->negotiatorIds = $negotiator_ids;
|
||||
|
||||
if (!$workspace_information instanceof WorkspaceInformationInterface) {
|
||||
@trigger_error('Calling ' . __METHOD__ . '() without the $workspace_information argument is deprecated in drupal:10.3.0 and will be required in drupal:11.0.0. See https://www.drupal.org/node/3324297', E_USER_DEPRECATED);
|
||||
$this->workspaceInfo = \Drupal::service('workspaces.information');
|
||||
|
||||
// The negotiator IDs are always the last constructor argument.
|
||||
$this->negotiatorIds = $workspace_information;
|
||||
}
|
||||
else {
|
||||
$this->workspaceInfo = $workspace_information;
|
||||
$this->negotiatorIds = $negotiator_ids;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEntityTypeSupported(EntityTypeInterface $entity_type) {
|
||||
$entity_type_id = $entity_type->id();
|
||||
if (!isset($this->supported[$entity_type_id])) {
|
||||
// Only entity types which are revisionable and publishable can belong
|
||||
// to a workspace.
|
||||
$this->supported[$entity_type_id] = $entity_type->entityClassImplements(EntityPublishedInterface::class) && $entity_type->isRevisionable();
|
||||
}
|
||||
return $this->supported[$entity_type_id];
|
||||
@trigger_error(__METHOD__ . '() is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use \Drupal\workspaces\WorkspaceInformation::isEntityTypeSupported instead. See https://www.drupal.org/node/3324297', E_USER_DEPRECATED);
|
||||
return $this->workspaceInfo->isEntityTypeSupported($entity_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSupportedEntityTypes() {
|
||||
$entity_types = [];
|
||||
foreach ($this->entityTypeManager->getDefinitions() as $entity_type_id => $entity_type) {
|
||||
if ($this->isEntityTypeSupported($entity_type)) {
|
||||
$entity_types[$entity_type_id] = $entity_type;
|
||||
}
|
||||
}
|
||||
return $entity_types;
|
||||
@trigger_error(__METHOD__ . '() is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use \Drupal\workspaces\WorkspaceInformation::getSupportedEntityTypes instead. See https://www.drupal.org/node/3324297', E_USER_DEPRECATED);
|
||||
return $this->workspaceInfo->getSupportedEntityTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -254,7 +254,7 @@ class WorkspaceManager implements WorkspaceManagerInterface {
|
|||
// Clear the static entity cache for the supported entity types.
|
||||
$cache_tags_to_invalidate = array_map(function ($entity_type_id) {
|
||||
return 'entity.memory_cache:' . $entity_type_id;
|
||||
}, array_keys($this->getSupportedEntityTypes()));
|
||||
}, array_keys($this->workspaceInfo->getSupportedEntityTypes()));
|
||||
$this->entityMemoryCache->invalidateTags($cache_tags_to_invalidate);
|
||||
|
||||
// Clear the static cache for path aliases. We can't inject the path alias
|
||||
|
@ -297,7 +297,8 @@ class WorkspaceManager implements WorkspaceManagerInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function shouldAlterOperations(EntityTypeInterface $entity_type) {
|
||||
return $this->isEntityTypeSupported($entity_type) && $this->hasActiveWorkspace();
|
||||
@trigger_error(__METHOD__ . '() is deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. There is no replacement. See https://www.drupal.org/node/3324297', E_USER_DEPRECATED);
|
||||
return $this->workspaceInfo->isEntityTypeSupported($entity_type) && $this->hasActiveWorkspace();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -318,7 +319,7 @@ class WorkspaceManager implements WorkspaceManagerInterface {
|
|||
$workspace_id = reset($deleted_workspace_ids);
|
||||
|
||||
$all_associated_revisions = [];
|
||||
foreach (array_keys($this->getSupportedEntityTypes()) as $entity_type_id) {
|
||||
foreach (array_keys($this->workspaceInfo->getSupportedEntityTypes()) as $entity_type_id) {
|
||||
$all_associated_revisions[$entity_type_id] = $this->workspaceAssociation->getAssociatedRevisions($workspace_id, $entity_type_id);
|
||||
}
|
||||
$all_associated_revisions = array_filter($all_associated_revisions);
|
||||
|
@ -359,7 +360,7 @@ class WorkspaceManager implements WorkspaceManagerInterface {
|
|||
// request a fresh list of tracked entities. If it is empty, we can go ahead
|
||||
// and remove the deleted workspace ID entry from state.
|
||||
$has_associated_revisions = FALSE;
|
||||
foreach (array_keys($this->getSupportedEntityTypes()) as $entity_type_id) {
|
||||
foreach (array_keys($this->workspaceInfo->getSupportedEntityTypes()) as $entity_type_id) {
|
||||
if (!empty($this->workspaceAssociation->getAssociatedRevisions($workspace_id, $entity_type_id))) {
|
||||
$has_associated_revisions = TRUE;
|
||||
break;
|
||||
|
|
|
@ -17,6 +17,11 @@ interface WorkspaceManagerInterface {
|
|||
*
|
||||
* @return bool
|
||||
* TRUE if the entity type can belong to a workspace, FALSE otherwise.
|
||||
*
|
||||
* @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use
|
||||
* \Drupal\workspaces\WorkspaceInformation::isEntityTypeSupported instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/3324297
|
||||
*/
|
||||
public function isEntityTypeSupported(EntityTypeInterface $entity_type);
|
||||
|
||||
|
@ -25,6 +30,11 @@ interface WorkspaceManagerInterface {
|
|||
*
|
||||
* @return \Drupal\Core\Entity\EntityTypeInterface[]
|
||||
* The entity types what can belong to workspaces.
|
||||
*
|
||||
* @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. Use
|
||||
* \Drupal\workspaces\WorkspaceInformation::getSupportedEntityTypes instead.
|
||||
*
|
||||
* @see https://www.drupal.org/node/3324297
|
||||
*/
|
||||
public function getSupportedEntityTypes();
|
||||
|
||||
|
@ -97,6 +107,11 @@ interface WorkspaceManagerInterface {
|
|||
* @return bool
|
||||
* TRUE if the entity operations or queries should be altered in the current
|
||||
* request, FALSE otherwise.
|
||||
*
|
||||
* @deprecated in drupal:10.3.0 and is removed from drupal:11.0.0. There is no
|
||||
* replacement.
|
||||
*
|
||||
* @see https://www.drupal.org/node/3324297
|
||||
*/
|
||||
public function shouldAlterOperations(EntityTypeInterface $entity_type);
|
||||
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\workspaces_test;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\workspaces\Entity\Handler\DefaultWorkspaceHandler;
|
||||
|
||||
/**
|
||||
* Provides a custom workspace handler for testing purposes.
|
||||
*/
|
||||
class EntityTestRevPubWorkspaceHandler extends DefaultWorkspaceHandler {
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isEntitySupported(EntityInterface $entity): bool {
|
||||
return $entity->bundle() !== 'ignored_bundle';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
name: 'Workspace Test'
|
||||
type: module
|
||||
description: 'Provides supporting code for testing workspaces.'
|
||||
package: Testing
|
||||
version: VERSION
|
||||
dependencies:
|
||||
- drupal:workspaces
|
|
@ -0,0 +1,178 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\Tests\workspaces\Kernel;
|
||||
|
||||
use Drupal\Core\Entity\EntityStorageException;
|
||||
use Drupal\KernelTests\KernelTestBase;
|
||||
use Drupal\Tests\user\Traits\UserCreationTrait;
|
||||
use Drupal\workspaces\Entity\Handler\IgnoredWorkspaceHandler;
|
||||
use Drupal\workspaces\Entity\Workspace;
|
||||
use Drupal\workspaces_test\EntityTestRevPubWorkspaceHandler;
|
||||
|
||||
/**
|
||||
* Tests the workspace information service.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\workspaces\WorkspaceInformation
|
||||
*
|
||||
* @group workspaces
|
||||
*/
|
||||
class WorkspaceInformationTest extends KernelTestBase {
|
||||
|
||||
use UserCreationTrait;
|
||||
use WorkspaceTestTrait;
|
||||
|
||||
/**
|
||||
* The entity type manager.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityTypeManagerInterface
|
||||
*/
|
||||
protected $entityTypeManager;
|
||||
|
||||
/**
|
||||
* The workspace information service.
|
||||
*
|
||||
* @var \Drupal\wse\Core\WorkspaceInformationInterface
|
||||
*/
|
||||
protected $workspaceInformation;
|
||||
|
||||
/**
|
||||
* The state store.
|
||||
*
|
||||
* @var \Drupal\Core\State\StateInterface
|
||||
*/
|
||||
protected $state;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected static $modules = [
|
||||
'entity_test',
|
||||
'path_alias',
|
||||
'user',
|
||||
'workspaces',
|
||||
'workspaces_test',
|
||||
];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->entityTypeManager = \Drupal::entityTypeManager();
|
||||
$this->workspaceInformation = \Drupal::service('workspaces.information');
|
||||
$this->state = \Drupal::state();
|
||||
|
||||
$this->installEntitySchema('entity_test');
|
||||
$this->installEntitySchema('entity_test_rev');
|
||||
$this->installEntitySchema('entity_test_revpub');
|
||||
$this->installEntitySchema('workspace');
|
||||
|
||||
$this->installSchema('workspaces', ['workspace_association']);
|
||||
|
||||
// Create a new workspace and activate it.
|
||||
Workspace::create(['id' => 'stage', 'label' => 'Stage'])->save();
|
||||
$this->switchToWorkspace('stage');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests fully supported entity types.
|
||||
*/
|
||||
public function testSupportedEntityTypes() {
|
||||
// Check a supported entity type.
|
||||
$entity = $this->entityTypeManager->getStorage('entity_test_revpub')->create();
|
||||
|
||||
$this->assertTrue($this->workspaceInformation->isEntitySupported($entity));
|
||||
$this->assertTrue($this->workspaceInformation->isEntityTypeSupported($entity->getEntityType()));
|
||||
|
||||
$this->assertFalse($this->workspaceInformation->isEntityIgnored($entity));
|
||||
$this->assertFalse($this->workspaceInformation->isEntityTypeIgnored($entity->getEntityType()));
|
||||
|
||||
// Check that supported entity types are tracked in a workspace. This entity
|
||||
// is published by default, so the second revision will be tracked.
|
||||
$entity->save();
|
||||
$this->assertWorkspaceAssociation(['stage' => [2]], 'entity_test_revpub');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests an entity type with a custom workspace handler.
|
||||
*/
|
||||
public function testCustomSupportEntityTypes() {
|
||||
$entity_type = clone $this->entityTypeManager->getDefinition('entity_test_revpub');
|
||||
$entity_type->setHandlerClass('workspace', EntityTestRevPubWorkspaceHandler::class);
|
||||
$this->state->set('entity_test_revpub.entity_type', $entity_type);
|
||||
$this->entityTypeManager->clearCachedDefinitions();
|
||||
|
||||
$entity = $this->entityTypeManager->getStorage('entity_test_revpub')->create([
|
||||
'type' => 'supported_bundle',
|
||||
]);
|
||||
|
||||
$this->assertTrue($this->workspaceInformation->isEntitySupported($entity));
|
||||
$this->assertTrue($this->workspaceInformation->isEntityTypeSupported($entity->getEntityType()));
|
||||
$this->assertFalse($this->workspaceInformation->isEntityIgnored($entity));
|
||||
$this->assertFalse($this->workspaceInformation->isEntityTypeIgnored($entity->getEntityType()));
|
||||
|
||||
// Check that supported entity types are tracked in a workspace. This entity
|
||||
// is published by default, so the second revision will be tracked.
|
||||
$entity->save();
|
||||
$this->assertWorkspaceAssociation(['stage' => [2]], 'entity_test_revpub');
|
||||
|
||||
$entity = $this->entityTypeManager->getStorage('entity_test_revpub')->create([
|
||||
'type' => 'ignored_bundle',
|
||||
]);
|
||||
|
||||
$this->assertFalse($this->workspaceInformation->isEntitySupported($entity));
|
||||
$this->assertTrue($this->workspaceInformation->isEntityTypeSupported($entity->getEntityType()));
|
||||
$this->assertTrue($this->workspaceInformation->isEntityIgnored($entity));
|
||||
$this->assertFalse($this->workspaceInformation->isEntityTypeIgnored($entity->getEntityType()));
|
||||
|
||||
// Check that an ignored entity can be saved, but won't be tracked.
|
||||
$entity->save();
|
||||
$this->assertWorkspaceAssociation(['stage' => [2]], 'entity_test_revpub');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests ignored entity types.
|
||||
*/
|
||||
public function testIgnoredEntityTypes() {
|
||||
$entity_type = clone $this->entityTypeManager->getDefinition('entity_test_rev');
|
||||
$entity_type->setHandlerClass('workspace', IgnoredWorkspaceHandler::class);
|
||||
$this->state->set('entity_test_rev.entity_type', $entity_type);
|
||||
$this->entityTypeManager->clearCachedDefinitions();
|
||||
|
||||
// Check an ignored entity type. CRUD operations for an ignored entity type
|
||||
// are allowed in a workspace, but their revisions are not tracked.
|
||||
$entity = $this->entityTypeManager->getStorage('entity_test_rev')->create();
|
||||
$this->assertTrue($this->workspaceInformation->isEntityIgnored($entity));
|
||||
$this->assertTrue($this->workspaceInformation->isEntityTypeIgnored($entity->getEntityType()));
|
||||
|
||||
$this->assertFalse($this->workspaceInformation->isEntitySupported($entity));
|
||||
$this->assertFalse($this->workspaceInformation->isEntityTypeSupported($entity->getEntityType()));
|
||||
|
||||
// Check that ignored entity types are not tracked in a workspace.
|
||||
$entity->save();
|
||||
$this->assertWorkspaceAssociation(['stage' => []], 'entity_test_rev');
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests unsupported entity types.
|
||||
*/
|
||||
public function testUnsupportedEntityTypes() {
|
||||
// Check an unsupported entity type.
|
||||
$entity_test = $this->entityTypeManager->getDefinition('entity_test');
|
||||
$this->assertFalse($entity_test->hasHandlerClass('workspace'));
|
||||
|
||||
$entity = $this->entityTypeManager->getStorage('entity_test')->create();
|
||||
$this->assertFalse($this->workspaceInformation->isEntitySupported($entity));
|
||||
$this->assertFalse($this->workspaceInformation->isEntityTypeSupported($entity_test));
|
||||
|
||||
$this->assertFalse($this->workspaceInformation->isEntityIgnored($entity));
|
||||
$this->assertFalse($this->workspaceInformation->isEntityTypeIgnored($entity_test));
|
||||
|
||||
// Check that unsupported entity types can not be saved in a workspace.
|
||||
$this->expectException(EntityStorageException::class);
|
||||
$this->expectExceptionMessage('This entity can only be saved in the default workspace.');
|
||||
$entity->save();
|
||||
}
|
||||
|
||||
}
|
|
@ -39,7 +39,7 @@ trait WorkspaceTestTrait {
|
|||
|
||||
// Install the entity schema for supported entity types to ensure that the
|
||||
// 'workspace' revision metadata field gets created.
|
||||
foreach (array_keys($this->workspaceManager->getSupportedEntityTypes()) as $entity_type_id) {
|
||||
foreach (array_keys(\Drupal::service('workspaces.information')->getSupportedEntityTypes()) as $entity_type_id) {
|
||||
$this->installEntitySchema($entity_type_id);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,11 +35,11 @@ function workspaces_module_preinstall($module) {
|
|||
return;
|
||||
}
|
||||
|
||||
/** @var \Drupal\workspaces\WorkspaceManagerInterface $workspace_manager */
|
||||
$workspace_manager = \Drupal::service('workspaces.manager');
|
||||
/** @var \Drupal\workspaces\WorkspaceInformationInterface $workspace_info */
|
||||
$workspace_info = \Drupal::service('workspaces.information');
|
||||
$entity_definition_update_manager = \Drupal::entityDefinitionUpdateManager();
|
||||
foreach ($entity_definition_update_manager->getEntityTypes() as $entity_type) {
|
||||
if ($workspace_manager->isEntityTypeSupported($entity_type)) {
|
||||
if ($workspace_info->isEntityTypeSupported($entity_type)) {
|
||||
$entity_type->setRevisionMetadataKey('workspace', 'workspace');
|
||||
$entity_definition_update_manager->updateEntityType($entity_type);
|
||||
}
|
||||
|
|
|
@ -148,7 +148,7 @@ function workspaces_entity_predelete(EntityInterface $entity) {
|
|||
* Implements hook_entity_delete().
|
||||
*/
|
||||
function workspaces_entity_delete(EntityInterface $entity) {
|
||||
if (\Drupal::service('workspaces.manager')->isEntityTypeSupported($entity->getEntityType())) {
|
||||
if (\Drupal::service('workspaces.information')->isEntityTypeSupported($entity->getEntityType())) {
|
||||
\Drupal::service('workspaces.association')
|
||||
->deleteAssociations(NULL, $entity->getEntityTypeId(), [$entity->id()]);
|
||||
}
|
||||
|
@ -158,7 +158,7 @@ function workspaces_entity_delete(EntityInterface $entity) {
|
|||
* Implements hook_entity_revision_delete().
|
||||
*/
|
||||
function workspaces_entity_revision_delete(EntityInterface $entity) {
|
||||
if (\Drupal::service('workspaces.manager')->isEntityTypeSupported($entity->getEntityType())) {
|
||||
if (\Drupal::service('workspaces.information')->isEntityTypeSupported($entity->getEntityType())) {
|
||||
\Drupal::service('workspaces.association')
|
||||
->deleteAssociations(NULL, $entity->getEntityTypeId(), [$entity->id()], [$entity->getRevisionId()]);
|
||||
}
|
||||
|
|
|
@ -3,10 +3,14 @@ services:
|
|||
autoconfigure: true
|
||||
workspaces.manager:
|
||||
class: Drupal\workspaces\WorkspaceManager
|
||||
arguments: ['@request_stack', '@entity_type.manager', '@entity.memory_cache', '@current_user', '@state', '@logger.channel.workspaces', '@class_resolver', '@workspaces.association']
|
||||
arguments: ['@request_stack', '@entity_type.manager', '@entity.memory_cache', '@current_user', '@state', '@logger.channel.workspaces', '@class_resolver', '@workspaces.association', '@workspaces.information']
|
||||
tags:
|
||||
- { name: service_id_collector, tag: workspace_negotiator }
|
||||
Drupal\workspaces\WorkspaceManagerInterface: '@workspaces.manager'
|
||||
workspaces.information:
|
||||
class: Drupal\workspaces\WorkspaceInformation
|
||||
arguments: [ '@entity_type.manager' ]
|
||||
Drupal\workspaces\WorkspaceInformationInterface: '@workspaces.information'
|
||||
workspaces.operation_factory:
|
||||
class: Drupal\workspaces\WorkspaceOperationFactory
|
||||
arguments: ['@entity_type.manager', '@database', '@workspaces.manager', '@workspaces.association', '@cache_tags.invalidator', '@event_dispatcher', '@logger.channel.workspaces']
|
||||
|
@ -41,7 +45,7 @@ services:
|
|||
|
||||
workspaces.entity_schema_listener:
|
||||
class: Drupal\workspaces\EventSubscriber\EntitySchemaSubscriber
|
||||
arguments: ['@entity.definition_update_manager', '@entity.last_installed_schema.repository', '@workspaces.manager']
|
||||
arguments: ['@entity.definition_update_manager', '@entity.last_installed_schema.repository', '@workspaces.information']
|
||||
workspaces.workspace_subscriber:
|
||||
class: Drupal\workspaces\EventSubscriber\WorkspaceRequestSubscriber
|
||||
arguments: ['@path_alias.manager', '@path.current', '@router.route_provider', '@workspaces.manager']
|
||||
|
@ -58,7 +62,7 @@ services:
|
|||
workspaces.entity.query.sql:
|
||||
decorates: entity.query.sql
|
||||
class: Drupal\workspaces\EntityQuery\QueryFactory
|
||||
arguments: ['@database', '@workspaces.manager']
|
||||
arguments: ['@database', '@workspaces.manager', '@workspaces.information']
|
||||
public: false
|
||||
decoration_priority: 50
|
||||
tags:
|
||||
|
@ -66,7 +70,7 @@ services:
|
|||
pgsql.workspaces.entity.query.sql:
|
||||
decorates: pgsql.entity.query.sql
|
||||
class: Drupal\workspaces\EntityQuery\PgsqlQueryFactory
|
||||
arguments: ['@database', '@workspaces.manager']
|
||||
arguments: ['@database', '@workspaces.manager', '@workspaces.information']
|
||||
public: false
|
||||
decoration_priority: 50
|
||||
|
||||
|
|
Loading…
Reference in New Issue