workspaces.install
Contains install, update and uninstall functions for the Workspaces module.
File
-
core/
modules/ workspaces/ workspaces.install
View source
<?php
/**
* @file
* Contains install, update and uninstall functions for the Workspaces module.
*/
use Drupal\Component\Utility\NestedArray;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\workspaces\Provider\DefaultWorkspaceProvider;
use Drupal\workspaces\WorkspaceTracker;
/**
* Implements hook_schema().
*/
function workspaces_schema() : array {
$schema['workspace_association'] = [
'description' => 'Stores the latest entity revisions tracked by a workspace.',
'fields' => [
'workspace' => [
'type' => 'varchar_ascii',
'length' => 128,
'not null' => TRUE,
'default' => '',
'description' => 'The workspace ID.',
],
'target_entity_type_id' => [
'type' => 'varchar_ascii',
'length' => EntityTypeInterface::ID_MAX_LENGTH,
'not null' => TRUE,
'default' => '',
'description' => 'The ID of the associated entity type.',
],
'target_entity_id' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The ID of the associated entity.',
],
'target_entity_id_string' => [
'type' => 'varchar_ascii',
'length' => 128,
'not null' => TRUE,
'default' => '',
'description' => 'The string ID of the associated entity.',
],
'target_entity_revision_id' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => 'The revision ID of the associated entity.',
],
],
'primary key' => [
'workspace',
'target_entity_type_id',
'target_entity_id',
'target_entity_id_string',
],
'indexes' => [
'target_entity_revision_id' => [
'target_entity_revision_id',
],
],
];
$schema['workspace_association_revision'] = NestedArray::mergeDeep($schema['workspace_association'], [
'description' => 'Stores all entity revisions tracked by a workspace.',
'fields' => [
'initial_revision' => [
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
'description' => 'Whether this entity was created in the workspace.',
],
],
]);
$schema['workspace_association_revision']['primary key'] = [
'workspace',
'target_entity_type_id',
'target_entity_id',
'target_entity_id_string',
'target_entity_revision_id',
];
$schema['workspace_association_revision']['indexes'] = [
'initial_revision' => [
'initial_revision',
],
];
return $schema;
}
/**
* Implements hook_update_last_removed().
*/
function workspaces_update_last_removed() : int {
return 8803;
}
/**
* Implements hook_update_dependencies().
*/
function workspaces_update_dependencies() : array {
// The workspaces updates must run after the router table is
// updated since it triggers route rebuilds due to the module install.
$dependencies['workspaces'][11102] = [
'system' => 11201,
];
return $dependencies;
}
/**
* Update workspace associations to support entity types with string IDs.
*/
function workspaces_update_11101() : void {
$schema = \Drupal::database()->schema();
$target_id_spec = [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The ID of the associated entity.',
];
$schema->changeField('workspace_association', 'target_entity_id', 'target_entity_id', $target_id_spec);
$target_id_string_spec = [
'type' => 'varchar_ascii',
'length' => 128,
'not null' => TRUE,
'default' => '',
'description' => 'The string ID of the associated entity.',
];
$schema->addField('workspace_association', 'target_entity_id_string', $target_id_string_spec, [
'primary key' => [
'workspace',
'target_entity_type_id',
'target_entity_id',
'target_entity_id_string',
],
]);
}
/**
* Install the new Workspaces UI module.
*/
function workspaces_update_11102() : void {
\Drupal::service('module_installer')->install([
'workspaces_ui',
]);
}
/**
* Create the 'workspace_association_revision' table.
*/
function workspaces_update_11301() : void {
$schema = \Drupal::database()->schema();
// Create the new workspace_association_revision table.
if (!$schema->tableExists('workspace_association_revision')) {
$workspace_association_revision_schema = [
'description' => 'Stores all entity revisions tracked by a workspace.',
'fields' => [
'workspace' => [
'type' => 'varchar_ascii',
'length' => 128,
'not null' => TRUE,
'default' => '',
'description' => 'The workspace ID.',
],
'target_entity_type_id' => [
'type' => 'varchar_ascii',
'length' => EntityTypeInterface::ID_MAX_LENGTH,
'not null' => TRUE,
'default' => '',
'description' => 'The ID of the associated entity type.',
],
'target_entity_id' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'default' => 0,
'description' => 'The ID of the associated entity.',
],
'target_entity_id_string' => [
'type' => 'varchar_ascii',
'length' => 128,
'not null' => TRUE,
'default' => '',
'description' => 'The string ID of the associated entity.',
],
'target_entity_revision_id' => [
'type' => 'int',
'unsigned' => TRUE,
'not null' => TRUE,
'description' => 'The revision ID of the associated entity.',
],
'initial_revision' => [
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
'description' => 'Whether this entity was created in the workspace.',
],
],
'primary key' => [
'workspace',
'target_entity_type_id',
'target_entity_id',
'target_entity_id_string',
'target_entity_revision_id',
],
'indexes' => [
'initial_revision' => [
'initial_revision',
],
],
];
$schema->createTable('workspace_association_revision', $workspace_association_revision_schema);
}
}
/**
* Populate the 'workspace_association_revision' table.
*/
function workspaces_update_11302() : void {
$database = \Drupal::database();
$entity_type_manager = \Drupal::entityTypeManager();
// Get all workspaces and their associations.
$workspace_associations = $database->select('workspace_association', 'wa')
->fields('wa')
->execute()
->fetchAll();
// Group associations by workspace and entity type.
$grouped_associations = [];
foreach ($workspace_associations as $association) {
$grouped_associations[$association->workspace][$association->target_entity_type_id][] = $association;
}
// Process each workspace and entity type combination.
$transaction = $database->startTransaction();
try {
foreach ($grouped_associations as $workspace_id => $entity_types) {
foreach ($entity_types as $entity_type_id => $associations) {
$storage = $entity_type_manager->getStorage($entity_type_id);
// Skip if the entity type doesn't use SQL storage.
if (!$storage instanceof SqlContentEntityStorage) {
// For non-SQL entities, we can only track the latest revision.
foreach ($associations as $association) {
$database->insert('workspace_association_revision')
->fields([
'workspace' => $association->workspace,
'target_entity_type_id' => $association->target_entity_type_id,
'target_entity_id' => $association->target_entity_id,
'target_entity_id_string' => $association->target_entity_id_string,
'target_entity_revision_id' => $association->target_entity_revision_id,
'initial_revision' => 0,
])
->execute();
}
continue;
}
$entity_type = $storage->getEntityType();
$table_mapping = $storage->getTableMapping();
// Get field names from the table mapping.
$workspace_field = $table_mapping->getColumnNames($entity_type->get('revision_metadata_keys')['workspace'])['target_id'];
$id_field = $table_mapping->getColumnNames($entity_type->getKey('id'))['value'];
$revision_id_field = $table_mapping->getColumnNames($entity_type->getKey('revision'))['value'];
// Determine which ID field to use based on entity type.
$uses_numeric_id = WorkspaceTracker::getIdField($entity_type_id) === 'target_entity_id';
// Collect entity IDs for querying revisions.
$id_field_name = $uses_numeric_id ? 'target_entity_id' : 'target_entity_id_string';
$entity_ids = array_filter(array_column($associations, $id_field_name));
// Query for all revisions created in this specific workspace.
if ($entity_ids) {
$revision_query = $database->select($entity_type->getRevisionTable(), 'revision');
$revision_query->leftJoin($entity_type->getBaseTable(), 'base', "[revision].[{$id_field}] = [base].[{$id_field}]");
$revision_query->fields('revision', [
$revision_id_field,
$id_field,
]);
$base_revision_id_field = $revision_query->addField('base', $revision_id_field, 'base_revision_id_field');
$revision_query->condition("revision.{$workspace_field}", $workspace_id)
->condition("revision.{$id_field}", $entity_ids, 'IN')
->where("[revision].[{$revision_id_field}] >= [base].[{$revision_id_field}]")
->orderBy("[revision].{$revision_id_field}");
$revisions = $revision_query->execute()
->fetchAll();
// Insert each revision into the workspace_association_revision table.
foreach ($revisions as $revision) {
$database->insert('workspace_association_revision')
->fields([
'workspace' => $workspace_id,
'target_entity_type_id' => $entity_type_id,
'target_entity_id' => $uses_numeric_id ? $revision->{$id_field} : 0,
'target_entity_id_string' => $uses_numeric_id ? '' : $revision->{$id_field},
'target_entity_revision_id' => $revision->{$revision_id_field},
// Check if this is an initial revision (the base revision was
// created in this workspace).
'initial_revision' => $revision->{$revision_id_field} == $revision->{$base_revision_id_field} ? 1 : 0,
])
->execute();
}
}
}
}
} catch (\Exception $e) {
$transaction->rollBack();
throw $e;
}
}
/**
* Add the workspace provider field.
*/
function workspaces_update_11303() : void {
$entity_definition_update = \Drupal::entityDefinitionUpdateManager();
$storage_definition = BaseFieldDefinition::create('string')->setLabel(new TranslatableMarkup('Provider'))
->setSetting('max_length', 128)
->setRequired(TRUE)
->setReadOnly(TRUE)
->setDefaultValue(DefaultWorkspaceProvider::getId())
->setInitialValue(DefaultWorkspaceProvider::getId());
$entity_definition_update->installFieldStorageDefinition('provider', 'workspace', 'workspaces', $storage_definition);
}
Functions
| Title | Deprecated | Summary |
|---|---|---|
| workspaces_schema | Implements hook_schema(). | |
| workspaces_update_11101 | Update workspace associations to support entity types with string IDs. | |
| workspaces_update_11102 | Install the new Workspaces UI module. | |
| workspaces_update_11301 | Create the 'workspace_association_revision' table. | |
| workspaces_update_11302 | Populate the 'workspace_association_revision' table. | |
| workspaces_update_11303 | Add the workspace provider field. | |
| workspaces_update_dependencies | Implements hook_update_dependencies(). | |
| workspaces_update_last_removed | Implements hook_update_last_removed(). |
Buggy or inaccurate documentation? Please file an issue. Need support? Need help programming? Connect with the Drupal community.