uuid.module 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. <?php
  2. /**
  3. * @file
  4. * Main module functions for the uuid module.
  5. */
  6. /**
  7. * Include main API functions.
  8. */
  9. module_load_include('inc', 'uuid', 'uuid');
  10. /**
  11. * Include the Entity API implementation of the UUID API.
  12. */
  13. module_load_include('inc', 'uuid', 'uuid.entity');
  14. /**
  15. * Include implementations for all core modules.
  16. *
  17. * Instead of having separate modules for all core implementations this file
  18. * implements all of them in their own name space. In some cases this adds some
  19. * unecessary code weight, but instead it saves us from module mania.
  20. */
  21. module_load_include('inc', 'uuid', 'uuid.core');
  22. /**
  23. * Implements hook_menu().
  24. */
  25. function uuid_menu() {
  26. $items = array();
  27. $items['uuid'] = array(
  28. 'title' => 'UUID redirector',
  29. 'description' => 'Redirects requests for UUID URIs to the referenced entity.',
  30. 'page callback' => 'uuid_redirector',
  31. // The access check is handled in the page callback.
  32. 'access callback' => TRUE,
  33. 'type' => MENU_CALLBACK,
  34. );
  35. $items['admin/config/system/uuid'] = array(
  36. 'title' => 'Universally unique identifiers',
  37. 'description' => 'Configure universally unique identifiers.',
  38. 'page callback' => 'drupal_get_form',
  39. 'page arguments' => array('uuid_admin_form'),
  40. 'access arguments' => array('administer uuid'),
  41. 'file' => 'uuid.admin.inc',
  42. );
  43. // Conditional support for Devel. A good thing for developers.
  44. if (module_exists('devel')) {
  45. $entity_types = array(
  46. 'user' => array('path' => 'user/%user/devel/load-by-uuid', 'arg' => 1),
  47. 'node' => array('path' => 'node/%node/devel/load-by-uuid', 'arg' => 1),
  48. 'comment' => array('path' => 'comment/%comment/devel/load-by-uuid', 'arg' => 1),
  49. 'taxonomy_term' => array('path' => 'taxonomy/term/%taxonomy_term/devel/load-by-uuid', 'arg' => 2),
  50. );
  51. foreach ($entity_types as $entity_type => $info) {
  52. $items[$info['path']] = array(
  53. 'title' => 'Load by UUID',
  54. 'page callback' => 'uuid_devel_load_by_uuid',
  55. 'page arguments' => array($entity_type, $info['arg']),
  56. 'access arguments' => array('access devel information'),
  57. 'type' => MENU_LOCAL_TASK,
  58. 'file' => 'uuid.admin.inc',
  59. 'weight' => 100,
  60. );
  61. }
  62. }
  63. return $items;
  64. }
  65. /**
  66. * Implements hook_ctools_plugin_directory().
  67. */
  68. function uuid_ctools_plugin_directory($module, $plugin) {
  69. if ($module == 'ctools') {
  70. return 'plugins/' . $plugin;
  71. }
  72. }
  73. /**
  74. * Implements hook_permission().
  75. */
  76. function uuid_permission() {
  77. return array(
  78. 'administer uuid' => array(
  79. 'title' => t('Administer UUID'),
  80. 'description' => t('Allows configuration of the UUID module and APIs.'),
  81. ),
  82. );
  83. }
  84. /**
  85. * Implements hook_hook_info().
  86. */
  87. function uuid_hook_info() {
  88. $hook_names = array(
  89. 'uuid_info',
  90. 'uuid_sync',
  91. 'entity_uuid_load',
  92. 'field_uuid_load',
  93. 'entity_uuid_presave',
  94. 'entity_uuid_save',
  95. 'entity_uuid_delete',
  96. 'field_uuid_presave',
  97. 'uuid_menu_path_to_uri_alter',
  98. 'uuid_menu_uri_to_path_alter',
  99. 'uuid_default_entities',
  100. 'uuid_entities_pre_rebuild',
  101. 'uuid_entities_pre_revert',
  102. 'uuid_entities_post_rebuild',
  103. 'uuid_entities_post_revert',
  104. 'uuid_entities_features_export_entity_alter',
  105. 'uuid_entities_features_export_field_alter',
  106. 'uuid_uri_data',
  107. 'uuid_id_uri_data',
  108. 'uuid_uri_data',
  109. 'uuid_id_uri_data',
  110. );
  111. return array_fill_keys($hook_names, array('group' => 'uuid'));
  112. }
  113. /**
  114. * Implements hook_views_api().
  115. */
  116. function uuid_views_api() {
  117. return array(
  118. 'api' => 2,
  119. 'path' => drupal_get_path('module', 'uuid'),
  120. );
  121. }
  122. /**
  123. * Implements hook_module_implements_alter().
  124. *
  125. * Moves hook_entity_info_alter() implementation to the bottom so it is
  126. * invoked after all modules relying on the entity API.
  127. *
  128. * @see uuid_entity_info_alter()
  129. */
  130. function uuid_module_implements_alter(&$implementss, $hook) {
  131. if ($hook == 'entity_info_alter') {
  132. // Move our hook Implements to the bottom.
  133. $group = $implementss['uuid'];
  134. unset($implementss['uuid']);
  135. $implementss['uuid'] = $group;
  136. }
  137. }
  138. /**
  139. * Implements hook_uuid_sync().
  140. */
  141. function uuid_uuid_sync() {
  142. foreach (entity_get_info() as $info) {
  143. if (isset($info['uuid']) && $info['uuid'] == TRUE && !empty($info['entity keys']['uuid'])) {
  144. _uuid_sync_table($info['base table'], $info['entity keys']['id'], $info['entity keys']['uuid']);
  145. if (!empty($info['entity keys']['revision uuid'])) {
  146. _uuid_sync_table($info['revision table'], $info['entity keys']['revision'], $info['entity keys']['revision uuid']);
  147. }
  148. }
  149. }
  150. }
  151. /**
  152. * Helper function that executes the update on the actual table.
  153. */
  154. function _uuid_sync_table($table, $id_field, $uuid_field) {
  155. // Fetch empty records.
  156. $result = db_select($table, 't')
  157. ->fields('t', array($id_field))
  158. ->condition(db_or()->condition($uuid_field, '')->isNull($uuid_field))
  159. ->execute();
  160. // Update empty records.
  161. foreach ($result as $record) {
  162. db_update($table)
  163. ->fields(array($uuid_field => uuid_generate()))
  164. ->condition($id_field, $record->{$id_field})
  165. ->execute();
  166. }
  167. }
  168. /**
  169. * Implements hook_features_api().
  170. *
  171. * The Features support consists of exporting entities from a Deploy
  172. * <em>fetch-only</em> plan. Deploy is only required to generate the feature
  173. * it self.
  174. *
  175. * The reason why we depend on Deploy for the generation of the content is
  176. * because Deploy has the kind of dependency detection framework we need, to
  177. * identify all dependencies for all entities.
  178. */
  179. function uuid_features_api() {
  180. return array(
  181. 'uuid_entities' => array(
  182. 'name' => t('UUID entities'),
  183. 'default_hook' => 'uuid_default_entities',
  184. 'default_file' => FEATURES_DEFAULTS_INCLUDED,
  185. 'feature_source' => TRUE,
  186. 'file' => drupal_get_path('module', 'uuid') . '/uuid.features.inc',
  187. ),
  188. );
  189. }
  190. /**
  191. * Redirects all UUID URI requests to the appropriate entity page.
  192. */
  193. function uuid_redirector() {
  194. $entity_data = uuid_uri_array_to_data(arg());
  195. $entity_info = entity_get_info($entity_data['entity_type']);
  196. if (empty($entity_info['uuid'])) {
  197. return MENU_NOT_FOUND;
  198. }
  199. $entities = entity_uuid_load($entity_data['entity_type'], array($entity_data['uuid']));
  200. if (!count($entities)) {
  201. return MENU_NOT_FOUND;
  202. }
  203. $uri = entity_uri($entity_data['entity_type'], current($entities));
  204. if (!drupal_valid_path($uri['path'])) {
  205. return MENU_ACCESS_DENIED;
  206. }
  207. drupal_goto($uri['path'], $uri['options'], 301);
  208. }