updated webform localization and phone, uuid, term_merge, spambot, performance

This commit is contained in:
Bachir Soussi Chiadmi
2016-11-05 17:14:57 +01:00
parent fdefc824d8
commit 0521608bb7
57 changed files with 3592 additions and 1629 deletions

View File

@@ -0,0 +1,74 @@
language: php
sudo: false
php:
- 5.5
- 5.6
- 7.0
- hhvm
matrix:
fast_finish: true
allow_failures:
- php: hhvm
mysql:
database: drupal
username: root
encoding: utf8
install:
# add composer's global bin directory to the path
# see: https://github.com/drush-ops/drush#install---composer
- export PATH="$HOME/.composer/vendor/bin:$PATH"
# install drush globally
- composer global require drush/drush:7.*
# Install PHP_CodeSniffer and Drupal config
- composer global require drupal/coder
- phpcs --config-set installed_paths ~/.composer/vendor/drupal/coder/coder_sniffer
# Create the database
- mysql -e 'create database drupal;'
before_script:
# Disable sendmail
- echo sendmail_path=`which true` >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
# Increase the MySQL connection timeout on the PHP end.
- echo "mysql.connect_timeout=3000" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
- echo "default_socket_timeout=3000" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
# Increase the MySQL server timetout and packet size.
- mysql -e "SET GLOBAL wait_timeout = 36000;"
- mysql -e "SET GLOBAL max_allowed_packet = 33554432;"
# Download Drupal 7.x
- drush pm-download drupal-7 --destination=/tmp --drupal-project-rename=drupal
# Add our module
- ln -s $(pwd) /tmp/drupal/sites/all/modules/
# Switch to the drupal site directory
- cd /tmp/drupal
# Install site and dependencies
- drush -vv --yes site-install --db-url=mysql://root:@127.0.0.1/drupal
- drush pm-download entity
- drush pm-enable simpletest entity uuid --yes
# Use the PHP builtin webserver to serve the site.
#- drush runserver 8080 > /dev/null 2>&1 &
- drush runserver 127.0.0.1:8888 > ~/server.log 2>&1 &
- export counter=0; until nc -zv localhost 8888; do if [ $counter -ge 12 ]; then echo "Failed to start server."; exit 1; fi; echo "Waiting for web server to start on port 8888..."; sleep 5; counter=$[$counter +1]; done
script:
- cd /tmp/drupal
- php ./scripts/run-tests.sh --verbose --color --php "$(which php)" --url http://127.0.0.1:8888 UUID | tee ~/tests.log
- phpcs --standard=Drupal --extensions=php,module,inc,install,test,profile,theme sites/all/modules/uuid
after_failure:
# See what happened with the server.
- cat ~/server.log

View File

@@ -11,6 +11,7 @@ FEATURES
* Automatic UUID generation:
UUIDs will be generated for all core entities. An API is provided for other
modules to enable support for custom entities.
See https://www.drupal.org/node/2387671
* UUID API for entities, properties and fields:
With this unified API you can load entities with entity_uuid_load() so that
all supported properties and fields are made with UUID references. You can

View File

@@ -6,8 +6,7 @@
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
* CTools UUID entity context plugin definition.
*/
$plugin = array(
'title' => t("Entity: UUID"),
@@ -18,7 +17,12 @@ $plugin = array(
);
/**
* @todo document me properly
* Fetches the "child" information for a given parent entity.
*
* @todo document me properly.
*
* @return array
* The children.
*/
function uuid_entity_uuid_get_child($plugin, $parent, $child) {
$plugins = uuid_entity_uuid_get_children($plugin, $parent);
@@ -26,7 +30,12 @@ function uuid_entity_uuid_get_child($plugin, $parent, $child) {
}
/**
* @todo document me properly
* Fetches all children types for a given parent entity.
*
* @todo document me properly.
*
* @return array
* All the children.
*/
function uuid_entity_uuid_get_children($original_plugin, $parent) {
$entities = entity_get_info();

View File

@@ -42,7 +42,9 @@ function uuid_devel_load_by_uuid($entity_type, $entity) {
// Get the keys for local ID and UUID.
$uuid_key = $info['entity keys']['uuid'];
$uuid_entities = entity_uuid_load($entity_type, array($entity->{$uuid_key}));
// @codingStandardsIgnoreStart
return kdevel_print_object(reset($uuid_entities), '$' . $entity_type . '->');
// @codingStandardsIgnoreEnd
}
else {
return t("This entity doesn't support UUID.");

View File

@@ -5,26 +5,6 @@
* Hooks provided by the UUID module.
*/
/**
* Defines one or more UUID generators exposed by a module.
*
* @return
* An associative array with the key being the machine name for the
* implementation and the values being an array with the following keys:
* - title: The human readable name for the generator.
* - callback: The function to be called for generating the UUID.
*
* @see uuid_get_info()
*/
function hook_uuid_info() {
$generators = array();
$generators['my_module'] = array(
'title' => t('My module UUID generator'),
'callback' => 'my_module_generate_uuid',
);
return $generators;
}
/**
* Ensures all records have a UUID assigned to them.
*
@@ -38,39 +18,35 @@ function hook_uuid_sync() {
}
/**
* Let modules transform their properties with local IDs to UUIDs when an
* entity is loaded.
* Transform entity properties from local IDs to UUIDs when they are loaded.
*/
function hook_entity_uuid_load(&$entities, $entity_type) {
}
/**
* Let modules transform their fields with local IDs to UUIDs when an entity
* is loaded.
* Transform field values from local IDs to UUIDs when an entity is loaded.
*/
function hook_field_uuid_load($entity_type, $entity, $field, $instance, $langcode, &$items) {
}
/**
* Let modules transform their properties with UUIDs to local IDs when an
* entity is saved.
* Transform entity properties from UUIDs to local IDs before entity is saved.
*/
function hook_entity_uuid_presave(&$entity, $entity_type) {
}
/**
* Let modules transform their fields with UUIDs to local IDs when an entity
* is saved.
* Transform field values from UUIDs to local IDs before an entity is saved.
*/
function hook_field_uuid_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
}
/**
* Let modules transform their properties when an entity is saved.
* Transform entity properties after an entity is saved.
*/
function hook_entity_uuid_save($entity, $entity_type) {
@@ -78,20 +54,24 @@ function hook_entity_uuid_save($entity, $entity_type) {
/**
* Let modules act when an entity is deleted.
*
* Generally hook_entity_delete() should be used instead of this hook.
*
* @see hook_entity_delete()
*/
function hook_entity_uuid_delete($entity, $entity_type) {
}
/**
* Let modules modify paths when they are being converted to UUID ones.
* Modifies paths when they are being converted to UUID ones.
*/
function hook_uuid_menu_path_to_uri_alter($path, &$uri) {
}
/**
* Let modules modify paths when they are being converted from UUID ones.
* Modifies paths when they are being converted from UUID ones.
*/
function hook_uuid_menu_uri_to_path(&$path, $uri) {

View File

@@ -32,6 +32,31 @@ function node_entity_uuid_presave(&$entity, $entity_type) {
if ($entity_type == 'node') {
entity_property_uuid_to_id($entity, 'user', array('uid', 'revision_uid'));
entity_property_uuid_to_id($entity, 'node', 'tnid');
// A node always must have an author.
if (empty($entity->uid)) {
global $user;
$entity->uid = $user->uid;
}
}
}
/**
* Implements hook_entity_uuid_save().
*/
function node_entity_uuid_save(&$entity, $entity_type) {
/*
* When a node is translated, the source node's tnid is set to it's own nid.
* When deploying the node for the first time the tnid can't be translated
* to an nid until after the node has been saved. So if the entity's tnid
* is still a uuid at this point it needs to be translated to an nid.
*/
if ($entity_type == 'node' && uuid_is_valid($entity->tnid)) {
entity_property_uuid_to_id($entity, 'node', 'tnid');
db_update('node')
->fields(array('tnid' => $entity->tnid))
->condition('nid', $entity->nid)
->execute();
}
}
@@ -64,17 +89,33 @@ function book_entity_uuid_presave(&$entity, $entity_type) {
* Implements hook_entity_uuid_presave().
*/
function user_entity_uuid_presave(&$entity, $entity_type) {
if ($entity_type == 'user') {
if (!empty($entity->picture)) {
$uuids = entity_get_id_by_uuid('file', array($entity->picture['uuid']));
$fid = current($uuids);
if (!$entity->is_new) {
$entity->picture = file_load($fid);
}
else {
$entity->picture = $fid;
}
}
if ($entity_type != 'user') {
return;
}
/*
* We need to ensure new user's passwords are encrypted. The Services module
* transparently encrypts the password for new users. md5() is used by
* users who's accounts were migrated from Drupal 6 and who haven't updated
* their password.
*/
if (isset($entity->pass)
&& (!('$S$D' == substr($entity->pass, 0, 4)) || preg_match('/^[a-f0-9]{32}$/', $entity->pass))) {
// Ensure user's password is hashed.
$entity->pass = user_hash_password($entity->pass);
}
if (empty($entity->picture)) {
return;
}
$uuids = entity_get_id_by_uuid('file', array($entity->picture['uuid']));
$fid = current($uuids);
if (!$entity->is_new) {
$entity->picture = file_load($fid);
}
else {
$entity->picture = $fid;
}
}
@@ -104,6 +145,10 @@ function comment_entity_uuid_presave(&$entity, $entity_type) {
break;
case 'comment':
// entity_make_entity_local() may have unset cid, add back if necessary.
if (!isset($entity->cid)) {
$entity->cid = NULL;
}
entity_property_uuid_to_id($entity, 'user', array('uid', 'u_uid'));
entity_property_uuid_to_id($entity, 'node', 'nid');
break;
@@ -124,10 +169,14 @@ function file_entity_uuid_load(&$entities, $entity_type) {
*/
function file_entity_uuid_presave(&$entity, $entity_type) {
if ($entity_type == 'file') {
// entity_make_entity_local() may have unset fid, add back if necessary.
if (!isset($entity->fid)) {
$entity->fid = NULL;
}
entity_property_uuid_to_id($entity, 'user', 'uid');
// Write the new file to the local filesystem.
if (isset($entity->file_contents)) {
if (isset($entity->file_contents) && !empty($entity->filesize)) {
// Don't try to write it if it uses a stream wrapper that isn't writeable
// (for example, if it is a remotely-hosted video).
$scheme = file_uri_scheme($entity->uri);
@@ -169,8 +218,9 @@ function file_entity_uuid_presave(&$entity, $entity_type) {
}
$directory = drupal_dirname($uri);
file_prepare_directory($directory, FILE_CREATE_DIRECTORY);
$entity->uri = file_unmanaged_save_data(base64_decode($entity->file_contents), $uri, $replace);
if (!empty($directory) && file_prepare_directory($directory, FILE_CREATE_DIRECTORY)) {
$entity->uri = file_unmanaged_save_data(base64_decode($entity->file_contents), $uri, $replace);
}
}
}
}
@@ -214,7 +264,7 @@ function taxonomy_entity_uuid_presave(&$entity, $entity_type) {
* Implements hook_entity_uuid_load().
*/
function field_entity_uuid_load(&$entities, $entity_type) {
foreach ($entities as $i => $entity) {
foreach ($entities as $entity) {
list(, , $bundle_name) = entity_extract_ids($entity_type, $entity);
$instances = field_info_instances($entity_type, $bundle_name);
@@ -311,34 +361,8 @@ function image_field_uuid_presave($entity_type, $entity, $field, $instance, $lan
/**
* Implements hook_field_uuid_load().
*/
function node_reference_field_uuid_load($entity_type, $entity, $field, $instance, $langcode, &$items) {
entity_property_id_to_uuid($items, 'node', 'nid');
}
/**
* Implements hook_field_uuid_presave().
*/
function node_reference_field_uuid_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
entity_property_uuid_to_id($items, 'node', 'nid');
}
/**
* Implements hook_field_uuid_load().
*/
function user_reference_field_uuid_load($entity_type, $entity, $field, $instance, $langcode, &$items) {
entity_property_id_to_uuid($items, 'user', 'uid');
}
/**
* Implements hook_field_uuid_presave().
*/
function user_reference_field_uuid_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
entity_property_uuid_to_id($items, 'user', 'uid');
}
/**
* Implements hook_field_uuid_load().
*
* Kept here because it is in D8 core.
*/
function entityreference_field_uuid_load($entity_type, $entity, $field, $instance, $langcode, &$items) {
// TODO: This is not really good, but as of now 'entity_property_id_to_uuid()'
@@ -348,6 +372,8 @@ function entityreference_field_uuid_load($entity_type, $entity, $field, $instanc
/**
* Implements hook_field_uuid_presave().
*
* Kept here because it is in D8 core.
*/
function entityreference_field_uuid_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
// TODO: This is not really good, but as of now 'entity_property_id_to_uuid()'
@@ -355,38 +381,6 @@ function entityreference_field_uuid_presave($entity_type, $entity, $field, $inst
entity_property_uuid_to_id($items, $field['settings']['target_type'], 'target_id');
}
/**
* Implements hook_entity_uuid_load().
*/
function field_collection_entity_uuid_load(&$entities, $entity_type) {
if ($entity_type == 'field_collection_item') {
entity_property_id_to_uuid($entities, 'field_collection_item', 'value');
}
}
/**
* Implements hook_entity_uuid_presave().
*/
function field_collection_entity_uuid_presave(&$entity, $entity_type) {
if ($entity_type == 'field_collection_item') {
entity_property_uuid_to_id($entity, 'field_collection_item', 'value');
}
}
/**
* Implements hook_field_uuid_load().
*/
function field_collection_field_uuid_load($entity_type, $entity, $field, $instance, $langcode, &$items) {
entity_property_id_to_uuid($items, 'field_collection_item', 'value');
}
/**
* Implements hook_field_uuid_presave().
*/
function field_collection_field_uuid_presave($entity_type, $entity, $field, $instance, $langcode, &$items) {
entity_property_uuid_to_id($items, 'field_collection_item', 'value');
}
/**
* @} End of "Field implementations"
*/
@@ -400,24 +394,35 @@ function field_collection_field_uuid_presave($entity_type, $entity, $field, $ins
* Implements hook_uuid_entities_features_export_entity_alter().
*/
function node_uuid_entities_features_export_entity_alter(&$entity, $entity_type) {
if ($entity_type == 'node') {
foreach (array('data', 'name', 'picture', 'revision_uid', 'last_comment_timestamp') as $property) {
if (property_exists($entity, $property)) {
unset($entity->{$property});
}
if ('node' != $entity_type) {
return;
}
$properties = array(
'data',
'name',
'picture',
'revision_uid',
'last_comment_timestamp',
);
foreach ($properties as $property) {
if (property_exists($entity, $property)) {
unset($entity->{$property});
}
}
}
/**
* Implementations hook_uuid_entities_features_export_entity_alter().
* Implements hook_uuid_entities_features_export_entity_alter().
*/
function user_uuid_entities_features_export_entity_alter(&$entity, $entity_type) {
if ($entity_type == 'user') {
foreach (array('data', 'access', 'login') as $property) {
if (property_exists($entity, $property)) {
unset($entity->{$property});
}
if ('user' != $entity_type) {
return;
}
foreach (array('data', 'access', 'login') as $property) {
if (property_exists($entity, $property)) {
unset($entity->{$property});
}
}
}
@@ -433,17 +438,6 @@ function file_uuid_entities_features_export_field_alter($entity_type, $entity, $
}
}
/**
* Implements hook_uuid_entities_features_export_entity_alter().
*/
function workbench_uuid_entities_features_export_entity_alter(&$entity, $entity_type) {
foreach (array('workbench_moderation', 'my_revision', 'workbench_access', 'workbench_access_scheme', 'workbench_access_by_role') as $property) {
if (isset($entity->{$property})) {
unset($entity->{$property});
}
}
}
/**
* @} End of "Export alterations"
*/

View File

@@ -6,7 +6,7 @@
*/
/**
* Implementats hook_drush_command().
* Implements hook_drush_command().
*/
function uuid_drush_command() {
$items = array();
@@ -18,7 +18,7 @@ function uuid_drush_command() {
}
/**
* Implementats of hook_drush_help().
* Implements hook_drush_help().
*/
function uuid_drush_help($section) {
switch ($section) {

View File

@@ -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()
@@ -98,7 +97,7 @@ function uuid_entity_info_alter(&$info) {
*/
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
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(
@@ -107,7 +106,7 @@ function uuid_entity_property_info_alter(&$info) {
'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'),
@@ -258,7 +257,7 @@ function entity_uuid_save($entity_type, $entity) {
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) {
@@ -267,6 +266,7 @@ function entity_uuid_save($entity_type, $entity) {
$function($entity, $entity_type);
}
}
return $result;
}
/**
@@ -340,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'])));
}
}
@@ -381,7 +381,7 @@ function entity_uuid_delete($entity_type, $uuid) {
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'])));
}
}
@@ -389,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'];
@@ -424,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'];
@@ -470,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;
}
/**
@@ -487,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).
*/
@@ -543,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).
*/

View File

@@ -84,7 +84,15 @@ function uuid_entities_features_export_render($module_name, $components, $export
}
// We unset some common timestamp properties, since those will change and
// constantly leave the feature overidden.
$keys = array('created', 'updated', 'changed', 'revision_timestamp', 'timestamp', 'stamp', 'current');
$keys = array(
'created',
'updated',
'changed',
'revision_timestamp',
'timestamp',
'stamp',
'current',
);
foreach ($keys as $key) {
if (isset($entity->{$key})) {
unset($entity->{$key});
@@ -121,7 +129,10 @@ function uuid_entities_features_export_render($module_name, $components, $export
}
uuid_entities_features_clean($entity);
// Convert entities to array to avoid having them in JSON, returned from standard implementation of $entity->export().
/*
* Convert entities to array to avoid having them in JSON, returned
* from standard implementation of $entity->export().
*/
if (is_object($entity) && method_exists($entity, 'export')) {
$entity = get_object_vars($entity);
}
@@ -134,14 +145,14 @@ function uuid_entities_features_export_render($module_name, $components, $export
}
/**
* Implements [component]_features_export_rebuild().
* Implements [component]_features_rebuild().
*/
function uuid_entities_features_rebuild($module_name) {
uuid_entities_rebuild($module_name, 'rebuild');
}
/**
* Implements [component]_features_export_revert().
* Implements [component]_features_revert().
*/
function uuid_entities_features_revert($module_name) {
uuid_entities_rebuild($module_name, 'revert');

View File

@@ -8,7 +8,7 @@
/**
* Pattern for detecting a valid UUID.
*/
define('UUID_PATTERN', '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}');
define('UUID_PATTERN', '[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-5][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}');
/**
* Generates an universally unique identifier.
@@ -17,7 +17,7 @@ define('UUID_PATTERN', '[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}');
* universally unique identifiers. If that doesn't exist, then it falls back on
* PHP for generating that.
*
* @return
* @return string
* An UUID, made up of 32 hex digits and 4 hyphens.
*/
function uuid_generate() {
@@ -37,6 +37,61 @@ function uuid_generate() {
return $callback();
}
/**
* Generates a version 5 compliant UUID.
*
* @param string $namespace
* Namespace UUID as a hex encoded string.
* @param string $name
* The name for the generating the UUID.
*
* @return string
* UUID as a hex encoded string.
*
* @link http://www.php.net/manual/en/function.uniqid.php#94959 Code lifted from
* PHP manual comment by Andrew Moore. @endlink
*/
function uuid_generate_v5($namespace, $name) {
if (!uuid_is_valid($namespace)) {
return FALSE;
}
// Get hexadecimal components of namespace.
$nhex = str_replace(array('-', '{', '}'), '', $namespace);
// Binary Value.
$nstr = '';
// Convert Namespace UUID to bits.
for ($i = 0; $i < strlen($nhex); $i += 2) {
$nstr .= chr(hexdec($nhex[$i] . $nhex[$i + 1]));
}
// Calculate hash value.
$hash = sha1($nstr . $name);
return sprintf('%08s-%04s-%04x-%04x-%12s',
// 32 bits for "time_low".
substr($hash, 0, 8),
// 16 bits for "time_mid".
substr($hash, 8, 4),
// 16 bits for "time_hi_and_version",
// four most significant bits holds version number 5.
(hexdec(substr($hash, 12, 4)) & 0x0fff) | 0x5000,
// 16 bits, 8 bits for "clk_seq_hi_res",
// 8 bits for "clk_seq_low",
// two most significant bits holds zero and one for variant DCE1.1.
(hexdec(substr($hash, 16, 4)) & 0x3fff) | 0x8000,
// 48 bits for "node".
substr($hash, 20, 12)
);
}
/**
* Generate all missing UUIDs.
*/
@@ -53,7 +108,7 @@ function uuid_sync_all() {
* The type of entity being used.
*
* @return string
* The generated UUID URI or normal URI if entity doesn't support UUIDs.
* The generated UUID URI or normal URI if entity doesn't support UUIDs.
*/
function uuid_entity_uuid_uri($entity, $entity_type) {
$entity_info = entity_get_info($entity_type);
@@ -73,13 +128,13 @@ function uuid_entity_uuid_uri($entity, $entity_type) {
/**
* Converts an ID URI string to an entity data array.
*
* @see uuid_id_uri_array_to_data()
*
* @param string $uri
* The URI to convert.
* The URI to convert.
*
* @return array
* The entity data.
* The entity data.
*
* @see uuid_id_uri_array_to_data()
*/
function uuid_id_uri_to_data($uri) {
$parts = explode('/', $uri);
@@ -90,10 +145,10 @@ function uuid_id_uri_to_data($uri) {
* Converts a URI array to entity data array.
*
* @param array $uri
* The URI parts, often taken from arg().
* The URI parts, often taken from arg().
*
* @return array
* The entity data.
* The entity data.
*/
function uuid_id_uri_array_to_data($uri) {
$data = array(
@@ -110,13 +165,13 @@ function uuid_id_uri_array_to_data($uri) {
/**
* Converts a UUID URI string to an entity data array.
*
* @see uuid_uri_array_to_data()
*
* @param string $uri
* The URI to convert.
* The URI to convert.
*
* @return array
* The entity data.
* The entity data.
*
* @see uuid_uri_array_to_data()
*/
function uuid_uri_to_data($uri, $strip_uuid = TRUE) {
return uuid_uri_array_to_data(explode('/', $uri));
@@ -126,10 +181,10 @@ function uuid_uri_to_data($uri, $strip_uuid = TRUE) {
* Converts a URI array to entity data array.
*
* @param array $uri
* The URI parts, often taken from arg().
* The URI parts, often taken from arg().
*
* @return array
* The entity data.
* The entity data.
*/
function uuid_uri_array_to_data($uri, $strip_uuid = TRUE) {
if ($strip_uuid) {
@@ -138,8 +193,8 @@ function uuid_uri_array_to_data($uri, $strip_uuid = TRUE) {
$data = array(
'request' => $uri,
'entity_type' => $uri[0],
'uuid' => $uri[1],
'entity_type' => isset($uri[0]) ? $uri[0] : NULL,
'uuid' => isset($uri[1]) ? $uri[1] : NULL,
);
drupal_alter('uuid_uri_data', $data);
@@ -165,40 +220,56 @@ function _uuid_generate_pecl() {
}
/**
* Generates a UUID v4 using PHP code.
* Generates a UUID v4 (RFC 4122 section 4.4) using PHP code.
*
* Based on code from http://php.net/uniqid#65879, but corrected.
* @see http://www.rfc-editor.org/rfc/rfc4122.txt
*
* The UUID layout and fields are defined in section 4.1.2.
*
* Note that there are inconsistencies in the RFC with respect to
* bit numbering. Network Order is correct, so the most significant bit
* always appears first (in left-to-right sequence). See errata 3546:
* http://www.rfc-editor.org/errata_search.php?rfc=4122&eid=3546
*
* Based on code from http://php.net/uniqid
*/
function _uuid_generate_php() {
// The field names refer to RFC 4122 section 4.1.2.
// We limit each generated number to 16 bits (maximum value 0xffff)
// because mt_rand() returns a *signed* integer, and hence a 32-bit
// value can only have a 31-bit magnitude. Constructing a 32-bit
// number from two 16-bit random numbers guarantees that all 32 bits
// are random.
return sprintf('%04x%04x-%04x-4%03x-%04x-%04x%04x%04x',
// 32 bits for "time_low".
mt_rand(0, 65535), mt_rand(0, 65535),
mt_rand(0, 0xffff), mt_rand(0, 0xffff),
// 16 bits for "time_mid".
mt_rand(0, 65535),
// 12 bits after the 0100 of (version) 4 for "time_hi_and_version".
mt_rand(0, 4095),
bindec(substr_replace(sprintf('%016b', mt_rand(0, 65535)), '10', 0, 2)),
// 8 bits, the last two of which (positions 6 and 7) are 01, for "clk_seq_hi_res"
// (hence, the 2nd hex digit after the 3rd hyphen can only be 1, 5, 9 or d)
// 8 bits for "clk_seq_low" 48 bits for "node".
mt_rand(0, 65535), mt_rand(0, 65535), mt_rand(0, 65535)
mt_rand(0, 0xffff),
// 12 bits after the initial 0100 (version 4) for "time_hi_and_version".
mt_rand(0, 0x0fff),
// 16 bits in total for "clk_seq_hi_res" and "clk_seq_low", with the
// most significant 2 bits of clk_seq_hi_res set to '10'. We do a
// bitwise OR of a random 14-bit value (maximum 0x3fff) with 0x8000
// (a 16-bit integer with only the most significant bit set).
mt_rand(0, 0x3fff) | 0x8000,
// 48 bits for "node".
mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
);
}
// This is wrapped in an if block to avoid conflicts with PECL's uuid_is_valid().
// The if block avoids conflicts with PECL's uuid_is_valid().
if (!function_exists('uuid_is_valid')) {
/**
* Check that a string appears to be in the format of a UUID.
*
* @param $uuid
* The string to test.
* @param string $uuid
* The string to test.
*
* @return
* TRUE if the string is well formed.
* @return bool
* TRUE if the string is well formed.
*/
function uuid_is_valid($uuid) {
return preg_match('/^' . UUID_PATTERN . '$/', $uuid);
}
}

View File

@@ -7,9 +7,9 @@ files[] = uuid.test
dependencies[] = node
dependencies[] = user
; Information added by Drupal.org packaging script on 2014-09-23
version = "7.x-1.0-alpha6"
; Information added by Drupal.org packaging script on 2016-08-02
version = "7.x-1.0-beta2"
core = "7.x"
project = "uuid"
datestamp = "1411455150"
datestamp = "1470153540"

View File

@@ -31,12 +31,26 @@ function uuid_schema_field_definition() {
/**
* Implements hook_schema_alter().
*/
function uuid_schema_alter(&$schema = array()) {
$field = uuid_schema_field_definition();
foreach (uuid_get_core_entity_info() as $entity_type => $info) {
$schema[$info['base table']]['fields'][$info['entity keys']['uuid']] = $field;
if (!empty($info['revision table']) && !empty($info['entity keys']['revision uuid'])) {
$schema[$info['revision table']]['fields'][$info['entity keys']['revision uuid']] = $field;
function uuid_schema_alter(array &$schema) {
$field_info = uuid_schema_field_definition();
$key_names = array(
'base table' => 'uuid',
'revision table' => 'revision uuid',
);
foreach (uuid_get_core_entity_info() as $entity_info) {
foreach ($key_names as $table_type => $key_name) {
if (isset($entity_info[$table_type], $entity_info['entity keys'][$key_name])) {
$field_name = $entity_info['entity keys'][$key_name];
$properties = array(
'fields' => $field_info,
'indexes' => array($field_name),
);
foreach ($properties as $property => $value) {
$schema[$entity_info[$table_type]][$property][$field_name] = $value;
}
}
}
}
}
@@ -46,19 +60,20 @@ function uuid_schema_alter(&$schema = array()) {
*/
function uuid_install() {
_uuid_install_uuid_fields();
module_load_include('inc', 'uuid');
uuid_sync_all();
}
/**
* Install the 'uuid' and 'vuuid' fields into Drupal core entity tables where needed.
* Install the uuid and vuuid fields for Drupal core entity tables where needed.
*
* IMPORTANT: This function is called both at install and update time. If this method
* is modified to add additional fields in the future, the update strategy must be
* considered. See the comment in uuid_update_7102.
* IMPORTANT: This function is called both at install and update time. If this
* method is modified to add additional fields in the future, the update
* strategy must be considered. See the comment in uuid_update_7102.
*/
function _uuid_install_uuid_fields() {
$field = uuid_schema_field_definition();
foreach (uuid_get_core_entity_info() as $entity_type => $info) {
foreach (uuid_get_core_entity_info() as $info) {
if (!db_field_exists($info['base table'], $info['entity keys']['uuid'])) {
db_add_field($info['base table'], $info['entity keys']['uuid'], $field);
db_add_index($info['base table'], $info['entity keys']['uuid'], array($info['entity keys']['uuid']));
@@ -76,7 +91,7 @@ function _uuid_install_uuid_fields() {
* Implements hook_uninstall().
*/
function uuid_uninstall() {
foreach (uuid_get_core_entity_info() as $entity_type => $info) {
foreach (uuid_get_core_entity_info() as $info) {
if (db_field_exists($info['base table'], $info['entity keys']['uuid'])) {
db_drop_field($info['base table'], $info['entity keys']['uuid']);
db_drop_index($info['base table'], $info['entity keys']['uuid']);
@@ -112,8 +127,7 @@ function uuid_update_6001() {
}
/**
* For each of out tables, drop the indexe on the UUID column and add a unique
* key on that column.
* Make all uuid columns unique keys instead of indexes.
*/
function uuid_update_6002() {
$ret = array();
@@ -138,8 +152,7 @@ function uuid_update_6003() {
}
/**
* Fix the column definitions for uuid columns in all tables
* to use the more efficient char spec.
* Change column definitions for uuid columns to more efficient char spec.
*/
function uuid_update_6004() {
$ret = array();
@@ -158,6 +171,8 @@ function uuid_update_6004() {
}
/**
* Support deleting node revision.
*
* Modify existing uuid_node_revisions table to support revision deletion, and
* add in as much legacy data as possible.
*/
@@ -204,15 +219,17 @@ function uuid_update_7100() {
}
/**
* Clear cache for installations that used alpha1. Modules that previously was
* enabled in uuid_update_7100() doesn't exist anymore.
* Clear cache for installations that used alpha1.
*
* Modules previously enabled in uuid_update_7100() don't exist any more. We
* need to clear the cache so Drupal detects this change.
*/
function uuid_update_7101() {
drupal_flush_all_caches();
}
/**
* Insure that the uuid and vuuid fields are added where needed.
* Ensure that the uuid and vuuid fields are added where needed.
*
* Note that update 7102 calls _uuid_install_uuid_fields(), which is an
* idempotent function. If _uuid_install_uuid_fields() is changed at some
@@ -220,8 +237,8 @@ function uuid_update_7101() {
* will have run update 7102, and some will not. A new uuid_update_7103()
* function would would therefore be necessary to update all users to
* the latest schema. At the same time, uuid_update_7102() could become
* an empty function, as it would not be necessary to call _uuid_install_uuid_fields()
* twice.
* an empty function, as it would not be necessary to call
* _uuid_install_uuid_fields() twice.
*/
function uuid_update_7102() {
// If the user have disabled the UUID module during upgrade (as UPGRADE.txt
@@ -232,9 +249,11 @@ function uuid_update_7102() {
}
/**
* Clean up entities created by uuid_default_entities_example module.
*
* Modify the labels of all example entities created by the now removed
* uuid_default_entities_example.module to make it clear they're examples.
* Also remove the administrator role of any example user.
* uuid_default_entities_example.module to make it clear they're examples. Also
* remove the administrator role of any example user.
*/
function uuid_update_7103() {
// These are UUIDs of all the example entities that might exist after having
@@ -249,7 +268,7 @@ function uuid_update_7103() {
'7cf875e6-dc15-4404-f190-5a7c3e91d14c',
),
);
// we can't assume taxonomy is enabled
// We can't assume taxonomy is enabled.
if (isset($info['taxonomy_term'])) {
$uuids['taxonomy_term'] = array(
'bcb92ce8-2236-e264-65c8-0c163ae716d1',
@@ -268,7 +287,7 @@ function uuid_update_7103() {
if ($entity_type == 'user' && $rid = array_search('administrator', $entity->roles)) {
unset($entity->roles[$rid]);
}
entity_save($entity);
entity_save($entity_type, $entity);
}
}
}

View File

@@ -34,6 +34,7 @@ function uuid_menu() {
'title' => 'UUID redirector',
'description' => 'Redirects requests for UUID URIs to the referenced entity.',
'page callback' => 'uuid_redirector',
// The access check is handled in the page callback.
'access callback' => TRUE,
'type' => MENU_CALLBACK,
);
@@ -44,7 +45,6 @@ function uuid_menu() {
'page callback' => 'drupal_get_form',
'page arguments' => array('uuid_admin_form'),
'access arguments' => array('administer uuid'),
'type' => MENU_NORMAL_ITEM,
'file' => 'uuid.admin.inc',
);
@@ -123,7 +123,6 @@ function uuid_hook_info() {
return array_fill_keys($hook_names, array('group' => 'uuid'));
}
/**
* Implements hook_views_api().
*/
@@ -155,7 +154,7 @@ function uuid_module_implements_alter(&$implementss, $hook) {
* Implements hook_uuid_sync().
*/
function uuid_uuid_sync() {
foreach (entity_get_info() as $entity_type => $info) {
foreach (entity_get_info() as $info) {
if (isset($info['uuid']) && $info['uuid'] == TRUE && !empty($info['entity keys']['uuid'])) {
_uuid_sync_table($info['base table'], $info['entity keys']['id'], $info['entity keys']['uuid']);
if (!empty($info['entity keys']['revision uuid'])) {
@@ -215,15 +214,19 @@ function uuid_redirector() {
$entity_info = entity_get_info($entity_data['entity_type']);
if (empty($entity_info['uuid'])) {
return drupal_not_found();
return MENU_NOT_FOUND;
}
$entities = entity_uuid_load($entity_data['entity_type'], array($entity_data['uuid']));
if (!count($entities)) {
return drupal_not_found();
return MENU_NOT_FOUND;
}
$uri = entity_uri($entity_data['entity_type'], current($entities));
drupal_goto($uri['path'], array(), 301);
}
if (!drupal_valid_path($uri['path'])) {
return MENU_ACCESS_DENIED;
}
drupal_goto($uri['path'], $uri['options'], 301);
}

View File

@@ -6,23 +6,28 @@
*/
/**
* Base class with some helper methods.
* UUID test helper trait.
*
* Contains methods that assist with running UUID tests.
*/
class UUIDTestCase extends DrupalWebTestCase {
/**
* {@inheritdoc}
*/
function setUp() {
parent::setUp(func_get_args());
}
trait UUIDTestHelper {
/**
* Helper function that asserts a UUID.
*/
function assertUUID($uuid, $message = NULL) {
protected function assertUuid($uuid, $message = NULL) {
$this->assertTrue(uuid_is_valid($uuid), $message);
}
}
/**
* Base class with some helper methods.
*/
abstract class UUIDTestCase extends DrupalWebTestCase {
use UUIDTestHelper;
}
/**
@@ -44,29 +49,125 @@ class UUIDAPITestCase extends UUIDTestCase {
/**
* {@inheritdoc}
*/
function setUp() {
parent::setUp('uuid');
protected function setUp() {
parent::setUp(array('uuid'));
}
/**
* Tests uuid function calls.
*/
function testAPIFunctions() {
public function testApiFunctions() {
// This is a valid UUID, we know that.
$valid_uuid = '0ab26e6b-f074-4e44-9da6-1205fa0e9761';
// Test the uuid_is_valid() function.
$this->assertUUID($valid_uuid, 'UUID validation works.');
$this->assertUuid($valid_uuid, 'UUID validation works.');
// The default generator is 'php'.
$uuid = uuid_generate();
$this->assertUUID($uuid, 'PHP generator works.');
$this->assertUuid($uuid, 'PHP generator works.');
// Test the 'mysql' generator.
variable_set('uuid_generator', 'mysql');
drupal_static_reset('uuid_generate');
$uuid = uuid_generate();
$this->assertUUID($uuid, 'MySQL generator works.');
$this->assertUuid($uuid, 'MySQL generator works.');
}
/**
* Checks that schema for tables of core entities is correctly defined.
*/
public function testSchemas() {
module_load_include('install', 'uuid');
$schemas = drupal_get_schema();
$field_info = uuid_schema_field_definition();
$key_names = array(
'base table' => 'uuid',
'revision table' => 'revision uuid',
);
foreach (uuid_get_core_entity_info() as $entity_info) {
// Test the fields in "base" and "revision" tables.
foreach ($key_names as $table_type => $key_name) {
// Table or field is not defined in entity.
if (!isset($entity_info[$table_type], $entity_info['entity keys'][$key_name])) {
// Not all entities have a revisions table.
continue;
}
$field_name = $entity_info['entity keys'][$key_name];
$table_name = $entity_info[$table_type];
if (!isset($schemas[$table_name])) {
$this->fail(sprintf('Database schema does not have a "%s" table.', $table_name));
continue;
}
$properties = array(
'field' => array('fields', $field_info),
'index' => array('indexes', array($field_name)),
);
// Check integrity of the field and index definition.
foreach ($properties as $type => $data) {
list($property, $value) = $data;
$message = sprintf('Definition of the "%s" %s in the "%s" schema', $field_name, $type, $table_name);
if (isset($schemas[$table_name][$property][$field_name])) {
$this->assertIdentical($schemas[$table_name][$property][$field_name], $value, "$message is correct.");
}
else {
$this->fail("$message does not exist.");
}
}
}
}
}
}
/**
* Tests the UUID API functions.
*/
class UUIDV5TestCase extends UUIDTestCase {
/**
* {@inheritdoc}
*/
public static function getInfo() {
return array(
'name' => 'UUID v5',
'description' => 'Tests the UUID v5 function.',
'group' => 'UUID',
);
}
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp(array('uuid'));
}
/**
* Tests uuid function calls.
*/
public function testV5Function() {
// DNS namespace UUID.
$dns_namespace = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
// Valid DNS generation test.
$uuid = uuid_generate_v5($dns_namespace, 'drupal.org');
$this->assertUuid($uuid, 'UUID for drupal.org is valid.');
$this->assertEqual($uuid, 'c809fd30-48df-52e3-a9f2-2cd78129b8b1', 'UUID for drupal.org is correct.');
// Invalid namespace test.
$invalid_namespace = '01234567-c7a9-feda-27e5-75d00dabc123';
$uuid = uuid_generate_v5($invalid_namespace, 'drupal.org');
$this->assertFalse($uuid, 'Invalid namespace UUID rejected.');
}
}
/**
@@ -88,14 +189,14 @@ class UUIDEntityTestCase extends UUIDTestCase {
/**
* {@inheritdoc}
*/
function setUp() {
parent::setUp('uuid');
protected function setUp() {
parent::setUp(array('uuid'));
}
/**
* Tests Entity API's UUID functions.
*/
function testEntityAPIFunctions() {
public function testEntityApiFunctions() {
// Create some entities that we will work with.
$user = $this->drupalCreateUser();
$node = $this->drupalCreateNode(array('title' => 'original title', 'uid' => $user->uid));
@@ -112,6 +213,7 @@ class UUIDEntityTestCase extends UUIDTestCase {
$vuuids = entity_get_uuid_by_id('node', array($node->vid), TRUE);
$this->assertTrue(in_array($node->vuuid, $vuuids), 'Lookup of entity revision UUID works.');
}
}
/**
@@ -133,22 +235,23 @@ class UUIDUserTestCase extends UUIDTestCase {
/**
* {@inheritdoc}
*/
function setUp() {
protected function setUp() {
$modules = array('uuid');
// Some tests depends on the optional Entity API module.
if (module_exists('entity')) {
parent::setUp('uuid', 'entity');
}
else {
parent::setUp('uuid');
$modules[] = 'entity';
}
parent::setUp($modules);
}
/**
* Test CRUD on users with UUID functions.
*/
function testUserCRUD() {
public function testUserCrud() {
$user = $this->drupalCreateUser();
$this->assertUUID($user->uuid, 'User UUID was generated.');
$this->assertUuid($user->uuid, 'User UUID was generated.');
// Test updating user.
$user_test = clone $user;
@@ -178,6 +281,7 @@ class UUIDUserTestCase extends UUIDTestCase {
$this->assertFalse($user_test, 'Deleting user with UUID worked.');
}
}
}
/**
@@ -199,14 +303,15 @@ class UUIDNodeTestCase extends UUIDTestCase {
/**
* {@inheritdoc}
*/
function setUp() {
protected function setUp() {
$modules = array('uuid');
// Some tests depends on the optional Entity API module.
if (module_exists('entity')) {
parent::setUp('uuid', 'entity');
}
else {
parent::setUp('uuid');
$modules[] = 'entity';
}
parent::setUp($modules);
}
/**
@@ -215,13 +320,13 @@ class UUIDNodeTestCase extends UUIDTestCase {
* @todo
* Break out into multiple test methods to loosen coupling between tests.
*/
function testNodeCRUD() {
public function testNodeCrud() {
// Create some entities that we will work with.
$user = $this->drupalCreateUser();
$node = $this->drupalCreateNode(array('title' => 'original title', 'uid' => $user->uid));
$this->assertUUID($node->uuid, 'Node UUID was generated.');
$this->assertUUID($node->vuuid, 'Node revision UUID was generated.');
$this->assertUuid($node->uuid, 'Node UUID was generated.');
$this->assertUuid($node->vuuid, 'Node revision UUID was generated.');
// Test node update, without creating new revision.
$node_test = clone $node;
@@ -244,7 +349,7 @@ class UUIDNodeTestCase extends UUIDTestCase {
$node_test = node_load($node->nid, FALSE, TRUE);
$this->assertEqual($node_test->uuid, $node->uuid, 'Node UUID was intact after updating, when creating new revision.');
$this->assertNotEqual($node_test->vuuid, $node->vuuid, 'A new node revision UUID was generated, when creating new revision.');
$this->assertUUID($node_test->vuuid, 'The new node revision UUID was valid.');
$this->assertUuid($node_test->vuuid, 'The new node revision UUID was valid.');
// Test entity_uuid_load().
// Save some variables that we will test against.
@@ -300,7 +405,7 @@ class UUIDNodeTestCase extends UUIDTestCase {
$this->assertEqual($node_test->title, 'newer title', 'Saving node with UUID mapped to correct node, when creating new revision.');
$this->assertEqual($node_test->uuid, $node->uuid, 'Node UUID was intact after saving with UUID, when creating new revision.');
$this->assertNotEqual($node_test->vuuid, $node->vuuid, 'A new node revison UUID was generated after saving with UUID, when creating new revision.');
$this->assertUUID($node_test->vuuid, 'New node revision UUID was valid.');
$this->assertUuid($node_test->vuuid, 'New node revision UUID was valid.');
$this->assertEqual($node_test->uid, $node->uid, "Node property 'uid' was intact after saving with UUID, when creating new revision.");
// Test the same thing again, but now triggering a new revision from a
@@ -310,12 +415,9 @@ class UUIDNodeTestCase extends UUIDTestCase {
$node_test = reset($nodes);
// Store the current local revision ID to test with later.
$vid_old1 = $node_test->vid;
$vuuid_old1 = $node_test->vuuid;
// Simulate this node coming from a remote environment by generating
// IDs that won't match. Only the UUID match at this point.
$node_test->uuid_services = TRUE;
$nid_remote = rand();
$vid_remote = rand();
$vuuid_test = uuid_generate();
$node_test->nid = $nid_test;
$node_test->vid = $vid_test;
@@ -375,6 +477,7 @@ class UUIDNodeTestCase extends UUIDTestCase {
$this->assertFalse($node_test, 'Deleting node with UUID worked.');
}
}
}
/**
@@ -385,6 +488,8 @@ class UUIDNodeTestCase extends UUIDTestCase {
*/
class UUIDCommentTestCase extends CommentHelperCase {
use UUIDTestHelper;
/**
* {@inheritdoc}
*/
@@ -396,31 +501,21 @@ class UUIDCommentTestCase extends CommentHelperCase {
);
}
/**
* Helper function that asserts a UUID.
*
* We have duplicated this function from UUIDTestCase since we have to extend
* CommentHelperCase instead.
*/
function assertUUID($uuid, $message = NULL) {
$this->assertTrue(uuid_is_valid($uuid), $message);
}
/**
* Test CRUD on comments with UUID functions.
*/
function testCommentCRUD() {
public function testCommentCrud() {
// This is sub optimal, but due to how CommentHelperCase::setUp() is
// constructed we are enforced to do this. So unfortunately this test
// depends on 'entity' module for now.
module_enable(array('uuid', 'entity'), TRUE);
module_enable(array('uuid', 'entity'));
$user = $this->drupalCreateUser();
$this->drupalLogin($user);
$node = $this->drupalCreateNode();
$return = $this->postComment($node, 'Lorem ipsum');
$comment = comment_load($return->id);
$this->assertUUID($comment->uuid, 'Comment UUID was generated.');
$this->assertUuid($comment->uuid, 'Comment UUID was generated.');
// Test updating comment.
$comment_test = clone $comment;
@@ -456,6 +551,7 @@ class UUIDCommentTestCase extends CommentHelperCase {
$this->assertFalse($comment_test, 'Deleting comment with UUID worked.');
}
}
}
/**
@@ -463,6 +559,8 @@ class UUIDCommentTestCase extends CommentHelperCase {
*/
class UUIDTaxonomyTestCase extends TaxonomyWebTestCase {
use UUIDTestHelper;
/**
* {@inheritdoc}
*/
@@ -479,38 +577,34 @@ class UUIDTaxonomyTestCase extends TaxonomyWebTestCase {
*
* A lot of code here is taken from TaxonomyTermTestCase::setUp().
*/
function setUp() {
protected function setUp() {
$modules = array('taxonomy', 'uuid');
// Some tests depends on the optional Entity API module.
if (module_exists('entity')) {
parent::setUp('taxonomy', 'uuid', 'entity');
$modules[] = 'entity';
}
else {
parent::setUp('taxonomy', 'uuid');
}
}
/**
* Helper function that asserts a UUID.
*
* We have duplicated this function from UUIDTestCase since we have to extend
* TaxonomyWebTestCase instead.
*/
function assertUUID($uuid, $message = NULL) {
$this->assertTrue(uuid_is_valid($uuid), $message);
parent::setUp($modules);
}
/**
* Test CRUD on comments with UUID functions.
*/
function testTaxonomyCRUD() {
$user = $this->drupalCreateUser(array('administer taxonomy', 'administer nodes', 'bypass node access'));
public function testTaxonomyCrud() {
$perms = array(
'administer taxonomy',
'administer nodes',
'bypass node access',
);
$user = $this->drupalCreateUser($perms);
$this->drupalLogin($user);
// Create a term by tagging a node. We'll use this node later too.
$vocabulary = new stdClass;
$vocabulary = new stdClass();
$vocabulary->vid = 1;
$term = $this->createTerm($vocabulary);
$this->assertUUID($term->uuid, 'Term UUID was generated.');
$this->assertUuid($term->uuid, 'Term UUID was generated.');
// Test updating term.
$term_test = clone $term;
@@ -542,6 +636,7 @@ class UUIDTaxonomyTestCase extends TaxonomyWebTestCase {
$this->assertFalse($term_test, 'Deleting term with UUID worked.');
}
}
}
/**
@@ -566,14 +661,14 @@ class UUIDSyncTestCase extends UUIDTestCase {
* @todo
* There are something weird around this assertion.
*/
function assertTableColumn($table, $column, $message) {
protected function assertTableColumn($table, $column, $message) {
$this->assertTrue(db_field_exists($table, $column), $message);
}
/**
* Tests creating UUIDs for entities that don't have them.
*/
function testSync() {
public function testSync() {
// These entities will not have UUID from the start, since the UUID module
// isn't installed yet.
$user = $this->drupalCreateUser();
@@ -600,11 +695,12 @@ class UUIDSyncTestCase extends UUIDTestCase {
// Test if UUID was generated for nodes.
$node_test = node_load($node->nid, FALSE, TRUE);
$this->assertUUID($node_test->uuid, 'Node UUID was generated when clicking the sync button.');
$this->assertUUID($node_test->vuuid, 'Node revision UUID was generated when clicking the sync button.');
$this->assertUuid($node_test->uuid, 'Node UUID was generated when clicking the sync button.');
$this->assertUuid($node_test->vuuid, 'Node revision UUID was generated when clicking the sync button.');
// Test if UUID was generated for users.
$user_test = user_load($user->uid, TRUE);
$this->assertUUID($user_test->uuid, 'User UUID was generated when clicking the sync button.');
$this->assertUuid($user_test->uuid, 'User UUID was generated when clicking the sync button.');
}
}

View File

@@ -1,7 +1,8 @@
<?php
/**
* @file
* Views Implementation for UUID
* Views Implementation for UUID.
*/
/**

View File

@@ -5,9 +5,9 @@ package = UUID
dependencies[] = uuid
; Information added by Drupal.org packaging script on 2014-09-23
version = "7.x-1.0-alpha6"
; Information added by Drupal.org packaging script on 2016-08-02
version = "7.x-1.0-beta2"
core = "7.x"
project = "uuid"
datestamp = "1411455150"
datestamp = "1470153540"

View File

@@ -2,7 +2,7 @@
/**
* @file
* UUID path module functions.
* UUID path module functions.
*/
/**
@@ -24,7 +24,7 @@ function uuid_path_entity_uuid_save(&$entity, $entity_type) {
*/
function _uuid_path_load_url_aliases(&$entities, $entity_type) {
$info = entity_get_info($entity_type);
// we only care about entities with URLs.
// We only care about entities with URLs.
if (!isset($info['uri callback'])) {
return;
}
@@ -35,7 +35,7 @@ function _uuid_path_load_url_aliases(&$entities, $entity_type) {
$aliases = _uuid_path_url_alias_load($path['path']);
// Ignore local IDs.
foreach($aliases as &$alias) {
foreach ($aliases as &$alias) {
unset($alias->pid);
unset($alias->source);
}
@@ -50,7 +50,7 @@ function _uuid_path_load_url_aliases(&$entities, $entity_type) {
function _uuid_path_save_url_aliases(&$entity, $entity_type) {
$info = entity_get_info($entity_type);
// We only care when there is a url callback
// We only care when there is a url callback.
if (!isset($info['uri callback'])) {
return FALSE;
}
@@ -63,7 +63,7 @@ function _uuid_path_save_url_aliases(&$entity, $entity_type) {
path_delete(array('source' => $path));
// Continue if aliases are present.
if(empty($entity->url_alias)) {
if (empty($entity->url_alias)) {
return FALSE;
}
@@ -77,10 +77,10 @@ function _uuid_path_save_url_aliases(&$entity, $entity_type) {
/**
* Loads all aliases associated with a path.
*
* @param $path
* @param string $path
* The source path to look up.
*
* @return
* @return array
* Array of paths or NULL if none found.
*/
function _uuid_path_url_alias_load($path) {
@@ -90,4 +90,3 @@ function _uuid_path_url_alias_load($path) {
->execute()
->fetchAll(PDO::FETCH_OBJ);
}

View File

@@ -1,20 +0,0 @@
<?php
/**
* @file
* Field Collection services definition functions.
*/
/**
* Define a services resource for field_collections.
*/
function _field_collection_resource_definition() {
if (module_exists('field_collection')) {
// We will allow uuid_services_services_resources_alter() to add the
// default UUID-related operations to this resource.
return array('field_collection_item' => array());
}
else {
return array();
}
}

View File

@@ -1,7 +1,15 @@
<?php
/**
* @file
* Administration functions for UUID Service module.
*/
/**
* Settings form for UUID Services.
*
* @return array
* Configuration form structure.
*/
function uuid_services_settings() {
$form['uuid_services_support_all_entity_types'] = array(

View File

@@ -7,9 +7,9 @@ dependencies[] = services
dependencies[] = uuid
dependencies[] = entity
; Information added by Drupal.org packaging script on 2014-09-23
version = "7.x-1.0-alpha6"
; Information added by Drupal.org packaging script on 2016-08-02
version = "7.x-1.0-beta2"
core = "7.x"
project = "uuid"
datestamp = "1411455150"
datestamp = "1470153540"

View File

@@ -1,16 +1,21 @@
<?php
/**
* Implementation of hook_menu().
* @file
* UUID Services module functions.
*/
/**
* Implements hook_menu().
*/
function uuid_services_menu() {
$items['admin/config/services/uuid-services'] = array(
'title' => 'UUID Services',
'description' => 'Configure settings for Module Filter.',
'description' => 'Configure settings for UUID Services.',
'access arguments' => array('administer services'),
'page callback' => 'drupal_get_form',
'page arguments' => array('uuid_services_settings'),
'file' => 'uuid_services.admin.inc'
'file' => 'uuid_services.admin.inc',
);
return $items;
}
@@ -158,7 +163,15 @@ function _uuid_services_entity_update($entity_type, $uuid, $entity) {
*/
function _uuid_services_entity_delete($entity_type, $uuid) {
try {
$return = entity_uuid_delete($entity_type, array($uuid));
$uuid_exist = (bool) entity_get_id_by_uuid($entity_type, array($uuid));
if (!$uuid_exist) {
/* UUID not found. Don't try to delete something that doesn't exist. */
$args = array('@uuid' => $uuid, '@type' => $entity_type);
watchdog('uuid_services', 'UUID @uuid not found for entity type @type', $args, WATCHDOG_WARNING);
return TRUE;
}
$return = entity_uuid_delete($entity_type, array($uuid)) !== FALSE;
return $return;
}
catch (Exception $exception) {
@@ -170,14 +183,14 @@ function _uuid_services_entity_delete($entity_type, $uuid) {
/**
* Access callback.
*
* @param $op
* @param string $op
* The operation we are trying to do on the entity. Can only be:
* - "view"
* - "update"
* - "delete"
* See 'uuid_services_services_resources_alter()' for an explanation why
* 'create' is missing.
* @param $args
* @param array $args
* The arguments passed to the method. The keys are holding the following:
* 0. <entity_type>
* 1. <uuid>
@@ -208,10 +221,9 @@ function _uuid_services_entity_access($op, $args) {
if ($op == 'update' && empty($entity_ids)) {
$op = 'create';
}
// Taxonomy and Comment module uses 'edit' instead of 'update'.
// Oh, how I love Drupal consistency.
if (($entity_type == 'taxonomy_term' || $entity_type == 'comment') && $op == 'update') {
$op = 'edit';
// If the user doesn't exist return 406 like services does.
if (($entity_type == 'user' && empty($entity) && $op == 'view')) {
return services_error(t('There is no user with UUID @uuid.', array('@uuid' => $args[1])), 406);;
}
// The following code is taken from entity_access() with some extra logic
// to handle the case where an entity type is not defining an access
@@ -227,18 +239,3 @@ function _uuid_services_entity_access($op, $args) {
return services_error($exception, 406, $entity_type);
}
}
/**
* Implements hook_services_resources().
*/
function uuid_services_services_resources() {
module_load_include('inc', 'uuid_services', 'resources/field_collection.resource');
$resources = array(
'#api_version' => 3002,
);
$resources += _field_collection_resource_definition();
return $resources;
}

View File

@@ -1,4 +1,5 @@
<?php
/**
* @file
* uuid_services_example.features.inc

View File

@@ -11,9 +11,9 @@ features[ctools][] = services:services:3
features[features_api][] = api:2
features[services_endpoint][] = uuid_services_example
; Information added by Drupal.org packaging script on 2014-09-23
version = "7.x-1.0-alpha6"
; Information added by Drupal.org packaging script on 2016-08-02
version = "7.x-1.0-beta2"
core = "7.x"
project = "uuid"
datestamp = "1411455150"
datestamp = "1470153540"

View File

@@ -1,7 +1,8 @@
<?php
/**
* @file
* Code for the UUID Services Example feature.
*/
include_once('uuid_services_example.features.inc');
include_once 'uuid_services_example.features.inc';

View File

@@ -1,4 +1,5 @@
<?php
/**
* @file
* uuid_services_example.services.inc