Projet

Général

Profil

Paste
Télécharger (8,71 ko) Statistiques
| Branche: | Révision:

root / drupal7 / sites / all / modules / uuid / uuid_services / uuid_services.module @ 3dfa8105

1
<?php
2

    
3
/**
4
 * Implements hook_services_resources_alter().
5
 *
6
 * Alter all resources that support UUIDs, to make use this functionality when
7
 * exposing them through Services.
8
 *
9
 * Since we are working with UUID enabled entities, the 'create' method is
10
 * redundant. Instead, clients should do a PUT to '<entity_type>/<uuid>'. This
11
 * will route through the 'update' method and create the entity if it doesn't
12
 * exist. This is the most logical thing to do, since it's up to the client to
13
 * generate and set the UUID on the entity.
14
 */
15
function uuid_services_services_resources_alter(&$resources, &$endpoint) {
16
  foreach (entity_get_info() as $entity_type => $entity_info) {
17
    if (isset($entity_info['uuid']) && $entity_info['uuid'] == TRUE && isset($resources[$entity_type])) {
18
      unset($resources[$entity_type]['operations']['create']);
19

    
20
      // Alter 'retrieve' method to use UUID enabled functions and arguments.
21
      $resources[$entity_type]['operations']['retrieve']['help'] = t('Retrieve %label entities based on UUID.', array('%label' => $entity_info['label']));
22
      $resources[$entity_type]['operations']['retrieve']['callback'] = '_uuid_services_entity_retrieve';
23
      $resources[$entity_type]['operations']['retrieve']['access callback'] = '_uuid_services_entity_access';
24
      $resources[$entity_type]['operations']['retrieve']['access arguments'] = array('view');
25
      $resources[$entity_type]['operations']['retrieve']['access arguments append'] = TRUE;
26
      $resources[$entity_type]['operations']['retrieve']['args'] = array(
27
        // This argument isn't exposed in the service, only used internally..
28
        array(
29
          'name' => 'entity_type',
30
          'description' => t('The entity type.'),
31
          'type' => 'string',
32
          'default value' => $entity_type,
33
          'optional' => TRUE,
34
        ),
35
        array(
36
          'name' => 'uuid',
37
          'description' => t('The %label UUID.', array('%label' => $entity_info['label'])),
38
          'type' => 'text',
39
          'source' => array('path' => 0),
40
        ),
41
      );
42

    
43
      // Alter 'update' method to use UUID enabled functions and arguments.
44
      $resources[$entity_type]['operations']['update']['help'] = t('Update or create %label entities based on UUID. The payload must be formatted according to the <a href="!url">OData protocol</a>.', array('%label' => $entity_info['label'], '!url' => 'http://www.odata.org/developers/protocols'));
45
      $resources[$entity_type]['operations']['update']['callback'] = '_uuid_services_entity_update';
46
      $resources[$entity_type]['operations']['update']['access callback'] = '_uuid_services_entity_access';
47
      $resources[$entity_type]['operations']['update']['access arguments'] = array('update');
48
      $resources[$entity_type]['operations']['update']['access arguments append'] = TRUE;
49
      $resources[$entity_type]['operations']['update']['args'] = array(
50
        // This argument isn't exposed in the service, only used internally..
51
        array(
52
          'name' => 'entity_type',
53
          'description' => t('The entity type.'),
54
          'type' => 'string',
55
          'default value' => $entity_type,
56
          'optional' => TRUE,
57
        ),
58
        array(
59
          'name' => 'uuid',
60
          'description' => t('The %label UUID.', array('%label' => $entity_info['label'])),
61
          'type' => 'text',
62
          'source' => array('path' => 0),
63
        ),
64
        array(
65
          'name' => 'entity',
66
          'description' => t('The %label entity object.', array('%label' => $entity_info['label'])),
67
          'type' => 'struct',
68
          'source' => 'data',
69
        ),
70
      );
71

    
72
      // Alter 'delete' method to use UUID enabled functions and arguments.
73
      $resources[$entity_type]['operations']['delete']['help'] = t('Delete %label entities based on UUID.', array('%label' => $entity_info['label']));
74
      $resources[$entity_type]['operations']['delete']['callback'] = '_uuid_services_entity_delete';
75
      $resources[$entity_type]['operations']['delete']['access callback'] = '_uuid_services_entity_access';
76
      $resources[$entity_type]['operations']['delete']['access arguments'] = array('delete');
77
      $resources[$entity_type]['operations']['delete']['access arguments append'] = TRUE;
78
      $resources[$entity_type]['operations']['delete']['args'] = array(
79
        // This argument isn't exposed in the service, only used internally..
80
        array(
81
          'name' => 'entity_type',
82
          'description' => t('The entity type.'),
83
          'type' => 'string',
84
          'default value' => $entity_type,
85
          'optional' => TRUE,
86
        ),
87
        array(
88
          'name' => 'uuid',
89
          'description' => t('The %label UUID.', array('%label' => $entity_info['label'])),
90
          'type' => 'text',
91
          'source' => array('path' => 0),
92
        ),
93
      );
94
    }
95
  }
96
}
97

    
98
/**
99
 * Callback for the 'retrieve' method.
100
 *
101
 * @see entity_uuid_load()
102
 */
103
function _uuid_services_entity_retrieve($entity_type, $uuid) {
104
  try {
105
    $entities = entity_uuid_load($entity_type, array($uuid));
106
    $entity = reset($entities);
107
    return $entity;
108
  }
109
  catch (Exception $exception) {
110
    watchdog_exception('uuid_services', $exception);
111
    return services_error($exception, 406, $uuid);
112
  }
113
}
114

    
115
/**
116
 * Callback for the 'update' method.
117
 *
118
 * @see entity_uuid_save()
119
 */
120
function _uuid_services_entity_update($entity_type, $uuid, $entity) {
121
  try {
122
    $controller = entity_get_controller($entity_type);
123
    if ($controller instanceof EntityAPIControllerInterface) {
124
      $entity = $controller->create($entity);
125
    }
126
    else {
127
      $entity = (object) $entity;
128
    }
129
    entity_uuid_save($entity_type, $entity);
130
    return $entity;
131
  }
132
  catch (Exception $exception) {
133
    watchdog_exception('uuid_services', $exception);
134
    return services_error($exception, 406, $entity);
135
  }
136
}
137

    
138
/**
139
 * Callback for the 'delete' method.
140
 *
141
 * @see entity_uuid_delete()
142
 */
143
function _uuid_services_entity_delete($entity_type, $uuid) {
144
  try {
145
    $return = entity_uuid_delete($entity_type, array($uuid));
146
    return $return;
147
  }
148
  catch (Exception $exception) {
149
    watchdog_exception('uuid_services', $exception);
150
    return services_error($exception, 406, $uuid);
151
  }
152
}
153

    
154
/**
155
 * Access callback.
156
 *
157
 * @param $op
158
 *   The operation we are trying to do on the entity. Can only be:
159
 *   - "view"
160
 *   - "update"
161
 *   - "delete"
162
 *   See 'uuid_services_services_resources_alter()' for an explanation why
163
 *   'create' is missing.
164
 * @param $args
165
 *   The arguments passed to the method. The keys are holding the following:
166
 *   0. <entity_type>
167
 *   1. <uuid>
168
 *   2. <entity> (only available if $op == 'update')
169
 */
170
function _uuid_services_entity_access($op, $args) {
171
  try {
172
    // Fetch the information we have to work with.
173
    $entity_type = $args[0];
174
    // Load functions always deal with multiple entities. So does this lookup
175
    // function. But in practice this will always only be one id.
176
    $entity_ids = entity_get_id_by_uuid($entity_type, array($args[1]));
177
    $entity = NULL;
178
    if (!empty($args[2])) {
179
      $entity = entity_create($entity_type, $args[2]);
180
      // We have to make the entity local (i.e. only have local references), for
181
      // access functions to work on it.
182
      entity_make_entity_local($entity_type, $entity);
183
    }
184
    // Fetch the local entity if we've got an id.
185
    elseif (!empty($entity_ids)) {
186
      $entities = entity_load($entity_type, $entity_ids);
187
      $entity = reset($entities);
188
    }
189

    
190
    // If we've been routed to the 'update' method and the entity we are
191
    // operating on doesn't exist yet, that should be reflected.
192
    if ($op == 'update' && empty($entity_ids)) {
193
      $op = 'create';
194
    }
195
    // Taxonomy and Comment module uses 'edit' instead of 'update'.
196
    // Oh, how I love Drupal consistency.
197
    if (($entity_type == 'taxonomy_term' || $entity_type == 'comment') && $op == 'update') {
198
      $op = 'edit';
199
    }
200
    // The following code is taken from entity_access() with some extra logic
201
    // to handle the case where an entity type is not defining an access
202
    // callback. With this logic, it's important that all entity types that
203
    // needs access control have an access callback defined.
204
    if (($info = entity_get_info()) && isset($info[$entity_type]['access callback'])) {
205
      return $info[$entity_type]['access callback']($op, $entity, NULL, $entity_type);
206
    }
207
    return TRUE;
208
  }
209
  catch (Exception $exception) {
210
    watchdog_exception('uuid_services', $exception);
211
    return services_error($exception, 406, $entity_type);
212
  }
213
}
214

    
215
/**
216
 * Implements hook_services_resources().
217
 */
218
function uuid_services_services_resources() {
219
  module_load_include('inc', 'uuid_services', 'resources/field_collection.resource');
220

    
221
  $resources = array(
222
    '#api_version' => 3002,
223
  );
224

    
225
  $resources += _field_collection_resource_definition();
226

    
227
  return $resources;
228
}