/[drupal]/drupal/modules/field/field.attach.inc
ViewVC logotype

Contents of /drupal/modules/field/field.attach.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


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

  ViewVC Help
Powered by ViewVC 1.1.2