Project

General

Profile

Paste
Download (8.74 KB) Statistics
| Branch: | Revision:

root / drupal7 / sites / all / modules / entity / entity.info.inc @ 7d7b5830

1
<?php
2

    
3
/**
4
 * @file
5
 * Provides basic entity property info for entities provided via the CRUD API,
6
 * as well as property info for all entity types defined by core. For that
7
 * the respective modules/MODULE.info.inc files are included.
8
 */
9

    
10
/**
11
 * Implements hook_entity_property_info().
12
 */
13
function entity_entity_property_info() {
14
  $items = array();
15
  // Add in info about entities provided by the CRUD API.
16
  foreach (entity_crud_get_info() as $type => $info) {
17
    // Automatically enable the controller only if the module does not implement
18
    // the hook itself.
19
    if (!isset($info['metadata controller class']) && !empty($info['base table']) && (!isset($info['module']) || !module_hook($info['module'], 'entity_property_info'))) {
20
      $info['metadata controller class'] = 'EntityDefaultMetadataController';
21
    }
22
    if (!empty($info['metadata controller class'])) {
23
      $controller = new $info['metadata controller class']($type);
24
      $items += $controller->entityPropertyInfo();
25
    }
26
  }
27
  // Add in info for all core entities.
28
  foreach (_entity_metadata_core_modules() as $module) {
29
    module_load_include('inc', 'entity', "modules/$module.info");
30
    if (function_exists($function = "entity_metadata_{$module}_entity_property_info")) {
31
      if ($return = $function()) {
32
        $items = array_merge_recursive($items, $return);
33
      }
34
    }
35
  }
36
  return $items;
37
}
38

    
39
/**
40
 * Implements hook_entity_property_info_alter().
41
 */
42
function entity_entity_property_info_alter(&$entity_info) {
43
  // Add in info for all core entities.
44
  foreach (_entity_metadata_core_modules() as $module) {
45
    module_load_include('inc', 'entity', "modules/$module.info");
46
    if (function_exists($function = "entity_metadata_{$module}_entity_property_info_alter")) {
47
      $function($entity_info);
48
    }
49
  }
50
}
51

    
52
function _entity_metadata_core_modules() {
53
  return array_filter(array('book', 'comment', 'field', 'locale', 'node', 'taxonomy', 'user', 'system', 'statistics'), 'module_exists');
54
}
55

    
56
/**
57
 * Default controller for generating some basic metadata for CRUD entity types.
58
 */
59
class EntityDefaultMetadataController {
60

    
61
  protected $type, $info;
62

    
63
  public function __construct($type) {
64
    $this->type = $type;
65
    $this->info = entity_get_info($type);
66
  }
67

    
68
  public function entityPropertyInfo() {
69
    $entity_label = drupal_strtolower($this->info['label']);
70

    
71
    // Provide defaults based on the schema.
72
    $info['properties'] = $this->convertSchema();
73
    foreach ($info['properties'] as $name => &$property) {
74
      // Add a description.
75
      $property['description'] = t('@entity "@property" property.', array('@entity' => drupal_ucfirst($entity_label), '@property' => $name));
76
    }
77

    
78
    // Set better metadata for known entity keys.
79
    $id_key = $this->info['entity keys']['id'];
80

    
81
    if (!empty($this->info['entity keys']['name']) && $key = $this->info['entity keys']['name']) {
82
      $info['properties'][$key]['type'] = 'token';
83
      $info['properties'][$key]['label'] = t('Machine-readable name');
84
      $info['properties'][$key]['description'] = t('The machine-readable name identifying this @entity.', array('@entity' => $entity_label));
85
      $info['properties'][$id_key]['label'] = t('Internal, numeric @entity ID', array('@entity' => $entity_label));
86
      $info['properties'][$id_key]['description'] = t('The ID used to identify this @entity internally.', array('@entity' => $entity_label));
87
    }
88
    else {
89
      $info['properties'][$id_key]['label'] = t('@entity ID', array('@entity' => drupal_ucfirst($entity_label)));
90
      $info['properties'][$id_key]['description'] = t('The unique ID of the @entity.', array('@entity' => $entity_label));
91
    }
92
    // Care for the bundle.
93
    if (!empty($this->info['entity keys']['bundle']) && $key = $this->info['entity keys']['bundle']) {
94
      $info['properties'][$key]['type'] = 'token';
95
      $info['properties'][$key]['options list'] = array(get_class($this), 'bundleOptionsList');
96
    }
97
    // Care for the label.
98
    if (!empty($this->info['entity keys']['label']) && $key = $this->info['entity keys']['label']) {
99
      $info['properties'][$key]['label'] = t('Label');
100
      $info['properties'][$key]['description'] = t('The human readable label.');
101
    }
102

    
103
    // Add a computed property for the entity URL and expose it to views.
104
    if (empty($info['properties']['url']) && !empty($this->info['uri callback'])) {
105
      $info['properties']['url'] = array(
106
        'label' => t('URL'),
107
        'description' => t('The URL of the entity.'),
108
        'getter callback' => 'entity_metadata_entity_get_properties',
109
        'type' => 'uri',
110
        'computed' => TRUE,
111
        'entity views field' => TRUE,
112
      );
113
    }
114

    
115
    return array($this->type => $info);
116
  }
117

    
118
  /**
119
   * A options list callback returning all bundles for an entity type.
120
   */
121
  public static function bundleOptionsList($name, $info) {
122
    if (!empty($info['parent']) && $type = $info['parent']) {
123
      $entity_info = $info['parent']->entityInfo();
124
      $options = array();
125
      foreach ($entity_info['bundles'] as $name => $bundle_info) {
126
        $options[$name] = $bundle_info['label'];
127
      }
128
      return $options;
129
    }
130
  }
131

    
132
  /**
133
   * Return a set of properties for an entity based on the schema definition
134
   */
135
  protected function convertSchema() {
136
    return entity_metadata_convert_schema($this->info['base table']);
137
  }
138
}
139

    
140
/**
141
 * Converts the schema information available for the given table to property info.
142
 *
143
 * @param $table
144
 *   The name of the table as used in hook_schema().
145
 * @return
146
 *   An array of property info as suiting for hook_entity_property_info().
147
 */
148
function entity_metadata_convert_schema($table) {
149
  $schema = drupal_get_schema($table);
150
  $properties = array();
151
  foreach ($schema['fields'] as $name => $info) {
152
    if ($type = _entity_metadata_convert_schema_type($info['type'])) {
153
      $properties[$name] = array(
154
        'type' => $type,
155
        'label' => drupal_ucfirst($name),
156
        'schema field' => $name,
157
        // As we cannot know about any setter access, leave out the setter
158
        // callback. For getting usually no further access callback is needed.
159
      );
160
      if ($info['type'] == 'serial') {
161
        $properties[$name]['validation callback'] = 'entity_metadata_validate_integer_positive';
162
      }
163
    }
164
  }
165
  return $properties;
166
}
167

    
168
function _entity_metadata_convert_schema_type($type) {
169
  switch ($type) {
170
    case 'int':
171
    case 'serial':
172
    case 'date':
173
      return 'integer';
174
    case 'float':
175
    case 'numeric':
176
      return 'decimal';
177
    case 'char':
178
    case 'varchar':
179
    case 'text':
180
      return 'text';
181
  }
182
}
183

    
184
/**
185
 * Interface for extra fields controller.
186
 *
187
 * Note: Displays extra fields exposed by this controller are rendered by
188
 * default by the EntityAPIController.
189
 */
190
interface EntityExtraFieldsControllerInterface {
191

    
192
  /**
193
   * Returns extra fields for this entity type.
194
   *
195
   * @see hook_field_extra_fields().
196
   */
197
  public function fieldExtraFields();
198
}
199

    
200
/**
201
 * Default controller for generating extra fields based on property metadata.
202
 *
203
 * By default a display extra field for each property not being a field, ID or
204
 * bundle is generated.
205
 */
206
class EntityDefaultExtraFieldsController implements EntityExtraFieldsControllerInterface {
207

    
208
  /**
209
   * @var string
210
   */
211
  protected $entityType;
212

    
213
  /**
214
   * @var array
215
   */
216
  protected $entityInfo;
217

    
218
  /**
219
   * Constructor.
220
   */
221
  public function __construct($type) {
222
    $this->entityType = $type;
223
    $this->entityInfo = entity_get_info($type);
224
    $this->propertyInfo = entity_get_property_info($type);
225
  }
226

    
227
  /**
228
   * Implements EntityExtraFieldsControllerInterface::fieldExtraFields().
229
   */
230
  public function fieldExtraFields() {
231
    $extra = array();
232
    foreach ($this->propertyInfo['properties'] as $name => $property_info) {
233
      // Skip adding the ID or bundle.
234
      if ($this->entityInfo['entity keys']['id'] == $name || $this->entityInfo['entity keys']['bundle'] == $name) {
235
        continue;
236
      }
237
      $extra[$this->entityType][$this->entityType]['display'][$name] = $this->generateExtraFieldInfo($name, $property_info);
238
    }
239

    
240
    // Handle bundle properties.
241
    $this->propertyInfo += array('bundles' => array());
242
    foreach ($this->propertyInfo['bundles'] as $bundle_name => $info) {
243
      foreach ($info['properties'] as $name => $property_info) {
244
        if (empty($property_info['field'])) {
245
          $extra[$this->entityType][$bundle_name]['display'][$name] = $this->generateExtraFieldInfo($name, $property_info);
246
        }
247
      }
248
    }
249
    return $extra;
250
  }
251

    
252
  /**
253
   * Generates the display field info for a given property.
254
   */
255
  protected function generateExtraFieldInfo($name, $property_info) {
256
    $info = array(
257
      'label' => $property_info['label'],
258
      'weight' => 0,
259
    );
260
    if (!empty($property_info['description'])) {
261
      $info['description'] = $property_info['description'];
262
    }
263
    return $info;
264
  }
265
}