Add Multiversion support for a new content entity type
Here we have the steps how to add Multiversion support for a new content entity and make it compatible with this module and other modules that depend on Multiversion.
Next example is based on the integration of the Poll and Poll Choice content entity types which are provided by Poll module:
- Multiversion modifies the storage for supported entity types, because of that we should check if the entity we want to integrate has a custom storage class. If the entity doesn't use a custom storage class, like Poll Choice (it uses core \Drupal\Core\Entity\Sql\SqlContentEntityStorage class) then go to step 3., otherwise Multiversion should implements a new class that extends the custom storage class the entity uses:
namespace Drupal\multiversion\Entity\Storage\Sql; use Drupal\multiversion\Entity\Storage\ContentEntityStorageInterface; use Drupal\multiversion\Entity\Storage\ContentEntityStorageTrait; use Drupal\poll\PollStorage as ContribPollStorage; /** * Storage handler for files. */ class PollStorage extends ContribPollStorage implements ContentEntityStorageInterface { use ContentEntityStorageTrait; }
- Edit
multiversion.module
- add next code inmultiversion_entity_type_alter()
:
case 'poll': $entity_type->setHandlerClass('storage', "$namespace\\PollStorage"); break;
-
Add poll and poll_choice content entity types to the supported_entity_types array in multiversion.settings.yml.
-
Only if the module has been installed before adding this integration - enable poll and poll_choice entity types with Drush:
drush met poll poll_choice -y
or do it in an update hook, in MODULE.install:
/** * Enable poll and poll_choices. */ function HOOK_update_N() { if (\Drupal::moduleHandler()->moduleExists('poll')) { $multiversion_settings = \Drupal::configFactory()->getEditable('multiversion.settings'); $supported_entity_types = $multiversion_settings->get('supported_entity_types') ?: []; $manager = \Drupal::entityTypeManager(); $entity_types = []; foreach (['poll_choice', 'poll'] as $id) { // Check which entity types should be added to the supported entity types // list. if (!in_array($id, $supported_entity_types)) { $supported_entity_types[] = $id; } // Get entity types that should be enabled. $entity_type = $manager->getStorage($id)->getEntityType(); if ($entity_type instanceof ContentEntityTypeInterface) { $entity_types[$id] = $entity_type; } } // Add new entity types to the supported entity types list. $multiversion_settings ->set('supported_entity_types', $supported_entity_types) ->save(); // Enable new entity types. if (!empty($entity_types)) { \Drupal::service('multiversion.manager')->enableEntityTypes($entity_types); } } }
- Testing. Testing. Testing. Manual and automated testing. Add tests for the new integration. What to test: entity creation, update, delete and also translated entities (if supports translations). Very important: Make sure that the new integration doesn't brake other integrations.
In an ideal world, after the steps above the new integration should be fully working, but not in our case (this is specific to the new integrated entities and we can have different technical challenges when integrating new entities). Because of the way poll and poll_choice entity types work (poll references poll_choice) and because of other modules that depend on Multiversion (like Replication) we needed this workaround in \Drupal\multiversion\Entity\Storage\ContentEntityStorageTrait::doPreSave():
// This is a workaround for the cases when referenced poll choices are stub
// entities (during replication). It will avoid deleting poll choice
// entities on target workspace in Drupal\poll\Entity\Poll::preSave() when
// not necessary.
if (!$entity->isNew() && $this->entityTypeId === 'poll' && isset($entity->original) && $entity->_deleted->value == FALSE) {
$original_choices = [];
foreach ($entity->original->choice as $choice_item) {
$original_choices[] = $choice_item->target_id;
}
$current_choices = [];
$current_choices_entities = [];
foreach ($entity->choice as $key => $choice_item) {
$current_choices[$key] = $choice_item->target_id;
$current_choices_entities[$key] = $choice_item->entity;
}
foreach ($current_choices as $key => $id) {
if ($id === NULL
&& isset($current_choices_entities[$key]->_rev->is_stub)
&& $current_choices_entities[$key]->_rev->is_stub == TRUE
&& isset($entity->original->choice)) {
unset($entity->original->choice);
}
}
}
If you will use Replication module, you might need some special entity handling in an existing or in a new normalizer. This, again, depends by the entity and its complexity. You can see as examples the normalizers form that module.
Help improve this page
You can:
- Log in, click Edit, and edit this page
- Log in, click Discuss, update the Page status value, and suggest an improvement
- Log in and create a Documentation issue with your suggestion