root / drupal7 / modules / field / field.api.php @ 76597ebf
1 |
<?php
|
---|---|
2 |
/**
|
3 |
* @file
|
4 |
* Hooks provided by the Field module.
|
5 |
*/
|
6 |
|
7 |
/**
|
8 |
* @addtogroup hooks
|
9 |
* @{
|
10 |
*/
|
11 |
|
12 |
/**
|
13 |
* Exposes "pseudo-field" components on fieldable entities.
|
14 |
*
|
15 |
* Field UI's "Manage fields" and "Manage display" pages let users re-order
|
16 |
* fields, but also non-field components. For nodes, these include the title,
|
17 |
* poll choices, and other elements exposed by modules through hook_form() or
|
18 |
* hook_form_alter().
|
19 |
*
|
20 |
* Fieldable entities or modules that want to have their components supported
|
21 |
* should expose them using this hook. The user-defined settings (weight,
|
22 |
* visible) are automatically applied on rendered forms and displayed
|
23 |
* entities in a #pre_render callback added by field_attach_form() and
|
24 |
* field_attach_view().
|
25 |
*
|
26 |
* @see _field_extra_fields_pre_render()
|
27 |
* @see hook_field_extra_fields_alter()
|
28 |
*
|
29 |
* @return
|
30 |
* A nested array of 'pseudo-field' elements. Each list is nested within the
|
31 |
* following keys: entity type, bundle name, context (either 'form' or
|
32 |
* 'display'). The keys are the name of the elements as appearing in the
|
33 |
* renderable array (either the entity form or the displayed entity). The
|
34 |
* value is an associative array:
|
35 |
* - label: The human readable name of the element.
|
36 |
* - description: A short description of the element contents.
|
37 |
* - weight: The default weight of the element.
|
38 |
* - edit: (optional) String containing markup (normally a link) used as the
|
39 |
* element's 'edit' operation in the administration interface. Only for
|
40 |
* 'form' context.
|
41 |
* - delete: (optional) String containing markup (normally a link) used as the
|
42 |
* element's 'delete' operation in the administration interface. Only for
|
43 |
* 'form' context.
|
44 |
*
|
45 |
* @ingroup field_types
|
46 |
*/
|
47 |
function hook_field_extra_fields() { |
48 |
$extra['node']['poll'] = array( |
49 |
'form' => array( |
50 |
'choice_wrapper' => array( |
51 |
'label' => t('Poll choices'), |
52 |
'description' => t('Poll choices'), |
53 |
'weight' => -4, |
54 |
), |
55 |
'settings' => array( |
56 |
'label' => t('Poll settings'), |
57 |
'description' => t('Poll module settings'), |
58 |
'weight' => -3, |
59 |
), |
60 |
), |
61 |
'display' => array( |
62 |
'poll_view_voting' => array( |
63 |
'label' => t('Poll vote'), |
64 |
'description' => t('Poll vote'), |
65 |
'weight' => 0, |
66 |
), |
67 |
'poll_view_results' => array( |
68 |
'label' => t('Poll results'), |
69 |
'description' => t('Poll results'), |
70 |
'weight' => 0, |
71 |
), |
72 |
) |
73 |
); |
74 |
|
75 |
return $extra; |
76 |
} |
77 |
|
78 |
/**
|
79 |
* Alter "pseudo-field" components on fieldable entities.
|
80 |
*
|
81 |
* @param $info
|
82 |
* The associative array of 'pseudo-field' components.
|
83 |
*
|
84 |
* @see hook_field_extra_fields()
|
85 |
*
|
86 |
* @ingroup field_types
|
87 |
*/
|
88 |
function hook_field_extra_fields_alter(&$info) { |
89 |
// Force node title to always be at the top of the list by default.
|
90 |
foreach (node_type_get_types() as $bundle) { |
91 |
if (isset($info['node'][$bundle->type]['form']['title'])) { |
92 |
$info['node'][$bundle->type]['form']['title']['weight'] = -20; |
93 |
} |
94 |
} |
95 |
} |
96 |
|
97 |
/**
|
98 |
* @defgroup field_types Field Types API
|
99 |
* @{
|
100 |
* Define field types.
|
101 |
*
|
102 |
* In the Field API, each field has a type, which determines what kind of data
|
103 |
* (integer, string, date, etc.) the field can hold, which settings it provides,
|
104 |
* and so on. The data type(s) accepted by a field are defined in
|
105 |
* hook_field_schema(); other basic properties of a field are defined in
|
106 |
* hook_field_info(). The other hooks below are called by the Field Attach API
|
107 |
* to perform field-type-specific actions.
|
108 |
*
|
109 |
* The Field Types API also defines two kinds of pluggable handlers: widgets
|
110 |
* and formatters. @link field_widget Widgets @endlink specify how the field
|
111 |
* appears in edit forms, while @link field_formatter formatters @endlink
|
112 |
* specify how the field appears in displayed entities.
|
113 |
*
|
114 |
* A third kind of pluggable handlers, storage backends, is defined by the
|
115 |
* @link field_storage Field Storage API @endlink.
|
116 |
*
|
117 |
* See @link field Field API @endlink for information about the other parts of
|
118 |
* the Field API.
|
119 |
*/
|
120 |
|
121 |
/**
|
122 |
* Define Field API field types.
|
123 |
*
|
124 |
* Along with this hook, you also need to implement other hooks. See
|
125 |
* @link field_types Field Types API @endlink for more information.
|
126 |
*
|
127 |
* @return
|
128 |
* An array whose keys are field type names and whose values are arrays
|
129 |
* describing the field type, with the following key/value pairs:
|
130 |
* - label: The human-readable name of the field type.
|
131 |
* - description: A short description for the field type.
|
132 |
* - settings: An array whose keys are the names of the settings available
|
133 |
* for the field type, and whose values are the default values for those
|
134 |
* settings.
|
135 |
* - instance_settings: An array whose keys are the names of the settings
|
136 |
* available for instances of the field type, and whose values are the
|
137 |
* default values for those settings. Instance-level settings can have
|
138 |
* different values on each field instance, and thus allow greater
|
139 |
* flexibility than field-level settings. It is recommended to put settings
|
140 |
* at the instance level whenever possible. Notable exceptions: settings
|
141 |
* acting on the schema definition, or settings that Views needs to use
|
142 |
* across field instances (for example, the list of allowed values).
|
143 |
* - default_widget: The machine name of the default widget to be used by
|
144 |
* instances of this field type, when no widget is specified in the
|
145 |
* instance definition. This widget must be available whenever the field
|
146 |
* type is available (i.e. provided by the field type module, or by a module
|
147 |
* the field type module depends on).
|
148 |
* - default_formatter: The machine name of the default formatter to be used
|
149 |
* by instances of this field type, when no formatter is specified in the
|
150 |
* instance definition. This formatter must be available whenever the field
|
151 |
* type is available (i.e. provided by the field type module, or by a module
|
152 |
* the field type module depends on).
|
153 |
* - no_ui: (optional) A boolean specifying that users should not be allowed
|
154 |
* to create fields and instances of this field type through the UI. Such
|
155 |
* fields can only be created programmatically with field_create_field()
|
156 |
* and field_create_instance(). Defaults to FALSE.
|
157 |
*
|
158 |
* @see hook_field_info_alter()
|
159 |
*/
|
160 |
function hook_field_info() { |
161 |
return array( |
162 |
'text' => array( |
163 |
'label' => t('Text'), |
164 |
'description' => t('This field stores varchar text in the database.'), |
165 |
'settings' => array('max_length' => 255), |
166 |
'instance_settings' => array('text_processing' => 0), |
167 |
'default_widget' => 'text_textfield', |
168 |
'default_formatter' => 'text_default', |
169 |
), |
170 |
'text_long' => array( |
171 |
'label' => t('Long text'), |
172 |
'description' => t('This field stores long text in the database.'), |
173 |
'settings' => array('max_length' => ''), |
174 |
'instance_settings' => array('text_processing' => 0), |
175 |
'default_widget' => 'text_textarea', |
176 |
'default_formatter' => 'text_default', |
177 |
), |
178 |
'text_with_summary' => array( |
179 |
'label' => t('Long text and summary'), |
180 |
'description' => t('This field stores long text in the database along with optional summary text.'), |
181 |
'settings' => array('max_length' => ''), |
182 |
'instance_settings' => array('text_processing' => 1, 'display_summary' => 0), |
183 |
'default_widget' => 'text_textarea_with_summary', |
184 |
'default_formatter' => 'text_summary_or_trimmed', |
185 |
), |
186 |
); |
187 |
} |
188 |
|
189 |
/**
|
190 |
* Perform alterations on Field API field types.
|
191 |
*
|
192 |
* @param $info
|
193 |
* Array of information on field types exposed by hook_field_info()
|
194 |
* implementations.
|
195 |
*/
|
196 |
function hook_field_info_alter(&$info) { |
197 |
// Add a setting to all field types.
|
198 |
foreach ($info as $field_type => $field_type_info) { |
199 |
$info[$field_type]['settings'] += array( |
200 |
'mymodule_additional_setting' => 'default value', |
201 |
); |
202 |
} |
203 |
|
204 |
// Change the default widget for fields of type 'foo'.
|
205 |
if (isset($info['foo'])) { |
206 |
$info['foo']['default widget'] = 'mymodule_widget'; |
207 |
} |
208 |
} |
209 |
|
210 |
/**
|
211 |
* Define the Field API schema for a field structure.
|
212 |
*
|
213 |
* This is invoked when a field is created, in order to obtain the database
|
214 |
* schema from the module that defines the field's type.
|
215 |
*
|
216 |
* This hook must be defined in the module's .install file for it to be detected
|
217 |
* during installation and upgrade.
|
218 |
*
|
219 |
* @param $field
|
220 |
* A field structure.
|
221 |
*
|
222 |
* @return
|
223 |
* An associative array with the following keys:
|
224 |
* - columns: An array of Schema API column specifications, keyed by column
|
225 |
* name. This specifies what comprises a value for a given field. For
|
226 |
* example, a value for a number field is simply 'value', while a value for
|
227 |
* a formatted text field is the combination of 'value' and 'format'. It is
|
228 |
* recommended to avoid having the column definitions depend on field
|
229 |
* settings when possible. No assumptions should be made on how storage
|
230 |
* engines internally use the original column name to structure their
|
231 |
* storage.
|
232 |
* - indexes: (optional) An array of Schema API indexes definitions. Only
|
233 |
* columns that appear in the 'columns' array are allowed. Those indexes
|
234 |
* will be used as default indexes. Callers of field_create_field() can
|
235 |
* specify additional indexes, or, at their own risk, modify the default
|
236 |
* indexes specified by the field-type module. Some storage engines might
|
237 |
* not support indexes.
|
238 |
* - foreign keys: (optional) An array of Schema API foreign keys
|
239 |
* definitions.
|
240 |
*/
|
241 |
function hook_field_schema($field) { |
242 |
if ($field['type'] == 'text_long') { |
243 |
$columns = array( |
244 |
'value' => array( |
245 |
'type' => 'text', |
246 |
'size' => 'big', |
247 |
'not null' => FALSE, |
248 |
), |
249 |
); |
250 |
} |
251 |
else {
|
252 |
$columns = array( |
253 |
'value' => array( |
254 |
'type' => 'varchar', |
255 |
'length' => $field['settings']['max_length'], |
256 |
'not null' => FALSE, |
257 |
), |
258 |
); |
259 |
} |
260 |
$columns += array( |
261 |
'format' => array( |
262 |
'type' => 'varchar', |
263 |
'length' => 255, |
264 |
'not null' => FALSE, |
265 |
), |
266 |
); |
267 |
return array( |
268 |
'columns' => $columns, |
269 |
'indexes' => array( |
270 |
'format' => array('format'), |
271 |
), |
272 |
'foreign keys' => array( |
273 |
'format' => array( |
274 |
'table' => 'filter_format', |
275 |
'columns' => array('format' => 'format'), |
276 |
), |
277 |
), |
278 |
); |
279 |
} |
280 |
|
281 |
/**
|
282 |
* Define custom load behavior for this module's field types.
|
283 |
*
|
284 |
* Unlike most other field hooks, this hook operates on multiple entities. The
|
285 |
* $entities, $instances and $items parameters are arrays keyed by entity ID.
|
286 |
* For performance reasons, information for all available entity should be
|
287 |
* loaded in a single query where possible.
|
288 |
*
|
289 |
* Note that the changes made to the field values get cached by the field cache
|
290 |
* for subsequent loads. You should never use this hook to load fieldable
|
291 |
* entities, since this is likely to cause infinite recursions when
|
292 |
* hook_field_load() is run on those as well. Use
|
293 |
* hook_field_formatter_prepare_view() instead.
|
294 |
*
|
295 |
* Make changes or additions to field values by altering the $items parameter by
|
296 |
* reference. There is no return value.
|
297 |
*
|
298 |
* @param $entity_type
|
299 |
* The type of $entity.
|
300 |
* @param $entities
|
301 |
* Array of entities being loaded, keyed by entity ID.
|
302 |
* @param $field
|
303 |
* The field structure for the operation.
|
304 |
* @param $instances
|
305 |
* Array of instance structures for $field for each entity, keyed by entity
|
306 |
* ID.
|
307 |
* @param $langcode
|
308 |
* The language code associated with $items.
|
309 |
* @param $items
|
310 |
* Array of field values already loaded for the entities, keyed by entity ID.
|
311 |
* Store your changes in this parameter (passed by reference).
|
312 |
* @param $age
|
313 |
* FIELD_LOAD_CURRENT to load the most recent revision for all fields, or
|
314 |
* FIELD_LOAD_REVISION to load the version indicated by each entity.
|
315 |
*/
|
316 |
function hook_field_load($entity_type, $entities, $field, $instances, $langcode, &$items, $age) { |
317 |
// Sample code from text.module: precompute sanitized strings so they are
|
318 |
// stored in the field cache.
|
319 |
foreach ($entities as $id => $entity) { |
320 |
foreach ($items[$id] as $delta => $item) { |
321 |
// Only process items with a cacheable format, the rest will be handled
|
322 |
// by formatters if needed.
|
323 |
if (empty($instances[$id]['settings']['text_processing']) || filter_format_allowcache($item['format'])) { |
324 |
$items[$id][$delta]['safe_value'] = isset($item['value']) ? _text_sanitize($instances[$id], $langcode, $item, 'value') : ''; |
325 |
if ($field['type'] == 'text_with_summary') { |
326 |
$items[$id][$delta]['safe_summary'] = isset($item['summary']) ? _text_sanitize($instances[$id], $langcode, $item, 'summary') : ''; |
327 |
} |
328 |
} |
329 |
} |
330 |
} |
331 |
} |
332 |
|
333 |
/**
|
334 |
* Prepare field values prior to display.
|
335 |
*
|
336 |
* This hook is invoked before the field values are handed to formatters
|
337 |
* for display, and runs before the formatters' own
|
338 |
* hook_field_formatter_prepare_view().
|
339 |
*
|
340 |
* Unlike most other field hooks, this hook operates on multiple entities. The
|
341 |
* $entities, $instances and $items parameters are arrays keyed by entity ID.
|
342 |
* For performance reasons, information for all available entities should be
|
343 |
* loaded in a single query where possible.
|
344 |
*
|
345 |
* Make changes or additions to field values by altering the $items parameter by
|
346 |
* reference. There is no return value.
|
347 |
*
|
348 |
* @param $entity_type
|
349 |
* The type of $entity.
|
350 |
* @param $entities
|
351 |
* Array of entities being displayed, keyed by entity ID.
|
352 |
* @param $field
|
353 |
* The field structure for the operation.
|
354 |
* @param $instances
|
355 |
* Array of instance structures for $field for each entity, keyed by entity
|
356 |
* ID.
|
357 |
* @param $langcode
|
358 |
* The language associated to $items.
|
359 |
* @param $items
|
360 |
* $entity->{$field['field_name']}, or an empty array if unset.
|
361 |
*/
|
362 |
function hook_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) { |
363 |
// Sample code from image.module: if there are no images specified at all,
|
364 |
// use the default image.
|
365 |
foreach ($entities as $id => $entity) { |
366 |
if (empty($items[$id]) && $field['settings']['default_image']) { |
367 |
if ($file = file_load($field['settings']['default_image'])) { |
368 |
$items[$id][0] = (array) $file + array( |
369 |
'is_default' => TRUE, |
370 |
'alt' => '', |
371 |
'title' => '', |
372 |
); |
373 |
} |
374 |
} |
375 |
} |
376 |
} |
377 |
|
378 |
/**
|
379 |
* Validate this module's field data.
|
380 |
*
|
381 |
* If there are validation problems, add to the $errors array (passed by
|
382 |
* reference). There is no return value.
|
383 |
*
|
384 |
* @param $entity_type
|
385 |
* The type of $entity.
|
386 |
* @param $entity
|
387 |
* The entity for the operation.
|
388 |
* @param $field
|
389 |
* The field structure for the operation.
|
390 |
* @param $instance
|
391 |
* The instance structure for $field on $entity's bundle.
|
392 |
* @param $langcode
|
393 |
* The language associated with $items.
|
394 |
* @param $items
|
395 |
* $entity->{$field['field_name']}[$langcode], or an empty array if unset.
|
396 |
* @param $errors
|
397 |
* The array of errors (keyed by field name, language code, and delta) that
|
398 |
* have already been reported for the entity. The function should add its
|
399 |
* errors to this array. Each error is an associative array with the following
|
400 |
* keys and values:
|
401 |
* - error: An error code (should be a string prefixed with the module name).
|
402 |
* - message: The human readable message to be displayed.
|
403 |
*/
|
404 |
function hook_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) { |
405 |
foreach ($items as $delta => $item) { |
406 |
if (!empty($item['value'])) { |
407 |
if (!empty($field['settings']['max_length']) && drupal_strlen($item['value']) > $field['settings']['max_length']) { |
408 |
$errors[$field['field_name']][$langcode][$delta][] = array( |
409 |
'error' => 'text_max_length', |
410 |
'message' => t('%name: the value may not be longer than %max characters.', array('%name' => $instance['label'], '%max' => $field['settings']['max_length'])), |
411 |
); |
412 |
} |
413 |
} |
414 |
} |
415 |
} |
416 |
|
417 |
/**
|
418 |
* Define custom presave behavior for this module's field types.
|
419 |
*
|
420 |
* Make changes or additions to field values by altering the $items parameter by
|
421 |
* reference. There is no return value.
|
422 |
*
|
423 |
* @param $entity_type
|
424 |
* The type of $entity.
|
425 |
* @param $entity
|
426 |
* The entity for the operation.
|
427 |
* @param $field
|
428 |
* The field structure for the operation.
|
429 |
* @param $instance
|
430 |
* The instance structure for $field on $entity's bundle.
|
431 |
* @param $langcode
|
432 |
* The language associated with $items.
|
433 |
* @param $items
|
434 |
* $entity->{$field['field_name']}[$langcode], or an empty array if unset.
|
435 |
*/
|
436 |
function hook_field_presave($entity_type, $entity, $field, $instance, $langcode, &$items) { |
437 |
if ($field['type'] == 'number_decimal') { |
438 |
// Let PHP round the value to ensure consistent behavior across storage
|
439 |
// backends.
|
440 |
foreach ($items as $delta => $item) { |
441 |
if (isset($item['value'])) { |
442 |
$items[$delta]['value'] = round($item['value'], $field['settings']['scale']); |
443 |
} |
444 |
} |
445 |
} |
446 |
} |
447 |
|
448 |
/**
|
449 |
* Define custom insert behavior for this module's field data.
|
450 |
*
|
451 |
* This hook is invoked from field_attach_insert() on the module that defines a
|
452 |
* field, during the process of inserting an entity object (node, taxonomy term,
|
453 |
* etc.). It is invoked just before the data for this field on the particular
|
454 |
* entity object is inserted into field storage. Only field modules that are
|
455 |
* storing or tracking information outside the standard field storage mechanism
|
456 |
* need to implement this hook.
|
457 |
*
|
458 |
* @param $entity_type
|
459 |
* The type of $entity.
|
460 |
* @param $entity
|
461 |
* The entity for the operation.
|
462 |
* @param $field
|
463 |
* The field structure for the operation.
|
464 |
* @param $instance
|
465 |
* The instance structure for $field on $entity's bundle.
|
466 |
* @param $langcode
|
467 |
* The language associated with $items.
|
468 |
* @param $items
|
469 |
* $entity->{$field['field_name']}[$langcode], or an empty array if unset.
|
470 |
*
|
471 |
* @see hook_field_update()
|
472 |
* @see hook_field_delete()
|
473 |
*/
|
474 |
function hook_field_insert($entity_type, $entity, $field, $instance, $langcode, &$items) { |
475 |
if (variable_get('taxonomy_maintain_index_table', TRUE) && $field['storage']['type'] == 'field_sql_storage' && $entity_type == 'node' && $entity->status) { |
476 |
$query = db_insert('taxonomy_index')->fields(array('nid', 'tid', 'sticky', 'created', )); |
477 |
foreach ($items as $item) { |
478 |
$query->values(array( |
479 |
'nid' => $entity->nid, |
480 |
'tid' => $item['tid'], |
481 |
'sticky' => $entity->sticky, |
482 |
'created' => $entity->created, |
483 |
)); |
484 |
} |
485 |
$query->execute();
|
486 |
} |
487 |
} |
488 |
|
489 |
/**
|
490 |
* Define custom update behavior for this module's field data.
|
491 |
*
|
492 |
* This hook is invoked from field_attach_update() on the module that defines a
|
493 |
* field, during the process of updating an entity object (node, taxonomy term,
|
494 |
* etc.). It is invoked just before the data for this field on the particular
|
495 |
* entity object is updated into field storage. Only field modules that are
|
496 |
* storing or tracking information outside the standard field storage mechanism
|
497 |
* need to implement this hook.
|
498 |
*
|
499 |
* @param $entity_type
|
500 |
* The type of $entity.
|
501 |
* @param $entity
|
502 |
* The entity for the operation.
|
503 |
* @param $field
|
504 |
* The field structure for the operation.
|
505 |
* @param $instance
|
506 |
* The instance structure for $field on $entity's bundle.
|
507 |
* @param $langcode
|
508 |
* The language associated with $items.
|
509 |
* @param $items
|
510 |
* $entity->{$field['field_name']}[$langcode], or an empty array if unset.
|
511 |
*
|
512 |
* @see hook_field_insert()
|
513 |
* @see hook_field_delete()
|
514 |
*/
|
515 |
function hook_field_update($entity_type, $entity, $field, $instance, $langcode, &$items) { |
516 |
if (variable_get('taxonomy_maintain_index_table', TRUE) && $field['storage']['type'] == 'field_sql_storage' && $entity_type == 'node') { |
517 |
$first_call = &drupal_static(__FUNCTION__, array()); |
518 |
|
519 |
// We don't maintain data for old revisions, so clear all previous values
|
520 |
// from the table. Since this hook runs once per field, per object, make
|
521 |
// sure we only wipe values once.
|
522 |
if (!isset($first_call[$entity->nid])) { |
523 |
$first_call[$entity->nid] = FALSE; |
524 |
db_delete('taxonomy_index')->condition('nid', $entity->nid)->execute(); |
525 |
} |
526 |
// Only save data to the table if the node is published.
|
527 |
if ($entity->status) { |
528 |
$query = db_insert('taxonomy_index')->fields(array('nid', 'tid', 'sticky', 'created')); |
529 |
foreach ($items as $item) { |
530 |
$query->values(array( |
531 |
'nid' => $entity->nid, |
532 |
'tid' => $item['tid'], |
533 |
'sticky' => $entity->sticky, |
534 |
'created' => $entity->created, |
535 |
)); |
536 |
} |
537 |
$query->execute();
|
538 |
} |
539 |
} |
540 |
} |
541 |
|
542 |
/**
|
543 |
* Update the storage information for a field.
|
544 |
*
|
545 |
* This is invoked on the field's storage module from field_update_field(),
|
546 |
* before the new field information is saved to the database. The field storage
|
547 |
* module should update its storage tables to agree with the new field
|
548 |
* information. If there is a problem, the field storage module should throw an
|
549 |
* exception.
|
550 |
*
|
551 |
* @param $field
|
552 |
* The updated field structure to be saved.
|
553 |
* @param $prior_field
|
554 |
* The previously-saved field structure.
|
555 |
* @param $has_data
|
556 |
* TRUE if the field has data in storage currently.
|
557 |
*/
|
558 |
function hook_field_storage_update_field($field, $prior_field, $has_data) { |
559 |
if (!$has_data) { |
560 |
// There is no data. Re-create the tables completely.
|
561 |
$prior_schema = _field_sql_storage_schema($prior_field); |
562 |
foreach ($prior_schema as $name => $table) { |
563 |
db_drop_table($name, $table); |
564 |
} |
565 |
$schema = _field_sql_storage_schema($field); |
566 |
foreach ($schema as $name => $table) { |
567 |
db_create_table($name, $table); |
568 |
} |
569 |
} |
570 |
else {
|
571 |
// There is data. See field_sql_storage_field_storage_update_field() for
|
572 |
// an example of what to do to modify the schema in place, preserving the
|
573 |
// old data as much as possible.
|
574 |
} |
575 |
drupal_get_schema(NULL, TRUE); |
576 |
} |
577 |
|
578 |
/**
|
579 |
* Define custom delete behavior for this module's field data.
|
580 |
*
|
581 |
* This hook is invoked from field_attach_delete() on the module that defines a
|
582 |
* field, during the process of deleting an entity object (node, taxonomy term,
|
583 |
* etc.). It is invoked just before the data for this field on the particular
|
584 |
* entity object is deleted from field storage. Only field modules that are
|
585 |
* storing or tracking information outside the standard field storage mechanism
|
586 |
* need to implement this hook.
|
587 |
*
|
588 |
* @param $entity_type
|
589 |
* The type of $entity.
|
590 |
* @param $entity
|
591 |
* The entity for the operation.
|
592 |
* @param $field
|
593 |
* The field structure for the operation.
|
594 |
* @param $instance
|
595 |
* The instance structure for $field on $entity's bundle.
|
596 |
* @param $langcode
|
597 |
* The language associated with $items.
|
598 |
* @param $items
|
599 |
* $entity->{$field['field_name']}[$langcode], or an empty array if unset.
|
600 |
*
|
601 |
* @see hook_field_insert()
|
602 |
* @see hook_field_update()
|
603 |
*/
|
604 |
function hook_field_delete($entity_type, $entity, $field, $instance, $langcode, &$items) { |
605 |
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
606 |
foreach ($items as $delta => $item) { |
607 |
// For hook_file_references(), remember that this is being deleted.
|
608 |
$item['file_field_name'] = $field['field_name']; |
609 |
// Pass in the ID of the object that is being removed so all references can
|
610 |
// be counted in hook_file_references().
|
611 |
$item['file_field_type'] = $entity_type; |
612 |
$item['file_field_id'] = $id; |
613 |
file_field_delete_file($item, $field, $entity_type, $id); |
614 |
} |
615 |
} |
616 |
|
617 |
/**
|
618 |
* Define custom revision delete behavior for this module's field types.
|
619 |
*
|
620 |
* This hook is invoked just before the data is deleted from field storage
|
621 |
* in field_attach_delete_revision(), and will only be called for fieldable
|
622 |
* types that are versioned.
|
623 |
*
|
624 |
* @param $entity_type
|
625 |
* The type of $entity.
|
626 |
* @param $entity
|
627 |
* The entity for the operation.
|
628 |
* @param $field
|
629 |
* The field structure for the operation.
|
630 |
* @param $instance
|
631 |
* The instance structure for $field on $entity's bundle.
|
632 |
* @param $langcode
|
633 |
* The language associated with $items.
|
634 |
* @param $items
|
635 |
* $entity->{$field['field_name']}[$langcode], or an empty array if unset.
|
636 |
*/
|
637 |
function hook_field_delete_revision($entity_type, $entity, $field, $instance, $langcode, &$items) { |
638 |
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
639 |
foreach ($items as $delta => $item) { |
640 |
// For hook_file_references, remember that this file is being deleted.
|
641 |
$item['file_field_name'] = $field['field_name']; |
642 |
if (file_field_delete_file($item, $field, $entity_type, $id)) { |
643 |
$items[$delta] = NULL; |
644 |
} |
645 |
} |
646 |
} |
647 |
|
648 |
/**
|
649 |
* Define custom prepare_translation behavior for this module's field types.
|
650 |
*
|
651 |
* @param $entity_type
|
652 |
* The type of $entity.
|
653 |
* @param $entity
|
654 |
* The entity for the operation.
|
655 |
* @param $field
|
656 |
* The field structure for the operation.
|
657 |
* @param $instance
|
658 |
* The instance structure for $field on $entity's bundle.
|
659 |
* @param $langcode
|
660 |
* The language associated to $items.
|
661 |
* @param $items
|
662 |
* $entity->{$field['field_name']}[$langcode], or an empty array if unset.
|
663 |
* @param $source_entity
|
664 |
* The source entity from which field values are being copied.
|
665 |
* @param $source_langcode
|
666 |
* The source language from which field values are being copied.
|
667 |
*
|
668 |
* @ingroup field_language
|
669 |
*/
|
670 |
function hook_field_prepare_translation($entity_type, $entity, $field, $instance, $langcode, &$items, $source_entity, $source_langcode) { |
671 |
// If the translating user is not permitted to use the assigned text format,
|
672 |
// we must not expose the source values.
|
673 |
$field_name = $field['field_name']; |
674 |
$formats = filter_formats();
|
675 |
$format_id = $source_entity->{$field_name}[$source_langcode][0]['format']; |
676 |
if (!filter_access($formats[$format_id])) { |
677 |
$items = array(); |
678 |
} |
679 |
} |
680 |
|
681 |
/**
|
682 |
* Define what constitutes an empty item for a field type.
|
683 |
*
|
684 |
* @param $item
|
685 |
* An item that may or may not be empty.
|
686 |
* @param $field
|
687 |
* The field to which $item belongs.
|
688 |
*
|
689 |
* @return
|
690 |
* TRUE if $field's type considers $item not to contain any data;
|
691 |
* FALSE otherwise.
|
692 |
*/
|
693 |
function hook_field_is_empty($item, $field) { |
694 |
if (empty($item['value']) && (string) $item['value'] !== '0') { |
695 |
return TRUE; |
696 |
} |
697 |
return FALSE; |
698 |
} |
699 |
|
700 |
/**
|
701 |
* @} End of "defgroup field_types".
|
702 |
*/
|
703 |
|
704 |
/**
|
705 |
* @defgroup field_widget Field Widget API
|
706 |
* @{
|
707 |
* Define Field API widget types.
|
708 |
*
|
709 |
* Field API widgets specify how fields are displayed in edit forms. Fields of a
|
710 |
* given @link field_types field type @endlink may be edited using more than one
|
711 |
* widget. In this case, the Field UI module allows the site builder to choose
|
712 |
* which widget to use. Widget types are defined by implementing
|
713 |
* hook_field_widget_info().
|
714 |
*
|
715 |
* Widgets are @link forms_api_reference.html Form API @endlink elements with
|
716 |
* additional processing capabilities. Widget hooks are typically called by the
|
717 |
* Field Attach API during the creation of the field form structure with
|
718 |
* field_attach_form().
|
719 |
*
|
720 |
* @see field
|
721 |
* @see field_types
|
722 |
* @see field_formatter
|
723 |
*/
|
724 |
|
725 |
/**
|
726 |
* Expose Field API widget types.
|
727 |
*
|
728 |
* @return
|
729 |
* An array describing the widget types implemented by the module.
|
730 |
* The keys are widget type names. To avoid name clashes, widget type
|
731 |
* names should be prefixed with the name of the module that exposes them.
|
732 |
* The values are arrays describing the widget type, with the following
|
733 |
* key/value pairs:
|
734 |
* - label: The human-readable name of the widget type.
|
735 |
* - description: A short description for the widget type.
|
736 |
* - field types: An array of field types the widget supports.
|
737 |
* - settings: An array whose keys are the names of the settings available
|
738 |
* for the widget type, and whose values are the default values for those
|
739 |
* settings.
|
740 |
* - behaviors: (optional) An array describing behaviors of the widget, with
|
741 |
* the following elements:
|
742 |
* - multiple values: One of the following constants:
|
743 |
* - FIELD_BEHAVIOR_DEFAULT: (default) If the widget allows the input of
|
744 |
* one single field value (most common case). The widget will be
|
745 |
* repeated for each value input.
|
746 |
* - FIELD_BEHAVIOR_CUSTOM: If one single copy of the widget can receive
|
747 |
* several field values. Examples: checkboxes, multiple select,
|
748 |
* comma-separated textfield.
|
749 |
* - default value: One of the following constants:
|
750 |
* - FIELD_BEHAVIOR_DEFAULT: (default) If the widget accepts default
|
751 |
* values.
|
752 |
* - FIELD_BEHAVIOR_NONE: if the widget does not support default values.
|
753 |
* - weight: (optional) An integer to determine the weight of this widget
|
754 |
* relative to other widgets in the Field UI when selecting a widget for a
|
755 |
* given field instance.
|
756 |
*
|
757 |
* @see hook_field_widget_info_alter()
|
758 |
* @see hook_field_widget_form()
|
759 |
* @see hook_field_widget_form_alter()
|
760 |
* @see hook_field_widget_WIDGET_TYPE_form_alter()
|
761 |
* @see hook_field_widget_error()
|
762 |
* @see hook_field_widget_settings_form()
|
763 |
*/
|
764 |
function hook_field_widget_info() { |
765 |
return array( |
766 |
'text_textfield' => array( |
767 |
'label' => t('Text field'), |
768 |
'field types' => array('text'), |
769 |
'settings' => array('size' => 60), |
770 |
'behaviors' => array( |
771 |
'multiple values' => FIELD_BEHAVIOR_DEFAULT, |
772 |
'default value' => FIELD_BEHAVIOR_DEFAULT, |
773 |
), |
774 |
), |
775 |
'text_textarea' => array( |
776 |
'label' => t('Text area (multiple rows)'), |
777 |
'field types' => array('text_long'), |
778 |
'settings' => array('rows' => 5), |
779 |
'behaviors' => array( |
780 |
'multiple values' => FIELD_BEHAVIOR_DEFAULT, |
781 |
'default value' => FIELD_BEHAVIOR_DEFAULT, |
782 |
), |
783 |
), |
784 |
'text_textarea_with_summary' => array( |
785 |
'label' => t('Text area with a summary'), |
786 |
'field types' => array('text_with_summary'), |
787 |
'settings' => array('rows' => 20, 'summary_rows' => 5), |
788 |
'behaviors' => array( |
789 |
'multiple values' => FIELD_BEHAVIOR_DEFAULT, |
790 |
'default value' => FIELD_BEHAVIOR_DEFAULT, |
791 |
), |
792 |
// As an advanced widget, force it to sink to the bottom of the choices.
|
793 |
'weight' => 2, |
794 |
), |
795 |
); |
796 |
} |
797 |
|
798 |
/**
|
799 |
* Perform alterations on Field API widget types.
|
800 |
*
|
801 |
* @param $info
|
802 |
* Array of informations on widget types exposed by hook_field_widget_info()
|
803 |
* implementations.
|
804 |
*/
|
805 |
function hook_field_widget_info_alter(&$info) { |
806 |
// Add a setting to a widget type.
|
807 |
$info['text_textfield']['settings'] += array( |
808 |
'mymodule_additional_setting' => 'default value', |
809 |
); |
810 |
|
811 |
// Let a new field type re-use an existing widget.
|
812 |
$info['options_select']['field types'][] = 'my_field_type'; |
813 |
} |
814 |
|
815 |
/**
|
816 |
* Return the form for a single field widget.
|
817 |
*
|
818 |
* Field widget form elements should be based on the passed-in $element, which
|
819 |
* contains the base form element properties derived from the field
|
820 |
* configuration.
|
821 |
*
|
822 |
* Field API will set the weight, field name and delta values for each form
|
823 |
* element. If there are multiple values for this field, the Field API will
|
824 |
* invoke this hook as many times as needed.
|
825 |
*
|
826 |
* Note that, depending on the context in which the widget is being included
|
827 |
* (regular entity form, field configuration form, advanced search form...),
|
828 |
* the values for $field and $instance might be different from the "official"
|
829 |
* definitions returned by field_info_field() and field_info_instance().
|
830 |
* Examples: mono-value widget even if the field is multi-valued, non-required
|
831 |
* widget even if the field is 'required'...
|
832 |
*
|
833 |
* Therefore, the FAPI element callbacks (such as #process, #element_validate,
|
834 |
* #value_callback...) used by the widget cannot use the field_info_field()
|
835 |
* or field_info_instance() functions to retrieve the $field or $instance
|
836 |
* definitions they should operate on. The field_widget_field() and
|
837 |
* field_widget_instance() functions should be used instead to fetch the
|
838 |
* current working definitions from $form_state, where Field API stores them.
|
839 |
*
|
840 |
* Alternatively, hook_field_widget_form() can extract the needed specific
|
841 |
* properties from $field and $instance and set them as ad-hoc
|
842 |
* $element['#custom'] properties, for later use by its element callbacks.
|
843 |
*
|
844 |
* Other modules may alter the form element provided by this function using
|
845 |
* hook_field_widget_form_alter().
|
846 |
*
|
847 |
* @param $form
|
848 |
* The form structure where widgets are being attached to. This might be a
|
849 |
* full form structure, or a sub-element of a larger form.
|
850 |
* @param $form_state
|
851 |
* An associative array containing the current state of the form.
|
852 |
* @param $field
|
853 |
* The field structure.
|
854 |
* @param $instance
|
855 |
* The field instance.
|
856 |
* @param $langcode
|
857 |
* The language associated with $items.
|
858 |
* @param $items
|
859 |
* Array of default values for this field.
|
860 |
* @param $delta
|
861 |
* The order of this item in the array of subelements (0, 1, 2, etc).
|
862 |
* @param $element
|
863 |
* A form element array containing basic properties for the widget:
|
864 |
* - #entity_type: The name of the entity the field is attached to.
|
865 |
* - #bundle: The name of the field bundle the field is contained in.
|
866 |
* - #field_name: The name of the field.
|
867 |
* - #language: The language the field is being edited in.
|
868 |
* - #field_parents: The 'parents' space for the field in the form. Most
|
869 |
* widgets can simply overlook this property. This identifies the
|
870 |
* location where the field values are placed within
|
871 |
* $form_state['values'], and is used to access processing information
|
872 |
* for the field through the field_form_get_state() and
|
873 |
* field_form_set_state() functions.
|
874 |
* - #columns: A list of field storage columns of the field.
|
875 |
* - #title: The sanitized element label for the field instance, ready for
|
876 |
* output.
|
877 |
* - #description: The sanitized element description for the field instance,
|
878 |
* ready for output.
|
879 |
* - #required: A Boolean indicating whether the element value is required;
|
880 |
* for required multiple value fields, only the first widget's values are
|
881 |
* required.
|
882 |
* - #delta: The order of this item in the array of subelements; see $delta
|
883 |
* above.
|
884 |
*
|
885 |
* @return
|
886 |
* The form elements for a single widget for this field.
|
887 |
*
|
888 |
* @see field_widget_field()
|
889 |
* @see field_widget_instance()
|
890 |
* @see hook_field_widget_form_alter()
|
891 |
* @see hook_field_widget_WIDGET_TYPE_form_alter()
|
892 |
*/
|
893 |
function hook_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { |
894 |
$element += array( |
895 |
'#type' => $instance['widget']['type'], |
896 |
'#default_value' => isset($items[$delta]) ? $items[$delta] : '', |
897 |
); |
898 |
return array('value' => $element); |
899 |
} |
900 |
|
901 |
/**
|
902 |
* Alter forms for field widgets provided by other modules.
|
903 |
*
|
904 |
* @param $element
|
905 |
* The field widget form element as constructed by hook_field_widget_form().
|
906 |
* @param $form_state
|
907 |
* An associative array containing the current state of the form.
|
908 |
* @param $context
|
909 |
* An associative array containing the following key-value pairs, matching the
|
910 |
* arguments received by hook_field_widget_form():
|
911 |
* - form: The form structure to which widgets are being attached. This may be
|
912 |
* a full form structure, or a sub-element of a larger form.
|
913 |
* - field: The field structure.
|
914 |
* - instance: The field instance structure.
|
915 |
* - langcode: The language associated with $items.
|
916 |
* - items: Array of default values for this field.
|
917 |
* - delta: The order of this item in the array of subelements (0, 1, 2, etc).
|
918 |
*
|
919 |
* @see hook_field_widget_form()
|
920 |
* @see hook_field_widget_WIDGET_TYPE_form_alter()
|
921 |
*/
|
922 |
function hook_field_widget_form_alter(&$element, &$form_state, $context) { |
923 |
// Add a css class to widget form elements for all fields of type mytype.
|
924 |
if ($context['field']['type'] == 'mytype') { |
925 |
// Be sure not to overwrite existing attributes.
|
926 |
$element['#attributes']['class'][] = 'myclass'; |
927 |
} |
928 |
} |
929 |
|
930 |
/**
|
931 |
* Alter widget forms for a specific widget provided by another module.
|
932 |
*
|
933 |
* Modules can implement hook_field_widget_WIDGET_TYPE_form_alter() to modify a
|
934 |
* specific widget form, rather than using hook_field_widget_form_alter() and
|
935 |
* checking the widget type.
|
936 |
*
|
937 |
* @param $element
|
938 |
* The field widget form element as constructed by hook_field_widget_form().
|
939 |
* @param $form_state
|
940 |
* An associative array containing the current state of the form.
|
941 |
* @param $context
|
942 |
* An associative array containing the following key-value pairs, matching the
|
943 |
* arguments received by hook_field_widget_form():
|
944 |
* - "form": The form structure where widgets are being attached to. This
|
945 |
* might be a full form structure, or a sub-element of a larger form.
|
946 |
* - "field": The field structure.
|
947 |
* - "instance": The field instance structure.
|
948 |
* - "langcode": The language associated with $items.
|
949 |
* - "items": Array of default values for this field.
|
950 |
* - "delta": The order of this item in the array of subelements (0, 1, 2,
|
951 |
* etc).
|
952 |
*
|
953 |
* @see hook_field_widget_form()
|
954 |
* @see hook_field_widget_form_alter()
|
955 |
*/
|
956 |
function hook_field_widget_WIDGET_TYPE_form_alter(&$element, &$form_state, $context) { |
957 |
// Code here will only act on widgets of type WIDGET_TYPE. For example,
|
958 |
// hook_field_widget_mymodule_autocomplete_form_alter() will only act on
|
959 |
// widgets of type 'mymodule_autocomplete'.
|
960 |
$element['#autocomplete_path'] = 'mymodule/autocomplete_path'; |
961 |
} |
962 |
|
963 |
/**
|
964 |
* Alters the widget properties of a field instance before it gets displayed.
|
965 |
*
|
966 |
* Note that instead of hook_field_widget_properties_alter(), which is called
|
967 |
* for all fields on all entity types,
|
968 |
* hook_field_widget_properties_ENTITY_TYPE_alter() may be used to alter widget
|
969 |
* properties for fields on a specific entity type only.
|
970 |
*
|
971 |
* This hook is called once per field per added or edit entity. If the result
|
972 |
* of the hook involves reading from the database, it is highly recommended to
|
973 |
* statically cache the information.
|
974 |
*
|
975 |
* @param $widget
|
976 |
* The instance's widget properties.
|
977 |
* @param $context
|
978 |
* An associative array containing:
|
979 |
* - entity_type: The entity type; e.g., 'node' or 'user'.
|
980 |
* - entity: The entity object.
|
981 |
* - field: The field that the widget belongs to.
|
982 |
* - instance: The instance of the field.
|
983 |
*
|
984 |
* @see hook_field_widget_properties_ENTITY_TYPE_alter()
|
985 |
*/
|
986 |
function hook_field_widget_properties_alter(&$widget, $context) { |
987 |
// Change a widget's type according to the time of day.
|
988 |
$field = $context['field']; |
989 |
if ($context['entity_type'] == 'node' && $field['field_name'] == 'field_foo') { |
990 |
$time = date('H'); |
991 |
$widget['type'] = $time < 12 ? 'widget_am' : 'widget_pm'; |
992 |
} |
993 |
} |
994 |
|
995 |
/**
|
996 |
* Flag a field-level validation error.
|
997 |
*
|
998 |
* @param $element
|
999 |
* An array containing the form element for the widget. The error needs to be
|
1000 |
* flagged on the right sub-element, according to the widget's internal
|
1001 |
* structure.
|
1002 |
* @param $error
|
1003 |
* An associative array with the following key-value pairs, as returned by
|
1004 |
* hook_field_validate():
|
1005 |
* - error: the error code. Complex widgets might need to report different
|
1006 |
* errors to different form elements inside the widget.
|
1007 |
* - message: the human readable message to be displayed.
|
1008 |
* @param $form
|
1009 |
* The form structure where field elements are attached to. This might be a
|
1010 |
* full form structure, or a sub-element of a larger form.
|
1011 |
* @param $form_state
|
1012 |
* An associative array containing the current state of the form.
|
1013 |
*/
|
1014 |
function hook_field_widget_error($element, $error, $form, &$form_state) { |
1015 |
form_error($element, $error['message']); |
1016 |
} |
1017 |
|
1018 |
|
1019 |
/**
|
1020 |
* @} End of "defgroup field_widget".
|
1021 |
*/
|
1022 |
|
1023 |
|
1024 |
/**
|
1025 |
* @defgroup field_formatter Field Formatter API
|
1026 |
* @{
|
1027 |
* Define Field API formatter types.
|
1028 |
*
|
1029 |
* Field API formatters specify how fields are displayed when the entity to
|
1030 |
* which the field is attached is displayed. Fields of a given
|
1031 |
* @link field_types field type @endlink may be displayed using more than one
|
1032 |
* formatter. In this case, the Field UI module allows the site builder to
|
1033 |
* choose which formatter to use. Field formatters are defined by implementing
|
1034 |
* hook_field_formatter_info().
|
1035 |
*
|
1036 |
* @see field
|
1037 |
* @see field_types
|
1038 |
* @see field_widget
|
1039 |
*/
|
1040 |
|
1041 |
/**
|
1042 |
* Expose Field API formatter types.
|
1043 |
*
|
1044 |
* Formatters handle the display of field values. Formatter hooks are typically
|
1045 |
* called by the Field Attach API field_attach_prepare_view() and
|
1046 |
* field_attach_view() functions.
|
1047 |
*
|
1048 |
* @return
|
1049 |
* An array describing the formatter types implemented by the module.
|
1050 |
* The keys are formatter type names. To avoid name clashes, formatter type
|
1051 |
* names should be prefixed with the name of the module that exposes them.
|
1052 |
* The values are arrays describing the formatter type, with the following
|
1053 |
* key/value pairs:
|
1054 |
* - label: The human-readable name of the formatter type.
|
1055 |
* - description: A short description for the formatter type.
|
1056 |
* - field types: An array of field types the formatter supports.
|
1057 |
* - settings: An array whose keys are the names of the settings available
|
1058 |
* for the formatter type, and whose values are the default values for
|
1059 |
* those settings.
|
1060 |
*
|
1061 |
* @see hook_field_formatter_info_alter()
|
1062 |
* @see hook_field_formatter_view()
|
1063 |
* @see hook_field_formatter_prepare_view()
|
1064 |
*/
|
1065 |
function hook_field_formatter_info() { |
1066 |
return array( |
1067 |
'text_default' => array( |
1068 |
'label' => t('Default'), |
1069 |
'field types' => array('text', 'text_long', 'text_with_summary'), |
1070 |
), |
1071 |
'text_plain' => array( |
1072 |
'label' => t('Plain text'), |
1073 |
'field types' => array('text', 'text_long', 'text_with_summary'), |
1074 |
), |
1075 |
|
1076 |
// The text_trimmed formatter displays the trimmed version of the
|
1077 |
// full element of the field. It is intended to be used with text
|
1078 |
// and text_long fields. It also works with text_with_summary
|
1079 |
// fields though the text_summary_or_trimmed formatter makes more
|
1080 |
// sense for that field type.
|
1081 |
'text_trimmed' => array( |
1082 |
'label' => t('Trimmed'), |
1083 |
'field types' => array('text', 'text_long', 'text_with_summary'), |
1084 |
), |
1085 |
|
1086 |
// The 'summary or trimmed' field formatter for text_with_summary
|
1087 |
// fields displays returns the summary element of the field or, if
|
1088 |
// the summary is empty, the trimmed version of the full element
|
1089 |
// of the field.
|
1090 |
'text_summary_or_trimmed' => array( |
1091 |
'label' => t('Summary or trimmed'), |
1092 |
'field types' => array('text_with_summary'), |
1093 |
), |
1094 |
); |
1095 |
} |
1096 |
|
1097 |
/**
|
1098 |
* Perform alterations on Field API formatter types.
|
1099 |
*
|
1100 |
* @param $info
|
1101 |
* An array of information on formatter types exposed by
|
1102 |
* hook_field_formatter_info() implementations.
|
1103 |
*/
|
1104 |
function hook_field_formatter_info_alter(&$info) { |
1105 |
// Add a setting to a formatter type.
|
1106 |
$info['text_default']['settings'] += array( |
1107 |
'mymodule_additional_setting' => 'default value', |
1108 |
); |
1109 |
|
1110 |
// Let a new field type re-use an existing formatter.
|
1111 |
$info['text_default']['field types'][] = 'my_field_type'; |
1112 |
} |
1113 |
|
1114 |
/**
|
1115 |
* Allow formatters to load information for field values being displayed.
|
1116 |
*
|
1117 |
* This should be used when a formatter needs to load additional information
|
1118 |
* from the database in order to render a field, for example a reference field
|
1119 |
* which displays properties of the referenced entities such as name or type.
|
1120 |
*
|
1121 |
* This hook is called after the field type's own hook_field_prepare_view().
|
1122 |
*
|
1123 |
* Unlike most other field hooks, this hook operates on multiple entities. The
|
1124 |
* $entities, $instances and $items parameters are arrays keyed by entity ID.
|
1125 |
* For performance reasons, information for all available entities should be
|
1126 |
* loaded in a single query where possible.
|
1127 |
*
|
1128 |
* @param $entity_type
|
1129 |
* The type of $entity.
|
1130 |
* @param $entities
|
1131 |
* Array of entities being displayed, keyed by entity ID.
|
1132 |
* @param $field
|
1133 |
* The field structure for the operation.
|
1134 |
* @param $instances
|
1135 |
* Array of instance structures for $field for each entity, keyed by entity
|
1136 |
* ID.
|
1137 |
* @param $langcode
|
1138 |
* The language the field values are to be shown in. If no language is
|
1139 |
* provided the current language is used.
|
1140 |
* @param $items
|
1141 |
* Array of field values for the entities, keyed by entity ID.
|
1142 |
* @param $displays
|
1143 |
* Array of display settings to use for each entity, keyed by entity ID.
|
1144 |
*
|
1145 |
* @return
|
1146 |
* Changes or additions to field values are done by altering the $items
|
1147 |
* parameter by reference.
|
1148 |
*/
|
1149 |
function hook_field_formatter_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items, $displays) { |
1150 |
$tids = array(); |
1151 |
|
1152 |
// Collect every possible term attached to any of the fieldable entities.
|
1153 |
foreach ($entities as $id => $entity) { |
1154 |
foreach ($items[$id] as $delta => $item) { |
1155 |
// Force the array key to prevent duplicates.
|
1156 |
$tids[$item['tid']] = $item['tid']; |
1157 |
} |
1158 |
} |
1159 |
|
1160 |
if ($tids) { |
1161 |
$terms = taxonomy_term_load_multiple($tids); |
1162 |
|
1163 |
// Iterate through the fieldable entities again to attach the loaded term
|
1164 |
// data.
|
1165 |
foreach ($entities as $id => $entity) { |
1166 |
$rekey = FALSE; |
1167 |
|
1168 |
foreach ($items[$id] as $delta => $item) { |
1169 |
// Check whether the taxonomy term field instance value could be loaded.
|
1170 |
if (isset($terms[$item['tid']])) { |
1171 |
// Replace the instance value with the term data.
|
1172 |
$items[$id][$delta]['taxonomy_term'] = $terms[$item['tid']]; |
1173 |
} |
1174 |
// Otherwise, unset the instance value, since the term does not exist.
|
1175 |
else {
|
1176 |
unset($items[$id][$delta]); |
1177 |
$rekey = TRUE; |
1178 |
} |
1179 |
} |
1180 |
|
1181 |
if ($rekey) { |
1182 |
// Rekey the items array.
|
1183 |
$items[$id] = array_values($items[$id]); |
1184 |
} |
1185 |
} |
1186 |
} |
1187 |
} |
1188 |
|
1189 |
/**
|
1190 |
* Build a renderable array for a field value.
|
1191 |
*
|
1192 |
* @param $entity_type
|
1193 |
* The type of $entity.
|
1194 |
* @param $entity
|
1195 |
* The entity being displayed.
|
1196 |
* @param $field
|
1197 |
* The field structure.
|
1198 |
* @param $instance
|
1199 |
* The field instance.
|
1200 |
* @param $langcode
|
1201 |
* The language associated with $items.
|
1202 |
* @param $items
|
1203 |
* Array of values for this field.
|
1204 |
* @param $display
|
1205 |
* The display settings to use, as found in the 'display' entry of instance
|
1206 |
* definitions. The array notably contains the following keys and values;
|
1207 |
* - type: The name of the formatter to use.
|
1208 |
* - settings: The array of formatter settings.
|
1209 |
*
|
1210 |
* @return
|
1211 |
* A renderable array for the $items, as an array of child elements keyed
|
1212 |
* by numeric indexes starting from 0.
|
1213 |
*/
|
1214 |
function hook_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { |
1215 |
$element = array(); |
1216 |
$settings = $display['settings']; |
1217 |
|
1218 |
switch ($display['type']) { |
1219 |
case 'sample_field_formatter_simple': |
1220 |
// Common case: each value is displayed individually in a sub-element
|
1221 |
// keyed by delta. The field.tpl.php template specifies the markup
|
1222 |
// wrapping each value.
|
1223 |
foreach ($items as $delta => $item) { |
1224 |
$element[$delta] = array('#markup' => $settings['some_setting'] . $item['value']); |
1225 |
} |
1226 |
break;
|
1227 |
|
1228 |
case 'sample_field_formatter_themeable': |
1229 |
// More elaborate formatters can defer to a theme function for easier
|
1230 |
// customization.
|
1231 |
foreach ($items as $delta => $item) { |
1232 |
$element[$delta] = array( |
1233 |
'#theme' => 'mymodule_theme_sample_field_formatter_themeable', |
1234 |
'#data' => $item['value'], |
1235 |
'#some_setting' => $settings['some_setting'], |
1236 |
); |
1237 |
} |
1238 |
break;
|
1239 |
|
1240 |
case 'sample_field_formatter_combined': |
1241 |
// Some formatters might need to display all values within a single piece
|
1242 |
// of markup.
|
1243 |
$rows = array(); |
1244 |
foreach ($items as $delta => $item) { |
1245 |
$rows[] = array($delta, $item['value']); |
1246 |
} |
1247 |
$element[0] = array( |
1248 |
'#theme' => 'table', |
1249 |
'#header' => array(t('Delta'), t('Value')), |
1250 |
'#rows' => $rows, |
1251 |
); |
1252 |
break;
|
1253 |
} |
1254 |
|
1255 |
return $element; |
1256 |
} |
1257 |
|
1258 |
/**
|
1259 |
* @} End of "defgroup field_formatter".
|
1260 |
*/
|
1261 |
|
1262 |
/**
|
1263 |
* @addtogroup field_attach
|
1264 |
* @{
|
1265 |
*/
|
1266 |
|
1267 |
/**
|
1268 |
* Act on field_attach_form().
|
1269 |
*
|
1270 |
* This hook is invoked after the field module has performed the operation.
|
1271 |
* Implementing modules should alter the $form or $form_state parameters.
|
1272 |
*
|
1273 |
* @param $entity_type
|
1274 |
* The type of $entity; for example, 'node' or 'user'.
|
1275 |
* @param $entity
|
1276 |
* The entity for which an edit form is being built.
|
1277 |
* @param $form
|
1278 |
* The form structure where field elements are attached to. This might be a
|
1279 |
* full form structure, or a sub-element of a larger form. The
|
1280 |
* $form['#parents'] property can be used to identify the corresponding part
|
1281 |
* of $form_state['values']. Hook implementations that need to act on the
|
1282 |
* top-level properties of the global form (like #submit, #validate...) can
|
1283 |
* add a #process callback to the array received in the $form parameter, and
|
1284 |
* act on the $complete_form parameter in the process callback.
|
1285 |
* @param $form_state
|
1286 |
* An associative array containing the current state of the form.
|
1287 |
* @param $langcode
|
1288 |
* The language the field values are going to be entered in. If no language
|
1289 |
* is provided the default site language will be used.
|
1290 |
*/
|
1291 |
function hook_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) { |
1292 |
// Add a checkbox allowing a given field to be emptied.
|
1293 |
// See hook_field_attach_submit() for the corresponding processing code.
|
1294 |
$form['empty_field_foo'] = array( |
1295 |
'#type' => 'checkbox', |
1296 |
'#title' => t("Empty the 'field_foo' field"), |
1297 |
); |
1298 |
} |
1299 |
|
1300 |
/**
|
1301 |
* Act on field_attach_load().
|
1302 |
*
|
1303 |
* This hook is invoked after the field module has performed the operation.
|
1304 |
*
|
1305 |
* Unlike other field_attach hooks, this hook accounts for 'multiple loads'.
|
1306 |
* Instead of the usual $entity parameter, it accepts an array of entities,
|
1307 |
* indexed by entity ID. For performance reasons, information for all available
|
1308 |
* entities should be loaded in a single query where possible.
|
1309 |
*
|
1310 |
* The changes made to the entities' field values get cached by the field cache
|
1311 |
* for subsequent loads.
|
1312 |
*
|
1313 |
* See field_attach_load() for details and arguments.
|
1314 |
*/
|
1315 |
function hook_field_attach_load($entity_type, $entities, $age, $options) { |
1316 |
// @todo Needs function body.
|
1317 |
} |
1318 |
|
1319 |
/**
|
1320 |
* Act on field_attach_validate().
|
1321 |
*
|
1322 |
* This hook is invoked after the field module has performed the operation.
|
1323 |
*
|
1324 |
* See field_attach_validate() for details and arguments.
|
1325 |
*
|
1326 |
* @param $entity_type
|
1327 |
* The type of $entity; e.g., 'node' or 'user'.
|
1328 |
* @param $entity
|
1329 |
* The entity with fields to validate.
|
1330 |
* @param array $errors
|
1331 |
* The array of errors (keyed by field name, language code, and delta) that
|
1332 |
* have already been reported for the entity. The function should add its
|
1333 |
* errors to this array. Each error is an associative array with the following
|
1334 |
* keys and values:
|
1335 |
* - error: An error code (should be a string prefixed with the module name).
|
1336 |
* - message: The human readable message to be displayed.
|
1337 |
*/
|
1338 |
function hook_field_attach_validate($entity_type, $entity, &$errors) { |
1339 |
// Make sure any images in article nodes have an alt text.
|
1340 |
if ($entity_type == 'node' && $entity->type == 'article' && !empty($entity->field_image)) { |
1341 |
foreach ($entity->field_image as $langcode => $items) { |
1342 |
foreach ($items as $delta => $item) { |
1343 |
if (!empty($item['fid']) && empty($item['alt'])) { |
1344 |
$errors['field_image'][$langcode][$delta][] = array( |
1345 |
'error' => 'field_example_invalid', |
1346 |
'message' => t('All images in articles need to have an alternative text set.'), |
1347 |
); |
1348 |
} |
1349 |
} |
1350 |
} |
1351 |
} |
1352 |
} |
1353 |
|
1354 |
/**
|
1355 |
* Act on field_attach_submit().
|
1356 |
*
|
1357 |
* This hook is invoked after the field module has performed the operation.
|
1358 |
*
|
1359 |
* @param $entity_type
|
1360 |
* The type of $entity; for example, 'node' or 'user'.
|
1361 |
* @param $entity
|
1362 |
* The entity for which an edit form is being submitted. The incoming form
|
1363 |
* values have been extracted as field values of the $entity object.
|
1364 |
* @param $form
|
1365 |
* The form structure where field elements are attached to. This might be a
|
1366 |
* full form structure, or a sub-part of a larger form. The $form['#parents']
|
1367 |
* property can be used to identify the corresponding part of
|
1368 |
* $form_state['values'].
|
1369 |
* @param $form_state
|
1370 |
* An associative array containing the current state of the form.
|
1371 |
*/
|
1372 |
function hook_field_attach_submit($entity_type, $entity, $form, &$form_state) { |
1373 |
// Sample case of an 'Empty the field' checkbox added on the form, allowing
|
1374 |
// a given field to be emptied.
|
1375 |
$values = drupal_array_get_nested_value($form_state['values'], $form['#parents']); |
1376 |
if (!empty($values['empty_field_foo'])) { |
1377 |
unset($entity->field_foo); |
1378 |
} |
1379 |
} |
1380 |
|
1381 |
/**
|
1382 |
* Act on field_attach_presave().
|
1383 |
*
|
1384 |
* This hook is invoked after the field module has performed the operation.
|
1385 |
*
|
1386 |
* See field_attach_presave() for details and arguments.
|
1387 |
*/
|
1388 |
function hook_field_attach_presave($entity_type, $entity) { |
1389 |
// @todo Needs function body.
|
1390 |
} |
1391 |
|
1392 |
/**
|
1393 |
* Act on field_attach_insert().
|
1394 |
*
|
1395 |
* This hook is invoked after the field module has performed the operation.
|
1396 |
*
|
1397 |
* See field_attach_insert() for details and arguments.
|
1398 |
*/
|
1399 |
function hook_field_attach_insert($entity_type, $entity) { |
1400 |
// @todo Needs function body.
|
1401 |
} |
1402 |
|
1403 |
/**
|
1404 |
* Act on field_attach_update().
|
1405 |
*
|
1406 |
* This hook is invoked after the field module has performed the operation.
|
1407 |
*
|
1408 |
* See field_attach_update() for details and arguments.
|
1409 |
*/
|
1410 |
function hook_field_attach_update($entity_type, $entity) { |
1411 |
// @todo Needs function body.
|
1412 |
} |
1413 |
|
1414 |
/**
|
1415 |
* Alter field_attach_preprocess() variables.
|
1416 |
*
|
1417 |
* This hook is invoked while preprocessing the field.tpl.php template file
|
1418 |
* in field_attach_preprocess().
|
1419 |
*
|
1420 |
* @param $variables
|
1421 |
* The variables array is passed by reference and will be populated with field
|
1422 |
* values.
|
1423 |
* @param $context
|
1424 |
* An associative array containing:
|
1425 |
* - entity_type: The type of $entity; for example, 'node' or 'user'.
|
1426 |
* - entity: The entity with fields to render.
|
1427 |
* - element: The structured array containing the values ready for rendering.
|
1428 |
*/
|
1429 |
function hook_field_attach_preprocess_alter(&$variables, $context) { |
1430 |
// @todo Needs function body.
|
1431 |
} |
1432 |
|
1433 |
/**
|
1434 |
* Act on field_attach_delete().
|
1435 |
*
|
1436 |
* This hook is invoked after the field module has performed the operation.
|
1437 |
*
|
1438 |
* See field_attach_delete() for details and arguments.
|
1439 |
*/
|
1440 |
function hook_field_attach_delete($entity_type, $entity) { |
1441 |
// @todo Needs function body.
|
1442 |
} |
1443 |
|
1444 |
/**
|
1445 |
* Act on field_attach_delete_revision().
|
1446 |
*
|
1447 |
* This hook is invoked after the field module has performed the operation.
|
1448 |
*
|
1449 |
* See field_attach_delete_revision() for details and arguments.
|
1450 |
*/
|
1451 |
function hook_field_attach_delete_revision($entity_type, $entity) { |
1452 |
// @todo Needs function body.
|
1453 |
} |
1454 |
|
1455 |
/**
|
1456 |
* Act on field_purge_data().
|
1457 |
*
|
1458 |
* This hook is invoked in field_purge_data() and allows modules to act on
|
1459 |
* purging data from a single field pseudo-entity. For example, if a module
|
1460 |
* relates data in the field with its own data, it may purge its own data
|
1461 |
* during this process as well.
|
1462 |
*
|
1463 |
* @param $entity_type
|
1464 |
* The type of $entity; for example, 'node' or 'user'.
|
1465 |
* @param $entity
|
1466 |
* The pseudo-entity whose field data is being purged.
|
1467 |
* @param $field
|
1468 |
* The (possibly deleted) field whose data is being purged.
|
1469 |
* @param $instance
|
1470 |
* The deleted field instance whose data is being purged.
|
1471 |
*
|
1472 |
* @see @link field_purge Field API bulk data deletion @endlink
|
1473 |
* @see field_purge_data()
|
1474 |
*/
|
1475 |
function hook_field_attach_purge($entity_type, $entity, $field, $instance) { |
1476 |
// find the corresponding data in mymodule and purge it
|
1477 |
if ($entity_type == 'node' && $field->field_name == 'my_field_name') { |
1478 |
mymodule_remove_mydata($entity->nid);
|
1479 |
} |
1480 |
} |
1481 |
|
1482 |
/**
|
1483 |
* Perform alterations on field_attach_view() or field_view_field().
|
1484 |
*
|
1485 |
* This hook is invoked after the field module has performed the operation.
|
1486 |
*
|
1487 |
* @param $output
|
1488 |
* The structured content array tree for all of the entity's fields.
|
1489 |
* @param $context
|
1490 |
* An associative array containing:
|
1491 |
* - entity_type: The type of $entity; for example, 'node' or 'user'.
|
1492 |
* - entity: The entity with fields to render.
|
1493 |
* - view_mode: View mode; for example, 'full' or 'teaser'.
|
1494 |
* - display: Either a view mode string or an array of display settings. If
|
1495 |
* this hook is being invoked from field_attach_view(), the 'display'
|
1496 |
* element is set to the view mode string. If this hook is being invoked
|
1497 |
* from field_view_field(), this element is set to the $display argument
|
1498 |
* and the view_mode element is set to '_custom'. See field_view_field()
|
1499 |
* for more information on what its $display argument contains.
|
1500 |
* - language: The language code used for rendering.
|
1501 |
*/
|
1502 |
function hook_field_attach_view_alter(&$output, $context) { |
1503 |
// Append RDF term mappings on displayed taxonomy links.
|
1504 |
foreach (element_children($output) as $field_name) { |
1505 |
$element = &$output[$field_name]; |
1506 |
if ($element['#field_type'] == 'taxonomy_term_reference' && $element['#formatter'] == 'taxonomy_term_reference_link') { |
1507 |
foreach ($element['#items'] as $delta => $item) { |
1508 |
$term = $item['taxonomy_term']; |
1509 |
if (!empty($term->rdf_mapping['rdftype'])) { |
1510 |
$element[$delta]['#options']['attributes']['typeof'] = $term->rdf_mapping['rdftype']; |
1511 |
} |
1512 |
if (!empty($term->rdf_mapping['name']['predicates'])) { |
1513 |
$element[$delta]['#options']['attributes']['property'] = $term->rdf_mapping['name']['predicates']; |
1514 |
} |
1515 |
} |
1516 |
} |
1517 |
} |
1518 |
} |
1519 |
|
1520 |
/**
|
1521 |
* Perform alterations on field_attach_prepare_translation().
|
1522 |
*
|
1523 |
* This hook is invoked after the field module has performed the operation.
|
1524 |
*
|
1525 |
* @param $entity
|
1526 |
* The entity being prepared for translation.
|
1527 |
* @param $context
|
1528 |
* An associative array containing:
|
1529 |
* - entity_type: The type of $entity; e.g. 'node' or 'user'.
|
1530 |
* - langcode: The language the entity has to be translated in.
|
1531 |
* - source_entity: The entity holding the field values to be translated.
|
1532 |
* - source_langcode: The source language from which translate.
|
1533 |
*/
|
1534 |
function hook_field_attach_prepare_translation_alter(&$entity, $context) { |
1535 |
if ($context['entity_type'] == 'custom_entity_type') { |
1536 |
$entity->custom_field = $context['source_entity']->custom_field; |
1537 |
} |
1538 |
} |
1539 |
|
1540 |
/**
|
1541 |
* Perform alterations on field_language() values.
|
1542 |
*
|
1543 |
* This hook is invoked to alter the array of display languages for the given
|
1544 |
* entity.
|
1545 |
*
|
1546 |
* @param $display_language
|
1547 |
* A reference to an array of language codes keyed by field name.
|
1548 |
* @param $context
|
1549 |
* An associative array containing:
|
1550 |
* - entity_type: The type of the entity to be displayed.
|
1551 |
* - entity: The entity with fields to render.
|
1552 |
* - langcode: The language code $entity has to be displayed in.
|
1553 |
*
|
1554 |
* @ingroup field_language
|
1555 |
*/
|
1556 |
function hook_field_language_alter(&$display_language, $context) { |
1557 |
// Do not apply core language fallback rules if they are disabled or if Locale
|
1558 |
// is not registered as a translation handler.
|
1559 |
if (variable_get('locale_field_language_fallback', TRUE) && field_has_translation_handler($context['entity_type'], 'locale')) { |
1560 |
locale_field_language_fallback($display_language, $context['entity'], $context['language']); |
1561 |
} |
1562 |
} |
1563 |
|
1564 |
/**
|
1565 |
* Alter field_available_languages() values.
|
1566 |
*
|
1567 |
* This hook is invoked from field_available_languages() to allow modules to
|
1568 |
* alter the array of available languages for the given field.
|
1569 |
*
|
1570 |
* @param $languages
|
1571 |
* A reference to an array of language codes to be made available.
|
1572 |
* @param $context
|
1573 |
* An associative array containing:
|
1574 |
* - entity_type: The type of the entity the field is attached to.
|
1575 |
* - field: A field data structure.
|
1576 |
*
|
1577 |
* @ingroup field_language
|
1578 |
*/
|
1579 |
function hook_field_available_languages_alter(&$languages, $context) { |
1580 |
// Add an unavailable language.
|
1581 |
$languages[] = 'xx'; |
1582 |
|
1583 |
// Remove an available language.
|
1584 |
$index = array_search('yy', $languages); |
1585 |
unset($languages[$index]); |
1586 |
} |
1587 |
|
1588 |
/**
|
1589 |
* Act on field_attach_create_bundle().
|
1590 |
*
|
1591 |
* This hook is invoked after the field module has performed the operation.
|
1592 |
*
|
1593 |
* See field_attach_create_bundle() for details and arguments.
|
1594 |
*/
|
1595 |
function hook_field_attach_create_bundle($entity_type, $bundle) { |
1596 |
// When a new bundle is created, the menu needs to be rebuilt to add the
|
1597 |
// Field UI menu item tabs.
|
1598 |
variable_set('menu_rebuild_needed', TRUE); |
1599 |
} |
1600 |
|
1601 |
/**
|
1602 |
* Act on field_attach_rename_bundle().
|
1603 |
*
|
1604 |
* This hook is invoked after the field module has performed the operation.
|
1605 |
*
|
1606 |
* See field_attach_rename_bundle() for details and arguments.
|
1607 |
*/
|
1608 |
function hook_field_attach_rename_bundle($entity_type, $bundle_old, $bundle_new) { |
1609 |
// Update the extra weights variable with new information.
|
1610 |
if ($bundle_old !== $bundle_new) { |
1611 |
$extra_weights = variable_get('field_extra_weights', array()); |
1612 |
if (isset($info[$entity_type][$bundle_old])) { |
1613 |
$extra_weights[$entity_type][$bundle_new] = $extra_weights[$entity_type][$bundle_old]; |
1614 |
unset($extra_weights[$entity_type][$bundle_old]); |
1615 |
variable_set('field_extra_weights', $extra_weights); |
1616 |
} |
1617 |
} |
1618 |
} |
1619 |
|
1620 |
/**
|
1621 |
* Act on field_attach_delete_bundle.
|
1622 |
*
|
1623 |
* This hook is invoked after the field module has performed the operation.
|
1624 |
*
|
1625 |
* @param $entity_type
|
1626 |
* The type of entity; for example, 'node' or 'user'.
|
1627 |
* @param $bundle
|
1628 |
* The name of the bundle that was just deleted.
|
1629 |
* @param $instances
|
1630 |
* An array of all instances that existed for the bundle before it was
|
1631 |
* deleted.
|
1632 |
*/
|
1633 |
function hook_field_attach_delete_bundle($entity_type, $bundle, $instances) { |
1634 |
// Remove the extra weights variable information for this bundle.
|
1635 |
$extra_weights = variable_get('field_extra_weights', array()); |
1636 |
if (isset($extra_weights[$entity_type][$bundle])) { |
1637 |
unset($extra_weights[$entity_type][$bundle]); |
1638 |
variable_set('field_extra_weights', $extra_weights); |
1639 |
} |
1640 |
} |
1641 |
|
1642 |
/**
|
1643 |
* @} End of "addtogroup field_attach".
|
1644 |
*/
|
1645 |
|
1646 |
/**
|
1647 |
* @addtogroup field_storage
|
1648 |
* @{
|
1649 |
*/
|
1650 |
|
1651 |
/**
|
1652 |
* Expose Field API storage backends.
|
1653 |
*
|
1654 |
* @return
|
1655 |
* An array describing the storage backends implemented by the module.
|
1656 |
* The keys are storage backend names. To avoid name clashes, storage backend
|
1657 |
* names should be prefixed with the name of the module that exposes them.
|
1658 |
* The values are arrays describing the storage backend, with the following
|
1659 |
* key/value pairs:
|
1660 |
* - label: The human-readable name of the storage backend.
|
1661 |
* - description: A short description for the storage backend.
|
1662 |
* - settings: An array whose keys are the names of the settings available
|
1663 |
* for the storage backend, and whose values are the default values for
|
1664 |
* those settings.
|
1665 |
*/
|
1666 |
function hook_field_storage_info() { |
1667 |
return array( |
1668 |
'field_sql_storage' => array( |
1669 |
'label' => t('Default SQL storage'), |
1670 |
'description' => t('Stores fields in the local SQL database, using per-field tables.'), |
1671 |
'settings' => array(), |
1672 |
), |
1673 |
); |
1674 |
} |
1675 |
|
1676 |
/**
|
1677 |
* Perform alterations on Field API storage types.
|
1678 |
*
|
1679 |
* @param $info
|
1680 |
* Array of informations on storage types exposed by
|
1681 |
* hook_field_field_storage_info() implementations.
|
1682 |
*/
|
1683 |
function hook_field_storage_info_alter(&$info) { |
1684 |
// Add a setting to a storage type.
|
1685 |
$info['field_sql_storage']['settings'] += array( |
1686 |
'mymodule_additional_setting' => 'default value', |
1687 |
); |
1688 |
} |
1689 |
|
1690 |
/**
|
1691 |
* Reveal the internal details about the storage for a field.
|
1692 |
*
|
1693 |
* For example, an SQL storage module might return the Schema API structure for
|
1694 |
* the table. A key/value storage module might return the server name,
|
1695 |
* authentication credentials, and bin name.
|
1696 |
*
|
1697 |
* Field storage modules are not obligated to implement this hook. Modules
|
1698 |
* that rely on these details must only use them for read operations.
|
1699 |
*
|
1700 |
* @param $field
|
1701 |
* A field structure.
|
1702 |
*
|
1703 |
* @return
|
1704 |
* An array of details.
|
1705 |
* - The first dimension is a store type (sql, solr, etc).
|
1706 |
* - The second dimension indicates the age of the values in the store
|
1707 |
* FIELD_LOAD_CURRENT or FIELD_LOAD_REVISION.
|
1708 |
* - Other dimensions are specific to the field storage module.
|
1709 |
*
|
1710 |
* @see hook_field_storage_details_alter()
|
1711 |
*/
|
1712 |
function hook_field_storage_details($field) { |
1713 |
$details = array(); |
1714 |
|
1715 |
// Add field columns.
|
1716 |
foreach ((array) $field['columns'] as $column_name => $attributes) { |
1717 |
$real_name = _field_sql_storage_columnname($field['field_name'], $column_name); |
1718 |
$columns[$column_name] = $real_name; |
1719 |
} |
1720 |
return array( |
1721 |
'sql' => array( |
1722 |
FIELD_LOAD_CURRENT => array( |
1723 |
_field_sql_storage_tablename($field) => $columns, |
1724 |
), |
1725 |
FIELD_LOAD_REVISION => array( |
1726 |
_field_sql_storage_revision_tablename($field) => $columns, |
1727 |
), |
1728 |
), |
1729 |
); |
1730 |
} |
1731 |
|
1732 |
/**
|
1733 |
* Perform alterations on Field API storage details.
|
1734 |
*
|
1735 |
* @param $details
|
1736 |
* An array of storage details for fields as exposed by
|
1737 |
* hook_field_storage_details() implementations.
|
1738 |
* @param $field
|
1739 |
* A field structure.
|
1740 |
*
|
1741 |
* @see hook_field_storage_details()
|
1742 |
*/
|
1743 |
function hook_field_storage_details_alter(&$details, $field) { |
1744 |
if ($field['field_name'] == 'field_of_interest') { |
1745 |
$columns = array(); |
1746 |
foreach ((array) $field['columns'] as $column_name => $attributes) { |
1747 |
$columns[$column_name] = $column_name; |
1748 |
} |
1749 |
$details['drupal_variables'] = array( |
1750 |
FIELD_LOAD_CURRENT => array( |
1751 |
'moon' => $columns, |
1752 |
), |
1753 |
FIELD_LOAD_REVISION => array( |
1754 |
'mars' => $columns, |
1755 |
), |
1756 |
); |
1757 |
} |
1758 |
} |
1759 |
|
1760 |
/**
|
1761 |
* Load field data for a set of entities.
|
1762 |
*
|
1763 |
* This hook is invoked from field_attach_load() to ask the field storage
|
1764 |
* module to load field data.
|
1765 |
*
|
1766 |
* Modules implementing this hook should load field values and add them to
|
1767 |
* objects in $entities. Fields with no values should be added as empty
|
1768 |
* arrays.
|
1769 |
*
|
1770 |
* @param $entity_type
|
1771 |
* The type of entity, such as 'node' or 'user'.
|
1772 |
* @param $entities
|
1773 |
* The array of entity objects to add fields to, keyed by entity ID.
|
1774 |
* @param $age
|
1775 |
* FIELD_LOAD_CURRENT to load the most recent revision for all fields, or
|
1776 |
* FIELD_LOAD_REVISION to load the version indicated by each entity.
|
1777 |
* @param $fields
|
1778 |
* An array listing the fields to be loaded. The keys of the array are field
|
1779 |
* IDs, and the values of the array are the entity IDs (or revision IDs,
|
1780 |
* depending on the $age parameter) to add each field to.
|
1781 |
* @param $options
|
1782 |
* An associative array of additional options, with the following keys:
|
1783 |
* - deleted: If TRUE, deleted fields should be loaded as well as
|
1784 |
* non-deleted fields. If unset or FALSE, only non-deleted fields should be
|
1785 |
* loaded.
|
1786 |
*/
|
1787 |
function hook_field_storage_load($entity_type, $entities, $age, $fields, $options) { |
1788 |
$load_current = $age == FIELD_LOAD_CURRENT; |
1789 |
|
1790 |
foreach ($fields as $field_id => $ids) { |
1791 |
// By the time this hook runs, the relevant field definitions have been
|
1792 |
// populated and cached in FieldInfo, so calling field_info_field_by_id()
|
1793 |
// on each field individually is more efficient than loading all fields in
|
1794 |
// memory upfront with field_info_field_by_ids().
|
1795 |
$field = field_info_field_by_id($field_id); |
1796 |
$field_name = $field['field_name']; |
1797 |
$table = $load_current ? _field_sql_storage_tablename($field) : _field_sql_storage_revision_tablename($field); |
1798 |
|
1799 |
$query = db_select($table, 't') |
1800 |
->fields('t')
|
1801 |
->condition('entity_type', $entity_type) |
1802 |
->condition($load_current ? 'entity_id' : 'revision_id', $ids, 'IN') |
1803 |
->condition('language', field_available_languages($entity_type, $field), 'IN') |
1804 |
->orderBy('delta');
|
1805 |
|
1806 |
if (empty($options['deleted'])) { |
1807 |
$query->condition('deleted', 0); |
1808 |
} |
1809 |
|
1810 |
$results = $query->execute(); |
1811 |
|
1812 |
$delta_count = array(); |
1813 |
foreach ($results as $row) { |
1814 |
if (!isset($delta_count[$row->entity_id][$row->language])) { |
1815 |
$delta_count[$row->entity_id][$row->language] = 0; |
1816 |
} |
1817 |
|
1818 |
if ($field['cardinality'] == FIELD_CARDINALITY_UNLIMITED || $delta_count[$row->entity_id][$row->language] < $field['cardinality']) { |
1819 |
$item = array(); |
1820 |
// For each column declared by the field, populate the item
|
1821 |
// from the prefixed database column.
|
1822 |
foreach ($field['columns'] as $column => $attributes) { |
1823 |
$column_name = _field_sql_storage_columnname($field_name, $column); |
1824 |
$item[$column] = $row->$column_name; |
1825 |
} |
1826 |
|
1827 |
// Add the item to the field values for the entity.
|
1828 |
$entities[$row->entity_id]->{$field_name}[$row->language][] = $item; |
1829 |
$delta_count[$row->entity_id][$row->language]++; |
1830 |
} |
1831 |
} |
1832 |
} |
1833 |
} |
1834 |
|
1835 |
/**
|
1836 |
* Write field data for an entity.
|
1837 |
*
|
1838 |
* This hook is invoked from field_attach_insert() and field_attach_update(),
|
1839 |
* to ask the field storage module to save field data.
|
1840 |
*
|
1841 |
* @param $entity_type
|
1842 |
* The entity type of entity, such as 'node' or 'user'.
|
1843 |
* @param $entity
|
1844 |
* The entity on which to operate.
|
1845 |
* @param $op
|
1846 |
* FIELD_STORAGE_UPDATE when updating an existing entity,
|
1847 |
* FIELD_STORAGE_INSERT when inserting a new entity.
|
1848 |
* @param $fields
|
1849 |
* An array listing the fields to be written. The keys and values of the
|
1850 |
* array are field IDs.
|
1851 |
*/
|
1852 |
function hook_field_storage_write($entity_type, $entity, $op, $fields) { |
1853 |
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
1854 |
if (!isset($vid)) { |
1855 |
$vid = $id; |
1856 |
} |
1857 |
|
1858 |
foreach ($fields as $field_id) { |
1859 |
$field = field_info_field_by_id($field_id); |
1860 |
$field_name = $field['field_name']; |
1861 |
$table_name = _field_sql_storage_tablename($field); |
1862 |
$revision_name = _field_sql_storage_revision_tablename($field); |
1863 |
|
1864 |
$all_languages = field_available_languages($entity_type, $field); |
1865 |
$field_languages = array_intersect($all_languages, array_keys((array) $entity->$field_name)); |
1866 |
|
1867 |
// Delete and insert, rather than update, in case a value was added.
|
1868 |
if ($op == FIELD_STORAGE_UPDATE) { |
1869 |
// Delete languages present in the incoming $entity->$field_name.
|
1870 |
// Delete all languages if $entity->$field_name is empty.
|
1871 |
$languages = !empty($entity->$field_name) ? $field_languages : $all_languages; |
1872 |
if ($languages) { |
1873 |
db_delete($table_name)
|
1874 |
->condition('entity_type', $entity_type) |
1875 |
->condition('entity_id', $id) |
1876 |
->condition('language', $languages, 'IN') |
1877 |
->execute(); |
1878 |
db_delete($revision_name)
|
1879 |
->condition('entity_type', $entity_type) |
1880 |
->condition('entity_id', $id) |
1881 |
->condition('revision_id', $vid) |
1882 |
->condition('language', $languages, 'IN') |
1883 |
->execute(); |
1884 |
} |
1885 |
} |
1886 |
|
1887 |
// Prepare the multi-insert query.
|
1888 |
$do_insert = FALSE; |
1889 |
$columns = array('entity_type', 'entity_id', 'revision_id', 'bundle', 'delta', 'language'); |
1890 |
foreach ($field['columns'] as $column => $attributes) { |
1891 |
$columns[] = _field_sql_storage_columnname($field_name, $column); |
1892 |
} |
1893 |
$query = db_insert($table_name)->fields($columns); |
1894 |
$revision_query = db_insert($revision_name)->fields($columns); |
1895 |
|
1896 |
foreach ($field_languages as $langcode) { |
1897 |
$items = (array) $entity->{$field_name}[$langcode]; |
1898 |
$delta_count = 0; |
1899 |
foreach ($items as $delta => $item) { |
1900 |
// We now know we have someting to insert.
|
1901 |
$do_insert = TRUE; |
1902 |
$record = array( |
1903 |
'entity_type' => $entity_type, |
1904 |
'entity_id' => $id, |
1905 |
'revision_id' => $vid, |
1906 |
'bundle' => $bundle, |
1907 |
'delta' => $delta, |
1908 |
'language' => $langcode, |
1909 |
); |
1910 |
foreach ($field['columns'] as $column => $attributes) { |
1911 |
$record[_field_sql_storage_columnname($field_name, $column)] = isset($item[$column]) ? $item[$column] : NULL; |
1912 |
} |
1913 |
$query->values($record); |
1914 |
if (isset($vid)) { |
1915 |
$revision_query->values($record); |
1916 |
} |
1917 |
|
1918 |
if ($field['cardinality'] != FIELD_CARDINALITY_UNLIMITED && ++$delta_count == $field['cardinality']) { |
1919 |
break;
|
1920 |
} |
1921 |
} |
1922 |
} |
1923 |
|
1924 |
// Execute the query if we have values to insert.
|
1925 |
if ($do_insert) { |
1926 |
$query->execute();
|
1927 |
$revision_query->execute();
|
1928 |
} |
1929 |
} |
1930 |
} |
1931 |
|
1932 |
/**
|
1933 |
* Delete all field data for an entity.
|
1934 |
*
|
1935 |
* This hook is invoked from field_attach_delete() to ask the field storage
|
1936 |
* module to delete field data.
|
1937 |
*
|
1938 |
* @param $entity_type
|
1939 |
* The entity type of entity, such as 'node' or 'user'.
|
1940 |
* @param $entity
|
1941 |
* The entity on which to operate.
|
1942 |
* @param $fields
|
1943 |
* An array listing the fields to delete. The keys and values of the
|
1944 |
* array are field IDs.
|
1945 |
*/
|
1946 |
function hook_field_storage_delete($entity_type, $entity, $fields) { |
1947 |
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
1948 |
|
1949 |
foreach (field_info_instances($entity_type, $bundle) as $instance) { |
1950 |
if (isset($fields[$instance['field_id']])) { |
1951 |
$field = field_info_field_by_id($instance['field_id']); |
1952 |
field_sql_storage_field_storage_purge($entity_type, $entity, $field, $instance); |
1953 |
} |
1954 |
} |
1955 |
} |
1956 |
|
1957 |
/**
|
1958 |
* Delete a single revision of field data for an entity.
|
1959 |
*
|
1960 |
* This hook is invoked from field_attach_delete_revision() to ask the field
|
1961 |
* storage module to delete field revision data.
|
1962 |
*
|
1963 |
* Deleting the current (most recently written) revision is not
|
1964 |
* allowed as has undefined results.
|
1965 |
*
|
1966 |
* @param $entity_type
|
1967 |
* The entity type of entity, such as 'node' or 'user'.
|
1968 |
* @param $entity
|
1969 |
* The entity on which to operate. The revision to delete is
|
1970 |
* indicated by the entity's revision ID property, as identified by
|
1971 |
* hook_fieldable_info() for $entity_type.
|
1972 |
* @param $fields
|
1973 |
* An array listing the fields to delete. The keys and values of the
|
1974 |
* array are field IDs.
|
1975 |
*/
|
1976 |
function hook_field_storage_delete_revision($entity_type, $entity, $fields) { |
1977 |
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
1978 |
|
1979 |
if (isset($vid)) { |
1980 |
foreach ($fields as $field_id) { |
1981 |
$field = field_info_field_by_id($field_id); |
1982 |
$revision_name = _field_sql_storage_revision_tablename($field); |
1983 |
db_delete($revision_name)
|
1984 |
->condition('entity_type', $entity_type) |
1985 |
->condition('entity_id', $id) |
1986 |
->condition('revision_id', $vid) |
1987 |
->execute(); |
1988 |
} |
1989 |
} |
1990 |
} |
1991 |
|
1992 |
/**
|
1993 |
* Execute an EntityFieldQuery.
|
1994 |
*
|
1995 |
* This hook is called to find the entities having certain entity and field
|
1996 |
* conditions and sort them in the given field order. If the field storage
|
1997 |
* engine also handles property sorts and orders, it should unset those
|
1998 |
* properties in the called object to signal that those have been handled.
|
1999 |
*
|
2000 |
* @param EntityFieldQuery $query
|
2001 |
* An EntityFieldQuery.
|
2002 |
*
|
2003 |
* @return
|
2004 |
* See EntityFieldQuery::execute() for the return values.
|
2005 |
*/
|
2006 |
function hook_field_storage_query($query) { |
2007 |
$groups = array(); |
2008 |
if ($query->age == FIELD_LOAD_CURRENT) { |
2009 |
$tablename_function = '_field_sql_storage_tablename'; |
2010 |
$id_key = 'entity_id'; |
2011 |
} |
2012 |
else {
|
2013 |
$tablename_function = '_field_sql_storage_revision_tablename'; |
2014 |
$id_key = 'revision_id'; |
2015 |
} |
2016 |
$table_aliases = array(); |
2017 |
// Add tables for the fields used.
|
2018 |
foreach ($query->fields as $key => $field) { |
2019 |
$tablename = $tablename_function($field); |
2020 |
// Every field needs a new table.
|
2021 |
$table_alias = $tablename . $key; |
2022 |
$table_aliases[$key] = $table_alias; |
2023 |
if ($key) { |
2024 |
$select_query->join($tablename, $table_alias, "$table_alias.entity_type = $field_base_table.entity_type AND $table_alias.$id_key = $field_base_table.$id_key"); |
2025 |
} |
2026 |
else {
|
2027 |
$select_query = db_select($tablename, $table_alias); |
2028 |
$select_query->addTag('entity_field_access'); |
2029 |
$select_query->addMetaData('base_table', $tablename); |
2030 |
$select_query->fields($table_alias, array('entity_type', 'entity_id', 'revision_id', 'bundle')); |
2031 |
$field_base_table = $table_alias; |
2032 |
} |
2033 |
if ($field['cardinality'] != 1) { |
2034 |
$select_query->distinct();
|
2035 |
} |
2036 |
} |
2037 |
|
2038 |
// Add field conditions.
|
2039 |
foreach ($query->fieldConditions as $key => $condition) { |
2040 |
$table_alias = $table_aliases[$key]; |
2041 |
$field = $condition['field']; |
2042 |
// Add the specified condition.
|
2043 |
$sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $condition['column']); |
2044 |
$query->addCondition($select_query, $sql_field, $condition); |
2045 |
// Add delta / language group conditions.
|
2046 |
foreach (array('delta', 'language') as $column) { |
2047 |
if (isset($condition[$column . '_group'])) { |
2048 |
$group_name = $condition[$column . '_group']; |
2049 |
if (!isset($groups[$column][$group_name])) { |
2050 |
$groups[$column][$group_name] = $table_alias; |
2051 |
} |
2052 |
else {
|
2053 |
$select_query->where("$table_alias.$column = " . $groups[$column][$group_name] . ".$column"); |
2054 |
} |
2055 |
} |
2056 |
} |
2057 |
} |
2058 |
|
2059 |
if (isset($query->deleted)) { |
2060 |
$select_query->condition("$field_base_table.deleted", (int) $query->deleted); |
2061 |
} |
2062 |
|
2063 |
// Is there a need to sort the query by property?
|
2064 |
$has_property_order = FALSE; |
2065 |
foreach ($query->order as $order) { |
2066 |
if ($order['type'] == 'property') { |
2067 |
$has_property_order = TRUE; |
2068 |
} |
2069 |
} |
2070 |
|
2071 |
if ($query->propertyConditions || $has_property_order) { |
2072 |
if (empty($query->entityConditions['entity_type']['value'])) { |
2073 |
throw new EntityFieldQueryException('Property conditions and orders must have an entity type defined.'); |
2074 |
} |
2075 |
$entity_type = $query->entityConditions['entity_type']['value']; |
2076 |
$entity_base_table = _field_sql_storage_query_join_entity($select_query, $entity_type, $field_base_table); |
2077 |
$query->entityConditions['entity_type']['operator'] = '='; |
2078 |
foreach ($query->propertyConditions as $property_condition) { |
2079 |
$query->addCondition($select_query, "$entity_base_table." . $property_condition['column'], $property_condition); |
2080 |
} |
2081 |
} |
2082 |
foreach ($query->entityConditions as $key => $condition) { |
2083 |
$query->addCondition($select_query, "$field_base_table.$key", $condition); |
2084 |
} |
2085 |
|
2086 |
// Order the query.
|
2087 |
foreach ($query->order as $order) { |
2088 |
if ($order['type'] == 'entity') { |
2089 |
$key = $order['specifier']; |
2090 |
$select_query->orderBy("$field_base_table.$key", $order['direction']); |
2091 |
} |
2092 |
elseif ($order['type'] == 'field') { |
2093 |
$specifier = $order['specifier']; |
2094 |
$field = $specifier['field']; |
2095 |
$table_alias = $table_aliases[$specifier['index']]; |
2096 |
$sql_field = "$table_alias." . _field_sql_storage_columnname($field['field_name'], $specifier['column']); |
2097 |
$select_query->orderBy($sql_field, $order['direction']); |
2098 |
} |
2099 |
elseif ($order['type'] == 'property') { |
2100 |
$select_query->orderBy("$entity_base_table." . $order['specifier'], $order['direction']); |
2101 |
} |
2102 |
} |
2103 |
|
2104 |
return $query->finishQuery($select_query, $id_key); |
2105 |
} |
2106 |
|
2107 |
/**
|
2108 |
* Act on creation of a new field.
|
2109 |
*
|
2110 |
* This hook is invoked from field_create_field() to ask the field storage
|
2111 |
* module to save field information and prepare for storing field instances.
|
2112 |
* If there is a problem, the field storage module should throw an exception.
|
2113 |
*
|
2114 |
* @param $field
|
2115 |
* The field structure being created.
|
2116 |
*/
|
2117 |
function hook_field_storage_create_field($field) { |
2118 |
$schema = _field_sql_storage_schema($field); |
2119 |
foreach ($schema as $name => $table) { |
2120 |
db_create_table($name, $table); |
2121 |
} |
2122 |
drupal_get_schema(NULL, TRUE); |
2123 |
} |
2124 |
|
2125 |
/**
|
2126 |
* Act on deletion of a field.
|
2127 |
*
|
2128 |
* This hook is invoked from field_delete_field() to ask the field storage
|
2129 |
* module to mark all information stored in the field for deletion.
|
2130 |
*
|
2131 |
* @param $field
|
2132 |
* The field being deleted.
|
2133 |
*/
|
2134 |
function hook_field_storage_delete_field($field) { |
2135 |
// Mark all data associated with the field for deletion.
|
2136 |
$field['deleted'] = 0; |
2137 |
$table = _field_sql_storage_tablename($field); |
2138 |
$revision_table = _field_sql_storage_revision_tablename($field); |
2139 |
db_update($table)
|
2140 |
->fields(array('deleted' => 1)) |
2141 |
->execute(); |
2142 |
|
2143 |
// Move the table to a unique name while the table contents are being deleted.
|
2144 |
$field['deleted'] = 1; |
2145 |
$new_table = _field_sql_storage_tablename($field); |
2146 |
$revision_new_table = _field_sql_storage_revision_tablename($field); |
2147 |
db_rename_table($table, $new_table); |
2148 |
db_rename_table($revision_table, $revision_new_table); |
2149 |
drupal_get_schema(NULL, TRUE); |
2150 |
} |
2151 |
|
2152 |
/**
|
2153 |
* Act on deletion of a field instance.
|
2154 |
*
|
2155 |
* This hook is invoked from field_delete_instance() to ask the field storage
|
2156 |
* module to mark all information stored for the field instance for deletion.
|
2157 |
*
|
2158 |
* @param $instance
|
2159 |
* The instance being deleted.
|
2160 |
*/
|
2161 |
function hook_field_storage_delete_instance($instance) { |
2162 |
$field = field_info_field($instance['field_name']); |
2163 |
$table_name = _field_sql_storage_tablename($field); |
2164 |
$revision_name = _field_sql_storage_revision_tablename($field); |
2165 |
db_update($table_name)
|
2166 |
->fields(array('deleted' => 1)) |
2167 |
->condition('entity_type', $instance['entity_type']) |
2168 |
->condition('bundle', $instance['bundle']) |
2169 |
->execute(); |
2170 |
db_update($revision_name)
|
2171 |
->fields(array('deleted' => 1)) |
2172 |
->condition('entity_type', $instance['entity_type']) |
2173 |
->condition('bundle', $instance['bundle']) |
2174 |
->execute(); |
2175 |
} |
2176 |
|
2177 |
/**
|
2178 |
* Act before the storage backends load field data.
|
2179 |
*
|
2180 |
* This hook allows modules to load data before the Field Storage API,
|
2181 |
* optionally preventing the field storage module from doing so.
|
2182 |
*
|
2183 |
* This lets 3rd party modules override, mirror, shard, or otherwise store a
|
2184 |
* subset of fields in a different way than the current storage engine.
|
2185 |
* Possible use cases include per-bundle storage, per-combo-field storage, etc.
|
2186 |
*
|
2187 |
* Modules implementing this hook should load field values and add them to
|
2188 |
* objects in $entities. Fields with no values should be added as empty
|
2189 |
* arrays. In addition, fields loaded should be added as keys to $skip_fields.
|
2190 |
*
|
2191 |
* @param $entity_type
|
2192 |
* The type of entity, such as 'node' or 'user'.
|
2193 |
* @param $entities
|
2194 |
* The array of entity objects to add fields to, keyed by entity ID.
|
2195 |
* @param $age
|
2196 |
* FIELD_LOAD_CURRENT to load the most recent revision for all fields, or
|
2197 |
* FIELD_LOAD_REVISION to load the version indicated by each entity.
|
2198 |
* @param $skip_fields
|
2199 |
* An array keyed by field IDs whose data has already been loaded and
|
2200 |
* therefore should not be loaded again. Add a key to this array to indicate
|
2201 |
* that your module has already loaded a field.
|
2202 |
* @param $options
|
2203 |
* An associative array of additional options, with the following keys:
|
2204 |
* - field_id: The field ID that should be loaded. If unset, all fields
|
2205 |
* should be loaded.
|
2206 |
* - deleted: If TRUE, deleted fields should be loaded as well as
|
2207 |
* non-deleted fields. If unset or FALSE, only non-deleted fields should be
|
2208 |
* loaded.
|
2209 |
*/
|
2210 |
function hook_field_storage_pre_load($entity_type, $entities, $age, &$skip_fields, $options) { |
2211 |
// @todo Needs function body.
|
2212 |
} |
2213 |
|
2214 |
/**
|
2215 |
* Act before the storage backends insert field data.
|
2216 |
*
|
2217 |
* This hook allows modules to store data before the Field Storage API,
|
2218 |
* optionally preventing the field storage module from doing so.
|
2219 |
*
|
2220 |
* @param $entity_type
|
2221 |
* The type of $entity; for example, 'node' or 'user'.
|
2222 |
* @param $entity
|
2223 |
* The entity with fields to save.
|
2224 |
* @param $skip_fields
|
2225 |
* An array keyed by field IDs whose data has already been written and
|
2226 |
* therefore should not be written again. The values associated with these
|
2227 |
* keys are not specified.
|
2228 |
* @return
|
2229 |
* Saved field IDs are set set as keys in $skip_fields.
|
2230 |
*/
|
2231 |
function hook_field_storage_pre_insert($entity_type, $entity, &$skip_fields) { |
2232 |
if ($entity_type == 'node' && $entity->status && _forum_node_check_node_type($entity)) { |
2233 |
$query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp')); |
2234 |
foreach ($entity->taxonomy_forums as $language) { |
2235 |
foreach ($language as $delta) { |
2236 |
$query->values(array( |
2237 |
'nid' => $entity->nid, |
2238 |
'title' => $entity->title, |
2239 |
'tid' => $delta['value'], |
2240 |
'sticky' => $entity->sticky, |
2241 |
'created' => $entity->created, |
2242 |
'comment_count' => 0, |
2243 |
'last_comment_timestamp' => $entity->created, |
2244 |
)); |
2245 |
} |
2246 |
} |
2247 |
$query->execute();
|
2248 |
} |
2249 |
} |
2250 |
|
2251 |
/**
|
2252 |
* Act before the storage backends update field data.
|
2253 |
*
|
2254 |
* This hook allows modules to store data before the Field Storage API,
|
2255 |
* optionally preventing the field storage module from doing so.
|
2256 |
*
|
2257 |
* @param $entity_type
|
2258 |
* The type of $entity; for example, 'node' or 'user'.
|
2259 |
* @param $entity
|
2260 |
* The entity with fields to save.
|
2261 |
* @param $skip_fields
|
2262 |
* An array keyed by field IDs whose data has already been written and
|
2263 |
* therefore should not be written again. The values associated with these
|
2264 |
* keys are not specified.
|
2265 |
* @return
|
2266 |
* Saved field IDs are set set as keys in $skip_fields.
|
2267 |
*/
|
2268 |
function hook_field_storage_pre_update($entity_type, $entity, &$skip_fields) { |
2269 |
$first_call = &drupal_static(__FUNCTION__, array()); |
2270 |
|
2271 |
if ($entity_type == 'node' && $entity->status && _forum_node_check_node_type($entity)) { |
2272 |
// We don't maintain data for old revisions, so clear all previous values
|
2273 |
// from the table. Since this hook runs once per field, per entity, make
|
2274 |
// sure we only wipe values once.
|
2275 |
if (!isset($first_call[$entity->nid])) { |
2276 |
$first_call[$entity->nid] = FALSE; |
2277 |
db_delete('forum_index')->condition('nid', $entity->nid)->execute(); |
2278 |
} |
2279 |
// Only save data to the table if the node is published.
|
2280 |
if ($entity->status) { |
2281 |
$query = db_insert('forum_index')->fields(array('nid', 'title', 'tid', 'sticky', 'created', 'comment_count', 'last_comment_timestamp')); |
2282 |
foreach ($entity->taxonomy_forums as $language) { |
2283 |
foreach ($language as $delta) { |
2284 |
$query->values(array( |
2285 |
'nid' => $entity->nid, |
2286 |
'title' => $entity->title, |
2287 |
'tid' => $delta['value'], |
2288 |
'sticky' => $entity->sticky, |
2289 |
'created' => $entity->created, |
2290 |
'comment_count' => 0, |
2291 |
'last_comment_timestamp' => $entity->created, |
2292 |
)); |
2293 |
} |
2294 |
} |
2295 |
$query->execute();
|
2296 |
// The logic for determining last_comment_count is fairly complex, so
|
2297 |
// call _forum_update_forum_index() too.
|
2298 |
_forum_update_forum_index($entity->nid);
|
2299 |
} |
2300 |
} |
2301 |
} |
2302 |
|
2303 |
/**
|
2304 |
* @} End of "addtogroup field_storage
|
2305 |
*/
|
2306 |
|
2307 |
/**
|
2308 |
* Returns the maximum weight for the entity components handled by the module.
|
2309 |
*
|
2310 |
* Field API takes care of fields and 'extra_fields'. This hook is intended for
|
2311 |
* third-party modules adding other entity components (e.g. field_group).
|
2312 |
*
|
2313 |
* @param $entity_type
|
2314 |
* The type of entity; e.g. 'node' or 'user'.
|
2315 |
* @param $bundle
|
2316 |
* The bundle name.
|
2317 |
* @param $context
|
2318 |
* The context for which the maximum weight is requested. Either 'form', or
|
2319 |
* the name of a view mode.
|
2320 |
*
|
2321 |
* @return
|
2322 |
* The maximum weight of the entity's components, or NULL if no components
|
2323 |
* were found.
|
2324 |
*
|
2325 |
* @ingroup field_info
|
2326 |
*/
|
2327 |
function hook_field_info_max_weight($entity_type, $bundle, $context) { |
2328 |
$weights = array(); |
2329 |
|
2330 |
foreach (my_module_entity_additions($entity_type, $bundle, $context) as $addition) { |
2331 |
$weights[] = $addition['weight']; |
2332 |
} |
2333 |
|
2334 |
return $weights ? max($weights) : NULL; |
2335 |
} |
2336 |
|
2337 |
/**
|
2338 |
* @addtogroup field_types
|
2339 |
* @{
|
2340 |
*/
|
2341 |
|
2342 |
/**
|
2343 |
* Alters the display settings of a field before it gets displayed.
|
2344 |
*
|
2345 |
* Note that instead of hook_field_display_alter(), which is called for all
|
2346 |
* fields on all entity types, hook_field_display_ENTITY_TYPE_alter() may be
|
2347 |
* used to alter display settings for fields on a specific entity type only.
|
2348 |
*
|
2349 |
* This hook is called once per field per displayed entity. If the result of the
|
2350 |
* hook involves reading from the database, it is highly recommended to
|
2351 |
* statically cache the information.
|
2352 |
*
|
2353 |
* @param $display
|
2354 |
* The display settings that will be used to display the field values, as
|
2355 |
* found in the 'display' key of $instance definitions.
|
2356 |
* @param $context
|
2357 |
* An associative array containing:
|
2358 |
* - entity_type: The entity type; e.g., 'node' or 'user'.
|
2359 |
* - field: The field being rendered.
|
2360 |
* - instance: The instance being rendered.
|
2361 |
* - entity: The entity being rendered.
|
2362 |
* - view_mode: The view mode, e.g. 'full', 'teaser'...
|
2363 |
*
|
2364 |
* @see hook_field_display_ENTITY_TYPE_alter()
|
2365 |
*/
|
2366 |
function hook_field_display_alter(&$display, $context) { |
2367 |
// Leave field labels out of the search index.
|
2368 |
// Note: The check against $context['entity_type'] == 'node' could be avoided
|
2369 |
// by using hook_field_display_node_alter() instead of
|
2370 |
// hook_field_display_alter(), resulting in less function calls when
|
2371 |
// rendering non-node entities.
|
2372 |
if ($context['entity_type'] == 'node' && $context['view_mode'] == 'search_index') { |
2373 |
$display['label'] = 'hidden'; |
2374 |
} |
2375 |
} |
2376 |
|
2377 |
/**
|
2378 |
* Alters the display settings of a field on a given entity type before it gets displayed.
|
2379 |
*
|
2380 |
* Modules can implement hook_field_display_ENTITY_TYPE_alter() to alter display
|
2381 |
* settings for fields on a specific entity type, rather than implementing
|
2382 |
* hook_field_display_alter().
|
2383 |
*
|
2384 |
* This hook is called once per field per displayed entity. If the result of the
|
2385 |
* hook involves reading from the database, it is highly recommended to
|
2386 |
* statically cache the information.
|
2387 |
*
|
2388 |
* @param $display
|
2389 |
* The display settings that will be used to display the field values, as
|
2390 |
* found in the 'display' key of $instance definitions.
|
2391 |
* @param $context
|
2392 |
* An associative array containing:
|
2393 |
* - entity_type: The entity type; e.g., 'node' or 'user'.
|
2394 |
* - field: The field being rendered.
|
2395 |
* - instance: The instance being rendered.
|
2396 |
* - entity: The entity being rendered.
|
2397 |
* - view_mode: The view mode, e.g. 'full', 'teaser'...
|
2398 |
*
|
2399 |
* @see hook_field_display_alter()
|
2400 |
*/
|
2401 |
function hook_field_display_ENTITY_TYPE_alter(&$display, $context) { |
2402 |
// Leave field labels out of the search index.
|
2403 |
if ($context['view_mode'] == 'search_index') { |
2404 |
$display['label'] = 'hidden'; |
2405 |
} |
2406 |
} |
2407 |
|
2408 |
/**
|
2409 |
* @} End of "addtogroup field_types
|
2410 |
*/
|
2411 |
|
2412 |
/**
|
2413 |
* Alters the display settings of pseudo-fields before an entity is displayed.
|
2414 |
*
|
2415 |
* This hook is called once per displayed entity. If the result of the hook
|
2416 |
* involves reading from the database, it is highly recommended to statically
|
2417 |
* cache the information.
|
2418 |
*
|
2419 |
* @param $displays
|
2420 |
* An array of display settings for the pseudo-fields in the entity, keyed
|
2421 |
* by pseudo-field names.
|
2422 |
* @param $context
|
2423 |
* An associative array containing:
|
2424 |
* - entity_type: The entity type; e.g., 'node' or 'user'.
|
2425 |
* - bundle: The bundle name.
|
2426 |
* - view_mode: The view mode, e.g. 'full', 'teaser'...
|
2427 |
*
|
2428 |
* @ingroup field_types
|
2429 |
*/
|
2430 |
function hook_field_extra_fields_display_alter(&$displays, $context) { |
2431 |
if ($context['entity_type'] == 'taxonomy_term' && $context['view_mode'] == 'full') { |
2432 |
$displays['description']['visible'] = FALSE; |
2433 |
} |
2434 |
} |
2435 |
|
2436 |
/**
|
2437 |
* Alters the widget properties of a field instance on a given entity type
|
2438 |
* before it gets displayed.
|
2439 |
*
|
2440 |
* Modules can implement hook_field_widget_properties_ENTITY_TYPE_alter() to
|
2441 |
* alter the widget properties for fields on a specific entity type, rather than
|
2442 |
* implementing hook_field_widget_properties_alter().
|
2443 |
*
|
2444 |
* This hook is called once per field per displayed widget entity. If the result
|
2445 |
* of the hook involves reading from the database, it is highly recommended to
|
2446 |
* statically cache the information.
|
2447 |
*
|
2448 |
* @param $widget
|
2449 |
* The instance's widget properties.
|
2450 |
* @param $context
|
2451 |
* An associative array containing:
|
2452 |
* - entity_type: The entity type; e.g., 'node' or 'user'.
|
2453 |
* - entity: The entity object.
|
2454 |
* - field: The field that the widget belongs to.
|
2455 |
* - instance: The instance of the field.
|
2456 |
*
|
2457 |
* @see hook_field_widget_properties_alter()
|
2458 |
*
|
2459 |
* @ingroup field_widget
|
2460 |
*/
|
2461 |
function hook_field_widget_properties_ENTITY_TYPE_alter(&$widget, $context) { |
2462 |
// Change a widget's type according to the time of day.
|
2463 |
$field = $context['field']; |
2464 |
if ($field['field_name'] == 'field_foo') { |
2465 |
$time = date('H'); |
2466 |
$widget['type'] = $time < 12 ? 'widget_am' : 'widget_pm'; |
2467 |
} |
2468 |
} |
2469 |
|
2470 |
/**
|
2471 |
* @addtogroup field_crud
|
2472 |
* @{
|
2473 |
*/
|
2474 |
|
2475 |
/**
|
2476 |
* Act on a field being created.
|
2477 |
*
|
2478 |
* This hook is invoked from field_create_field() after the field is created, to
|
2479 |
* allow modules to act on field creation.
|
2480 |
*
|
2481 |
* @param $field
|
2482 |
* The field just created.
|
2483 |
*/
|
2484 |
function hook_field_create_field($field) { |
2485 |
// @todo Needs function body.
|
2486 |
} |
2487 |
|
2488 |
/**
|
2489 |
* Act on a field instance being created.
|
2490 |
*
|
2491 |
* This hook is invoked from field_create_instance() after the instance record
|
2492 |
* is saved, so it cannot be used to modify the instance itself.
|
2493 |
*
|
2494 |
* @param $instance
|
2495 |
* The instance just created.
|
2496 |
*/
|
2497 |
function hook_field_create_instance($instance) { |
2498 |
// @todo Needs function body.
|
2499 |
} |
2500 |
|
2501 |
/**
|
2502 |
* Forbid a field update from occurring.
|
2503 |
*
|
2504 |
* Any module may forbid any update for any reason. For example, the
|
2505 |
* field's storage module might forbid an update if it would change
|
2506 |
* the storage schema while data for the field exists. A field type
|
2507 |
* module might forbid an update if it would change existing data's
|
2508 |
* semantics, or if there are external dependencies on field settings
|
2509 |
* that cannot be updated.
|
2510 |
*
|
2511 |
* To forbid the update from occurring, throw a FieldUpdateForbiddenException.
|
2512 |
*
|
2513 |
* @param $field
|
2514 |
* The field as it will be post-update.
|
2515 |
* @param $prior_field
|
2516 |
* The field as it is pre-update.
|
2517 |
* @param $has_data
|
2518 |
* Whether any data already exists for this field.
|
2519 |
*/
|
2520 |
function hook_field_update_forbid($field, $prior_field, $has_data) { |
2521 |
// A 'list' field stores integer keys mapped to display values. If
|
2522 |
// the new field will have fewer values, and any data exists for the
|
2523 |
// abandoned keys, the field will have no way to display them. So,
|
2524 |
// forbid such an update.
|
2525 |
if ($has_data && count($field['settings']['allowed_values']) < count($prior_field['settings']['allowed_values'])) { |
2526 |
// Identify the keys that will be lost.
|
2527 |
$lost_keys = array_diff(array_keys($field['settings']['allowed_values']), array_keys($prior_field['settings']['allowed_values'])); |
2528 |
// If any data exist for those keys, forbid the update.
|
2529 |
$query = new EntityFieldQuery(); |
2530 |
$found = $query |
2531 |
->fieldCondition($prior_field['field_name'], 'value', $lost_keys) |
2532 |
->range(0, 1) |
2533 |
->execute(); |
2534 |
if ($found) { |
2535 |
throw new FieldUpdateForbiddenException("Cannot update a list field not to include keys with existing data"); |
2536 |
} |
2537 |
} |
2538 |
} |
2539 |
|
2540 |
/**
|
2541 |
* Act on a field being updated.
|
2542 |
*
|
2543 |
* This hook is invoked just after field is updated in field_update_field().
|
2544 |
*
|
2545 |
* @param $field
|
2546 |
* The field as it is post-update.
|
2547 |
* @param $prior_field
|
2548 |
* The field as it was pre-update.
|
2549 |
* @param $has_data
|
2550 |
* Whether any data already exists for this field.
|
2551 |
*/
|
2552 |
function hook_field_update_field($field, $prior_field, $has_data) { |
2553 |
// Reset the static value that keeps track of allowed values for list fields.
|
2554 |
drupal_static_reset('list_allowed_values');
|
2555 |
} |
2556 |
|
2557 |
/**
|
2558 |
* Act on a field being deleted.
|
2559 |
*
|
2560 |
* This hook is invoked just after a field is deleted by field_delete_field().
|
2561 |
*
|
2562 |
* @param $field
|
2563 |
* The field just deleted.
|
2564 |
*/
|
2565 |
function hook_field_delete_field($field) { |
2566 |
// @todo Needs function body.
|
2567 |
} |
2568 |
|
2569 |
/**
|
2570 |
* Act on a field instance being updated.
|
2571 |
*
|
2572 |
* This hook is invoked from field_update_instance() after the instance record
|
2573 |
* is saved, so it cannot be used by a module to modify the instance itself.
|
2574 |
*
|
2575 |
* @param $instance
|
2576 |
* The instance as it is post-update.
|
2577 |
* @param $prior_instance
|
2578 |
* The instance as it was pre-update.
|
2579 |
*/
|
2580 |
function hook_field_update_instance($instance, $prior_instance) { |
2581 |
// @todo Needs function body.
|
2582 |
} |
2583 |
|
2584 |
/**
|
2585 |
* Act on a field instance being deleted.
|
2586 |
*
|
2587 |
* This hook is invoked from field_delete_instance() after the instance is
|
2588 |
* deleted.
|
2589 |
*
|
2590 |
* @param $instance
|
2591 |
* The instance just deleted.
|
2592 |
*/
|
2593 |
function hook_field_delete_instance($instance) { |
2594 |
// @todo Needs function body.
|
2595 |
} |
2596 |
|
2597 |
/**
|
2598 |
* Act on field records being read from the database.
|
2599 |
*
|
2600 |
* This hook is invoked from field_read_fields() on each field being read.
|
2601 |
*
|
2602 |
* @param $field
|
2603 |
* The field record just read from the database.
|
2604 |
*/
|
2605 |
function hook_field_read_field($field) { |
2606 |
// @todo Needs function body.
|
2607 |
} |
2608 |
|
2609 |
/**
|
2610 |
* Act on a field record being read from the database.
|
2611 |
*
|
2612 |
* This hook is invoked from field_read_instances() on each instance being read.
|
2613 |
*
|
2614 |
* @param $instance
|
2615 |
* The instance record just read from the database.
|
2616 |
*/
|
2617 |
function hook_field_read_instance($instance) { |
2618 |
// @todo Needs function body.
|
2619 |
} |
2620 |
|
2621 |
/**
|
2622 |
* Acts when a field record is being purged.
|
2623 |
*
|
2624 |
* In field_purge_field(), after the field configuration has been
|
2625 |
* removed from the database, the field storage module has had a chance to
|
2626 |
* run its hook_field_storage_purge_field(), and the field info cache
|
2627 |
* has been cleared, this hook is invoked on all modules to allow them to
|
2628 |
* respond to the field being purged.
|
2629 |
*
|
2630 |
* @param $field
|
2631 |
* The field being purged.
|
2632 |
*/
|
2633 |
function hook_field_purge_field($field) { |
2634 |
db_delete('my_module_field_info')
|
2635 |
->condition('id', $field['id']) |
2636 |
->execute(); |
2637 |
} |
2638 |
|
2639 |
/**
|
2640 |
* Acts when a field instance is being purged.
|
2641 |
*
|
2642 |
* In field_purge_instance(), after the field instance has been
|
2643 |
* removed from the database, the field storage module has had a chance to
|
2644 |
* run its hook_field_storage_purge_instance(), and the field info cache
|
2645 |
* has been cleared, this hook is invoked on all modules to allow them to
|
2646 |
* respond to the field instance being purged.
|
2647 |
*
|
2648 |
* @param $instance
|
2649 |
* The instance being purged.
|
2650 |
*/
|
2651 |
function hook_field_purge_instance($instance) { |
2652 |
db_delete('my_module_field_instance_info')
|
2653 |
->condition('id', $instance['id']) |
2654 |
->execute(); |
2655 |
} |
2656 |
|
2657 |
/**
|
2658 |
* Remove field storage information when a field record is purged.
|
2659 |
*
|
2660 |
* Called from field_purge_field() to allow the field storage module
|
2661 |
* to remove field information when a field is being purged.
|
2662 |
*
|
2663 |
* @param $field
|
2664 |
* The field being purged.
|
2665 |
*
|
2666 |
* @ingroup field_storage
|
2667 |
*/
|
2668 |
function hook_field_storage_purge_field($field) { |
2669 |
$table_name = _field_sql_storage_tablename($field); |
2670 |
$revision_name = _field_sql_storage_revision_tablename($field); |
2671 |
db_drop_table($table_name);
|
2672 |
db_drop_table($revision_name);
|
2673 |
} |
2674 |
|
2675 |
/**
|
2676 |
* Remove field storage information when a field instance is purged.
|
2677 |
*
|
2678 |
* Called from field_purge_instance() to allow the field storage module
|
2679 |
* to remove field instance information when a field instance is being
|
2680 |
* purged.
|
2681 |
*
|
2682 |
* @param $instance
|
2683 |
* The instance being purged.
|
2684 |
*
|
2685 |
* @ingroup field_storage
|
2686 |
*/
|
2687 |
function hook_field_storage_purge_field_instance($instance) { |
2688 |
db_delete('my_module_field_instance_info')
|
2689 |
->condition('id', $instance['id']) |
2690 |
->execute(); |
2691 |
} |
2692 |
|
2693 |
/**
|
2694 |
* Remove field storage information when field data is purged.
|
2695 |
*
|
2696 |
* Called from field_purge_data() to allow the field storage
|
2697 |
* module to delete field data information.
|
2698 |
*
|
2699 |
* @param $entity_type
|
2700 |
* The type of $entity; for example, 'node' or 'user'.
|
2701 |
* @param $entity
|
2702 |
* The pseudo-entity whose field data to delete.
|
2703 |
* @param $field
|
2704 |
* The (possibly deleted) field whose data is being purged.
|
2705 |
* @param $instance
|
2706 |
* The deleted field instance whose data is being purged.
|
2707 |
*
|
2708 |
* @ingroup field_storage
|
2709 |
*/
|
2710 |
function hook_field_storage_purge($entity_type, $entity, $field, $instance) { |
2711 |
list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); |
2712 |
|
2713 |
$table_name = _field_sql_storage_tablename($field); |
2714 |
$revision_name = _field_sql_storage_revision_tablename($field); |
2715 |
db_delete($table_name)
|
2716 |
->condition('entity_type', $entity_type) |
2717 |
->condition('entity_id', $id) |
2718 |
->execute(); |
2719 |
db_delete($revision_name)
|
2720 |
->condition('entity_type', $entity_type) |
2721 |
->condition('entity_id', $id) |
2722 |
->execute(); |
2723 |
} |
2724 |
|
2725 |
/**
|
2726 |
* @} End of "addtogroup field_crud".
|
2727 |
*/
|
2728 |
|
2729 |
/**
|
2730 |
* Determine whether the user has access to a given field.
|
2731 |
*
|
2732 |
* This hook is invoked from field_access() to let modules block access to
|
2733 |
* operations on fields. If no module returns FALSE, the operation is allowed.
|
2734 |
*
|
2735 |
* @param $op
|
2736 |
* The operation to be performed. Possible values: 'edit', 'view'.
|
2737 |
* @param $field
|
2738 |
* The field on which the operation is to be performed.
|
2739 |
* @param $entity_type
|
2740 |
* The type of $entity; for example, 'node' or 'user'.
|
2741 |
* @param $entity
|
2742 |
* (optional) The entity for the operation.
|
2743 |
* @param $account
|
2744 |
* (optional) The account to check; if not given use currently logged in user.
|
2745 |
*
|
2746 |
* @return
|
2747 |
* TRUE if the operation is allowed, and FALSE if the operation is denied.
|
2748 |
*
|
2749 |
* @ingroup field_types
|
2750 |
*/
|
2751 |
function hook_field_access($op, $field, $entity_type, $entity, $account) { |
2752 |
if ($field['field_name'] == 'field_of_interest' && $op == 'edit') { |
2753 |
return user_access('edit field of interest', $account); |
2754 |
} |
2755 |
return TRUE; |
2756 |
} |
2757 |
|
2758 |
/**
|
2759 |
* @} End of "addtogroup hooks".
|
2760 |
*/
|