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

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

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


Revision 1.41 - (show annotations) (download) (as text)
Sat Oct 31 16:06:35 2009 UTC (3 weeks, 5 days ago) by dries
Branch: MAIN
CVS Tags: DRUPAL-7-0-UNSTABLE-10, HEAD
Changes since 1.40: +5 -5 lines
File MIME type: text/x-php
- Patch #606994 by yched: move entity handling out of Field API.
1 <?php
2 // $Id: field.crud.inc,v 1.40 2009/10/22 00:49:12 dries Exp $
3
4 /**
5 * @file
6 * Field CRUD API, handling field and field instance creation and deletion.
7 */
8
9 /**
10 * @defgroup field_structs Field API data structures
11 * @{
12 * Represent Field API fields and instances.
13 *
14 * The Field API defines two primary data structures, Field and
15 * Instance, and the concept of a Bundle. A Field defines a
16 * particular type of data that can be attached to objects. A Field
17 * Instance is a Field attached to a single Bundle. A Bundle is a set
18 * of fields that are treated as a group by the Field Attach API and
19 * is related to a single fieldable entity type.
20 *
21 * For example, suppose a site administrator wants Article nodes to
22 * have a subtitle and photo. Using the Field API or Field UI module,
23 * the administrator creates a field named 'subtitle' of type 'text'
24 * and a field named 'photo' of type 'image'. The administrator
25 * (again, via a UI) creates two Field Instances, one attaching the
26 * field 'subtitle' to the 'node' bundle 'article' and one attaching
27 * the field 'photo' to the 'node' bundle 'article'. When the node
28 * system uses the Field Attach API to load all fields for an Article
29 * node, it passes the node's entity type (which is 'node') and
30 * content type (which is 'article') as the node's bundle.
31 * field_attach_load() then loads the 'subtitle' and 'photo' fields
32 * because they are both attached to the 'node' bundle 'article'.
33 *
34 * Field objects are (currently) represented as an array of key/value
35 * pairs. The object properties are:
36 *
37 * @param array $field:
38 * - id (integer, read-only)
39 * The primary identifier of the field. It is assigned automatically
40 * by field_create_field().
41 * - field_name (string)
42 * The name of the field. Each field name is unique within Field API.
43 * When a field is attached to an object, the field's data is stored
44 * in $object->$field_name.
45 * - type (string)
46 * The type of the field, such as 'text' or 'image'. Field types
47 * are defined by modules that implement hook_field_info().
48 * - cardinality (integer)
49 * The number of values the field can hold. Legal values are any
50 * positive integer or FIELD_CARDINALITY_UNLIMITED.
51 * - translatable (integer)
52 * Whether the field is translatable.
53 * - locked (integer)
54 * TODO: undefined.
55 * - module (string, read-only)
56 * The name of the module that implements the field type.
57 * - active (integer, read-only)
58 * TRUE if the module that implements the field type is currently
59 * enabled, FALSE otherwise.
60 * - deleted (integer, read-only)
61 * TRUE if this field has been deleted, FALSE otherwise. Deleted
62 * fields are ignored by the Field Attach API. This property exists
63 * because fields can be marked for deletion but only actually
64 * destroyed by a separate garbage-collection process.
65 * - columns (array, read-only).
66 * An array of the Field API columns used to store each value of
67 * this field. The column list may depend on field settings; it is
68 * not constant per field type. Field API column specifications are
69 * exactly like Schema API column specifications but, depending on
70 * the field storage module in use, the name of the column may not
71 * represent an actual column in an SQL database.
72 * - indexes (array).
73 * An array of indexes on data columns, using the same definition format
74 * as Schema API index specifications. Only columns that appear in the
75 * 'columns' setting are allowed. Note that field types can specify
76 * default indexes, which can be modified or added to when
77 * creating a field.
78 * - settings (array)
79 * A sub-array of key/value pairs of field-type-specific settings. Each
80 * field type module defines and documents its own field settings.
81 * - storage (array)
82 * A sub-array of key/value pairs identifying the storage backend to use for
83 * the for the field.
84 * - type (string)
85 * The storage backend used by the field. Storage backends are defined
86 * by modules that implement hook_field_storage_info().
87 * - module (string, read-only)
88 * The name of the module that implements the storage backend.
89 * - active (integer, read-only)
90 * TRUE if the module that implements the storage backend is currently
91 * enabled, FALSE otherwise.
92 * - settings (array)
93 * A sub-array of key/value pairs of settings. Each storage backend
94 * defines and documents its own settings.
95 *
96 * Field Instance objects are (currently) represented as an array of
97 * key/value pairs. The object properties are:
98 *
99 * @param array $instance:
100 * - id (integer, read-only)
101 * The primary identifier of this field instance. It is assigned
102 * automatically by field_create_instance().
103 * - field_id (integer, read-only)
104 * The foreign key of the field attached to the bundle by this instance.
105 * It is populated automatically by field_create_instance().
106 * - field_name (string)
107 * The name of the field attached to the bundle by this instance.
108 * - object_type (string)
109 * The name of the object type the instance is attached to.
110 * - bundle (string)
111 * The name of the bundle that the field is attached to.
112 * - label (string)
113 * A human-readable label for the field when used with this
114 * bundle. For example, the label will be the title of Form API
115 * elements for this instance.
116 * - description (string)
117 * A human-readable description for the field when used with this
118 * bundle. For example, the description will be the help text of
119 * Form API elements for this instance.
120 * - required (integer)
121 * TRUE if a value for this field is required when used with this
122 * bundle, FALSE otherwise. Currently, required-ness is only enforced
123 * during Form API operations, not by field_attach_load(),
124 * field_attach_insert(), or field_attach_update().
125 * - default_value_function (string)
126 * The name of the function, if any, that will provide a default value.
127 * - deleted (integer, read-only)
128 * TRUE if this instance has been deleted, FALSE otherwise.
129 * Deleted instances are ignored by the Field Attach API.
130 * This property exists because instances can be marked for deletion but
131 * only actually destroyed by a separate garbage-collection process.
132 * - settings (array)
133 * A sub-array of key/value pairs of field-type-specific instance
134 * settings. Each field type module defines and documents its own
135 * instance settings.
136 * - widget (array)
137 * A sub-array of key/value pairs identifying the Form API input widget
138 * for the field when used by this bundle.
139 * - type (string)
140 * The type of the widget, such as text_textfield. Widget types
141 * are defined by modules that implement hook_field_widget_info().
142 * - settings (array)
143 * A sub-array of key/value pairs of widget-type-specific settings.
144 * Each field widget type module defines and documents its own
145 * widget settings.
146 * - weight (float)
147 * The weight of the widget relative to the other elements in object
148 * edit forms.
149 * - module (string, read-only)
150 * The name of the module that implements the widget type.
151 * - display (array)
152 * A sub-array of key/value pairs identifying build modes and the way the
153 * field values should be displayed in each build mode.
154 * - full (array)
155 * A sub-array of key/value pairs of the display options to be used
156 * when the field is being displayed in the "full" build mode.
157 * - label (string)
158 * Position of the label. 'inline', 'above' and 'hidden' are the
159 * values recognized by the default 'field' theme implementation.
160 * - type (string)
161 * The type of the display formatter, or 'hidden' for no display.
162 * - settings (array)
163 * A sub-array of key/value pairs of display options specific to
164 * the formatter.
165 * - weight (float)
166 * The weight of the field relative to the other object components
167 * displayed in this build mode.
168 * - module (string, read-only)
169 * The name of the module which implements the display formatter.
170 * - teaser
171 * - ...
172 * - other_build_mode
173 * - ...
174 *
175 * Bundles are represented by two strings, an entity type and a bundle name.
176 *
177 * TODO D7 : document max length for field types, widget types,
178 * formatter names...
179 */
180 /**
181 * @} End of "defgroup field_structs".
182 */
183
184 /**
185 * @defgroup field_crud Field CRUD API
186 * @{
187 * Create, update, and delete Field API fields, bundles, and instances.
188 *
189 * Modules use this API, often in hook_install(), to create custom
190 * data structures. UI modules will use it to create a user interface.
191 *
192 * The Field CRUD API uses
193 * @link field_structs Field API data structures @endlink.
194 */
195
196 /**
197 * Create a field.
198 *
199 * This function does not bind the field to any bundle; use
200 * field_create_instance() for that.
201 *
202 * @param $field
203 * A field structure. The field_name and type properties are required.
204 * Other properties, if omitted, will be given the following default values:
205 * - cardinality: 1
206 * - locked: FALSE
207 * - indexes: the field-type indexes, specified by the field type's
208 * hook_field_schema(). The indexes specified in $field are added
209 * to those default indexes. It is possible to override the
210 * definition of a field-type index by providing an index with the
211 * same name, or to remove it by redefining it as an empty array
212 * of columns. Overriding field-type indexes should be done
213 * carefully, for it might seriously affect the site's performance.
214 * - settings: each omitted setting is given the default value defined in
215 * hook_field_info().
216 * - storage:
217 * - type: the storage backend specified in the 'field_default_storage'
218 * system variable.
219 * - settings: each omitted setting is given the default value specified in
220 * hook_field_storage_info().
221 * @return
222 * The $field structure with the id property filled in.
223 * @throw
224 * FieldException
225 */
226 function field_create_field($field) {
227 // Field name is required.
228 if (empty($field['field_name'])) {
229 throw new FieldException('Attempt to create an unnamed field.');
230 }
231 // Field type is required.
232 if (empty($field['type'])) {
233 throw new FieldException('Attempt to create a field with no type.');
234 }
235 // Field name cannot contain invalid characters.
236 if (!preg_match('/^[_a-z]+[_a-z0-9]*$/', $field['field_name'])) {
237 throw new FieldException('Attempt to create a field with invalid characters. Only lowercase alphanumeric characters and underscores are allowed, and only lowercase letters and underscore are allowed as the first character');
238 }
239
240 // Field name cannot be longer than 32 characters. We use drupal_strlen()
241 // because the DB layer assumes that column widths are given in characters,
242 // not bytes.
243 if (drupal_strlen($field['field_name']) > 32) {
244 throw new FieldException(t('Attempt to create a field with a name longer than 32 characters: %name',
245 array('%name' => $field['field_name'])));
246 }
247
248 // Ensure the field name is unique over active and disabled fields.
249 // We do not care about deleted fields.
250 $prior_field = field_read_field($field['field_name'], array('include_inactive' => TRUE));
251 if (!empty($prior_field)) {
252 $message = $prior_field['active']?
253 t('Attempt to create field name %name which already exists and is active.', array('%name' => $field['field_name'])):
254 t('Attempt to create field name %name which already exists, although it is inactive.', array('%name' => $field['field_name']));
255 throw new FieldException($message);
256 }
257
258 // Disallow reserved field names. This can't prevent all field name
259 // collisions with existing object properties, but some is better
260 // than none.
261 foreach (entity_get_info() as $type => $info) {
262 if (in_array($field['field_name'], $info['object keys'])) {
263 throw new FieldException(t('Attempt to create field name %name which is reserved by entity type %type.', array('%name' => $field['field_name'], '%type' => $type)));
264 }
265 }
266
267 $field += array(
268 'cardinality' => 1,
269 'translatable' => FALSE,
270 'locked' => FALSE,
271 'settings' => array(),
272 'storage' => array(),
273 'deleted' => 0,
274 );
275
276 // Check that the field type is known.
277 $field_type = field_info_field_types($field['type']);
278 if (!$field_type) {
279 throw new FieldException(t('Attempt to create a field of unknown type %type.', array('%type' => $field['type'])));
280 }
281 // Create all per-field-type properties (needed here as long as we have
282 // settings that impact column definitions).
283 $field['settings'] += field_info_field_settings($field['type']);
284 $field['module'] = $field_type['module'];
285 $field['active'] = 1;
286
287 // Provide default storage.
288 $field['storage'] += array(
289 'type' => variable_get('field_storage_default', 'field_sql_storage'),
290 'settings' => array(),
291 );
292 // Check that the storage type is known.
293 $storage_type = field_info_storage_types($field['storage']['type']);
294 if (!$storage_type) {
295 throw new FieldException(t('Attempt to create a field with unknown storage type %type.', array('%type' => $field['storage']['type'])));
296 }
297 // Provide default storage settings.
298 $field['storage']['settings'] += field_info_storage_settings($field['storage']['type']);
299 $field['storage']['module'] = $storage_type['module'];
300 $field['storage']['active'] = 1;
301 // Collect storage information.
302 $schema = (array) module_invoke($field['module'], 'field_schema', $field);
303 $schema += array('columns' => array(), 'indexes' => array());
304 // 'columns' are hardcoded in the field type.
305 $field['columns'] = $schema['columns'];
306 // 'indexes' can be both hardcoded in the field type, and specified in the
307 // incoming $field definition.
308 $field += array(
309 'indexes' => array(),
310 );
311 $field['indexes'] += $schema['indexes'];
312
313 // The serialized 'data' column contains everything from $field that does not
314 // have its own column and is not automatically populated when the field is
315 // read.
316 $data = $field;
317 unset($data['columns'], $data['field_name'], $data['type'], $data['active'], $data['module'], $data['storage_type'], $data['storage_active'], $data['storage_module'], $data['locked'], $data['cardinality'], $data['deleted']);
318
319 $record = array(
320 'field_name' => $field['field_name'],
321 'type' => $field['type'],
322 'module' => $field['module'],
323 'active' => $field['active'],
324 'storage_type' => $field['storage']['type'],
325 'storage_module' => $field['storage']['module'],
326 'storage_active' => $field['storage']['active'],
327 'locked' => $field['locked'],
328 'data' => $data,
329 'cardinality' => $field['cardinality'],
330 'translatable' => $field['translatable'],
331 'deleted' => $field['deleted'],
332 );
333
334 // Store the field and get the id back.
335 drupal_write_record('field_config', $record);
336 $field['id'] = $record['id'];
337
338 // Invoke hook_field_storage_create_field after the field is
339 // complete (e.g. it has its id).
340 try {
341 // Invoke hook_field_storage_create_field after
342 // drupal_write_record() sets the field id.
343 module_invoke($storage_type['module'], 'field_storage_create_field', $field);
344 }
345 catch (Exception $e) {
346 // If storage creation failed, remove the field_config record before
347 // rethrowing the exception.
348 db_delete('field_config')
349 ->condition('id', $field['id'])
350 ->execute();
351 throw $e;
352 }
353
354 // Clear caches
355 field_cache_clear(TRUE);
356
357 // Invoke external hooks after the cache is cleared for API consistency.
358 module_invoke_all('field_create_field', $field);
359
360 return $field;
361 }
362
363 /*
364 * Update a field.
365 *
366 * Any module may forbid any update for any reason. For example, the
367 * field's storage module might forbid an update if it would change
368 * the storage schema while data for the field exists. A field type
369 * module might forbid an update if it would change existing data's
370 * semantics, or if there are external dependencies on field settings
371 * that cannot be updated.
372 *
373 * @param $field
374 * A field structure. $field['field_name'] must provided; it
375 * identifies the field that will be updated to match this
376 * structure. Any other properties of the field that are not
377 * specified in $field will be left unchanged, so it is not
378 * necessary to pass in a fully populated $field structure.
379 * @return
380 * Throws a FieldException if the update cannot be performed.
381 * @see field_create_field()
382 */
383 function field_update_field($field) {
384 // Check that the specified field exists.
385 $prior_field = field_read_field($field['field_name']);
386 if (empty($prior_field)) {
387 throw new FieldException('Attempt to update a non-existent field.');
388 }
389
390 // Use the prior field values for anything not specifically set by the new
391 // field to be sure that all values are set.
392 $field += $prior_field;
393 $field['settings'] += $prior_field['settings'];
394
395 // Some updates are always disallowed.
396 if ($field['type'] != $prior_field['type']) {
397 throw new FieldException("Cannot change an existing field's type.");
398 }
399 if ($field['storage']['type'] != $prior_field['storage']['type']) {
400 throw new FieldException("Cannot change an existing field's storage type.");
401 }
402
403 // Collect the new storage information, since what is in
404 // $prior_field may no longer be right.
405 $schema = (array) module_invoke($field['module'], 'field_schema', $field);
406 $schema += array('columns' => array(), 'indexes' => array());
407 // 'columns' are hardcoded in the field type.
408 $field['columns'] = $schema['columns'];
409 // 'indexes' can be both hardcoded in the field type, and specified in the
410 // incoming $field definition.
411 $field += array(
412 'indexes' => array(),
413 );
414 $field['indexes'] += $schema['indexes'];
415
416 $has_data = field_has_data($field);
417
418 // See if any module forbids the update by throwing an exception.
419 foreach (module_implements('field_update_forbid') as $module) {
420 $function = $module . '_field_update_forbid';
421 $function($field, $prior_field, $has_data);
422 }
423
424 // Tell the storage engine to update the field. Do this before
425 // saving the new definition since it still might fail.
426 module_invoke(variable_get('field_storage_module', 'field_sql_storage'), 'field_storage_update_field', $field, $prior_field, $has_data);
427
428 // Save the new field definition. @todo: refactor with
429 // field_create_field.
430
431 // The serialized 'data' column contains everything from $field that does not
432 // have its own column and is not automatically populated when the field is
433 // read.
434 $data = $field;
435 unset($data['columns'], $data['field_name'], $data['type'], $data['locked'], $data['module'], $data['cardinality'], $data['active'], $data['deleted']);
436 $field['data'] = $data;
437
438 // Store the field and create the id.
439 $primary_key = array('id');
440 drupal_write_record('field_config', $field, $primary_key);
441
442 // Clear caches
443 field_cache_clear(TRUE);
444
445 // Invoke external hooks after the cache is cleared for API consistency.
446 module_invoke_all('field_update_field', $field, $prior_field, $has_data);
447 }
448
449 /**
450 * Read a single field record directly from the database. Generally,
451 * you should use the field_info_field() instead.
452 *
453 * This function will not return deleted fields. Use
454 * field_read_fields() instead for this purpose.
455 *
456 * @param $field_name
457 * The field name to read.
458 * @param array $include_additional
459 * The default behavior of this function is to not return a field that
460 * is inactive. Setting
461 * $include_additional['include_inactive'] to TRUE will override this
462 * behavior.
463 * @return
464 * A field structure, or FALSE.
465 */
466 function field_read_field($field_name, $include_additional = array()) {
467 $fields = field_read_fields(array('field_name' => $field_name), $include_additional);
468 return $fields ? current($fields) : FALSE;
469 }
470
471 /**
472 * Read in fields that match an array of conditions.
473 *
474 * @param array $params
475 * An array of conditions to match against.
476 * @param array $include_additional
477 * The default behavior of this function is to not return fields that
478 * are inactive or have been deleted. Setting
479 * $include_additional['include_inactive'] or
480 * $include_additional['include_deleted'] to TRUE will override this
481 * behavior.
482 * @return
483 * An array of fields matching $params. If
484 * $include_additional['include_deletd'] is TRUE, the array is keyed
485 * by field id, otherwise it is keyed by field name.
486 */
487 function field_read_fields($params = array(), $include_additional = array()) {
488 $query = db_select('field_config', 'fc', array('fetch' => PDO::FETCH_ASSOC));
489 $query->fields('fc');
490
491 // Turn the conditions into a query.
492 foreach ($params as $key => $value) {
493 $query->condition($key, $value);
494 }
495 if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) {
496 $query
497 ->condition('fc.active', 1)
498 ->condition('fc.storage_active', 1);
499 }
500 $include_deleted = (isset($include_additional['include_deleted']) && $include_additional['include_deleted']);
501 if (!$include_deleted) {
502 $query->condition('fc.deleted', 0);
503 }
504
505 $fields = array();
506 $results = $query->execute();
507 foreach ($results as $record) {
508 $field = unserialize($record['data']);
509 $field['id'] = $record['id'];
510 $field['field_name'] = $record['field_name'];
511 $field['type'] = $record['type'];
512 $field['module'] = $record['module'];
513 $field['active'] = $record['active'];
514 $field['storage']['type'] = $record['storage_type'];
515 $field['storage']['module'] = $record['storage_module'];
516 $field['storage']['active'] = $record['storage_active'];
517 $field['locked'] = $record['locked'];
518 $field['cardinality'] = $record['cardinality'];
519 $field['translatable'] = $record['translatable'];
520 $field['deleted'] = $record['deleted'];
521
522 module_invoke_all('field_read_field', $field);
523
524 // Populate storage information.
525 $schema = (array) module_invoke($field['module'], 'field_schema', $field);
526 $schema += array('columns' => array(), 'indexes' => array());
527 $field['columns'] = $schema['columns'];
528
529 $field_name = $field['field_name'];
530 if ($include_deleted) {
531 $field_name = $field['id'];
532 }
533 $fields[$field_name] = $field;
534 }
535 return $fields;
536 }
537
538 /**
539 * Mark a field for deletion, including all its instances and all data
540 * associated with it.
541 *
542 * @param $field_name
543 * The field name to delete.
544 */
545 function field_delete_field($field_name) {
546 // Delete all non-deleted instances.
547 $field = field_info_field($field_name);
548 if (isset($field['bundles'])) {
549 foreach ($field['bundles'] as $obj_type => $bundles) {
550 foreach ($bundles as $bundle) {
551 $instance = field_info_instance($obj_type, $field_name, $bundle);
552 field_delete_instance($instance);
553 }
554 }
555 }
556
557 // Mark field data for deletion.
558 module_invoke($field['storage']['module'], 'field_storage_delete_field', $field);
559
560 // Mark the field for deletion.
561 db_update('field_config')
562 ->fields(array('deleted' => 1))
563 ->condition('field_name', $field_name)
564 ->execute();
565
566 // Clear the cache.
567 field_cache_clear(TRUE);
568
569 module_invoke_all('field_delete_field', $field);
570 }
571
572 /**
573 * Creates an instance of a field, binding it to a bundle.
574 *
575 * @param $instance
576 * A field instance structure. The field_name, object_type and
577 * bundle properties are required. Other properties, if omitted,
578 * will be given the following default values:
579 * - label: the field name
580 * - description: empty string
581 * - weight: 0
582 * - required: FALSE
583 * - default_value_function: empty string
584 * - settings: each omitted setting is given the default value specified in
585 * hook_field_info().
586 * - widget:
587 * - type: the default widget specified in hook_field_info().
588 * - settings: each omitted setting is given the default value specified in
589 * hook_field_widget_info().
590 * - display:
591 * Settings for the 'full' build mode will be added, and each build mode
592 * will be completed with the follwong default values:
593 * - label: 'above'
594 * - type: the default formatter specified in hook_field_info().
595 * - settings: each omitted setting is given the default value specified in
596 * hook_field_formatter_info().
597 * @return
598 * The $instance structure with the id property filled in.
599 * @throw
600 * FieldException
601 */
602 function field_create_instance($instance) {
603 $field = field_read_field($instance['field_name']);
604 if (empty($field)) {
605 throw new FieldException("Attempt to create an instance of a field that doesn't exist or is currently inactive.");
606 }
607 // Check that the required properties exists.
608 if (empty($instance['object_type'])) {
609 throw new FieldException(t('Attempt to create an instance of field @field_name without an object type.', array('@field_name' => $instance['field_name'])));
610 }
611 if (empty($instance['bundle'])) {
612 throw new FieldException(t('Attempt to create an instance of field @field_name without a bundle.', array('@field_name' => $instance['field_name'])));
613 }
614
615 // Set the field id.
616 $instance['field_id'] = $field['id'];
617
618 // Note that we do *not* prevent creating a field on non-existing bundles,
619 // because that would break the 'Body as field' upgrade for contrib
620 // node types.
621
622 // TODO: Check that the widget type is known and can handle the field type ?
623 // TODO: Check that the formatters are known and can handle the field type ?
624 // TODO: Check that the display build modes are known for the object type ?
625 // Those checks should probably happen in _field_write_instance() ?
626 // Problem : this would mean that a UI module cannot update an instance with a disabled formatter.
627
628 // Ensure the field instance is unique within the bundle.
629 // We only check for instances of active fields, since adding an instance of
630 // a disabled field is not supported.
631 $prior_instance = field_read_instance($instance['object_type'], $instance['field_name'], $instance['bundle']);
632 if (!empty($prior_instance)) {
633 $message = t('Attempt to create a field instance that already exists.');
634 throw new FieldException($message);
635 }
636
637 _field_write_instance($instance);
638
639 // Clear caches
640 field_cache_clear();
641
642 // Invoke external hooks after the cache is cleared for API consistency.
643 module_invoke_all('field_create_instance', $instance);
644
645 return $instance;
646 }
647
648 /*
649 * Update an instance of a field.
650 *
651 * @param $instance
652 * An associative array represeting an instance structure. The required
653 * keys and values are:
654 * field_name: The name of an existing field.
655 * bundle: The bundle this field belongs to.
656 * Read-only_id properties are assigned automatically. Any other
657 * properties specified in $instance overwrite the existing values for
658 * the instance.
659 * @throw
660 * FieldException
661 * @see field_create_instance()
662 */
663 function field_update_instance($instance) {
664 // Check that the specified field exists.
665 $field = field_read_field($instance['field_name']);
666 if (empty($field)) {
667 throw new FieldException("Attempt to update an instance of a nonexistent field.");
668 }
669
670 // Check that the field instance exists (even if it is inactive, since we
671 // want to be able to replace inactive widgets with new ones).
672 $prior_instance = field_read_instance($instance['object_type'], $instance['field_name'], $instance['bundle'], array('include_inactive' => TRUE));
673 if (empty($prior_instance)) {
674 throw new FieldException("Attempt to update a field instance that doesn't exist.");
675 }
676
677 $instance['id'] = $prior_instance['id'];
678 $instance['field_id'] = $prior_instance['field_id'];
679
680 _field_write_instance($instance, TRUE);
681
682 // Clear caches.
683 field_cache_clear();
684 }
685
686 /**
687 * Store an instance record in the field configuration database.
688 *
689 * @param $instance
690 * An instance structure.
691 * @param $update
692 * Whether this is a new or existing instance.
693 */
694 function _field_write_instance($instance, $update = FALSE) {
695 $field = field_read_field($instance['field_name']);
696 $field_type = field_info_field_types($field['type']);
697
698 // Set defaults.
699 $instance += array(
700 'settings' => array(),
701 'display' => array(),
702 'widget' => array(),
703 'required' => FALSE,
704 'label' => $instance['field_name'],
705 'description' => '',
706 'weight' => 0,
707 'deleted' => 0,
708 );
709
710 // Set default instance settings.
711 $instance['settings'] += field_info_instance_settings($field['type']);
712
713 // Set default widget and settings.
714 $instance['widget'] += array(
715 // TODO: what if no 'default_widget' specified ?
716 'type' => $field_type['default_widget'],
717 'settings' => array(),
718 'weight' => 0,
719 );
720 // Check widget module.
721 $widget_type = field_info_widget_types($instance['widget']['type']);
722 $instance['widget']['module'] = $widget_type['module'];
723 $instance['widget']['settings'] += field_info_widget_settings($instance['widget']['type']);
724
725 // Make sure there is at least display info for the 'full' build mode.
726 $instance['display'] += array(
727 'full' => array(),
728 );
729 // Set default display settings for each build mode.
730 foreach ($instance['display'] as $build_mode => $display) {
731 $instance['display'][$build_mode] += array(
732 'label' => 'above',
733 // TODO: what if no 'default_formatter' specified ?
734 'type' => $field_type['default_formatter'],
735 'settings' => array(),
736 'weight' => 0,
737 );
738 $formatter_type = field_info_formatter_types($instance['display'][$build_mode]['type']);
739 // TODO : 'hidden' will raise PHP warnings.
740 $instance['display'][$build_mode]['module'] = $formatter_type['module'];
741 $instance['display'][$build_mode]['settings'] += field_info_formatter_settings($instance['display'][$build_mode]['type']);
742 }
743
744 // The serialized 'data' column contains everything from $instance that does
745 // not have its own column and is not automatically populated when the
746 // instance is read.
747 $data = $instance;
748 unset($data['id'], $data['field_id'], $data['field_name'], $data['bundle'], $data['deleted']);
749
750 $record = array(
751 'field_id' => $instance['field_id'],
752 'field_name' => $instance['field_name'],
753 'object_type' => $instance['object_type'],
754 'bundle' => $instance['bundle'],
755 'data' => $data,
756 'deleted' => $instance['deleted'],
757 );
758 // We need to tell drupal_update_record() the primary keys to trigger an
759 // update.
760 if ($update) {
761 $record['id'] = $instance['id'];
762 $primary_key = array('id');
763 }
764 else {
765 $primary_key = array();
766 }
767 drupal_write_record('field_config_instance', $record, $primary_key);
768 }
769
770 /**
771 * Read a single instance record directly from the database. Generally,
772 * you should use the field_info_instance() instead.
773 *
774 * This function will not return deleted instances. Use
775 * field_read_instances() instead for this purpose.
776 *
777 * @param $obj_type
778 * The type of object to which the field is bound.
779 * @param $field_name
780 * The field name to read.
781 * @param $bundle
782 * The bundle to which the field is bound.
783 * @param array $include_additional
784 * The default behavior of this function is to not return an instance that
785 * has been deleted, or whose field is inactive. Setting
786 * $include_additional['include_inactive'] or
787 * $include_additional['include_deleted'] to TRUE will override this
788 * behavior.
789 * @return
790 * An instance structure, or FALSE.
791 */
792 function field_read_instance($obj_type, $field_name, $bundle, $include_additional = array()) {
793 $instances = field_read_instances(array('object_type' => $obj_type, 'field_name' => $field_name, 'bundle' => $bundle), $include_additional);
794 return $instances ? current($instances) : FALSE;
795 }
796
797 /**
798 * Read in field instances that match an array of conditions.
799 *
800 * @param $param
801 * An array of properties to use in selecting a field
802 * instance. Valid keys include any column of the
803 * field_config_instance table. If NULL, all instances will be returned.
804 * @param $include_additional
805 * The default behavior of this function is to not return field
806 * instances that have been marked deleted, or whose field is inactive.
807 * Setting $include_additional['include_inactive'] or
808 * $include_additional['include_deleted'] to TRUE will override this
809 * behavior.
810 * @return
811 * An array of instances matching the arguments.
812 */
813 function field_read_instances($params = array(), $include_additional = array()) {
814 $query = db_select('field_config_instance', 'fci', array('fetch' => PDO::FETCH_ASSOC));
815 $query->join('field_config', 'fc', 'fc.id = fci.field_id');
816 $query->fields('fci');
817
818 // Turn the conditions into a query.
819 foreach ($params as $key => $value) {
820 $query->condition('fci.' . $key, $value);
821 }
822 if (!isset($include_additional['include_inactive']) || !$include_additional['include_inactive']) {
823 $query
824 ->condition('fc.active', 1)
825 ->condition('fc.storage_active', 1);
826 }
827 if (!isset($include_additional['include_deleted']) || !$include_additional['include_deleted']) {
828 $query->condition('fc.deleted', 0);
829 $query->condition('fci.deleted', 0);
830 }
831
832 $instances = array();
833 $results = $query->execute();
834
835 foreach ($results as $record) {
836 $instance = unserialize($record['data']);
837 $instance['id'] = $record['id'];
838 $instance['field_id'] = $record['field_id'];
839 $instance['field_name'] = $record['field_name'];
840 $instance['object_type'] = $record['object_type'];
841 $instance['bundle'] = $record['bundle'];
842 $instance['deleted'] = $record['deleted'];
843
844 module_invoke_all('field_read_instance', $instance);
845 $instances[] = $instance;
846 }
847 return $instances;
848 }
849
850 /**
851 * Mark a field instance for deletion, including all data associated with
852 * it.
853 *
854 * @param $instance
855 * An instance structure.
856 */
857 function field_delete_instance($instance) {
858 // Mark the field instance for deletion.
859 db_update('field_config_instance')
860 ->fields(array('deleted' => 1))
861 ->condition('field_name', $instance['field_name'])
862 ->condition('object_type', $instance['object_type'])
863 ->condition('bundle', $instance['bundle'])
864 ->execute();
865
866 // Mark instance data for deletion.
867 $field = field_info_field($instance['field_name']);
868 module_invoke($field['storage']['module'], 'field_storage_delete_instance', $instance);
869
870 // Clear the cache.
871 field_cache_clear();
872
873 module_invoke_all('field_delete_instance', $instance);
874 }
875
876 /**
877 * @} End of "defgroup field_crud".
878 */
879
880 /*
881 * @defgroup field_purge Field API bulk data deletion
882 * @{
883 * Clean up after Field API bulk deletion operations.
884 *
885 * Field API provides functions for deleting data attached to individual
886 * objects as well as deleting entire fields or field instances in a single
887 * operation.
888 *
889 * Deleting field data items for an object with field_attach_delete() involves
890 * three separate operations:
891 * - Invoking the Field Type API hook_field_delete() for each field on the
892 * object. The hook for each field type receives the object and the specific
893 * field being deleted. A file field module might use this hook to delete
894 * uploaded files from the filesystem.
895 * - Invoking the Field Storage API hook_field_storage_delete() to remove
896 * data from the primary field storage. The hook implementation receives the
897 * object being deleted and deletes data for all of the object's bundle's
898 * fields.
899 * - Invoking the global Field Attach API hook_field_attach_delete() for all
900 * modules that implement it. Each hook implementation receives the object
901 * being deleted and can operate on whichever subset of the object's bundle's
902 * fields it chooses to.
903 *
904 * These hooks are invoked immediately when field_attach_delete() is
905 * called. Similar operations are performed for field_attach_delete_revision().
906 *
907 * When a field, bundle, or field instance is deleted, it is not practical to
908 * invoke these hooks immediately on every affected object in a single page
909 * request; there could be thousands or millions of them. Instead, the
910 * appropriate field data items, instances, and/or fields are marked as deleted
911 * so that subsequent load or query operations will not return them. Later, a
912 * separate process cleans up, or "purges", the marked-as-deleted data by going
913 * through the three-step process described above and, finally, removing
914 * deleted field and instance records.
915 *
916 * Purging field data is made somewhat tricky by the fact that, while
917 * field_attach_delete() has a complete object to pass to the various deletion
918 * hooks, the Field API purge process only has the field data it has previously
919 * stored. It cannot reconstruct complete original objects to pass to the
920 * deletion hooks. It is even possible that the original object to which some
921 * Field API data was attached has been itself deleted before the field purge
922 * operation takes place.
923 *
924 * Field API resolves this problem by using "pseudo-objects" during purge
925 * operations. A pseudo-object contains only the information from the original
926 * object that Field API knows about: entity type, id, revision id, and
927 * bundle. It also contains the field data for whichever field instance is
928 * currently being purged. For example, suppose that the node type 'story' used
929 * to contain a field called 'subtitle' but the field was deleted. If node 37
930 * was a story with a subtitle, the pseudo-object passed to the purge hooks
931 * would look something like this:
932 *
933 * @code
934 * $obj = stdClass Object(
935 * [nid] => 37,
936 * [vid] => 37,
937 * [type] => 'story',
938 * [subtitle] => array(
939 * [0] => array(
940 * 'value' => 'subtitle text',
941 * ),
942 * ),
943 * );
944 * @endcode
945 */
946
947 /**
948 * Purge some deleted Field API data, instances, or fields.
949 *
950 * This function will purge deleted field data on up to a specified maximum
951 * number of objects and then return. If a deleted field instance with no
952 * remaining data records is found, the instance itself will be purged.
953 * If a deleted field with no remaining field instances is found, the field
954 * itself will be purged.
955 *
956 * @param $batch_size
957 * The maximum number of field data records to purge before returning.
958 */
959 function field_purge_batch($batch_size) {
960 // Retrieve all deleted field instances. We cannot use field_info_instances()
961 // because that function does not return deleted instances.
962 $instances = field_read_instances(array('deleted' => 1), array('include_deleted' => 1));
963
964 foreach ($instances as $instance) {
965 $field = field_info_field_by_id($instance['field_id']);
966
967 // Retrieve some pseudo-objects.
968 $obj_types = field_attach_query($instance['field_id'], array(array('bundle', $instance['bundle']), array('deleted', 1)), array('limit' => $batch_size));
969
970 if (count($obj_types) > 0) {
971 // Field data for the instance still exists.
972 foreach ($obj_types as $obj_type => $objects) {
973 field_attach_load($obj_type, $objects, FIELD_LOAD_CURRENT, array('field_id' => $field['id'], 'deleted' => 1));
974
975 foreach ($objects as $id => $object) {
976 // field_attach_query() may return more results than we asked for.
977 // Stop when he have done our batch size.
978 if ($batch_size-- <= 0) {
979 return;
980 }
981
982 // Purge the data for the object.
983 field_purge_data($obj_type, $object, $field, $instance);
984 }
985 }
986 }
987 else {
988 // No field data remains for the instance, so we can remove it.
989 field_purge_instance($instance);
990 }
991 }
992
993 // Retrieve all deleted fields. Any that have no bundles can be purged.
994 $fields = field_read_fields(array('deleted' => 1), array('include_deleted' => 1));
995 foreach ($fields as $field) {
996 // field_read_fields() does not return $field['bundles'] which we need.
997 $field = field_info_field_by_id($field['id']);
998 if (!isset($field['bundles']) || count($field['bundles']) == 0) {
999 field_purge_field($field);
1000 }
1001 }
1002 }
1003
1004 /**
1005 * Purge the field data for a single field on a single pseudo-object.
1006 *
1007 * This is basically the same as field_attach_delete() except it only applies
1008 * to a single field. The object itself is not being deleted, and it is quite
1009 * possible that other field data will remain attached to it.
1010 *
1011 * @param $obj_type
1012 * The type of $object; e.g. 'node' or 'user'.
1013 * @param $object
1014 * The pseudo-object whose field data to delete.
1015 * @param $field
1016 * The (possibly deleted) field whose data is being purged.
1017 * @param $instance
1018 * The deleted field instance whose data is being purged.
1019 */
1020 function field_purge_data($obj_type, $object, $field, $instance) {
1021 // Each field type's hook_field_delete() only expects to operate on a single
1022 // field at a time, so we can use it as-is for purging.
1023 $options = array('field_id' => $instance['field_id'], 'deleted' => TRUE);
1024 _field_invoke('delete', $obj_type, $object, $dummy, $dummy, $options);
1025
1026 // Tell the field storage system to purge the data.
1027 module_invoke($field['storage']['module'], 'field_storage_purge', $obj_type, $object, $field, $instance);
1028
1029 // Let other modules act on purging the data.
1030 foreach (module_implements('field_attach_purge') as $module) {
1031 $function = $module . '_field_attach_purge';
1032 $function($obj_type, $object, $field, $instance);
1033 }
1034 }
1035
1036 /**
1037 * Purge a field instance record from the database.
1038 *
1039 * This function assumes all data for the instance has already been purged, and
1040 * should only be called by field_purge_batch().
1041 *
1042 * @param $instance
1043 * The instance record to purge.
1044 */
1045 function field_purge_instance($instance) {
1046 db_delete('field_config_instance')
1047 ->condition('id', $instance['id'])
1048 ->execute();
1049
1050 // Notify the storage engine.
1051 $field = field_info_field_by_id($instance['field_id']);
1052 module_invoke($field['storage']['module'], 'field_storage_purge_instance', $instance);
1053
1054 // Clear the cache.
1055 field_info_cache_clear();
1056
1057 // Invoke external hooks after the cache is cleared for API consistency.
1058 module_invoke_all('field_purge_instance', $instance);
1059 }
1060
1061 /**
1062 * Purge a field record from the database.
1063 *
1064 * This function assumes all instances for the field has already been purged,
1065 * and should only be called by field_purge_batch().
1066 *
1067 * @param $field
1068 * The field record to purge.
1069 */
1070 function field_purge_field($field) {
1071 $instances = field_read_instances(array('field_id' => $field['id']), array('include_deleted' => 1));
1072 if (count($instances) > 0) {
1073 throw new FieldException("Attempt to purge a field that still has instances.");
1074 }
1075
1076 db_delete('field_config')
1077 ->condition('id', $field['id'])
1078 ->execute();
1079
1080 // Notify the storage engine.
1081 module_invoke($field['storage']['module'], 'field_storage_purge_field', $field);
1082
1083 // Clear the cache.
1084 field_info_cache_clear();
1085
1086 // Invoke external hooks after the cache is cleared for API consistency.
1087 module_invoke_all('field_purge_field', $field);
1088 }
1089
1090 /**
1091 * @} End of "defgroup field_purge".
1092 */
1093

  ViewVC Help
Powered by ViewVC 1.1.2