multiversion-8.x-1.0-beta34/src/Entity/Workspace.php
src/Entity/Workspace.php
<?php namespace Drupal\multiversion\Entity; use Drupal\Component\Serialization\PhpSerialize; use Drupal\Core\Entity\ContentEntityBase; use Drupal\Core\Entity\EntityChangedTrait; use Drupal\Core\Entity\EntityPublishedTrait; use Drupal\Core\Entity\EntityTypeInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\user\UserInterface; use Drupal\workspace\Entity\Replication; use Drupal\workspace\Entity\WorkspacePointer; /** * The workspace entity class. * * @ContentEntityType( * id = "workspace", * label = @Translation("Workspace"), * bundle_label = @Translation("Workspace type"), * handlers = { * "storage" = "Drupal\Core\Entity\Sql\SqlContentEntityStorage", * "views_data" = "Drupal\views\EntityViewsData" * }, * admin_permission = "administer workspaces", * base_table = "workspace", * revision_table = "workspace_revision", * data_table = "workspace_field_data", * revision_data_table = "workspace_field_revision", * bundle_entity_type = "workspace_type", * entity_keys = { * "id" = "id", * "revision" = "revision_id", * "bundle" = "type", * "uuid" = "uuid", * "label" = "label", * "machine_name" = "machine_name", * "uid" = "uid", * "created" = "created", * "published" = "published" * }, * multiversion = FALSE, * local = TRUE * ) */ class Workspace extends ContentEntityBase implements WorkspaceInterface { use EntityChangedTrait; use EntityPublishedTrait; /** * {@inheritdoc} */ public static function baseFieldDefinitions(EntityTypeInterface $entity_type) { $fields = parent::baseFieldDefinitions($entity_type); // Add the published field. $fields += static::publishedBaseFieldDefinitions($entity_type); $fields['label'] = BaseFieldDefinition::create('string') ->setLabel(t('Workspace name')) ->setDescription(t('The workspace name.')) ->setRevisionable(TRUE) ->setSetting('max_length', 128) ->setRequired(TRUE); $fields['machine_name'] = BaseFieldDefinition::create('string') ->setLabel(t('Workspace ID')) ->setDescription(t('The workspace machine name.')) ->setRevisionable(TRUE) ->setSetting('max_length', 128) ->setRequired(TRUE) ->addPropertyConstraints('value', ['Regex' => ['pattern' => '/^[\da-z_$()+-\/]*$/']]); $fields['uid'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Owner')) ->setDescription(t('The workspace owner.')) ->setRevisionable(TRUE) ->setSetting('target_type', 'user') ->setDefaultValueCallback('Drupal\multiversion\Entity\Workspace::getCurrentUserId'); $fields['type'] = BaseFieldDefinition::create('entity_reference') ->setLabel(t('Type')) ->setDescription(t('The workspace type.')) ->setSetting('target_type', 'workspace_type') ->setReadOnly(TRUE); $fields['changed'] = BaseFieldDefinition::create('changed') ->setLabel(t('Changed')) ->setDescription(t('The time that the workspace was last edited.')) ->setRevisionable(TRUE); $fields['created'] = BaseFieldDefinition::create('created') ->setLabel(t('Created')) ->setDescription(t('The UNIX timestamp of when the workspace has been created.')); $fields['published']->addConstraint('UnpublishWorkspace'); $fields['queued_for_delete'] = BaseFieldDefinition::create('boolean') ->setLabel(t('Queued for delete')) ->setDescription(t('A flag that specifies if the entity has been queued for delete on next cron run.')) ->setRevisionable(FALSE) ->setTranslatable(FALSE) ->setRequired(FALSE) ->setDefaultValue(FALSE) ->setInitialValue(FALSE); return $fields; } /** * {@inheritdoc} */ public function delete() { if (!$this->isNew()) { $workspace_id = $this->id(); // Execute predelete action on workspace entity, this hook is needed to // be executed before the workspace is deleted on cron and before entity // predelete hooks provided by core. \Drupal::moduleHandler()->invokeAll('multiversion_workspace_predelete', [$this]); /** @var \Drupal\Core\Queue\QueueInterface $queue */ $queue = \Drupal::queue('deleted_workspace_queue'); $queue->createQueue(); /** @var \Drupal\multiversion\MultiversionManagerInterface $multiversion_manager */ $multiversion_manager = \Drupal::service('multiversion.manager'); $entity_type_manager = $this->entityTypeManager(); /** @var \Drupal\Core\Entity\ContentEntityInterface $entity_type */ foreach ($multiversion_manager->getEnabledEntityTypes() as $entity_type) { // Load IDs for deleted entities. $deleted_entity_ids = $entity_type_manager ->getStorage($entity_type->id()) ->getQuery() ->useWorkspace($workspace_id) ->isDeleted() ->execute(); // Load IDs for non-deleted entities. $entity_ids = $entity_type_manager ->getStorage($entity_type->id()) ->getQuery() ->useWorkspace($workspace_id) ->isNotDeleted() ->execute(); foreach (array_merge($entity_ids, $deleted_entity_ids) as $entity_id) { $data = [ 'workspace_id' => $workspace_id, 'entity_type_id' => $entity_type->id(), 'entity_id' => $entity_id, ]; $queue->createItem($data); } } // Add the workspace to the queue to be deleted. $data = [ 'entity_type_id' => 'workspace', 'entity_id' => $workspace_id, ]; $queue->createItem($data); $this->setQueuedForDelete()->save(); if ($this->id() === $multiversion_manager->getActiveWorkspaceId()) { $multiversion_manager->setActiveWorkspaceId(\Drupal::getContainer()->getParameter('workspace.default')); } // Deleted workspace won't be active anymore for users that had it as // active, the default workspace will became active for them. $this->deleteWorkspaceActiveSessions($workspace_id); } } /** * {@inheritdoc} */ public function getUpdateSeq() { return \Drupal::service('multiversion.entity_index.sequence')->useWorkspace($this->id())->getLastSequenceId(); } /** * {@inheritdoc} */ public function setCreatedTime($created) { $this->set('created', (int) $created); return $this; } /** * {@inheritdoc} */ public function getStartTime() { return $this->get('created')->value; } /** * {@inheritdoc} */ public function getMachineName() { return $this->get('machine_name')->value; } /** * {@inheritdoc} */ public function getOwner() { return $this->get('uid')->entity; } /** * {@inheritdoc} */ public function setOwner(UserInterface $account) { $this->set('uid', $account->id()); return $this; } /** * {@inheritdoc} */ public function getOwnerId() { return $this->get('uid')->target_id; } /** * {@inheritdoc} */ public function setOwnerId($uid) { $this->set('uid', $uid); return $this; } /** * {@inheritdoc} */ public function setQueuedForDelete($queued = TRUE) { $this->set('queued_for_delete', (bool) $queued); return $this; } /** * {@inheritdoc} */ public function getQueuedForDelete() { return $this->get('queued_for_delete')->value; } /** * {@inheritdoc} */ public function isDefaultWorkspace() { return $this->id() == \Drupal::getContainer()->getParameter('workspace.default'); } /** * Default value callback for 'uid' base field definition. * * @see ::baseFieldDefinitions() * * @return array * An array of default values. */ public static function getCurrentUserId() { return [\Drupal::currentUser()->id()]; } /** * Deletes from users private store entries where the workspace is active. * * This will lead to using the default active workspace as the active * workspace for users that had as active the deleted workspace. * * @param $workspace_id */ protected function deleteWorkspaceActiveSessions($workspace_id) { // Get all collections for the workspace session negotiator and delete those // that have as active workspace the currently deleted workspace. // Manipulate directly with the database here becase for private tempstore // the access is restricted per current user. $session_negociator_collection = 'user.private_tempstore.workspace.negotiator.session'; $values = \Drupal::database() ->select('key_value_expire', 'kve') ->fields('kve', ['name', 'value']) ->condition('collection', $session_negociator_collection) ->execute() ->fetchAll(); foreach ($values as $value) { if (!empty($value->value) && !empty($value->name)) { $data = PhpSerialize::decode($value->value); if (!empty($data->data) && $data->data == $workspace_id) { \Drupal::database() ->delete('key_value_expire') ->condition('name', $value->name) ->execute(); } } } } }