|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Field attach API, allowing entities (nodes, users, ...) to be 'fieldable'. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * Exception thrown by field_attach_validate() on field validation errors. |
|
10 */ |
|
11 class FieldValidationException extends FieldException { |
|
12 var $errors; |
|
13 |
|
14 /** |
|
15 * Constructor for FieldValidationException. |
|
16 * |
|
17 * @param $errors |
|
18 * An array of field validation errors, keyed by field name and |
|
19 * delta that contains two keys: |
|
20 * - 'error': A machine-readable error code string, prefixed by |
|
21 * the field module name. A field widget may use this code to decide |
|
22 * how to report the error. |
|
23 * - 'message': A human-readable error message such as to be |
|
24 * passed to form_error() for the appropriate form element. |
|
25 */ |
|
26 function __construct($errors) { |
|
27 $this->errors = $errors; |
|
28 parent::__construct(t('Field validation errors')); |
|
29 } |
|
30 } |
|
31 |
|
32 /** |
|
33 * @defgroup field_storage Field Storage API |
|
34 * @{ |
|
35 * Implement a storage engine for Field API data. |
|
36 * |
|
37 * The Field Attach API uses the Field Storage API to perform all "database |
|
38 * access". Each Field Storage API hook function defines a primitive database |
|
39 * operation such as read, write, or delete. The default field storage module, |
|
40 * field_sql_storage.module, uses the local SQL database to implement these |
|
41 * operations, but alternative field storage backends can choose to represent |
|
42 * the data in SQL differently or use a completely different storage mechanism |
|
43 * such as a cloud-based database. |
|
44 * |
|
45 * Each field defines which storage backend it uses. The Drupal system variable |
|
46 * 'field_storage_default' identifies the storage backend used by default. |
|
47 * |
|
48 * See @link field Field API @endlink for information about the other parts of |
|
49 * the Field API. |
|
50 */ |
|
51 |
|
52 /** |
|
53 * Argument for an update operation. |
|
54 * |
|
55 * This is used in hook_field_storage_write when updating an |
|
56 * existing entity. |
|
57 */ |
|
58 define('FIELD_STORAGE_UPDATE', 'update'); |
|
59 |
|
60 /** |
|
61 * Argument for an insert operation. |
|
62 * |
|
63 * This is used in hook_field_storage_write when inserting a new entity. |
|
64 */ |
|
65 define('FIELD_STORAGE_INSERT', 'insert'); |
|
66 |
|
67 /** |
|
68 * @} End of "defgroup field_storage". |
|
69 */ |
|
70 |
|
71 /** |
|
72 * @defgroup field_attach Field Attach API |
|
73 * @{ |
|
74 * Operate on Field API data attached to Drupal entities. |
|
75 * |
|
76 * Field Attach API functions load, store, display, generate Field API |
|
77 * structures, and perform a variety of other functions for field data attached |
|
78 * to individual entities. |
|
79 * |
|
80 * Field Attach API functions generally take $entity_type and $entity arguments |
|
81 * along with additional function-specific arguments. $entity_type is the type |
|
82 * of the fieldable entity, such as 'node' or 'user', and $entity is the entity |
|
83 * itself. |
|
84 * |
|
85 * hook_entity_info() is the central place for entity types to define if and |
|
86 * how Field API should operate on their entity objects. Notably, the |
|
87 * 'fieldable' property needs to be set to TRUE. |
|
88 * |
|
89 * The Field Attach API uses the concept of bundles: the set of fields for a |
|
90 * given entity is defined on a per-bundle basis. The collection of bundles for |
|
91 * an entity type is defined its hook_entity_info() implementation. For |
|
92 * instance, node_entity_info() exposes each node type as its own bundle. This |
|
93 * means that the set of fields of a node is determined by the node type. The |
|
94 * Field API reads the bundle name for a given entity from a particular |
|
95 * property of the entity object, and hook_entity_info() defines which property |
|
96 * to use. For instance, node_entity_info() specifies: |
|
97 * @code $info['entity keys']['bundle'] = 'type'@endcode |
|
98 * This indicates that for a particular node object, the bundle name can be |
|
99 * found in $node->type. This property can be omitted if the entity type only |
|
100 * exposes a single bundle (all entities of this type have the same collection |
|
101 * of fields). This is the case for the 'user' entity type. |
|
102 * |
|
103 * Most Field Attach API functions define a corresponding hook function that |
|
104 * allows any module to act on Field Attach operations for any entity after the |
|
105 * operation is complete, and access or modify all the field, form, or display |
|
106 * data for that entity and operation. For example, field_attach_view() invokes |
|
107 * hook_field_attach_view_alter(). These all-module hooks are distinct from |
|
108 * those of the Field Types API, such as hook_field_load(), that are only |
|
109 * invoked for the module that defines a specific field type. |
|
110 * |
|
111 * field_attach_load(), field_attach_insert(), and field_attach_update() also |
|
112 * define pre-operation hooks, e.g. hook_field_attach_pre_load(). These hooks |
|
113 * run before the corresponding Field Storage API and Field Type API |
|
114 * operations. They allow modules to define additional storage locations (e.g. |
|
115 * denormalizing, mirroring) for field data on a per-field basis. They also |
|
116 * allow modules to take over field storage completely by instructing other |
|
117 * implementations of the same hook and the Field Storage API itself not to |
|
118 * operate on specified fields. |
|
119 * |
|
120 * The pre-operation hooks do not make the Field Storage API irrelevant. The |
|
121 * Field Storage API is essentially the "fallback mechanism" for any fields |
|
122 * that aren't being intercepted explicitly by pre-operation hooks. |
|
123 * |
|
124 * @link field_language Field Language API @endlink provides information about |
|
125 * the structure of field objects. |
|
126 * |
|
127 * See @link field Field API @endlink for information about the other parts of |
|
128 * the Field API. |
|
129 */ |
|
130 |
|
131 /** |
|
132 * Invoke a field hook. |
|
133 * |
|
134 * @param $op |
|
135 * Possible operations include: |
|
136 * - form |
|
137 * - validate |
|
138 * - presave |
|
139 * - insert |
|
140 * - update |
|
141 * - delete |
|
142 * - delete revision |
|
143 * - view |
|
144 * - prepare translation |
|
145 * @param $entity_type |
|
146 * The type of $entity; e.g. 'node' or 'user'. |
|
147 * @param $entity |
|
148 * The fully formed $entity_type entity. |
|
149 * @param $a |
|
150 * - The $form in the 'form' operation. |
|
151 * - The value of $view_mode in the 'view' operation. |
|
152 * - Otherwise NULL. |
|
153 * @param $b |
|
154 * - The $form_state in the 'submit' operation. |
|
155 * - Otherwise NULL. |
|
156 * @param $options |
|
157 * An associative array of additional options, with the following keys: |
|
158 * - 'field_name': The name of the field whose operation should be |
|
159 * invoked. By default, the operation is invoked on all the fields |
|
160 * in the entity's bundle. NOTE: This option is not compatible with |
|
161 * the 'deleted' option; the 'field_id' option should be used |
|
162 * instead. |
|
163 * - 'field_id': The id of the field whose operation should be |
|
164 * invoked. By default, the operation is invoked on all the fields |
|
165 * in the entity's' bundles. |
|
166 * - 'default': A boolean value, specifying which implementation of |
|
167 * the operation should be invoked. |
|
168 * - if FALSE (default), the field types implementation of the operation |
|
169 * will be invoked (hook_field_[op]) |
|
170 * - If TRUE, the default field implementation of the field operation |
|
171 * will be invoked (field_default_[op]) |
|
172 * Internal use only. Do not explicitely set to TRUE, but use |
|
173 * _field_invoke_default() instead. |
|
174 * - 'deleted': If TRUE, the function will operate on deleted fields |
|
175 * as well as non-deleted fields. If unset or FALSE, only |
|
176 * non-deleted fields are operated on. |
|
177 * - 'language': A language code or an array of language codes keyed by field |
|
178 * name. It will be used to narrow down to a single value the available |
|
179 * languages to act on. |
|
180 */ |
|
181 function _field_invoke($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $options = array()) { |
|
182 // Merge default options. |
|
183 $default_options = array( |
|
184 'default' => FALSE, |
|
185 'deleted' => FALSE, |
|
186 'language' => NULL, |
|
187 ); |
|
188 $options += $default_options; |
|
189 |
|
190 // Determine the list of instances to iterate on. |
|
191 list(, , $bundle) = entity_extract_ids($entity_type, $entity); |
|
192 $instances = _field_invoke_get_instances($entity_type, $bundle, $options); |
|
193 |
|
194 // Iterate through the instances and collect results. |
|
195 $return = array(); |
|
196 foreach ($instances as $instance) { |
|
197 // field_info_field() is not available for deleted fields, so use |
|
198 // field_info_field_by_id(). |
|
199 $field = field_info_field_by_id($instance['field_id']); |
|
200 $field_name = $field['field_name']; |
|
201 $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op; |
|
202 if (function_exists($function)) { |
|
203 // Determine the list of languages to iterate on. |
|
204 $available_languages = field_available_languages($entity_type, $field); |
|
205 $languages = _field_language_suggestion($available_languages, $options['language'], $field_name); |
|
206 |
|
207 foreach ($languages as $langcode) { |
|
208 $items = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array(); |
|
209 $result = $function($entity_type, $entity, $field, $instance, $langcode, $items, $a, $b); |
|
210 if (isset($result)) { |
|
211 // For hooks with array results, we merge results together. |
|
212 // For hooks with scalar results, we collect results in an array. |
|
213 if (is_array($result)) { |
|
214 $return = array_merge($return, $result); |
|
215 } |
|
216 else { |
|
217 $return[] = $result; |
|
218 } |
|
219 } |
|
220 |
|
221 // Populate $items back in the field values, but avoid replacing missing |
|
222 // fields with an empty array (those are not equivalent on update). |
|
223 if ($items !== array() || isset($entity->{$field_name}[$langcode])) { |
|
224 $entity->{$field_name}[$langcode] = $items; |
|
225 } |
|
226 } |
|
227 } |
|
228 } |
|
229 |
|
230 return $return; |
|
231 } |
|
232 |
|
233 /** |
|
234 * Invoke a field hook across fields on multiple entities. |
|
235 * |
|
236 * @param $op |
|
237 * Possible operations include: |
|
238 * - load |
|
239 * - prepare_view |
|
240 * For all other operations, use _field_invoke() / field_invoke_default() |
|
241 * instead. |
|
242 * @param $entity_type |
|
243 * The type of $entity; e.g. 'node' or 'user'. |
|
244 * @param $entities |
|
245 * An array of entities, keyed by entity id. |
|
246 * @param $a |
|
247 * - The $age parameter in the 'load' operation. |
|
248 * - Otherwise NULL. |
|
249 * @param $b |
|
250 * Currently always NULL. |
|
251 * @param $options |
|
252 * An associative array of additional options, with the following keys: |
|
253 * - 'field_name': The name of the field whose operation should be |
|
254 * invoked. By default, the operation is invoked on all the fields |
|
255 * in the entity's bundle. NOTE: This option is not compatible with |
|
256 * the 'deleted' option; the 'field_id' option should be used instead. |
|
257 * - 'field_id': The id of the field whose operation should be |
|
258 * invoked. By default, the operation is invoked on all the fields |
|
259 * in the entity's' bundles. |
|
260 * - 'default': A boolean value, specifying which implementation of |
|
261 * the operation should be invoked. |
|
262 * - if FALSE (default), the field types implementation of the operation |
|
263 * will be invoked (hook_field_[op]) |
|
264 * - If TRUE, the default field implementation of the field operation |
|
265 * will be invoked (field_default_[op]) |
|
266 * Internal use only. Do not explicitely set to TRUE, but use |
|
267 * _field_invoke_multiple_default() instead. |
|
268 * - 'deleted': If TRUE, the function will operate on deleted fields |
|
269 * as well as non-deleted fields. If unset or FALSE, only |
|
270 * non-deleted fields are operated on. |
|
271 * - 'language': A language code or an array of arrays of language codes keyed |
|
272 * by entity id and field name. It will be used to narrow down to a single |
|
273 * value the available languages to act on. |
|
274 * |
|
275 * @return |
|
276 * An array of returned values keyed by entity id. |
|
277 */ |
|
278 function _field_invoke_multiple($op, $entity_type, $entities, &$a = NULL, &$b = NULL, $options = array()) { |
|
279 // Merge default options. |
|
280 $default_options = array( |
|
281 'default' => FALSE, |
|
282 'deleted' => FALSE, |
|
283 'language' => NULL, |
|
284 ); |
|
285 $options += $default_options; |
|
286 |
|
287 $fields = array(); |
|
288 $grouped_instances = array(); |
|
289 $grouped_entities = array(); |
|
290 $grouped_items = array(); |
|
291 $return = array(); |
|
292 |
|
293 // Go through the entities and collect the fields on which the hook should be |
|
294 // invoked. |
|
295 // |
|
296 // We group fields by id, not by name, because this function can operate on |
|
297 // deleted fields which may have non-unique names. However, entities can only |
|
298 // contain data for a single field for each name, even if that field |
|
299 // is deleted, so we reference field data via the |
|
300 // $entity->$field_name property. |
|
301 foreach ($entities as $entity) { |
|
302 // Determine the list of instances to iterate on. |
|
303 list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
|
304 $instances = _field_invoke_get_instances($entity_type, $bundle, $options); |
|
305 |
|
306 foreach ($instances as $instance) { |
|
307 $field_id = $instance['field_id']; |
|
308 $field_name = $instance['field_name']; |
|
309 $field = field_info_field_by_id($field_id); |
|
310 $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op; |
|
311 if (function_exists($function)) { |
|
312 // Add the field to the list of fields to invoke the hook on. |
|
313 if (!isset($fields[$field_id])) { |
|
314 $fields[$field_id] = $field; |
|
315 } |
|
316 // Extract the field values into a separate variable, easily accessed |
|
317 // by hook implementations. |
|
318 // Unless a language suggestion is provided we iterate on all the |
|
319 // available languages. |
|
320 $available_languages = field_available_languages($entity_type, $field); |
|
321 $language = is_array($options['language']) && !empty($options['language'][$id]) ? $options['language'][$id] : $options['language']; |
|
322 $languages = _field_language_suggestion($available_languages, $language, $field_name); |
|
323 foreach ($languages as $langcode) { |
|
324 $grouped_items[$field_id][$langcode][$id] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : array(); |
|
325 // Group the instances and entities corresponding to the current |
|
326 // field. |
|
327 $grouped_instances[$field_id][$langcode][$id] = $instance; |
|
328 $grouped_entities[$field_id][$langcode][$id] = $entities[$id]; |
|
329 } |
|
330 } |
|
331 } |
|
332 // Initialize the return value for each entity. |
|
333 $return[$id] = array(); |
|
334 } |
|
335 |
|
336 // For each field, invoke the field hook and collect results. |
|
337 foreach ($fields as $field_id => $field) { |
|
338 $field_name = $field['field_name']; |
|
339 $function = $options['default'] ? 'field_default_' . $op : $field['module'] . '_field_' . $op; |
|
340 // Iterate over all the field translations. |
|
341 foreach ($grouped_items[$field_id] as $langcode => &$items) { |
|
342 $entities = $grouped_entities[$field_id][$langcode]; |
|
343 $instances = $grouped_instances[$field_id][$langcode]; |
|
344 $results = $function($entity_type, $entities, $field, $instances, $langcode, $items, $a, $b); |
|
345 if (isset($results)) { |
|
346 // Collect results by entity. |
|
347 // For hooks with array results, we merge results together. |
|
348 // For hooks with scalar results, we collect results in an array. |
|
349 foreach ($results as $id => $result) { |
|
350 if (is_array($result)) { |
|
351 $return[$id] = array_merge($return[$id], $result); |
|
352 } |
|
353 else { |
|
354 $return[$id][] = $result; |
|
355 } |
|
356 } |
|
357 } |
|
358 } |
|
359 |
|
360 // Populate field values back in the entities, but avoid replacing missing |
|
361 // fields with an empty array (those are not equivalent on update). |
|
362 foreach ($grouped_entities[$field_id] as $langcode => $entities) { |
|
363 foreach ($entities as $id => $entity) { |
|
364 if ($grouped_items[$field_id][$langcode][$id] !== array() || isset($entity->{$field_name}[$langcode])) { |
|
365 $entity->{$field_name}[$langcode] = $grouped_items[$field_id][$langcode][$id]; |
|
366 } |
|
367 } |
|
368 } |
|
369 } |
|
370 |
|
371 return $return; |
|
372 } |
|
373 |
|
374 /** |
|
375 * Invoke field.module's version of a field hook. |
|
376 * |
|
377 * This function invokes the field_default_[op]() function. |
|
378 * Use _field_invoke() to invoke the field type implementation, |
|
379 * hook_field_[op](). |
|
380 * |
|
381 * @see _field_invoke() |
|
382 */ |
|
383 function _field_invoke_default($op, $entity_type, $entity, &$a = NULL, &$b = NULL, $options = array()) { |
|
384 $options['default'] = TRUE; |
|
385 return _field_invoke($op, $entity_type, $entity, $a, $b, $options); |
|
386 } |
|
387 |
|
388 /** |
|
389 * Invoke field.module's version of a field hook on multiple entities. |
|
390 * |
|
391 * This function invokes the field_default_[op]() function. |
|
392 * Use _field_invoke_multiple() to invoke the field type implementation, |
|
393 * hook_field_[op](). |
|
394 * |
|
395 * @see _field_invoke_multiple() |
|
396 */ |
|
397 function _field_invoke_multiple_default($op, $entity_type, $entities, &$a = NULL, &$b = NULL, $options = array()) { |
|
398 $options['default'] = TRUE; |
|
399 return _field_invoke_multiple($op, $entity_type, $entities, $a, $b, $options); |
|
400 } |
|
401 |
|
402 /** |
|
403 * Helper for _field_invoke(): retrieves a list of instances to operate on. |
|
404 * |
|
405 * @param $entity_type |
|
406 * The entity type. |
|
407 * @param $bundle |
|
408 * The bundle name. |
|
409 * @param $options |
|
410 * An associative array of options, as provided to _field_invoke(). Only the |
|
411 * following keys are considered : |
|
412 * - deleted |
|
413 * - field_name |
|
414 * - field_id |
|
415 * See _field_invoke() for details. |
|
416 * |
|
417 * @return |
|
418 * The array of selected instance definitions. |
|
419 */ |
|
420 function _field_invoke_get_instances($entity_type, $bundle, $options) { |
|
421 if ($options['deleted']) { |
|
422 // Deleted fields are not included in field_info_instances(), and need to |
|
423 // be fetched from the database with field_read_instances(). |
|
424 $params = array('entity_type' => $entity_type, 'bundle' => $bundle); |
|
425 if (isset($options['field_id'])) { |
|
426 // Single-field mode by field id: field_read_instances() does the filtering. |
|
427 // Single-field mode by field name is not compatible with the 'deleted' |
|
428 // option. |
|
429 $params['field_id'] = $options['field_id']; |
|
430 } |
|
431 $instances = field_read_instances($params, array('include_deleted' => TRUE)); |
|
432 } |
|
433 elseif (isset($options['field_name'])) { |
|
434 // Single-field mode by field name: field_info_instance() does the |
|
435 // filtering. |
|
436 $instances = array(field_info_instance($entity_type, $options['field_name'], $bundle)); |
|
437 } |
|
438 else { |
|
439 $instances = field_info_instances($entity_type, $bundle); |
|
440 if (isset($options['field_id'])) { |
|
441 // Single-field mode by field id: we need to loop on each instance to |
|
442 // find the right one. |
|
443 foreach ($instances as $instance) { |
|
444 if ($instance['field_id'] == $options['field_id']) { |
|
445 $instances = array($instance); |
|
446 break; |
|
447 } |
|
448 } |
|
449 } |
|
450 } |
|
451 |
|
452 return $instances; |
|
453 } |
|
454 |
|
455 /** |
|
456 * Add form elements for all fields for an entity to a form structure. |
|
457 * |
|
458 * The form elements for the entity's fields are added by reference as direct |
|
459 * children in the $form parameter. This parameter can be a full form structure |
|
460 * (most common case for entity edit forms), or a sub-element of a larger form. |
|
461 * |
|
462 * By default, submitted field values appear at the top-level of |
|
463 * $form_state['values']. A different location within $form_state['values'] can |
|
464 * be specified by setting the '#parents' property on the incoming $form |
|
465 * parameter. Because of name clashes, two instances of the same field cannot |
|
466 * appear within the same $form element, or within the same '#parents' space. |
|
467 * |
|
468 * For each call to field_attach_form(), field values are processed by calling |
|
469 * field_attach_form_validate() and field_attach_submit() on the same $form |
|
470 * element. |
|
471 * |
|
472 * Sample resulting structure in $form: |
|
473 * @code |
|
474 * '#parents' => The location of field values in $form_state['values'], |
|
475 * '#entity_type' => The name of the entity type, |
|
476 * '#bundle' => The name of the bundle, |
|
477 * // One sub-array per field appearing in the entity, keyed by field name. |
|
478 * // The structure of the array differs slightly depending on whether the |
|
479 * // widget is 'single-value' (provides the input for one field value, |
|
480 * // most common case), and will therefore be repeated as many times as |
|
481 * // needed, or 'multiple-values' (one single widget allows the input of |
|
482 * // several values, e.g checkboxes, select box...). |
|
483 * // The sub-array is nested into a $langcode key where $langcode has the |
|
484 * // same value of the $langcode parameter above. |
|
485 * // The '#language' key holds the same value of $langcode and it is used |
|
486 * // to access the field sub-array when $langcode is unknown. |
|
487 * 'field_foo' => array( |
|
488 * '#tree' => TRUE, |
|
489 * '#field_name' => The name of the field, |
|
490 * '#language' => $langcode, |
|
491 * $langcode => array( |
|
492 * '#field_name' => The name of the field, |
|
493 * '#language' => $langcode, |
|
494 * '#field_parents' => The 'parents' space for the field in the form, |
|
495 * equal to the #parents property of the $form parameter received by |
|
496 * field_attach_form(), |
|
497 * '#required' => Whether or not the field is required, |
|
498 * '#title' => The label of the field instance, |
|
499 * '#description' => The description text for the field instance, |
|
500 * |
|
501 * // Only for 'single' widgets: |
|
502 * '#theme' => 'field_multiple_value_form', |
|
503 * '#cardinality' => The field cardinality, |
|
504 * // One sub-array per copy of the widget, keyed by delta. |
|
505 * 0 => array( |
|
506 * '#entity_type' => The name of the entity type, |
|
507 * '#bundle' => The name of the bundle, |
|
508 * '#field_name' => The name of the field, |
|
509 * '#field_parents' => The 'parents' space for the field in the form, |
|
510 * equal to the #parents property of the $form parameter received by |
|
511 * field_attach_form(), |
|
512 * '#title' => The title to be displayed by the widget, |
|
513 * '#default_value' => The field value for delta 0, |
|
514 * '#required' => Whether the widget should be marked required, |
|
515 * '#delta' => 0, |
|
516 * '#columns' => The array of field columns, |
|
517 * // The remaining elements in the sub-array depend on the widget. |
|
518 * '#type' => The type of the widget, |
|
519 * ... |
|
520 * ), |
|
521 * 1 => array( |
|
522 * ... |
|
523 * ), |
|
524 * |
|
525 * // Only for multiple widgets: |
|
526 * '#entity_type' => The name of the entity type, |
|
527 * '#bundle' => $instance['bundle'], |
|
528 * '#columns' => array_keys($field['columns']), |
|
529 * // The remaining elements in the sub-array depend on the widget. |
|
530 * '#type' => The type of the widget, |
|
531 * ... |
|
532 * ), |
|
533 * ... |
|
534 * ), |
|
535 * ) |
|
536 * @endcode |
|
537 * |
|
538 * Additionally, some processing data is placed in $form_state, and can be |
|
539 * accessed by field_form_get_state() and field_form_set_state(). |
|
540 * |
|
541 * @param $entity_type |
|
542 * The type of $entity; e.g. 'node' or 'user'. |
|
543 * @param $entity |
|
544 * The entity for which to load form elements, used to initialize |
|
545 * default form values. |
|
546 * @param $form |
|
547 * The form structure to fill in. This can be a full form structure, or a |
|
548 * sub-element of a larger form. The #parents property can be set to control |
|
549 * the location of submitted field values within $form_state['values']. If |
|
550 * not specified, $form['#parents'] is set to an empty array, placing field |
|
551 * values at the top-level of $form_state['values']. |
|
552 * @param $form_state |
|
553 * An associative array containing the current state of the form. |
|
554 * @param $langcode |
|
555 * The language the field values are going to be entered, if no language |
|
556 * is provided the default site language will be used. |
|
557 * @param array $options |
|
558 * An associative array of additional options. See _field_invoke() for |
|
559 * details. |
|
560 * |
|
561 * @see field_form_get_state() |
|
562 * @see field_form_set_state() |
|
563 */ |
|
564 function field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode = NULL, $options = array()) { |
|
565 // Validate $options since this is a new parameter added after Drupal 7 was |
|
566 // released. |
|
567 $options = is_array($options) ? $options : array(); |
|
568 |
|
569 // Set #parents to 'top-level' by default. |
|
570 $form += array('#parents' => array()); |
|
571 |
|
572 // If no language is provided use the default site language. |
|
573 $options['language'] = field_valid_language($langcode); |
|
574 $form += (array) _field_invoke_default('form', $entity_type, $entity, $form, $form_state, $options); |
|
575 |
|
576 // Add custom weight handling. |
|
577 list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
|
578 $form['#pre_render'][] = '_field_extra_fields_pre_render'; |
|
579 $form['#entity_type'] = $entity_type; |
|
580 $form['#bundle'] = $bundle; |
|
581 |
|
582 // Let other modules make changes to the form. |
|
583 // Avoid module_invoke_all() to let parameters be taken by reference. |
|
584 foreach (module_implements('field_attach_form') as $module) { |
|
585 $function = $module . '_field_attach_form'; |
|
586 $function($entity_type, $entity, $form, $form_state, $langcode); |
|
587 } |
|
588 } |
|
589 |
|
590 /** |
|
591 * Loads fields for the current revisions of a group of entities. |
|
592 * |
|
593 * Loads all fields for each entity object in a group of a single entity type. |
|
594 * The loaded field values are added directly to the entity objects. |
|
595 * |
|
596 * field_attach_load() is automatically called by the default entity controller |
|
597 * class, and thus, in most cases, doesn't need to be explicitly called by the |
|
598 * entity type module. |
|
599 * |
|
600 * @param $entity_type |
|
601 * The type of $entity; e.g., 'node' or 'user'. |
|
602 * @param $entities |
|
603 * An array of entities for which to load fields, keyed by entity ID. |
|
604 * Each entity needs to have its 'bundle', 'id' and (if applicable) |
|
605 * 'revision' keys filled in. The function adds the loaded field data |
|
606 * directly in the entity objects of the $entities array. |
|
607 * @param $age |
|
608 * FIELD_LOAD_CURRENT to load the most recent revision for all |
|
609 * fields, or FIELD_LOAD_REVISION to load the version indicated by |
|
610 * each entity. Defaults to FIELD_LOAD_CURRENT; use |
|
611 * field_attach_load_revision() instead of passing FIELD_LOAD_REVISION. |
|
612 * @param $options |
|
613 * An associative array of additional options, with the following keys: |
|
614 * - 'field_id': The field ID that should be loaded, instead of |
|
615 * loading all fields, for each entity. Note that returned entities |
|
616 * may contain data for other fields, for example if they are read |
|
617 * from a cache. |
|
618 * - 'deleted': If TRUE, the function will operate on deleted fields |
|
619 * as well as non-deleted fields. If unset or FALSE, only |
|
620 * non-deleted fields are operated on. |
|
621 */ |
|
622 function field_attach_load($entity_type, $entities, $age = FIELD_LOAD_CURRENT, $options = array()) { |
|
623 $load_current = $age == FIELD_LOAD_CURRENT; |
|
624 |
|
625 // Merge default options. |
|
626 $default_options = array( |
|
627 'deleted' => FALSE, |
|
628 ); |
|
629 $options += $default_options; |
|
630 |
|
631 $info = entity_get_info($entity_type); |
|
632 // Only the most current revision of non-deleted fields for cacheable entity |
|
633 // types can be cached. |
|
634 $cache_read = $load_current && $info['field cache'] && empty($options['deleted']); |
|
635 // In addition, do not write to the cache when loading a single field. |
|
636 $cache_write = $cache_read && !isset($options['field_id']); |
|
637 |
|
638 if (empty($entities)) { |
|
639 return; |
|
640 } |
|
641 |
|
642 // Assume all entities will need to be queried. Entities found in the cache |
|
643 // will be removed from the list. |
|
644 $queried_entities = $entities; |
|
645 |
|
646 // Fetch available entities from cache, if applicable. |
|
647 if ($cache_read) { |
|
648 // Build the list of cache entries to retrieve. |
|
649 $cids = array(); |
|
650 foreach ($entities as $id => $entity) { |
|
651 $cids[] = "field:$entity_type:$id"; |
|
652 } |
|
653 $cache = cache_get_multiple($cids, 'cache_field'); |
|
654 // Put the cached field values back into the entities and remove them from |
|
655 // the list of entities to query. |
|
656 foreach ($entities as $id => $entity) { |
|
657 $cid = "field:$entity_type:$id"; |
|
658 if (isset($cache[$cid])) { |
|
659 unset($queried_entities[$id]); |
|
660 foreach ($cache[$cid]->data as $field_name => $values) { |
|
661 $entity->$field_name = $values; |
|
662 } |
|
663 } |
|
664 } |
|
665 } |
|
666 |
|
667 // Fetch other entities from their storage location. |
|
668 if ($queried_entities) { |
|
669 // The invoke order is: |
|
670 // - hook_field_storage_pre_load() |
|
671 // - storage backend's hook_field_storage_load() |
|
672 // - field-type module's hook_field_load() |
|
673 // - hook_field_attach_load() |
|
674 |
|
675 // Invoke hook_field_storage_pre_load(): let any module load field |
|
676 // data before the storage engine, accumulating along the way. |
|
677 $skip_fields = array(); |
|
678 foreach (module_implements('field_storage_pre_load') as $module) { |
|
679 $function = $module . '_field_storage_pre_load'; |
|
680 $function($entity_type, $queried_entities, $age, $skip_fields, $options); |
|
681 } |
|
682 |
|
683 $instances = array(); |
|
684 |
|
685 // Collect the storage backends used by the remaining fields in the entities. |
|
686 $storages = array(); |
|
687 foreach ($queried_entities as $entity) { |
|
688 list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
|
689 $instances = _field_invoke_get_instances($entity_type, $bundle, $options); |
|
690 |
|
691 foreach ($instances as $instance) { |
|
692 $field_name = $instance['field_name']; |
|
693 $field_id = $instance['field_id']; |
|
694 // Make sure all fields are present at least as empty arrays. |
|
695 if (!isset($queried_entities[$id]->{$field_name})) { |
|
696 $queried_entities[$id]->{$field_name} = array(); |
|
697 } |
|
698 // Collect the storage backend if the field has not been loaded yet. |
|
699 if (!isset($skip_fields[$field_id])) { |
|
700 $field = field_info_field_by_id($field_id); |
|
701 $storages[$field['storage']['type']][$field_id][] = $load_current ? $id : $vid; |
|
702 } |
|
703 } |
|
704 } |
|
705 |
|
706 // Invoke hook_field_storage_load() on the relevant storage backends. |
|
707 foreach ($storages as $storage => $fields) { |
|
708 $storage_info = field_info_storage_types($storage); |
|
709 module_invoke($storage_info['module'], 'field_storage_load', $entity_type, $queried_entities, $age, $fields, $options); |
|
710 } |
|
711 |
|
712 // Invoke field-type module's hook_field_load(). |
|
713 $null = NULL; |
|
714 _field_invoke_multiple('load', $entity_type, $queried_entities, $age, $null, $options); |
|
715 |
|
716 // Invoke hook_field_attach_load(): let other modules act on loading the |
|
717 // entity. |
|
718 module_invoke_all('field_attach_load', $entity_type, $queried_entities, $age, $options); |
|
719 |
|
720 // Build cache data. |
|
721 if ($cache_write) { |
|
722 foreach ($queried_entities as $id => $entity) { |
|
723 $data = array(); |
|
724 list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
|
725 $instances = field_info_instances($entity_type, $bundle); |
|
726 foreach ($instances as $instance) { |
|
727 $data[$instance['field_name']] = $queried_entities[$id]->{$instance['field_name']}; |
|
728 } |
|
729 $cid = "field:$entity_type:$id"; |
|
730 cache_set($cid, $data, 'cache_field'); |
|
731 } |
|
732 } |
|
733 } |
|
734 } |
|
735 |
|
736 /** |
|
737 * Load all fields for previous versions of a group of entities. |
|
738 * |
|
739 * Loading different versions of the same entities is not supported, and should |
|
740 * be done by separate calls to the function. |
|
741 * |
|
742 * field_attach_load_revision() is automatically called by the default entity |
|
743 * controller class, and thus, in most cases, doesn't need to be explicitly |
|
744 * called by the entity type module. |
|
745 * |
|
746 * @param $entity_type |
|
747 * The type of $entity; e.g. 'node' or 'user'. |
|
748 * @param $entities |
|
749 * An array of entities for which to load fields, keyed by entity ID. Each |
|
750 * entity needs to have its 'bundle', 'id' and (if applicable) 'revision' |
|
751 * keys filled. The function adds the loaded field data directly in the |
|
752 * entity objects of the $entities array. |
|
753 * @param $options |
|
754 * An associative array of additional options. See field_attach_load() for |
|
755 * details. |
|
756 */ |
|
757 function field_attach_load_revision($entity_type, $entities, $options = array()) { |
|
758 return field_attach_load($entity_type, $entities, FIELD_LOAD_REVISION, $options); |
|
759 } |
|
760 |
|
761 /** |
|
762 * Perform field validation against the field data in an entity. |
|
763 * |
|
764 * This function does not perform field widget validation on form |
|
765 * submissions. It is intended to be called during API save |
|
766 * operations. Use field_attach_form_validate() to validate form |
|
767 * submissions. |
|
768 * |
|
769 * @param $entity_type |
|
770 * The type of $entity; e.g. 'node' or 'user'. |
|
771 * @param $entity |
|
772 * The entity with fields to validate. |
|
773 * @throws FieldValidationException |
|
774 * If validation errors are found, a FieldValidationException is thrown. The |
|
775 * 'errors' property contains the array of errors, keyed by field name, |
|
776 * language and delta. |
|
777 * @param array $options |
|
778 * An associative array of additional options. See _field_invoke() for |
|
779 * details. |
|
780 */ |
|
781 function field_attach_validate($entity_type, $entity, $options = array()) { |
|
782 // Validate $options since this is a new parameter added after Drupal 7 was |
|
783 // released. |
|
784 $options = is_array($options) ? $options : array(); |
|
785 |
|
786 $errors = array(); |
|
787 // Check generic, field-type-agnostic errors first. |
|
788 $null = NULL; |
|
789 _field_invoke_default('validate', $entity_type, $entity, $errors, $null, $options); |
|
790 // Check field-type specific errors. |
|
791 _field_invoke('validate', $entity_type, $entity, $errors, $null, $options); |
|
792 |
|
793 // Let other modules validate the entity. |
|
794 // Avoid module_invoke_all() to let $errors be taken by reference. |
|
795 foreach (module_implements('field_attach_validate') as $module) { |
|
796 $function = $module . '_field_attach_validate'; |
|
797 $function($entity_type, $entity, $errors); |
|
798 } |
|
799 |
|
800 if ($errors) { |
|
801 throw new FieldValidationException($errors); |
|
802 } |
|
803 } |
|
804 |
|
805 /** |
|
806 * Perform field validation against form-submitted field values. |
|
807 * |
|
808 * There are two levels of validation for fields in forms: widget |
|
809 * validation, and field validation. |
|
810 * - Widget validation steps are specific to a given widget's own form |
|
811 * structure and UI metaphors. They are executed through FAPI's |
|
812 * #element_validate property during normal form validation. |
|
813 * - Field validation steps are common to a given field type, independently of |
|
814 * the specific widget being used in a given form. They are defined in the |
|
815 * field type's implementation of hook_field_validate(). |
|
816 * |
|
817 * This function performs field validation in the context of a form |
|
818 * submission. It converts field validation errors into form errors |
|
819 * on the correct form elements. Fieldable entity types should call |
|
820 * this function during their own form validation function. |
|
821 * |
|
822 * @param $entity_type |
|
823 * The type of $entity; e.g. 'node' or 'user'. |
|
824 * @param $entity |
|
825 * The entity being submitted. The 'bundle', 'id' and (if applicable) |
|
826 * 'revision' keys should be present. The actual field values will be read |
|
827 * from $form_state['values']. |
|
828 * @param $form |
|
829 * The form structure where field elements are attached to. This might be a |
|
830 * full form structure, or a sub-element of a larger form. |
|
831 * @param $form_state |
|
832 * An associative array containing the current state of the form. |
|
833 * @param array $options |
|
834 * An associative array of additional options. See _field_invoke() for |
|
835 * details. |
|
836 */ |
|
837 function field_attach_form_validate($entity_type, $entity, $form, &$form_state, $options = array()) { |
|
838 // Validate $options since this is a new parameter added after Drupal 7 was |
|
839 // released. |
|
840 $options = is_array($options) ? $options : array(); |
|
841 |
|
842 // Extract field values from submitted values. |
|
843 _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state); |
|
844 |
|
845 // Perform field_level validation. |
|
846 try { |
|
847 field_attach_validate($entity_type, $entity, $options); |
|
848 } |
|
849 catch (FieldValidationException $e) { |
|
850 // Pass field-level validation errors back to widgets for accurate error |
|
851 // flagging. |
|
852 foreach ($e->errors as $field_name => $field_errors) { |
|
853 foreach ($field_errors as $langcode => $errors) { |
|
854 $field_state = field_form_get_state($form['#parents'], $field_name, $langcode, $form_state); |
|
855 $field_state['errors'] = $errors; |
|
856 field_form_set_state($form['#parents'], $field_name, $langcode, $form_state, $field_state); |
|
857 } |
|
858 } |
|
859 _field_invoke_default('form_errors', $entity_type, $entity, $form, $form_state, $options); |
|
860 } |
|
861 } |
|
862 |
|
863 /** |
|
864 * Perform necessary operations on field data submitted by a form. |
|
865 * |
|
866 * Currently, this accounts for drag-and-drop reordering of |
|
867 * field values, and filtering of empty values. |
|
868 * |
|
869 * @param $entity_type |
|
870 * The type of $entity; e.g. 'node' or 'user'. |
|
871 * @param $entity |
|
872 * The entity being submitted. The 'bundle', 'id' and (if applicable) |
|
873 * 'revision' keys should be present. The actual field values will be read |
|
874 * from $form_state['values']. |
|
875 * @param $form |
|
876 * The form structure where field elements are attached to. This might be a |
|
877 * full form structure, or a sub-element of a larger form. |
|
878 * @param $form_state |
|
879 * An associative array containing the current state of the form. |
|
880 * @param array $options |
|
881 * An associative array of additional options. See _field_invoke() for |
|
882 * details. |
|
883 */ |
|
884 function field_attach_submit($entity_type, $entity, $form, &$form_state, $options = array()) { |
|
885 // Validate $options since this is a new parameter added after Drupal 7 was |
|
886 // released. |
|
887 $options = is_array($options) ? $options : array(); |
|
888 |
|
889 // Extract field values from submitted values. |
|
890 _field_invoke_default('extract_form_values', $entity_type, $entity, $form, $form_state, $options); |
|
891 |
|
892 _field_invoke_default('submit', $entity_type, $entity, $form, $form_state, $options); |
|
893 |
|
894 // Let other modules act on submitting the entity. |
|
895 // Avoid module_invoke_all() to let $form_state be taken by reference. |
|
896 foreach (module_implements('field_attach_submit') as $module) { |
|
897 $function = $module . '_field_attach_submit'; |
|
898 $function($entity_type, $entity, $form, $form_state); |
|
899 } |
|
900 } |
|
901 |
|
902 /** |
|
903 * Perform necessary operations just before fields data get saved. |
|
904 * |
|
905 * We take no specific action here, we just give other |
|
906 * modules the opportunity to act. |
|
907 * |
|
908 * @param $entity_type |
|
909 * The type of $entity; e.g. 'node' or 'user'. |
|
910 * @param $entity |
|
911 * The entity with fields to process. |
|
912 */ |
|
913 function field_attach_presave($entity_type, $entity) { |
|
914 _field_invoke('presave', $entity_type, $entity); |
|
915 |
|
916 // Let other modules act on presaving the entity. |
|
917 module_invoke_all('field_attach_presave', $entity_type, $entity); |
|
918 } |
|
919 |
|
920 /** |
|
921 * Save field data for a new entity. |
|
922 * |
|
923 * The passed-in entity must already contain its id and (if applicable) |
|
924 * revision id attributes. |
|
925 * Default values (if any) will be saved for fields not present in the |
|
926 * $entity. |
|
927 * |
|
928 * @param $entity_type |
|
929 * The type of $entity; e.g. 'node' or 'user'. |
|
930 * @param $entity |
|
931 * The entity with fields to save. |
|
932 * @return |
|
933 * Default values (if any) will be added to the $entity parameter for fields |
|
934 * it leaves unspecified. |
|
935 */ |
|
936 function field_attach_insert($entity_type, $entity) { |
|
937 _field_invoke_default('insert', $entity_type, $entity); |
|
938 _field_invoke('insert', $entity_type, $entity); |
|
939 |
|
940 list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
|
941 |
|
942 // Let any module insert field data before the storage engine, accumulating |
|
943 // saved fields along the way. |
|
944 $skip_fields = array(); |
|
945 foreach (module_implements('field_storage_pre_insert') as $module) { |
|
946 $function = $module . '_field_storage_pre_insert'; |
|
947 $function($entity_type, $entity, $skip_fields); |
|
948 } |
|
949 |
|
950 // Collect the storage backends used by the remaining fields in the entities. |
|
951 $storages = array(); |
|
952 foreach (field_info_instances($entity_type, $bundle) as $instance) { |
|
953 $field = field_info_field_by_id($instance['field_id']); |
|
954 $field_id = $field['id']; |
|
955 $field_name = $field['field_name']; |
|
956 if (!empty($entity->$field_name)) { |
|
957 // Collect the storage backend if the field has not been written yet. |
|
958 if (!isset($skip_fields[$field_id])) { |
|
959 $storages[$field['storage']['type']][$field_id] = $field_id; |
|
960 } |
|
961 } |
|
962 } |
|
963 |
|
964 // Field storage backends save any remaining unsaved fields. |
|
965 foreach ($storages as $storage => $fields) { |
|
966 $storage_info = field_info_storage_types($storage); |
|
967 module_invoke($storage_info['module'], 'field_storage_write', $entity_type, $entity, FIELD_STORAGE_INSERT, $fields); |
|
968 } |
|
969 |
|
970 // Let other modules act on inserting the entity. |
|
971 module_invoke_all('field_attach_insert', $entity_type, $entity); |
|
972 |
|
973 $entity_info = entity_get_info($entity_type); |
|
974 } |
|
975 |
|
976 /** |
|
977 * Save field data for an existing entity. |
|
978 * |
|
979 * When calling this function outside an entity save operation be sure to |
|
980 * clear caches for the entity: |
|
981 * @code |
|
982 * entity_get_controller($entity_type)->resetCache(array($entity_id)) |
|
983 * @endcode |
|
984 * |
|
985 * @param $entity_type |
|
986 * The type of $entity; e.g. 'node' or 'user'. |
|
987 * @param $entity |
|
988 * The entity with fields to save. |
|
989 */ |
|
990 function field_attach_update($entity_type, $entity) { |
|
991 _field_invoke('update', $entity_type, $entity); |
|
992 |
|
993 list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
|
994 |
|
995 // Let any module update field data before the storage engine, accumulating |
|
996 // saved fields along the way. |
|
997 $skip_fields = array(); |
|
998 foreach (module_implements('field_storage_pre_update') as $module) { |
|
999 $function = $module . '_field_storage_pre_update'; |
|
1000 $function($entity_type, $entity, $skip_fields); |
|
1001 } |
|
1002 |
|
1003 // Collect the storage backends used by the remaining fields in the entities. |
|
1004 $storages = array(); |
|
1005 foreach (field_info_instances($entity_type, $bundle) as $instance) { |
|
1006 $field = field_info_field_by_id($instance['field_id']); |
|
1007 $field_id = $field['id']; |
|
1008 $field_name = $field['field_name']; |
|
1009 // Leave the field untouched if $entity comes with no $field_name property, |
|
1010 // but empty the field if it comes as a NULL value or an empty array. |
|
1011 // Function property_exists() is slower, so we catch the more frequent |
|
1012 // cases where it's an empty array with the faster isset(). |
|
1013 if (isset($entity->$field_name) || property_exists($entity, $field_name)) { |
|
1014 // Collect the storage backend if the field has not been written yet. |
|
1015 if (!isset($skip_fields[$field_id])) { |
|
1016 $storages[$field['storage']['type']][$field_id] = $field_id; |
|
1017 } |
|
1018 } |
|
1019 } |
|
1020 |
|
1021 // Field storage backends save any remaining unsaved fields. |
|
1022 foreach ($storages as $storage => $fields) { |
|
1023 $storage_info = field_info_storage_types($storage); |
|
1024 module_invoke($storage_info['module'], 'field_storage_write', $entity_type, $entity, FIELD_STORAGE_UPDATE, $fields); |
|
1025 } |
|
1026 |
|
1027 // Let other modules act on updating the entity. |
|
1028 module_invoke_all('field_attach_update', $entity_type, $entity); |
|
1029 |
|
1030 $entity_info = entity_get_info($entity_type); |
|
1031 if ($entity_info['field cache']) { |
|
1032 cache_clear_all("field:$entity_type:$id", 'cache_field'); |
|
1033 } |
|
1034 } |
|
1035 |
|
1036 /** |
|
1037 * Delete field data for an existing entity. This deletes all |
|
1038 * revisions of field data for the entity. |
|
1039 * |
|
1040 * @param $entity_type |
|
1041 * The type of $entity; e.g. 'node' or 'user'. |
|
1042 * @param $entity |
|
1043 * The entity whose field data to delete. |
|
1044 */ |
|
1045 function field_attach_delete($entity_type, $entity) { |
|
1046 _field_invoke('delete', $entity_type, $entity); |
|
1047 |
|
1048 list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
|
1049 |
|
1050 // Collect the storage backends used by the fields in the entities. |
|
1051 $storages = array(); |
|
1052 foreach (field_info_instances($entity_type, $bundle) as $instance) { |
|
1053 $field = field_info_field_by_id($instance['field_id']); |
|
1054 $field_id = $field['id']; |
|
1055 $storages[$field['storage']['type']][$field_id] = $field_id; |
|
1056 } |
|
1057 |
|
1058 // Field storage backends delete their data. |
|
1059 foreach ($storages as $storage => $fields) { |
|
1060 $storage_info = field_info_storage_types($storage); |
|
1061 module_invoke($storage_info['module'], 'field_storage_delete', $entity_type, $entity, $fields); |
|
1062 } |
|
1063 |
|
1064 // Let other modules act on deleting the entity. |
|
1065 module_invoke_all('field_attach_delete', $entity_type, $entity); |
|
1066 |
|
1067 $entity_info = entity_get_info($entity_type); |
|
1068 if ($entity_info['field cache']) { |
|
1069 cache_clear_all("field:$entity_type:$id", 'cache_field'); |
|
1070 } |
|
1071 } |
|
1072 |
|
1073 /** |
|
1074 * Delete field data for a single revision of an existing entity. The |
|
1075 * passed entity must have a revision id attribute. |
|
1076 * |
|
1077 * @param $entity_type |
|
1078 * The type of $entity; e.g. 'node' or 'user'. |
|
1079 * @param $entity |
|
1080 * The entity with fields to save. |
|
1081 */ |
|
1082 function field_attach_delete_revision($entity_type, $entity) { |
|
1083 _field_invoke('delete_revision', $entity_type, $entity); |
|
1084 |
|
1085 list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
|
1086 |
|
1087 // Collect the storage backends used by the fields in the entities. |
|
1088 $storages = array(); |
|
1089 foreach (field_info_instances($entity_type, $bundle) as $instance) { |
|
1090 $field = field_info_field_by_id($instance['field_id']); |
|
1091 $field_id = $field['id']; |
|
1092 $storages[$field['storage']['type']][$field_id] = $field_id; |
|
1093 } |
|
1094 |
|
1095 // Field storage backends delete their data. |
|
1096 foreach ($storages as $storage => $fields) { |
|
1097 $storage_info = field_info_storage_types($storage); |
|
1098 module_invoke($storage_info['module'], 'field_storage_delete_revision', $entity_type, $entity, $fields); |
|
1099 } |
|
1100 |
|
1101 // Let other modules act on deleting the revision. |
|
1102 module_invoke_all('field_attach_delete_revision', $entity_type, $entity); |
|
1103 } |
|
1104 |
|
1105 /** |
|
1106 * Prepare field data prior to display. |
|
1107 * |
|
1108 * This function lets field types and formatters load additional data |
|
1109 * needed for display that is not automatically loaded during |
|
1110 * field_attach_load(). It accepts an array of entities to allow query |
|
1111 * optimisation when displaying lists of entities. |
|
1112 * |
|
1113 * field_attach_prepare_view() and field_attach_view() are two halves |
|
1114 * of the same operation. It is safe to call |
|
1115 * field_attach_prepare_view() multiple times on the same entity |
|
1116 * before calling field_attach_view() on it, but calling any Field |
|
1117 * API operation on an entity between passing that entity to these two |
|
1118 * functions may yield incorrect results. |
|
1119 * |
|
1120 * @param $entity_type |
|
1121 * The type of $entities; e.g. 'node' or 'user'. |
|
1122 * @param $entities |
|
1123 * An array of entities, keyed by entity id. |
|
1124 * @param $view_mode |
|
1125 * View mode, e.g. 'full', 'teaser'... |
|
1126 * @param $langcode |
|
1127 * (Optional) The language the field values are to be shown in. If no language |
|
1128 * is provided the current language is used. |
|
1129 * @param array $options |
|
1130 * An associative array of additional options. See _field_invoke() for |
|
1131 * details. |
|
1132 */ |
|
1133 function field_attach_prepare_view($entity_type, $entities, $view_mode, $langcode = NULL, $options = array()) { |
|
1134 // Validate $options since this is a new parameter added after Drupal 7 was |
|
1135 // released. |
|
1136 $options = is_array($options) ? $options : array(); |
|
1137 |
|
1138 $options['language'] = array(); |
|
1139 |
|
1140 // To ensure hooks are only run once per entity, only process items without |
|
1141 // the _field_view_prepared flag. |
|
1142 // @todo: resolve this more generally for both entity and field level hooks. |
|
1143 $prepare = array(); |
|
1144 foreach ($entities as $id => $entity) { |
|
1145 if (empty($entity->_field_view_prepared)) { |
|
1146 // Add this entity to the items to be prepared. |
|
1147 $prepare[$id] = $entity; |
|
1148 |
|
1149 // Determine the actual language to display for each field, given the |
|
1150 // languages available in the field data. |
|
1151 $options['language'][$id] = field_language($entity_type, $entity, NULL, $langcode); |
|
1152 |
|
1153 // Mark this item as prepared. |
|
1154 $entity->_field_view_prepared = TRUE; |
|
1155 } |
|
1156 } |
|
1157 |
|
1158 $null = NULL; |
|
1159 // First let the field types do their preparation. |
|
1160 _field_invoke_multiple('prepare_view', $entity_type, $prepare, $null, $null, $options); |
|
1161 // Then let the formatters do their own specific massaging. |
|
1162 // field_default_prepare_view() takes care of dispatching to the correct |
|
1163 // formatters according to the display settings for the view mode. |
|
1164 _field_invoke_multiple_default('prepare_view', $entity_type, $prepare, $view_mode, $null, $options); |
|
1165 } |
|
1166 |
|
1167 /** |
|
1168 * Returns a renderable array for the fields on an entity. |
|
1169 * |
|
1170 * Each field is displayed according to the display options specified in the |
|
1171 * $instance definition for the given $view_mode. |
|
1172 * |
|
1173 * field_attach_prepare_view() and field_attach_view() are two halves |
|
1174 * of the same operation. It is safe to call |
|
1175 * field_attach_prepare_view() multiple times on the same entity |
|
1176 * before calling field_attach_view() on it, but calling any Field |
|
1177 * API operation on an entity between passing that entity to these two |
|
1178 * functions may yield incorrect results. |
|
1179 * |
|
1180 * Sample structure: |
|
1181 * @code |
|
1182 * array( |
|
1183 * 'field_foo' => array( |
|
1184 * '#theme' => 'field', |
|
1185 * '#title' => the label of the field instance, |
|
1186 * '#label_display' => the label display mode, |
|
1187 * '#object' => the fieldable entity being displayed, |
|
1188 * '#entity_type' => the type of the entity being displayed, |
|
1189 * '#language' => the language of the field values being displayed, |
|
1190 * '#view_mode' => the view mode, |
|
1191 * '#field_name' => the name of the field, |
|
1192 * '#field_type' => the type of the field, |
|
1193 * '#formatter' => the name of the formatter, |
|
1194 * '#items' => the field values being displayed, |
|
1195 * // The element's children are the formatted values returned by |
|
1196 * // hook_field_formatter_view(). |
|
1197 * ), |
|
1198 * ); |
|
1199 * @endcode |
|
1200 * |
|
1201 * @param $entity_type |
|
1202 * The type of $entity; e.g. 'node' or 'user'. |
|
1203 * @param $entity |
|
1204 * The entity with fields to render. |
|
1205 * @param $view_mode |
|
1206 * View mode, e.g. 'full', 'teaser'... |
|
1207 * @param $langcode |
|
1208 * The language the field values are to be shown in. If no language is |
|
1209 * provided the current language is used. |
|
1210 * @param array $options |
|
1211 * An associative array of additional options. See _field_invoke() for |
|
1212 * details. |
|
1213 * @return |
|
1214 * A renderable array for the field values. |
|
1215 */ |
|
1216 function field_attach_view($entity_type, $entity, $view_mode, $langcode = NULL, $options = array()) { |
|
1217 // Validate $options since this is a new parameter added after Drupal 7 was |
|
1218 // released. |
|
1219 $options = is_array($options) ? $options : array(); |
|
1220 |
|
1221 // Determine the actual language to display for each field, given the |
|
1222 // languages available in the field data. |
|
1223 $display_language = field_language($entity_type, $entity, NULL, $langcode); |
|
1224 $options['language'] = $display_language; |
|
1225 |
|
1226 // Invoke field_default_view(). |
|
1227 $null = NULL; |
|
1228 $output = _field_invoke_default('view', $entity_type, $entity, $view_mode, $null, $options); |
|
1229 |
|
1230 // Add custom weight handling. |
|
1231 list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
|
1232 $output['#pre_render'][] = '_field_extra_fields_pre_render'; |
|
1233 $output['#entity_type'] = $entity_type; |
|
1234 $output['#bundle'] = $bundle; |
|
1235 |
|
1236 // Let other modules alter the renderable array. |
|
1237 $context = array( |
|
1238 'entity_type' => $entity_type, |
|
1239 'entity' => $entity, |
|
1240 'view_mode' => $view_mode, |
|
1241 'display' => $view_mode, |
|
1242 'language' => $langcode, |
|
1243 ); |
|
1244 drupal_alter('field_attach_view', $output, $context); |
|
1245 |
|
1246 // Reset the _field_view_prepared flag set in field_attach_prepare_view(), |
|
1247 // in case the same entity is displayed with different settings later in |
|
1248 // the request. |
|
1249 unset($entity->_field_view_prepared); |
|
1250 |
|
1251 return $output; |
|
1252 } |
|
1253 |
|
1254 /** |
|
1255 * Populate the template variables with the field values available for rendering. |
|
1256 * |
|
1257 * The $variables array will be populated with all the field instance values |
|
1258 * associated with the given entity type, keyed by field name; in case of |
|
1259 * translatable fields the language currently chosen for display will be |
|
1260 * selected. |
|
1261 * |
|
1262 * @param $entity_type |
|
1263 * The type of $entity; e.g. 'node' or 'user'. |
|
1264 * @param $entity |
|
1265 * The entity with fields to render. |
|
1266 * @param $element |
|
1267 * The structured array containing the values ready for rendering. |
|
1268 * @param $variables |
|
1269 * The variables array is passed by reference and will be populated with field |
|
1270 * values. |
|
1271 */ |
|
1272 function field_attach_preprocess($entity_type, $entity, $element, &$variables) { |
|
1273 list(, , $bundle) = entity_extract_ids($entity_type, $entity); |
|
1274 |
|
1275 foreach (field_info_instances($entity_type, $bundle) as $instance) { |
|
1276 $field_name = $instance['field_name']; |
|
1277 if (isset($element[$field_name]['#language'])) { |
|
1278 $langcode = $element[$field_name]['#language']; |
|
1279 $variables[$field_name] = isset($entity->{$field_name}[$langcode]) ? $entity->{$field_name}[$langcode] : NULL; |
|
1280 } |
|
1281 } |
|
1282 |
|
1283 // Let other modules make changes to the $variables array. |
|
1284 $context = array( |
|
1285 'entity_type' => $entity_type, |
|
1286 'entity' => $entity, |
|
1287 'element' => $element, |
|
1288 ); |
|
1289 drupal_alter('field_attach_preprocess', $variables, $context); |
|
1290 } |
|
1291 |
|
1292 /** |
|
1293 * Prepares an entity for translation. |
|
1294 * |
|
1295 * This function is used to fill-in the form default values for Field API fields |
|
1296 * while performing entity translation. By default it copies all the source |
|
1297 * values in the given source language to the new entity and assigns them the |
|
1298 * target language. |
|
1299 * |
|
1300 * This is used as part of the 'per entity' translation pattern, which is |
|
1301 * implemented only for nodes by translation.module. Other entity types may be |
|
1302 * supported through contributed modules. |
|
1303 * |
|
1304 * @param $entity_type |
|
1305 * The type of $entity; e.g. 'node' or 'user'. |
|
1306 * @param $entity |
|
1307 * The entity to be prepared for translation. |
|
1308 * @param $langcode |
|
1309 * The language the entity has to be translated in. |
|
1310 * @param $source_entity |
|
1311 * The source entity holding the field values to be translated. |
|
1312 * @param $source_langcode |
|
1313 * The source language from which translate. |
|
1314 */ |
|
1315 function field_attach_prepare_translation($entity_type, $entity, $langcode, $source_entity, $source_langcode) { |
|
1316 $options = array('language' => $langcode); |
|
1317 // Copy source field values into the entity to be prepared. |
|
1318 _field_invoke_default('prepare_translation', $entity_type, $entity, $source_entity, $source_langcode, $options); |
|
1319 // Let field types handle their own advanced translation pattern if needed. |
|
1320 _field_invoke('prepare_translation', $entity_type, $entity, $source_entity, $source_langcode, $options); |
|
1321 // Let other modules alter the entity translation. |
|
1322 $context = array( |
|
1323 'entity_type' => $entity_type, |
|
1324 'langcode' => $langcode, |
|
1325 'source_entity' => $source_entity, |
|
1326 'source_langcode' => $source_langcode, |
|
1327 ); |
|
1328 drupal_alter('field_attach_prepare_translation', $entity, $context); |
|
1329 } |
|
1330 |
|
1331 /** |
|
1332 * Notify field.module that a new bundle was created. |
|
1333 * |
|
1334 * The default SQL-based storage doesn't need to do anything about it, but |
|
1335 * others might. |
|
1336 * |
|
1337 * @param $entity_type |
|
1338 * The entity type to which the bundle is bound. |
|
1339 * @param $bundle |
|
1340 * The name of the newly created bundle. |
|
1341 */ |
|
1342 function field_attach_create_bundle($entity_type, $bundle) { |
|
1343 // Clear the cache. |
|
1344 field_cache_clear(); |
|
1345 |
|
1346 // Let other modules act on creating the bundle. |
|
1347 module_invoke_all('field_attach_create_bundle', $entity_type, $bundle); |
|
1348 } |
|
1349 |
|
1350 /** |
|
1351 * Notify field.module that a bundle was renamed. |
|
1352 * |
|
1353 * @param $entity_type |
|
1354 * The entity type to which the bundle is bound. |
|
1355 * @param $bundle_old |
|
1356 * The previous name of the bundle. |
|
1357 * @param $bundle_new |
|
1358 * The new name of the bundle. |
|
1359 */ |
|
1360 function field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) { |
|
1361 db_update('field_config_instance') |
|
1362 ->fields(array('bundle' => $bundle_new)) |
|
1363 ->condition('entity_type', $entity_type) |
|
1364 ->condition('bundle', $bundle_old) |
|
1365 ->execute(); |
|
1366 |
|
1367 // Clear the cache. |
|
1368 field_cache_clear(); |
|
1369 |
|
1370 // Update bundle settings. |
|
1371 $settings = variable_get('field_bundle_settings_' . $entity_type . '__' . $bundle_old, array()); |
|
1372 variable_set('field_bundle_settings_' . $entity_type . '__' . $bundle_new, $settings); |
|
1373 variable_del('field_bundle_settings_' . $entity_type . '__' . $bundle_old); |
|
1374 |
|
1375 // Let other modules act on renaming the bundle. |
|
1376 module_invoke_all('field_attach_rename_bundle', $entity_type, $bundle_old, $bundle_new); |
|
1377 } |
|
1378 |
|
1379 /** |
|
1380 * Notify field.module the a bundle was deleted. |
|
1381 * |
|
1382 * This deletes the data for the field instances as well as the field instances |
|
1383 * themselves. This function actually just marks the data and field instances |
|
1384 * and deleted, leaving the garbage collection for a separate process, because |
|
1385 * it is not always possible to delete this much data in a single page request |
|
1386 * (particularly since for some field types, the deletion is more than just a |
|
1387 * simple DELETE query). |
|
1388 * |
|
1389 * @param $entity_type |
|
1390 * The entity type to which the bundle is bound. |
|
1391 * @param $bundle |
|
1392 * The bundle to delete. |
|
1393 */ |
|
1394 function field_attach_delete_bundle($entity_type, $bundle) { |
|
1395 // First, delete the instances themselves. field_read_instances() must be |
|
1396 // used here since field_info_instances() does not return instances for |
|
1397 // disabled entity types or bundles. |
|
1398 $instances = field_read_instances(array('entity_type' => $entity_type, 'bundle' => $bundle), array('include_inactive' => 1)); |
|
1399 foreach ($instances as $instance) { |
|
1400 field_delete_instance($instance); |
|
1401 } |
|
1402 |
|
1403 // Clear the cache. |
|
1404 field_cache_clear(); |
|
1405 |
|
1406 // Clear bundle display settings. |
|
1407 variable_del('field_bundle_settings_' . $entity_type . '__' . $bundle); |
|
1408 |
|
1409 // Let other modules act on deleting the bundle. |
|
1410 module_invoke_all('field_attach_delete_bundle', $entity_type, $bundle, $instances); |
|
1411 } |
|
1412 |
|
1413 |
|
1414 /** |
|
1415 * @} End of "defgroup field_attach". |
|
1416 */ |