diff --git a/core/modules/entity/entity.api.php b/core/modules/entity/entity.api.php index 37263a6..7727b32 100644 --- a/core/modules/entity/entity.api.php +++ b/core/modules/entity/entity.api.php @@ -77,6 +77,10 @@ * 'subject' should be specified here. If complex logic is required to * build the label, a 'label callback' should be defined instead (see * the 'label callback' section above for details). + * - uuid: The name of the property that contains the universally unique + * identifier of the entity, which is used to distinctly identify an + * entity across different Drupal installations, and is therefore a + * prerequisite an entity being supported by a content staging mechanism. * - bundle keys: An array describing how the Field API can extract the * information it needs from the bundle objects for this type (e.g * $vocabulary objects for terms; not applicable for nodes). This entry can @@ -148,6 +152,7 @@ function hook_entity_info() { 'id' => 'nid', 'revision' => 'vid', 'bundle' => 'type', + 'uuid' => 'uuid', ), 'bundle keys' => array( 'bundle' => 'type', diff --git a/core/modules/entity/entity.module b/core/modules/entity/entity.module index daaa9f6..a339df7 100644 --- a/core/modules/entity/entity.module +++ b/core/modules/entity/entity.module @@ -217,6 +217,54 @@ function entity_load($entity_type, $id, $reset = FALSE) { } /** + * Load entity from the database by given UUID. + * + * If an entity type supports a UUID-type entity identifier, this function can + * find an entity by that UUID-type entity identifier. + * Not all entities support that kind of UUID-type entity identifier + * (which can be defined in hook_entity_info). + * + * @param string $entity_type + * The entity type to load, e.g. node or user. + * @param string $uuid + * The uuid of the entity to load. + * @param bool $reset + * Whether to reset the internal cache for the requested entity type. + * + * @return EntityInterface|FALSE + * The entity object, or FALSE if there is no entity with the given UUID. + * + * @see hook_entity_info() + * + */ +function entity_load_by_uuid($entity_type, $uuid, $reset = FALSE) { + $entity = FALSE; + + // Only consider entities that have a "uuid"-type key declared via + // hook_entity_info. + $entity_info = entity_get_info($entity_type); + if (is_array($entity_info) && isset($entity_info['entity keys']) && isset($entity_info['entity keys']['uuid'])) { + $uuid_key_name = $entity_info['entity keys']['uuid']; + + // Retrieve entity record for given uuid to get its entity id. + $entity_query = new Drupal\entity\EntityFieldQuery(); + $entity_query_result = $entity_query->entityCondition('entity_type', $entity_type) + ->propertyCondition($uuid_key_name, $uuid) + ->range(0, 1) + ->execute(); + + // Mine result for entity id and load the entity by its id. + if (is_array($entity_query_result) && isset($entity_query_result[$entity_type])) { + $entity_ids = array_keys($entity_query_result[$entity_type]); + $entity_id = array_shift($entity_ids); + $entity = entity_load($entity_type, $entity_id, $reset); + } + } + + return $entity; +} + +/** * Loads multiple entities from the database. * * This function should be used whenever you need to load more than one entity diff --git a/core/modules/node/lib/Drupal/node/Node.php b/core/modules/node/lib/Drupal/node/Node.php index 1aac6fb..9694624 100644 --- a/core/modules/node/lib/Drupal/node/Node.php +++ b/core/modules/node/lib/Drupal/node/Node.php @@ -29,6 +29,13 @@ class Node extends Entity { public $vid; /** + * The node UUID. + * + * @var integer + */ + public $uuid; + + /** * The node content type (bundle). * * @var string diff --git a/core/modules/node/lib/Drupal/node/NodeStorageController.php b/core/modules/node/lib/Drupal/node/NodeStorageController.php index aa52582..897b387 100644 --- a/core/modules/node/lib/Drupal/node/NodeStorageController.php +++ b/core/modules/node/lib/Drupal/node/NodeStorageController.php @@ -10,6 +10,7 @@ namespace Drupal\node; use Drupal\entity\DatabaseStorageController; use Drupal\entity\EntityInterface; use Drupal\entity\EntityStorageException; +use Drupal\Component\Uuid\Uuid; use Exception; /** @@ -30,6 +31,8 @@ class NodeStorageController extends DatabaseStorageController { if (empty($node->created)) { $node->created = REQUEST_TIME; } + $uuid = new Uuid(); + $node->uuid = $uuid->generate(); return $node; } diff --git a/core/modules/node/node.install b/core/modules/node/node.install index 6f806e9..34aebd8 100644 --- a/core/modules/node/node.install +++ b/core/modules/node/node.install @@ -27,6 +27,13 @@ function node_schema() { 'not null' => FALSE, 'default' => NULL, ), + 'uuid' => array( + 'description' => 'The universally unique identifier for a node.', + 'type' => 'varchar', + 'length' => 36, + 'not null' => TRUE, + 'default' => '', + ), 'type' => array( 'description' => 'The {node_type}.type of this node.', 'type' => 'varchar', @@ -114,6 +121,7 @@ function node_schema() { 'uid' => array('uid'), 'tnid' => array('tnid'), 'translate' => array('translate'), + 'uuid' => array('uuid'), ), 'unique keys' => array( 'vid' => array('vid'), @@ -543,6 +551,31 @@ function node_update_8002() { } /** + * Create an uuid column for node table. + * + * @ToDo: Batch generate uuids for all existing nodes without a uuid. + */ +function node_update_8003() { + db_add_field( + 'node', + 'uuid', + array( + 'description' => 'The universally unique identifier for a node.', + 'type' => 'varchar', + 'length' => 36, + 'not null' => TRUE, + 'default' => '', + ), + array( + 'indexes' => array( + 'uuid' => array('uuid'), + ) + ) + ); +} + + +/** * @} End of "addtogroup updates-7.x-to-8.x". * The next series of updates should start at 9000. */ diff --git a/core/modules/node/node.module b/core/modules/node/node.module index e787c7d..8c8a482 100644 --- a/core/modules/node/node.module +++ b/core/modules/node/node.module @@ -204,6 +204,7 @@ function node_entity_info() { 'revision' => 'vid', 'bundle' => 'type', 'label' => 'title', + 'uuid' => 'uuid', ), 'bundle keys' => array( 'bundle' => 'type',