security update for uuid xmlsitemap file_field_path
This commit is contained in:
@@ -11,8 +11,7 @@
|
||||
class UuidEntityException extends Exception {}
|
||||
|
||||
/**
|
||||
* Helper function that returns entity info for all supported core modules,
|
||||
* relevant for UUID functionality.
|
||||
* Returns entity info for all supported core entities.
|
||||
*
|
||||
* @see uuid_entity_info()
|
||||
* @see uuid_schema_alter()
|
||||
@@ -76,9 +75,9 @@ function uuid_get_core_entity_info() {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implements of hook_entity_info_alter().
|
||||
* Implements hook_entity_info_alter().
|
||||
*
|
||||
* @see uuid_core_entity_info().
|
||||
* @see uuid_core_entity_info()
|
||||
*/
|
||||
function uuid_entity_info_alter(&$info) {
|
||||
foreach (uuid_get_core_entity_info() as $entity_type => $core_info) {
|
||||
@@ -91,21 +90,24 @@ function uuid_entity_info_alter(&$info) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements of hook_entity_property_info_alter().
|
||||
* Implements hook_entity_property_info_alter().
|
||||
*
|
||||
* This adds the UUID as an entity property for all UUID-enabled entities
|
||||
* which automatically gives us token and Rules integration.
|
||||
*/
|
||||
function uuid_entity_property_info_alter(&$info) {
|
||||
foreach (entity_get_info() as $entity_type => $entity_info) {
|
||||
if (isset($entity_info['uuid']) && $entity_info['uuid'] == TRUE && !empty($entity_info['entity keys']['uuid'])) {
|
||||
if (isset($entity_info['uuid']) && $entity_info['uuid'] == TRUE
|
||||
&& !empty($entity_info['entity keys']['uuid'])
|
||||
&& empty($info[$entity_type]['properties'][$entity_info['entity keys']['uuid']])) {
|
||||
$info[$entity_type]['properties'][$entity_info['entity keys']['uuid']] = array(
|
||||
'label' => t('UUID'),
|
||||
'type' => 'text',
|
||||
'description' => t('The universally unique ID.'),
|
||||
'schema field' => $entity_info['entity keys']['uuid'],
|
||||
);
|
||||
if (!empty($entity_info['entity keys']['revision uuid'])) {
|
||||
if (!empty($entity_info['entity keys']['revision uuid'])
|
||||
&& empty($info[$entity_type]['properties'][$entity_info['entity keys']['revision uuid']])) {
|
||||
$info[$entity_type]['properties'][$entity_info['entity keys']['revision uuid']] = array(
|
||||
'label' => t('Revision UUID'),
|
||||
'type' => 'text',
|
||||
@@ -118,7 +120,7 @@ function uuid_entity_property_info_alter(&$info) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements of hook_entity_presave().
|
||||
* Implements hook_entity_presave().
|
||||
*
|
||||
* This is where all UUID-enabled entities get their UUIDs.
|
||||
*/
|
||||
@@ -131,7 +133,19 @@ function uuid_entity_presave($entity, $entity_type) {
|
||||
}
|
||||
if (!empty($info['entity keys']['revision uuid'])) {
|
||||
$vuuid_key = $info['entity keys']['revision uuid'];
|
||||
if ((isset($entity->revision) && $entity->revision == TRUE) || empty($entity->{$vuuid_key})) {
|
||||
// If this entity comes from a remote environment and have a revision UUID
|
||||
// that exists locally we should not create a new revision. Because
|
||||
// otherwise revisions won't be tracked universally.
|
||||
// TODO: Move code dependent on the uuid_services module into it's own
|
||||
// implementation of hook_entity_presave().
|
||||
if (!empty($entity->uuid_services) && isset($entity->{$vuuid_key})) {
|
||||
$vuuid_exists = (bool) entity_get_id_by_uuid($entity_type, array($entity->{$vuuid_key}), TRUE);
|
||||
if ($vuuid_exists) {
|
||||
$entity->revision = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((isset($entity->revision) && $entity->revision == TRUE && empty($entity->uuid_services)) || empty($entity->{$vuuid_key})) {
|
||||
$entity->{$vuuid_key} = uuid_generate();
|
||||
}
|
||||
}
|
||||
@@ -151,12 +165,26 @@ function uuid_entity_presave($entity, $entity_type) {
|
||||
/**
|
||||
* Load entities by their UUID, that only should containing UUID references.
|
||||
*
|
||||
* Optionally load revisions by their VUUID by passing it into $conditions.
|
||||
* Ex. $conditions['vuuid'][$vuuid]
|
||||
*
|
||||
* This function is mostly useful if you want to load an entity from the local
|
||||
* database that only should contain UUID references.
|
||||
*
|
||||
* @see entity_load()
|
||||
*/
|
||||
function entity_uuid_load($entity_type, $uuids = array(), $conditions = array(), $reset = FALSE) {
|
||||
// Allow Revision UUID to be passed in $conditions and translate.
|
||||
$entity_info[$entity_type] = entity_get_info($entity_type);
|
||||
$revision_key = $entity_info[$entity_type]['entity keys']['revision'];
|
||||
if (isset($entity_info[$entity_type]['entity keys']['revision uuid'])) {
|
||||
$revision_uuid_key = $entity_info[$entity_type]['entity keys']['revision uuid'];
|
||||
}
|
||||
if (isset($revision_uuid_key) && isset($conditions[$revision_uuid_key])) {
|
||||
$revision_id = entity_get_id_by_uuid($entity_type, array($conditions[$revision_uuid_key]), TRUE);
|
||||
$conditions[$revision_key] = $revision_id[$conditions[$revision_uuid_key]];
|
||||
unset($conditions[$revision_uuid_key]);
|
||||
}
|
||||
$ids = entity_get_id_by_uuid($entity_type, $uuids);
|
||||
$results = entity_load($entity_type, $ids, $conditions, $reset);
|
||||
$entities = array();
|
||||
@@ -209,10 +237,27 @@ function entity_uuid_save($entity_type, $entity) {
|
||||
throw new UuidEntityException(t('Calling %function requires the Entity API module (!link).', array('%function' => __FUNCTION__, '!link' => 'http://drupal.org/project/entity')));
|
||||
}
|
||||
|
||||
$info = entity_get_info($entity_type);
|
||||
$uuid_key = $info['entity keys']['uuid'];
|
||||
if (empty($entity->{$uuid_key}) || !uuid_is_valid($entity->{$uuid_key})) {
|
||||
watchdog('Entity UUID', 'Attempted to save an entity with an invalid UUID', array(), WATCHDOG_ERROR);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Falling back on the variable node_options_[type] is not something an API
|
||||
// function should take care of. With normal (non UUID) nodes this is dealt
|
||||
// with in the form submit handler, i.e. not in node_save().
|
||||
// But since using entity_uuid_save() usually means you're trying to manage
|
||||
// entities remotely we do respect this variable here to make it work as the
|
||||
// node form, but only if we explicitly haven't set $node->revision already.
|
||||
if ($entity_type == 'node' && !isset($entity->revision) && in_array('revision', variable_get('node_options_' . $entity->type, array()))) {
|
||||
$entity->revision = 1;
|
||||
}
|
||||
|
||||
entity_make_entity_local($entity_type, $entity);
|
||||
|
||||
// Save the entity.
|
||||
entity_save($entity_type, $entity);
|
||||
$result = entity_save($entity_type, $entity);
|
||||
|
||||
$hook = 'entity_uuid_save';
|
||||
foreach (module_implements($hook) as $module) {
|
||||
@@ -221,6 +266,7 @@ function entity_uuid_save($entity_type, $entity) {
|
||||
$function($entity, $entity_type);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,6 +305,10 @@ function entity_make_entity_local($entity_type, $entity) {
|
||||
$vid = NULL;
|
||||
// Fetch the local revision ID by its UUID.
|
||||
if (isset($entity->{$vuuid_key})) {
|
||||
// It's important to note that the revision UUID might be set here but
|
||||
// there might not exist a correspondant local revision ID in which case
|
||||
// we should unset the assigned revision ID to not confuse anyone with
|
||||
// revision IDs that might come from other environments.
|
||||
$vids = entity_get_id_by_uuid($entity_type, array($entity->{$vuuid_key}), TRUE);
|
||||
$vid = reset($vids);
|
||||
}
|
||||
@@ -268,9 +318,10 @@ function entity_make_entity_local($entity_type, $entity) {
|
||||
elseif (!empty($vid)) {
|
||||
$entity->{$vid_key} = $vid;
|
||||
}
|
||||
// Nodes need this when trying to save an existing node without a vid.
|
||||
// If the revision ID was unset before this (or just missing for some
|
||||
// reason) we fetch the current revision ID to build a better
|
||||
// representation of the node object we're working with.
|
||||
if ($entity_type == 'node' && !isset($entity->vid) && !$entity->is_new) {
|
||||
$entity->revision = 0;
|
||||
$entity->vid = db_select('node', 'n')
|
||||
->condition('n.nid', $entity->nid)
|
||||
->fields('n', array('vid'))
|
||||
@@ -289,7 +340,7 @@ function entity_make_entity_local($entity_type, $entity) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new UuidEntityException(t('Trying to operate on a @type entity, which doesn\'t support UUIDs.', array('@type' => $info['label'])));
|
||||
throw new UuidEntityException(t("Trying to operate on a @type entity, which doesn\'t support UUIDs.", array('@type' => $info['label'])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -312,6 +363,7 @@ function entity_uuid_delete($entity_type, $uuid) {
|
||||
// Fetch the local ID by its UUID.
|
||||
$ids = entity_get_id_by_uuid($entity_type, array($uuid));
|
||||
$id = reset($ids);
|
||||
$entity = entity_load($entity_type, array($id));
|
||||
|
||||
// Let other modules transform UUID references to local ID references.
|
||||
$hook = 'entity_uuid_delete';
|
||||
@@ -322,11 +374,14 @@ function entity_uuid_delete($entity_type, $uuid) {
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($entity)) {
|
||||
return FALSE;
|
||||
}
|
||||
// Delete the entity.
|
||||
return entity_delete($entity_type, $id);
|
||||
}
|
||||
else {
|
||||
throw new UuidEntityException(t('Trying to delete a @type entity, which doesn\'t support UUIDs.', array('@type' => $info['label'])));
|
||||
throw new UuidEntityException(t("Trying to delete a @type entity, which doesn\'t support UUIDs.", array('@type' => $info['label'])));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,24 +389,34 @@ function entity_uuid_delete($entity_type, $uuid) {
|
||||
* Helper function that retrieves entity IDs by their UUIDs.
|
||||
*
|
||||
* @todo
|
||||
* Statically cache as many IDs as possible and limit the query.
|
||||
* Limit the query.
|
||||
*
|
||||
* @param $entity_type
|
||||
* @param string $entity_type
|
||||
* The entity type we should be dealing with.
|
||||
* @param $uuids
|
||||
* An array of UUIDs for which we should find their entity IDs. If $revision
|
||||
* @param array $uuids
|
||||
* List of UUIDs for which we should find their entity IDs. If $revision
|
||||
* is TRUE this should be revision UUIDs instead.
|
||||
* @param $revision
|
||||
* @param bool $revision
|
||||
* If TRUE the revision IDs is returned instead.
|
||||
* @return
|
||||
* Array of entity IDs keyed by their UUIDs. If $revision is TRUE revision
|
||||
*
|
||||
* @return array
|
||||
* List of entity IDs keyed by their UUIDs. If $revision is TRUE revision
|
||||
* IDs and UUIDs are returned instead.
|
||||
*/
|
||||
function entity_get_id_by_uuid($entity_type, $uuids, $revision = FALSE) {
|
||||
if (empty($uuids)) {
|
||||
return array();
|
||||
}
|
||||
$cached_ids = entity_uuid_id_cache($entity_type, $uuids, $revision);
|
||||
if (count($cached_ids) == count($uuids)) {
|
||||
return $cached_ids;
|
||||
}
|
||||
$uuids = array_diff($uuids, $cached_ids);
|
||||
$info = entity_get_info($entity_type);
|
||||
// Some contrib entities has no support for UUID, let's skip them.
|
||||
if (empty($info['uuid'])) {
|
||||
return array();
|
||||
}
|
||||
// Find out what entity keys to use.
|
||||
if (!$revision) {
|
||||
$table = $info['base table'];
|
||||
@@ -369,35 +434,61 @@ function entity_get_id_by_uuid($entity_type, $uuids, $revision = FALSE) {
|
||||
}
|
||||
|
||||
// Get all UUIDs in one query.
|
||||
return db_select($table, 't')
|
||||
$result = db_select($table, 't')
|
||||
->fields('t', array($uuid_key, $id_key))
|
||||
->condition($uuid_key, array_values($uuids), 'IN')
|
||||
->execute()
|
||||
->fetchAllKeyed();
|
||||
$cache = &drupal_static('entity_uuid_id_cache', array());
|
||||
$cache[$entity_type][(int) $revision] += $result;
|
||||
return $result + $cached_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper caching function.
|
||||
*/
|
||||
function entity_uuid_id_cache($entity_type, $ids, $revision) {
|
||||
$cache = &drupal_static(__FUNCTION__, array());
|
||||
if (empty($cache[$entity_type][(int) $revision])) {
|
||||
$cache[$entity_type][(int) $revision] = array();
|
||||
}
|
||||
$cached_ids = $cache[$entity_type][(int) $revision];
|
||||
return array_intersect_key($cached_ids, array_flip($ids));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that retrieves UUIDs by their entity IDs.
|
||||
*
|
||||
* @todo
|
||||
* Statically cache as many IDs as possible and limit the query.
|
||||
* Limit the query.
|
||||
*
|
||||
* @param $entity_type
|
||||
* @param string $entity_type
|
||||
* The entity type we should be dealing with.
|
||||
* @param $ids
|
||||
* An array of entity IDs for which we should find their UUIDs. If $revision
|
||||
* @param array $ids
|
||||
* List of entity IDs for which we should find their UUIDs. If $revision
|
||||
* is TRUE this should be revision IDs instead.
|
||||
* @param $revision
|
||||
* @param bool $revision
|
||||
* If TRUE the revision UUIDs is returned instead.
|
||||
* @return
|
||||
* Array of entity UUIDs keyed by their IDs. If $revision is TRUE revision
|
||||
*
|
||||
* @return array
|
||||
* List of entity UUIDs keyed by their IDs. If $revision is TRUE revision
|
||||
* IDs and UUIDs are returned instead.
|
||||
*/
|
||||
function entity_get_uuid_by_id($entity_type, $ids, $revision = FALSE) {
|
||||
if (empty($ids)) {
|
||||
return array();
|
||||
}
|
||||
$cached_ids = array_flip(entity_uuid_id_cache($entity_type, $ids, $revision));
|
||||
if (count($cached_ids) == count($ids)) {
|
||||
return $cached_ids;
|
||||
}
|
||||
$ids = array_diff($ids, $cached_ids);
|
||||
|
||||
$info = entity_get_info($entity_type);
|
||||
// Some contrib entities has no support for UUID, let's skip them.
|
||||
if (empty($info['uuid'])) {
|
||||
return array();
|
||||
}
|
||||
// Find out what entity keys to use.
|
||||
if (!$revision) {
|
||||
$table = $info['base table'];
|
||||
@@ -415,11 +506,14 @@ function entity_get_uuid_by_id($entity_type, $ids, $revision = FALSE) {
|
||||
}
|
||||
|
||||
// Get all UUIDs in one query.
|
||||
return db_select($table, 't')
|
||||
$result = db_select($table, 't')
|
||||
->fields('t', array($id_key, $uuid_key))
|
||||
->condition($id_key, array_values($ids), 'IN')
|
||||
->execute()
|
||||
->fetchAllKeyed();
|
||||
$cache = &drupal_static('entity_uuid_id_cache', array());
|
||||
$cache[$entity_type][(int) $revision] += array_flip($result);
|
||||
return $result + $cached_ids;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -432,12 +526,12 @@ function entity_get_uuid_by_id($entity_type, $ids, $revision = FALSE) {
|
||||
* @todo
|
||||
* Add tests for this function.
|
||||
*
|
||||
* @param $objects
|
||||
* An array of objects that should get $properties changed. Can be either an
|
||||
* @param array $objects
|
||||
* List of objects that should get $properties changed. Can be either an
|
||||
* entity object or a field items array.
|
||||
* @param $entity_type
|
||||
* @param string $entity_type
|
||||
* The type of entity that all $properties refers to.
|
||||
* @param $properties
|
||||
* @param array $properties
|
||||
* An array of properties that should be changed. All properties must refer to
|
||||
* the same type of entity (the one referenced in $entity_type).
|
||||
*/
|
||||
@@ -488,12 +582,12 @@ function entity_property_id_to_uuid(&$objects, $entity_type, $properties) {
|
||||
* @todo
|
||||
* Add tests for this function.
|
||||
*
|
||||
* @param $objects
|
||||
* An array of objects that should get $properties changed. Can be either an
|
||||
* @param array $objects
|
||||
* List of objects that should get $properties changed. Can be either an
|
||||
* entity object or a field items array.
|
||||
* @param $entity_type
|
||||
* @param string $entity_type
|
||||
* The type of entity that all $properties refers to.
|
||||
* @param $properties
|
||||
* @param array $properties
|
||||
* An array of properties that should be changed. All properties must refer to
|
||||
* the same type of entity (the one referenced in $entity_type).
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user