View source
<?php
namespace Drupal\config_entity_revisions\Entity\Handler;
use Drupal\config_entity_revisions\ConfigEntityRevisionsConfigEntityInterface;
use Drupal\config_entity_revisions\ConfigEntityRevisionsRevisionStorageHandlerInterface;
use Drupal\config_entity_revisions\Entity\ConfigEntityRevisions;
use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Cache\MemoryCache\MemoryCacheInterface;
use Drupal\Core\Database\Connection;
use Drupal\Component\Datetime\Time;
use Drupal\Core\Entity\ContentEntityInterface;
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\Entity\EntityTypeBundleInfo;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\EntityTypeManager;
use Drupal\Core\Entity\Sql\SqlContentEntityStorage;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Session\AccountProxyInterface;
use mysql_xdevapi\Exception;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\DependencyInjection\ContainerInterface;
class ConfigEntityRevisionsRevisionStorageHandler extends SqlContentEntityStorage implements ConfigEntityRevisionsRevisionStorageHandlerInterface {
protected $configEntity;
protected $revisionStates = NULL;
protected $serialiser = NULL;
protected $currentUser = NULL;
protected $dateTimeService = NULL;
public function __construct(EntityTypeInterface $entity_type, Connection $database, EntityManagerInterface $entity_manager, CacheBackendInterface $cache, LanguageManagerInterface $language_manager, MemoryCacheInterface $memory_cache = NULL, Serializer $serialiser, AccountProxyInterface $current_user, Time $date_time, EntityTypeBundleInfo $bundle_info, EntityTypeManager $entity_type_manager) {
parent::__construct($entity_type, $database, $entity_manager, $cache, $language_manager, $memory_cache, $bundle_info, $entity_type_manager);
$this->serialiser = $serialiser;
$this->currentUser = $current_user;
$this->dateTimeService = $date_time;
$this->entityTypeManager = $entity_type_manager;
}
public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) {
return new static($entity_type, $container
->get('database'), $container
->get('entity.manager'), $container
->get('cache.entity'), $container
->get('language_manager'), $container
->get('entity.memory_cache'), $container
->get('serializer'), $container
->get('current_user'), $container
->get('datetime.time'), $container
->get('entity_type.bundle.info'), $container
->get('entity_type.manager'));
}
public function setConfigEntity(ConfigEntityRevisionsConfigEntityInterface $configEntity) {
$this->configEntity = $configEntity;
}
protected function ensureRevisionStatesLoaded() {
if (is_null($this->revisionStates)) {
$this->revisionStates = $this->database
->select("config_entity_revisions_revision", 'c')
->fields('c', [])
->condition($this->entityType
->getKey('id'), $this->configEntity
->getContentEntityID())
->orderby('revision', 'DESC')
->execute()
->fetchAll();
}
}
public function getLatestPublishedRevisionId($ignore = NULL) {
$this
->ensureRevisionStatesLoaded();
foreach ($this->revisionStates as $state) {
if (!is_null($ignore) && $state->revision == $ignore) {
continue;
}
if ($state->published) {
return $state->revision;
}
}
return NULL;
}
public function getLatestPublishedRevision($ignore = NULL) {
$revision = NULL;
$revision_id = $this
->getLatestPublishedRevisionId($ignore);
if ($revision_id) {
$revision = $this
->loadRevision($revision_id);
}
return $revision;
}
public function getLatestRevisionId($ignore = NULL) {
$this
->ensureRevisionStatesLoaded();
return empty($this->revisionStates) ? NULL : $this->revisionStates[0]->revision;
}
public function getLatestRevision($ignore = NULL) {
$id = $this
->getLatestRevisionId($ignore);
return $id ? $this
->loadRevision($id) : NULL;
}
public function getLatestPublishedRevisionOrLatestId($ignore = NULL) {
$revision_id = $this
->getLatestPublishedRevisionId($ignore);
return $revision_id ? $revision_id : $this
->getLatestRevisionId($ignore);
}
public function getConfigEntity(ConfigEntityRevisions $content_entity, $class = '') {
if ($class == '') {
if (!$this->configEntity) {
throw new Exception('No class name or instance suppled to ConfigEntityRevisionsRevisionStorageHandler::getConfigEntity');
}
$class = get_class($this->configEntity);
}
$config_entity = $this->serialiser
->deserialize($content_entity
->get('configuration')->value, $class, 'json');
$config_entity
->set('settingsOriginal', $config_entity
->get('settings'));
$config_entity
->set('enforceIsNew', FALSE);
$config_entity->loadedRevisionId = $content_entity
->getRevisionId();
if ($config_entity->moderation_state) {
$config_entity->moderation_state->value = $content_entity->moderation_state->value;
}
return $config_entity;
}
public function createInitialRevision(ConfigEntityRevisionsConfigEntityInterface $config_entity) {
$contentID = $config_entity
->getContentEntityID();
if ($contentID) {
return NULL;
}
$originalEntity = $config_entity
->contentEntityStorage()
->load($config_entity
->id());
$source = $originalEntity ? $originalEntity : $config_entity;
$bundle_type = $config_entity
->getBundleName();
$contentEntity = $config_entity
->contentEntityStorage()
->create([
'form' => $source
->get('uuid'),
'configuration' => $this->serialiser
->serialize($source, 'json'),
'revision_user' => $this->currentUser
->id(),
'revision_creation_time' => $this->dateTimeService
->getRequestTime(),
'revision_log_message' => 'Original revision.',
'moderation_state' => 'draft',
'type' => $bundle_type,
]);
$contentEntity
->save();
$contentID = $contentEntity
->id();
$config_entity
->setContentEntityID($contentID);
$config_entity
->save();
return $contentEntity;
}
public function createUpdateRevision(ConfigEntityRevisionsConfigEntityInterface $config_entity) {
$revisionsEntity = NULL;
$previous_state = FALSE;
$moderated = FALSE;
if (!empty($config_entity
->getRevisionId())) {
$revisionsEntity = $config_entity
->contentEntityStorage()
->loadRevision($config_entity
->getRevisionID());
$moderated = $revisionsEntity
->hasField('moderation_state');
if ($moderated) {
$previous_state = $revisionsEntity->moderation_state->value;
}
}
else {
$contentID = $config_entity
->getContentEntityID();
if (is_null($contentID)) {
return;
}
$revisionsEntity = $config_entity
->contentEntityStorage()
->load($contentID);
}
$revisionsEntity
->set('configuration', $this->serialiser
->serialize($config_entity, 'json'));
$revisionsEntity
->setRevisionUserId($this->currentUser
->id());
$revisionsEntity
->setRevisionCreationTime($this->dateTimeService
->getRequestTime());
$new_message = $config_entity
->get('revision_log_message')[0]['value'];
$new_revision = $config_entity
->get('revision');
$moderation_state = $moderated ? $config_entity->moderation_state->value : NULL;
$published = NULL;
if (!is_null($moderation_state)) {
$published = $moderation_state == 'published';
}
if (is_null($moderation_state) && is_null($new_revision)) {
$new_revision = FALSE;
}
if (!is_null($new_message)) {
$revisionsEntity
->setRevisionLogMessage($config_entity
->get('revision_log_message')[0]['value']);
}
$revisionsEntity
->setNewRevision($new_revision);
if (!is_null($moderation_state)) {
$revisionsEntity->moderation_state = $moderation_state;
}
if (!is_null($published)) {
if ($published) {
$revisionsEntity
->setPublished();
}
else {
$revisionsEntity
->setUnpublished();
}
$revisionsEntity
->isDefaultRevision($published);
}
$revisionsEntity
->save();
if (($previous_state == 'published') !== $published) {
$this
->resetDefaultRevision($revisionsEntity);
}
return $revisionsEntity
->getRevisionId();
}
public function resetDefaultRevision(ContentEntityInterface $content_entity, $deleting = NULL) {
$content_entity_id = $content_entity
->id();
$this->revisionStates = NULL;
$this
->ensureRevisionStatesLoaded();
$first_published = NULL;
$first_revision = NULL;
$remove_default = [];
foreach ($this->revisionStates as $revision) {
if (!$first_revision && $revision->revision != $deleting) {
$first_revision = $revision;
}
if ($revision->published && !$first_published && $revision->revision != $deleting) {
$first_published = $revision;
}
if ($revision->revision_default) {
$remove_default[$revision->revision] = 1;
}
}
$default_revision = $first_published ?: $first_revision;
if ($default_revision) {
unset($remove_default[$default_revision->revision]);
}
if (!empty($remove_default)) {
$this->database
->update("config_entity_revisions_revision")
->condition('revision', array_keys($remove_default), 'IN')
->fields([
'revision_default' => 0,
])
->execute();
}
if ($default_revision) {
$this->database
->update("config_entity_revisions")
->condition('id', $content_entity_id)
->fields([
'revision' => $default_revision->revision,
])
->execute();
if ($this->database
->schema()
->tableExists('content_moderation_state_field_revision')) {
$content_moderation_rev_ids = $this->database
->select('content_moderation_state_field_revision', 'c')
->condition('content_entity_type_id', 'config_entity_revisions')
->condition('content_entity_id', $content_entity_id)
->condition('content_entity_revision_id', $default_revision->revision)
->fields('c', [
'id',
'revision_id',
])
->execute()
->fetchAssoc();
$this->database
->update('content_moderation_state')
->condition('id', $content_moderation_rev_ids['id'])
->fields([
'revision_id' => $content_moderation_rev_ids['revision_id'],
])
->execute();
}
}
}
public function getRevisionIds($content_entity_id) {
$revisions = $this->connection
->select("config_entity_revisions_revision", 'c')
->fields('c', [
'revision',
])
->condition('id', $content_entity_id)
->orderBy('revision', 'DESC')
->execute()
->fetchCol();
return $revisions;
}
public function deleteSingleRevision(ContentEntityInterface $revision) {
$was_default = $revision
->isDefaultRevision();
if ($was_default) {
$revisions = $this
->getRevisionIds($revision
->id());
$revision_to_use = $revisions[0] == $revision
->getRevisionId() ? $revisions[1] : $revisions[0];
$new_default = $this->entityTypeManager
->getStorage('config_entity_revisions')
->loadRevision($revision_to_use);
$new_default
->enforceIsNew(FALSE);
$new_default
->isDefaultRevision(TRUE);
$new_default
->save();
$content_moderation_state_storage = $this->entityTypeManager
->getStorage('content_moderation_state');
if ($content_moderation_state_storage) {
$content_moderation_ids = $content_moderation_state_storage
->getQuery()
->allRevisions()
->condition('content_entity_type_id', 'config_entity_revisions')
->condition('content_entity_revision_id', $revision_to_use)
->execute();
$target_entity_type = $this->entityTypeManager
->getDefinition('content_moderation_state');
$this->connection
->update($target_entity_type
->getBaseTable())
->condition('id', array_values($content_moderation_ids)[0])
->fields([
'revision_id' => array_keys($content_moderation_ids)[0],
])
->execute();
$content_moderation_state_storage
->resetCache();
}
}
$this->entityTypeManager
->getStorage('config_entity_revisions')
->deleteRevision($revision
->getRevisionId());
}
public function deleteRevisions(ConfigEntityRevisionsConfigEntityInterface $config_entity) {
$contentEntity = $config_entity
->getContentEntity();
if ($contentEntity) {
$config_entity
->contentEntityStorage()
->delete([
$contentEntity,
]);
}
}
public function loadConfigEntityRevision($revision = NULL, $entity = '') {
$config_entity_name = $this
->configEntityName();
if (!$entity) {
$match = \Drupal::service('router')
->matchRequest(\Drupal::request());
$entity = $match[$config_entity_name];
}
if (is_string($entity)) {
$entity = $this->entityTypeManager
->getStorage($config_entity_name)
->load($entity);
}
if ($revision) {
$revisionsEntity = $this->entityTypeManager
->getStorage('config_entity_revisions')
->loadRevision($revision);
$entity = \Drupal::getContainer()
->get('serializer')
->deserialize($revisionsEntity
->get('configuration')->value, get_class($entity), 'json');
$entity
->set('settingsOriginal', $entity
->get('settings'));
$entity
->set('enforceIsNew', FALSE);
}
return $entity;
}
}