danielebarchiesi@4
|
1 <?php
|
danielebarchiesi@4
|
2
|
danielebarchiesi@4
|
3 /**
|
danielebarchiesi@4
|
4 * @file
|
danielebarchiesi@4
|
5 * Provides basic entity property info for entities provided via the CRUD API,
|
danielebarchiesi@4
|
6 * as well as property info for all entity types defined by core. For that
|
danielebarchiesi@4
|
7 * the respective modules/MODULE.info.inc files are included.
|
danielebarchiesi@4
|
8 */
|
danielebarchiesi@4
|
9
|
danielebarchiesi@4
|
10 /**
|
danielebarchiesi@4
|
11 * Implements hook_entity_property_info().
|
danielebarchiesi@4
|
12 */
|
danielebarchiesi@4
|
13 function entity_entity_property_info() {
|
danielebarchiesi@4
|
14 $items = array();
|
danielebarchiesi@4
|
15 // Add in info about entities provided by the CRUD API.
|
danielebarchiesi@4
|
16 foreach (entity_crud_get_info() as $type => $info) {
|
danielebarchiesi@4
|
17 // Automatically enable the controller only if the module does not implement
|
danielebarchiesi@4
|
18 // the hook itself.
|
danielebarchiesi@4
|
19 if (!isset($info['metadata controller class']) && !empty($info['base table']) && (!isset($info['module']) || !module_hook($info['module'], 'entity_property_info'))) {
|
danielebarchiesi@4
|
20 $info['metadata controller class'] = 'EntityDefaultMetadataController';
|
danielebarchiesi@4
|
21 }
|
danielebarchiesi@4
|
22 if (!empty($info['metadata controller class'])) {
|
danielebarchiesi@4
|
23 $controller = new $info['metadata controller class']($type);
|
danielebarchiesi@4
|
24 $items += $controller->entityPropertyInfo();
|
danielebarchiesi@4
|
25 }
|
danielebarchiesi@4
|
26 }
|
danielebarchiesi@4
|
27 // Add in info for all core entities.
|
danielebarchiesi@4
|
28 foreach (_entity_metadata_core_modules() as $module) {
|
danielebarchiesi@4
|
29 module_load_include('inc', 'entity', "modules/$module.info");
|
danielebarchiesi@4
|
30 if (function_exists($function = "entity_metadata_{$module}_entity_property_info")) {
|
danielebarchiesi@4
|
31 if ($return = $function()) {
|
danielebarchiesi@4
|
32 $items = array_merge_recursive($items, $return);
|
danielebarchiesi@4
|
33 }
|
danielebarchiesi@4
|
34 }
|
danielebarchiesi@4
|
35 }
|
danielebarchiesi@4
|
36 return $items;
|
danielebarchiesi@4
|
37 }
|
danielebarchiesi@4
|
38
|
danielebarchiesi@4
|
39 /**
|
danielebarchiesi@4
|
40 * Implements hook_entity_property_info_alter().
|
danielebarchiesi@4
|
41 */
|
danielebarchiesi@4
|
42 function entity_entity_property_info_alter(&$entity_info) {
|
danielebarchiesi@4
|
43 // Add in info for all core entities.
|
danielebarchiesi@4
|
44 foreach (_entity_metadata_core_modules() as $module) {
|
danielebarchiesi@4
|
45 module_load_include('inc', 'entity', "modules/$module.info");
|
danielebarchiesi@4
|
46 if (function_exists($function = "entity_metadata_{$module}_entity_property_info_alter")) {
|
danielebarchiesi@4
|
47 $function($entity_info);
|
danielebarchiesi@4
|
48 }
|
danielebarchiesi@4
|
49 }
|
danielebarchiesi@4
|
50 }
|
danielebarchiesi@4
|
51
|
danielebarchiesi@4
|
52 function _entity_metadata_core_modules() {
|
danielebarchiesi@4
|
53 return array_filter(array('book', 'comment', 'field', 'locale', 'node', 'taxonomy', 'user', 'system', 'statistics'), 'module_exists');
|
danielebarchiesi@4
|
54 }
|
danielebarchiesi@4
|
55
|
danielebarchiesi@4
|
56 /**
|
danielebarchiesi@4
|
57 * Default controller for generating some basic metadata for CRUD entity types.
|
danielebarchiesi@4
|
58 */
|
danielebarchiesi@4
|
59 class EntityDefaultMetadataController {
|
danielebarchiesi@4
|
60
|
danielebarchiesi@4
|
61 protected $type, $info;
|
danielebarchiesi@4
|
62
|
danielebarchiesi@4
|
63 public function __construct($type) {
|
danielebarchiesi@4
|
64 $this->type = $type;
|
danielebarchiesi@4
|
65 $this->info = entity_get_info($type);
|
danielebarchiesi@4
|
66 }
|
danielebarchiesi@4
|
67
|
danielebarchiesi@4
|
68 public function entityPropertyInfo() {
|
danielebarchiesi@4
|
69 $entity_label = drupal_strtolower($this->info['label']);
|
danielebarchiesi@4
|
70
|
danielebarchiesi@4
|
71 // Provide defaults based on the schema.
|
danielebarchiesi@4
|
72 $info['properties'] = $this->convertSchema();
|
danielebarchiesi@4
|
73 foreach ($info['properties'] as $name => &$property) {
|
danielebarchiesi@4
|
74 // Add a description.
|
danielebarchiesi@4
|
75 $property['description'] = t('@entity "@property" property.', array('@entity' => drupal_ucfirst($entity_label), '@property' => $name));
|
danielebarchiesi@4
|
76 }
|
danielebarchiesi@4
|
77
|
danielebarchiesi@4
|
78 // Set better metadata for known entity keys.
|
danielebarchiesi@4
|
79 $id_key = $this->info['entity keys']['id'];
|
danielebarchiesi@4
|
80
|
danielebarchiesi@4
|
81 if (!empty($this->info['entity keys']['name']) && $key = $this->info['entity keys']['name']) {
|
danielebarchiesi@4
|
82 $info['properties'][$key]['type'] = 'token';
|
danielebarchiesi@4
|
83 $info['properties'][$key]['label'] = t('Machine-readable name');
|
danielebarchiesi@4
|
84 $info['properties'][$key]['description'] = t('The machine-readable name identifying this @entity.', array('@entity' => $entity_label));
|
danielebarchiesi@4
|
85 $info['properties'][$id_key]['label'] = t('Internal, numeric @entity ID', array('@entity' => $entity_label));
|
danielebarchiesi@4
|
86 $info['properties'][$id_key]['description'] = t('The ID used to identify this @entity internally.', array('@entity' => $entity_label));
|
danielebarchiesi@4
|
87 }
|
danielebarchiesi@4
|
88 else {
|
danielebarchiesi@4
|
89 $info['properties'][$id_key]['label'] = t('@entity ID', array('@entity' => drupal_ucfirst($entity_label)));
|
danielebarchiesi@4
|
90 $info['properties'][$id_key]['description'] = t('The unique ID of the @entity.', array('@entity' => $entity_label));
|
danielebarchiesi@4
|
91 }
|
danielebarchiesi@4
|
92 // Care for the bundle.
|
danielebarchiesi@4
|
93 if (!empty($this->info['entity keys']['bundle']) && $key = $this->info['entity keys']['bundle']) {
|
danielebarchiesi@4
|
94 $info['properties'][$key]['type'] = 'token';
|
danielebarchiesi@4
|
95 $info['properties'][$key]['options list'] = array(get_class($this), 'bundleOptionsList');
|
danielebarchiesi@4
|
96 }
|
danielebarchiesi@4
|
97 // Care for the label.
|
danielebarchiesi@4
|
98 if (!empty($this->info['entity keys']['label']) && $key = $this->info['entity keys']['label']) {
|
danielebarchiesi@4
|
99 $info['properties'][$key]['label'] = t('Label');
|
danielebarchiesi@4
|
100 $info['properties'][$key]['description'] = t('The human readable label.');
|
danielebarchiesi@4
|
101 }
|
danielebarchiesi@4
|
102
|
danielebarchiesi@4
|
103 // Add a computed property for the entity URL and expose it to views.
|
danielebarchiesi@4
|
104 if (empty($info['properties']['url']) && !empty($this->info['uri callback'])) {
|
danielebarchiesi@4
|
105 $info['properties']['url'] = array(
|
danielebarchiesi@4
|
106 'label' => t('URL'),
|
danielebarchiesi@4
|
107 'description' => t('The URL of the entity.'),
|
danielebarchiesi@4
|
108 'getter callback' => 'entity_metadata_entity_get_properties',
|
danielebarchiesi@4
|
109 'type' => 'uri',
|
danielebarchiesi@4
|
110 'computed' => TRUE,
|
danielebarchiesi@4
|
111 'entity views field' => TRUE,
|
danielebarchiesi@4
|
112 );
|
danielebarchiesi@4
|
113 }
|
danielebarchiesi@4
|
114
|
danielebarchiesi@4
|
115 return array($this->type => $info);
|
danielebarchiesi@4
|
116 }
|
danielebarchiesi@4
|
117
|
danielebarchiesi@4
|
118 /**
|
danielebarchiesi@4
|
119 * A options list callback returning all bundles for an entity type.
|
danielebarchiesi@4
|
120 */
|
danielebarchiesi@4
|
121 public static function bundleOptionsList($name, $info) {
|
danielebarchiesi@4
|
122 if (!empty($info['parent']) && $type = $info['parent']) {
|
danielebarchiesi@4
|
123 $entity_info = $info['parent']->entityInfo();
|
danielebarchiesi@4
|
124 $options = array();
|
danielebarchiesi@4
|
125 foreach ($entity_info['bundles'] as $name => $bundle_info) {
|
danielebarchiesi@4
|
126 $options[$name] = $bundle_info['label'];
|
danielebarchiesi@4
|
127 }
|
danielebarchiesi@4
|
128 return $options;
|
danielebarchiesi@4
|
129 }
|
danielebarchiesi@4
|
130 }
|
danielebarchiesi@4
|
131
|
danielebarchiesi@4
|
132 /**
|
danielebarchiesi@4
|
133 * Return a set of properties for an entity based on the schema definition
|
danielebarchiesi@4
|
134 */
|
danielebarchiesi@4
|
135 protected function convertSchema() {
|
danielebarchiesi@4
|
136 return entity_metadata_convert_schema($this->info['base table']);
|
danielebarchiesi@4
|
137 }
|
danielebarchiesi@4
|
138 }
|
danielebarchiesi@4
|
139
|
danielebarchiesi@4
|
140 /**
|
danielebarchiesi@4
|
141 * Converts the schema information available for the given table to property info.
|
danielebarchiesi@4
|
142 *
|
danielebarchiesi@4
|
143 * @param $table
|
danielebarchiesi@4
|
144 * The name of the table as used in hook_schema().
|
danielebarchiesi@4
|
145 * @return
|
danielebarchiesi@4
|
146 * An array of property info as suiting for hook_entity_property_info().
|
danielebarchiesi@4
|
147 */
|
danielebarchiesi@4
|
148 function entity_metadata_convert_schema($table) {
|
danielebarchiesi@4
|
149 $schema = drupal_get_schema($table);
|
danielebarchiesi@4
|
150 $properties = array();
|
danielebarchiesi@4
|
151 foreach ($schema['fields'] as $name => $info) {
|
danielebarchiesi@4
|
152 if ($type = _entity_metadata_convert_schema_type($info['type'])) {
|
danielebarchiesi@4
|
153 $properties[$name] = array(
|
danielebarchiesi@4
|
154 'type' => $type,
|
danielebarchiesi@4
|
155 'label' => drupal_ucfirst($name),
|
danielebarchiesi@4
|
156 'schema field' => $name,
|
danielebarchiesi@4
|
157 // As we cannot know about any setter access, leave out the setter
|
danielebarchiesi@4
|
158 // callback. For getting usually no further access callback is needed.
|
danielebarchiesi@4
|
159 );
|
danielebarchiesi@4
|
160 if ($info['type'] == 'serial') {
|
danielebarchiesi@4
|
161 $properties[$name]['validation callback'] = 'entity_metadata_validate_integer_positive';
|
danielebarchiesi@4
|
162 }
|
danielebarchiesi@4
|
163 }
|
danielebarchiesi@4
|
164 }
|
danielebarchiesi@4
|
165 return $properties;
|
danielebarchiesi@4
|
166 }
|
danielebarchiesi@4
|
167
|
danielebarchiesi@4
|
168 function _entity_metadata_convert_schema_type($type) {
|
danielebarchiesi@4
|
169 switch ($type) {
|
danielebarchiesi@4
|
170 case 'int':
|
danielebarchiesi@4
|
171 case 'serial':
|
danielebarchiesi@4
|
172 return 'integer';
|
danielebarchiesi@4
|
173 case 'float':
|
danielebarchiesi@4
|
174 case 'numeric':
|
danielebarchiesi@4
|
175 return 'decimal';
|
danielebarchiesi@4
|
176 case 'char':
|
danielebarchiesi@4
|
177 case 'varchar':
|
danielebarchiesi@4
|
178 case 'text':
|
danielebarchiesi@4
|
179 return 'text';
|
danielebarchiesi@4
|
180 }
|
danielebarchiesi@4
|
181 }
|
danielebarchiesi@4
|
182
|
danielebarchiesi@4
|
183 /**
|
danielebarchiesi@4
|
184 * Interface for extra fields controller.
|
danielebarchiesi@4
|
185 *
|
danielebarchiesi@4
|
186 * Note: Displays extra fields exposed by this controller are rendered by
|
danielebarchiesi@4
|
187 * default by the EntityAPIController.
|
danielebarchiesi@4
|
188 */
|
danielebarchiesi@4
|
189 interface EntityExtraFieldsControllerInterface {
|
danielebarchiesi@4
|
190
|
danielebarchiesi@4
|
191 /**
|
danielebarchiesi@4
|
192 * Returns extra fields for this entity type.
|
danielebarchiesi@4
|
193 *
|
danielebarchiesi@4
|
194 * @see hook_field_extra_fields().
|
danielebarchiesi@4
|
195 */
|
danielebarchiesi@4
|
196 public function fieldExtraFields();
|
danielebarchiesi@4
|
197 }
|
danielebarchiesi@4
|
198
|
danielebarchiesi@4
|
199 /**
|
danielebarchiesi@4
|
200 * Default controller for generating extra fields based on property metadata.
|
danielebarchiesi@4
|
201 *
|
danielebarchiesi@4
|
202 * By default a display extra field for each property not being a field, ID or
|
danielebarchiesi@4
|
203 * bundle is generated.
|
danielebarchiesi@4
|
204 */
|
danielebarchiesi@4
|
205 class EntityDefaultExtraFieldsController implements EntityExtraFieldsControllerInterface {
|
danielebarchiesi@4
|
206
|
danielebarchiesi@4
|
207 /**
|
danielebarchiesi@4
|
208 * @var string
|
danielebarchiesi@4
|
209 */
|
danielebarchiesi@4
|
210 protected $entityType;
|
danielebarchiesi@4
|
211
|
danielebarchiesi@4
|
212 /**
|
danielebarchiesi@4
|
213 * @var array
|
danielebarchiesi@4
|
214 */
|
danielebarchiesi@4
|
215 protected $entityInfo;
|
danielebarchiesi@4
|
216
|
danielebarchiesi@4
|
217 /**
|
danielebarchiesi@4
|
218 * Constructor.
|
danielebarchiesi@4
|
219 */
|
danielebarchiesi@4
|
220 public function __construct($type) {
|
danielebarchiesi@4
|
221 $this->entityType = $type;
|
danielebarchiesi@4
|
222 $this->entityInfo = entity_get_info($type);
|
danielebarchiesi@4
|
223 $this->propertyInfo = entity_get_property_info($type);
|
danielebarchiesi@4
|
224 }
|
danielebarchiesi@4
|
225
|
danielebarchiesi@4
|
226 /**
|
danielebarchiesi@4
|
227 * Implements EntityExtraFieldsControllerInterface::fieldExtraFields().
|
danielebarchiesi@4
|
228 */
|
danielebarchiesi@4
|
229 public function fieldExtraFields() {
|
danielebarchiesi@4
|
230 $extra = array();
|
danielebarchiesi@4
|
231 foreach ($this->propertyInfo['properties'] as $name => $property_info) {
|
danielebarchiesi@4
|
232 // Skip adding the ID or bundle.
|
danielebarchiesi@4
|
233 if ($this->entityInfo['entity keys']['id'] == $name || $this->entityInfo['entity keys']['bundle'] == $name) {
|
danielebarchiesi@4
|
234 continue;
|
danielebarchiesi@4
|
235 }
|
danielebarchiesi@4
|
236 $extra[$this->entityType][$this->entityType]['display'][$name] = $this->generateExtraFieldInfo($name, $property_info);
|
danielebarchiesi@4
|
237 }
|
danielebarchiesi@4
|
238
|
danielebarchiesi@4
|
239 // Handle bundle properties.
|
danielebarchiesi@4
|
240 $this->propertyInfo += array('bundles' => array());
|
danielebarchiesi@4
|
241 foreach ($this->propertyInfo['bundles'] as $bundle_name => $info) {
|
danielebarchiesi@4
|
242 foreach ($info['properties'] as $name => $property_info) {
|
danielebarchiesi@4
|
243 $extra[$this->entityType][$bundle_name]['display'][$name] = $this->generateExtraFieldInfo($name, $property_info);
|
danielebarchiesi@4
|
244 }
|
danielebarchiesi@4
|
245 }
|
danielebarchiesi@4
|
246 return $extra;
|
danielebarchiesi@4
|
247 }
|
danielebarchiesi@4
|
248
|
danielebarchiesi@4
|
249 /**
|
danielebarchiesi@4
|
250 * Generates the display field info for a given property.
|
danielebarchiesi@4
|
251 */
|
danielebarchiesi@4
|
252 protected function generateExtraFieldInfo($name, $property_info) {
|
danielebarchiesi@4
|
253 $info = array(
|
danielebarchiesi@4
|
254 'label' => $property_info['label'],
|
danielebarchiesi@4
|
255 'weight' => 0,
|
danielebarchiesi@4
|
256 );
|
danielebarchiesi@4
|
257 if (!empty($property_info['description'])) {
|
danielebarchiesi@4
|
258 $info['description'] = $property_info['description'];
|
danielebarchiesi@4
|
259 }
|
danielebarchiesi@4
|
260 return $info;
|
danielebarchiesi@4
|
261 }
|
danielebarchiesi@4
|
262 }
|