From d0851c208012fab840fcae0f9a5e95da8f487bb3 Mon Sep 17 00:00:00 2001 From: Dave Hall Date: Sun, 25 Nov 2012 22:58:56 +1100 Subject: [PATCH] Issue #1812202 by skwashd: Add revision UUIDs to Entity API and node --- .../Core/Entity/DatabaseStorageController.php | 18 ++++++++ core/lib/Drupal/Core/Entity/Entity.php | 10 +++++ core/lib/Drupal/Core/Entity/EntityInterface.php | 11 +++++ .../node/lib/Drupal/node/NodeStorageController.php | 1 + .../lib/Drupal/node/Plugin/Core/Entity/Node.php | 10 ++++- core/modules/node/node.install | 43 ++++++++++++++++++++ 6 files changed, 92 insertions(+), 1 deletion(-) diff --git a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php index bf515de..dbbcf1f 100644 --- a/core/lib/Drupal/Core/Entity/DatabaseStorageController.php +++ b/core/lib/Drupal/Core/Entity/DatabaseStorageController.php @@ -136,6 +136,14 @@ public function __construct($entityType) { $this->revisionKey = FALSE; } + // Check if the entity type supports revision UUIDs. + if (!empty($this->entityInfo['entity_keys']['vuuid'])) { + $this->vuuidKey = $this->entityInfo['entity_keys']['vuuid']; + } + else { + $this->vuuidKey = FALSE; + } + // Check if the entity type supports static caching of loaded entities. $this->cache = !empty($this->entityInfo['static_cache']); } @@ -555,6 +563,16 @@ protected function saveRevision(EntityInterface $entity) { // ensure that a new revision will actually be created. if ($entity->isNewRevision() && $record[$this->revisionKey]) { $record[$this->revisionKey] = NULL; + + // Generating a new revision should generate a new revision UUID. There are + // cases where external sources may preset the revision UUID, so we need to + // allow for that here. + if ($this->vuuidKey && (empty($record['vuuid']) + || (isset($entity->original) + && $entity->original->{$this->vuuidKey} == $record[$this->vuuidKey]))) { + $uuid = new Uuid(); + $record[$this->vuuidKey] = $uuid->generate(); + } } // Cast to object as preSaveRevision() expects one to be compatible with the diff --git a/core/lib/Drupal/Core/Entity/Entity.php b/core/lib/Drupal/Core/Entity/Entity.php index 979614f..7c14a75 100644 --- a/core/lib/Drupal/Core/Entity/Entity.php +++ b/core/lib/Drupal/Core/Entity/Entity.php @@ -88,6 +88,13 @@ public function uuid() { } /** + * Implements EntityInterface::vuuid(). + */ + public function vuuid() { + return isset($this->vuuid) ? $this->vuuid : NULL; + } + + /** * Implements EntityInterface::isNew(). */ public function isNew() { @@ -344,6 +351,9 @@ public function createDuplicate() { $uuid = new Uuid(); $duplicate->{$entity_info['entity_keys']['uuid']} = $uuid->generate(); } + if (!empty($entity_info['entity_keys']['vuuid'])) { + $duplicate->{$entity_info['entity_keys']['vuuid']} = NULL; + } return $duplicate; } diff --git a/core/lib/Drupal/Core/Entity/EntityInterface.php b/core/lib/Drupal/Core/Entity/EntityInterface.php index 9b751d4..ee7bb5b 100644 --- a/core/lib/Drupal/Core/Entity/EntityInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityInterface.php @@ -40,6 +40,17 @@ public function id(); public function uuid(); /** + * Returns the revision UUID (Universally Unique Identifier) for the entity. + * + * The revision UUID is guaranteed to be unique and can be used to identify + * an entity revision across multiple systems. + * + * @return string + * The revision UUID for the entity, or NULL if the entity does not have one. + */ + public function vuuid(); + + /** * Returns whether the entity is new. * * Usually an entity is new if no ID exists for it yet. However, entities may diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php index d855384..a7cd045 100644 --- a/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -9,6 +9,7 @@ use Drupal\Core\Entity\DatabaseStorageController; use Drupal\Core\Entity\EntityInterface; +use Drupal\Component\Uuid\Uuid; /** * Controller class for nodes. diff --git a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php index 1fd8fc8..0f537a4 100644 --- a/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php +++ b/core/modules/node/lib/Drupal/node/Plugin/Core/Entity/Node.php @@ -34,7 +34,8 @@ * "revision" = "vid", * "bundle" = "type", * "label" = "title", - * "uuid" = "uuid" + * "uuid" = "uuid", + * "vuuid" = "vuuid" * }, * bundle_keys = { * "bundle" = "type" @@ -89,6 +90,13 @@ class Node extends Entity implements ContentEntityInterface { public $uuid; /** + * The node revision UUID. + * + * @var string + */ + public $vuuid; + + /** * The node content type (bundle). * * @var string diff --git a/core/modules/node/node.install b/core/modules/node/node.install index c6fd7e6..b3abab5 100644 --- a/core/modules/node/node.install +++ b/core/modules/node/node.install @@ -213,6 +213,12 @@ function node_schema() { 'unsigned' => TRUE, 'not null' => TRUE, ), + 'vuuid' => array( + 'description' => 'The universally unique identifier (UUID) for this version.', + 'type' => 'varchar', + 'length' => 128, + 'not null' => FALSE, + ), 'uid' => array( 'description' => 'The {users}.uid that created this version.', 'type' => 'int', @@ -269,6 +275,9 @@ function node_schema() { 'uid' => array('uid'), ), 'primary key' => array('vid'), + 'unique keys' => array( + 'vuuid' => array('vuuid'), + ), 'foreign keys' => array( 'versioned_node' => array( 'table' => 'node', @@ -717,6 +726,40 @@ function node_update_8012() { update_module_enable(array('history')); } +/** + * Create a revision UUID column for node_revision and generate the UUIDs. + */ +function node_update_8013(&$sandbox) { + $spec = array( + 'description' => 'The universally unique identifier (UUID) for this version.', + 'type' => 'varchar', + 'length' => 128, + 'not null' => FALSE, + ); + $keys = array( + 'unique keys' => array( + 'vuuid' => array('vuuid'), + ), + ); + // Account for sites having the contributed UUID module installed. + if (db_field_exists('node_revision', 'vuuid')) { + db_change_field('node_revision', 'vuuid', 'vuuid', $spec, $keys); + } + else { + db_add_field('node_revision', 'vuuid', $spec, $keys); + } + + if (!isset($sandbox['progress'])) { + $sandbox['progress'] = 0; + $sandbox['last'] = 0; + $sandbox['max'] = db_query('SELECT COUNT(vid) FROM {node_revision} WHERE vuuid IS NULL')->fetchField(); + } + + $vids = db_query_range('SELECT vid FROM {node_revision} WHERE vid > :vid AND vuuid IS NULL ORDER BY vid ASC', 0, 10, array(':vid' => $sandbox['last']))->fetchCol(); + update_add_uuids($sandbox, 'node_revision', 'vid', $vids); + + $sandbox['#finished'] = empty($sandbox['max']) ? 1 : ($sandbox['progress'] / $sandbox['max']); +} /** * @} End of "addtogroup updates-7.x-to-8.x" -- 1.7.10.4