2009-02-05 03:42:58 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
/**
|
2012-03-09 16:23:34 +00:00
|
|
|
* @addtogroup hooks
|
2009-02-05 03:42:58 +00:00
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2012-12-17 21:54:13 +00:00
|
|
|
use Drupal\Component\Utility\NestedArray;
|
2014-03-05 16:50:56 +00:00
|
|
|
use Drupal\field\FieldConfigUpdateForbiddenException;
|
2012-05-07 02:56:49 +00:00
|
|
|
|
2009-02-05 03:42:58 +00:00
|
|
|
/**
|
|
|
|
* @defgroup field_types Field Types API
|
|
|
|
* @{
|
2012-09-27 15:44:17 +00:00
|
|
|
* Defines field, widget, display formatter, and storage types.
|
2009-02-05 03:42:58 +00:00
|
|
|
*
|
2012-03-09 16:23:34 +00:00
|
|
|
* In the Field API, each field has a type, which determines what kind of data
|
|
|
|
* (integer, string, date, etc.) the field can hold, which settings it provides,
|
|
|
|
* and so on. The data type(s) accepted by a field are defined in
|
2013-06-25 10:27:47 +00:00
|
|
|
* hook_field_schema().
|
2009-08-01 06:03:48 +00:00
|
|
|
*
|
|
|
|
* The Field Types API also defines two kinds of pluggable handlers: widgets
|
2012-03-09 16:23:34 +00:00
|
|
|
* and formatters. @link field_widget Widgets @endlink specify how the field
|
|
|
|
* appears in edit forms, while @link field_formatter formatters @endlink
|
|
|
|
* specify how the field appears in displayed entities.
|
- Patch #443422 by yched, bjaspan | chx, merlinofchaos, Scott Reynolds, plach, profix898, mattyoung: added support for pluggable 'per field' storage engine. Comes with documentation and tests.
The Field Attach API uses the Field Storage API to perform all "database access". Each Field Storage API hook function defines a primitive database operation such as read, write, or delete. The default field storage module, field_sql_storage.module, uses the local SQL database to implement these operations, but alternative field storage backends can choose to represent the data in SQL differently or use a completely different storage mechanism such as a cloud-based database.
2009-09-27 12:52:55 +00:00
|
|
|
*
|
2011-12-22 09:32:53 +00:00
|
|
|
* See @link field Field API @endlink for information about the other parts of
|
|
|
|
* the Field API.
|
2009-02-05 03:42:58 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
2009-06-30 03:12:03 +00:00
|
|
|
/**
|
|
|
|
* Perform alterations on Field API field types.
|
|
|
|
*
|
|
|
|
* @param $info
|
2013-06-25 10:27:47 +00:00
|
|
|
* Array of information on field types as collected by the "field type" plugin
|
|
|
|
* manager.
|
2009-06-30 03:12:03 +00:00
|
|
|
*/
|
|
|
|
function hook_field_info_alter(&$info) {
|
|
|
|
// Change the default widget for fields of type 'foo'.
|
|
|
|
if (isset($info['foo'])) {
|
|
|
|
$info['foo']['default widget'] = 'mymodule_widget';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:42:58 +00:00
|
|
|
/**
|
2012-05-17 12:58:49 +00:00
|
|
|
* @} End of "defgroup field_types".
|
2012-03-09 16:23:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @defgroup field_widget Field Widget API
|
|
|
|
* @{
|
|
|
|
* Define Field API widget types.
|
|
|
|
*
|
|
|
|
* Field API widgets specify how fields are displayed in edit forms. Fields of a
|
|
|
|
* given @link field_types field type @endlink may be edited using more than one
|
|
|
|
* widget. In this case, the Field UI module allows the site builder to choose
|
2012-09-26 19:39:39 +00:00
|
|
|
* which widget to use.
|
|
|
|
*
|
|
|
|
* Widgets are Plugins managed by the
|
2013-10-18 11:57:37 +00:00
|
|
|
* Drupal\Core\Field\WidgetPluginManager class. A widget is
|
2012-09-26 19:39:39 +00:00
|
|
|
* implemented by providing a class that implements
|
2013-10-18 11:57:37 +00:00
|
|
|
* Drupal\Core\Field\WidgetInterface (in most cases, by
|
|
|
|
* subclassing Drupal\Core\Field\WidgetBase), and provides the
|
2012-09-26 19:39:39 +00:00
|
|
|
* proper annotation block.
|
2009-04-13 05:18:18 +00:00
|
|
|
*
|
2012-05-04 20:07:43 +00:00
|
|
|
* Widgets are @link forms_api_reference.html Form API @endlink
|
2012-09-26 19:39:39 +00:00
|
|
|
* elements with additional processing capabilities. The methods of the
|
2014-03-25 18:24:33 +00:00
|
|
|
* WidgetInterface object are typically called by respective methods in the
|
|
|
|
* \Drupal\entity\Entity\EntityFormDisplay class.
|
2012-03-09 16:23:34 +00:00
|
|
|
*
|
|
|
|
* @see field
|
|
|
|
* @see field_types
|
|
|
|
* @see field_formatter
|
|
|
|
*/
|
|
|
|
|
2009-08-01 06:03:48 +00:00
|
|
|
/**
|
|
|
|
* Perform alterations on Field API widget types.
|
|
|
|
*
|
2012-09-26 19:39:39 +00:00
|
|
|
* @param array $info
|
2014-03-26 09:32:27 +00:00
|
|
|
* An array of information on existing widget types, as collected by the
|
2012-09-26 19:39:39 +00:00
|
|
|
* annotation discovery mechanism.
|
2009-08-01 06:03:48 +00:00
|
|
|
*/
|
2012-09-26 19:39:39 +00:00
|
|
|
function hook_field_widget_info_alter(array &$info) {
|
2009-08-01 06:03:48 +00:00
|
|
|
// Let a new field type re-use an existing widget.
|
2012-09-26 19:39:39 +00:00
|
|
|
$info['options_select']['field_types'][] = 'my_field_type';
|
2009-02-05 03:42:58 +00:00
|
|
|
}
|
|
|
|
|
2011-08-29 18:00:33 +00:00
|
|
|
/**
|
|
|
|
* Alter forms for field widgets provided by other modules.
|
|
|
|
*
|
|
|
|
* @param $element
|
|
|
|
* The field widget form element as constructed by hook_field_widget_form().
|
|
|
|
* @param $form_state
|
|
|
|
* An associative array containing the current state of the form.
|
|
|
|
* @param $context
|
2013-06-16 08:27:11 +00:00
|
|
|
* An associative array containing the following key-value pairs:
|
2012-04-17 22:13:57 +00:00
|
|
|
* - form: The form structure to which widgets are being attached. This may be
|
|
|
|
* a full form structure, or a sub-element of a larger form.
|
2013-06-16 08:27:11 +00:00
|
|
|
* - widget: The widget plugin instance.
|
2013-09-28 11:29:14 +00:00
|
|
|
* - items: The field values, as a
|
2013-10-19 08:12:13 +00:00
|
|
|
* \Drupal\Core\Field\FieldItemListInterface object.
|
2012-04-17 22:13:57 +00:00
|
|
|
* - delta: The order of this item in the array of subelements (0, 1, 2, etc).
|
2012-08-15 14:20:02 +00:00
|
|
|
* - default: A boolean indicating whether the form is being shown as a dummy
|
|
|
|
* form to set default values.
|
2011-08-29 18:00:33 +00:00
|
|
|
*
|
2013-10-18 11:57:37 +00:00
|
|
|
* @see \Drupal\Core\Field\WidgetBase::formSingleElement()
|
2012-04-17 22:13:57 +00:00
|
|
|
* @see hook_field_widget_WIDGET_TYPE_form_alter()
|
2011-08-29 18:00:33 +00:00
|
|
|
*/
|
|
|
|
function hook_field_widget_form_alter(&$element, &$form_state, $context) {
|
|
|
|
// Add a css class to widget form elements for all fields of type mytype.
|
2013-09-16 15:52:28 +00:00
|
|
|
$field_definition = $context['items']->getFieldDefinition();
|
2013-12-09 23:19:58 +00:00
|
|
|
if ($field_definition->getType() == 'mytype') {
|
2011-08-29 18:00:33 +00:00
|
|
|
// Be sure not to overwrite existing attributes.
|
|
|
|
$element['#attributes']['class'][] = 'myclass';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Alter widget forms for a specific widget provided by another module.
|
|
|
|
*
|
|
|
|
* Modules can implement hook_field_widget_WIDGET_TYPE_form_alter() to modify a
|
|
|
|
* specific widget form, rather than using hook_field_widget_form_alter() and
|
|
|
|
* checking the widget type.
|
|
|
|
*
|
|
|
|
* @param $element
|
|
|
|
* The field widget form element as constructed by hook_field_widget_form().
|
|
|
|
* @param $form_state
|
|
|
|
* An associative array containing the current state of the form.
|
|
|
|
* @param $context
|
2013-06-16 08:27:11 +00:00
|
|
|
* An associative array. See hook_field_widget_form_alter() for the structure
|
|
|
|
* and content of the array.
|
2011-08-29 18:00:33 +00:00
|
|
|
*
|
2013-10-18 11:57:37 +00:00
|
|
|
* @see \Drupal\Core\Field\WidgetBase::formSingleElement()
|
2011-08-29 18:00:33 +00:00
|
|
|
* @see hook_field_widget_form_alter()
|
|
|
|
*/
|
|
|
|
function hook_field_widget_WIDGET_TYPE_form_alter(&$element, &$form_state, $context) {
|
|
|
|
// Code here will only act on widgets of type WIDGET_TYPE. For example,
|
|
|
|
// hook_field_widget_mymodule_autocomplete_form_alter() will only act on
|
|
|
|
// widgets of type 'mymodule_autocomplete'.
|
2013-10-15 11:54:21 +00:00
|
|
|
$element['#autocomplete_route_name'] = 'mymodule.autocomplete_route';
|
2011-08-29 18:00:33 +00:00
|
|
|
}
|
|
|
|
|
2012-03-09 16:23:34 +00:00
|
|
|
/**
|
2012-05-17 12:58:49 +00:00
|
|
|
* @} End of "defgroup field_widget".
|
2012-03-09 16:23:34 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @defgroup field_formatter Field Formatter API
|
|
|
|
* @{
|
|
|
|
* Define Field API formatter types.
|
|
|
|
*
|
|
|
|
* Field API formatters specify how fields are displayed when the entity to
|
|
|
|
* which the field is attached is displayed. Fields of a given
|
|
|
|
* @link field_types field type @endlink may be displayed using more than one
|
|
|
|
* formatter. In this case, the Field UI module allows the site builder to
|
2012-10-14 06:04:15 +00:00
|
|
|
* choose which formatter to use.
|
|
|
|
*
|
|
|
|
* Formatters are Plugins managed by the
|
2013-10-18 11:57:37 +00:00
|
|
|
* Drupal\Core\Field\FormatterPluginManager class. A formatter
|
2012-10-14 06:04:15 +00:00
|
|
|
* is implemented by providing a class that implements
|
2013-10-18 11:57:37 +00:00
|
|
|
* Drupal\Core\Field\FormatterInterface (in most cases, by
|
|
|
|
* subclassing Drupal\Core\Field\FormatterBase), and provides
|
2012-10-14 06:04:15 +00:00
|
|
|
* the proper annotation block.
|
2012-03-09 16:23:34 +00:00
|
|
|
*
|
|
|
|
* @see field
|
|
|
|
* @see field_types
|
|
|
|
* @see field_widget
|
|
|
|
*/
|
|
|
|
|
2009-08-01 06:03:48 +00:00
|
|
|
/**
|
|
|
|
* Perform alterations on Field API formatter types.
|
|
|
|
*
|
2012-10-14 06:04:15 +00:00
|
|
|
* @param array $info
|
2014-03-26 09:32:27 +00:00
|
|
|
* An array of information on existing formatter types, as collected by the
|
2012-10-14 06:04:15 +00:00
|
|
|
* annotation discovery mechanism.
|
2009-08-01 06:03:48 +00:00
|
|
|
*/
|
2012-10-14 06:04:15 +00:00
|
|
|
function hook_field_formatter_info_alter(array &$info) {
|
2009-08-01 06:03:48 +00:00
|
|
|
// Let a new field type re-use an existing formatter.
|
|
|
|
$info['text_default']['field types'][] = 'my_field_type';
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:42:58 +00:00
|
|
|
/**
|
2012-05-17 12:58:49 +00:00
|
|
|
* @} End of "defgroup field_formatter".
|
2009-02-05 03:42:58 +00:00
|
|
|
*/
|
|
|
|
|
2010-09-11 00:03:42 +00:00
|
|
|
/**
|
|
|
|
* Returns the maximum weight for the entity components handled by the module.
|
|
|
|
*
|
|
|
|
* Field API takes care of fields and 'extra_fields'. This hook is intended for
|
|
|
|
* third-party modules adding other entity components (e.g. field_group).
|
|
|
|
*
|
2013-05-19 20:02:16 +00:00
|
|
|
* @param string $entity_type
|
2010-09-11 00:03:42 +00:00
|
|
|
* The type of entity; e.g. 'node' or 'user'.
|
2013-05-19 20:02:16 +00:00
|
|
|
* @param string $bundle
|
2010-09-11 00:03:42 +00:00
|
|
|
* The bundle name.
|
2013-05-19 20:02:16 +00:00
|
|
|
* @param string $context
|
|
|
|
* The context for which the maximum weight is requested. Either 'form' or
|
|
|
|
* 'display'.
|
|
|
|
* @param string $context_mode
|
|
|
|
* The view or form mode name.
|
|
|
|
*
|
|
|
|
* @return int
|
2010-09-11 00:03:42 +00:00
|
|
|
* The maximum weight of the entity's components, or NULL if no components
|
|
|
|
* were found.
|
|
|
|
*/
|
2013-05-19 20:02:16 +00:00
|
|
|
function hook_field_info_max_weight($entity_type, $bundle, $context, $context_mode) {
|
2010-09-11 00:03:42 +00:00
|
|
|
$weights = array();
|
|
|
|
|
2013-05-19 20:02:16 +00:00
|
|
|
foreach (my_module_entity_additions($entity_type, $bundle, $context, $context_mode) as $addition) {
|
2010-09-11 00:03:42 +00:00
|
|
|
$weights[] = $addition['weight'];
|
|
|
|
}
|
|
|
|
|
|
|
|
return $weights ? max($weights) : NULL;
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:42:58 +00:00
|
|
|
/**
|
2012-05-17 12:58:49 +00:00
|
|
|
* @addtogroup field_crud
|
2009-02-05 03:42:58 +00:00
|
|
|
* @{
|
|
|
|
*/
|
|
|
|
|
2009-09-26 15:57:39 +00:00
|
|
|
/**
|
|
|
|
* Forbid a field update from occurring.
|
|
|
|
*
|
|
|
|
* Any module may forbid any update for any reason. For example, the
|
|
|
|
* field's storage module might forbid an update if it would change
|
|
|
|
* the storage schema while data for the field exists. A field type
|
|
|
|
* module might forbid an update if it would change existing data's
|
|
|
|
* semantics, or if there are external dependencies on field settings
|
|
|
|
* that cannot be updated.
|
|
|
|
*
|
2012-05-07 02:56:49 +00:00
|
|
|
* To forbid the update from occurring, throw a
|
2014-03-05 16:50:56 +00:00
|
|
|
* Drupal\field\FieldConfigUpdateForbiddenException.
|
2010-05-03 07:37:51 +00:00
|
|
|
*
|
2014-03-05 16:50:56 +00:00
|
|
|
* @param \Drupal\field\FieldConfigInterface $field
|
2009-09-26 15:57:39 +00:00
|
|
|
* The field as it will be post-update.
|
2014-03-05 16:50:56 +00:00
|
|
|
* @param \Drupal\field\FieldConfigInterface $prior_field
|
2009-09-26 15:57:39 +00:00
|
|
|
* The field as it is pre-update.
|
|
|
|
*/
|
2014-03-05 16:50:56 +00:00
|
|
|
function hook_field_config_update_forbid(\Drupal\field\FieldConfigInterface $field, \Drupal\field\FieldConfigInterface $prior_field) {
|
2009-09-26 15:57:39 +00:00
|
|
|
// A 'list' field stores integer keys mapped to display values. If
|
|
|
|
// the new field will have fewer values, and any data exists for the
|
2010-01-25 10:38:35 +00:00
|
|
|
// abandoned keys, the field will have no way to display them. So,
|
2009-09-26 15:57:39 +00:00
|
|
|
// forbid such an update.
|
2013-06-17 00:22:30 +00:00
|
|
|
if ($field->hasData() && count($field['settings']['allowed_values']) < count($prior_field['settings']['allowed_values'])) {
|
2009-09-26 15:57:39 +00:00
|
|
|
// Identify the keys that will be lost.
|
|
|
|
$lost_keys = array_diff(array_keys($field['settings']['allowed_values']), array_keys($prior_field['settings']['allowed_values']));
|
|
|
|
// If any data exist for those keys, forbid the update.
|
2010-06-17 13:16:57 +00:00
|
|
|
$query = new EntityFieldQuery();
|
2010-06-14 15:41:03 +00:00
|
|
|
$found = $query
|
|
|
|
->fieldCondition($prior_field['field_name'], 'value', $lost_keys)
|
|
|
|
->range(0, 1)
|
|
|
|
->execute();
|
|
|
|
if ($found) {
|
2014-03-05 16:50:56 +00:00
|
|
|
throw new FieldConfigUpdateForbiddenException("Cannot update a list field not to include keys with existing data");
|
2009-09-26 15:57:39 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-04-22 22:51:54 +00:00
|
|
|
/**
|
|
|
|
* Acts when a field record is being purged.
|
|
|
|
*
|
2013-09-02 20:26:08 +00:00
|
|
|
* In field_purge_field(), after the field definition has been removed from the
|
|
|
|
* the system, the entity storage has purged stored field data, and the field
|
|
|
|
* info cache has been cleared, this hook is invoked on all modules to allow
|
|
|
|
* them to respond to the field being purged.
|
2010-04-22 22:51:54 +00:00
|
|
|
*
|
|
|
|
* @param $field
|
|
|
|
* The field being purged.
|
|
|
|
*/
|
|
|
|
function hook_field_purge_field($field) {
|
|
|
|
db_delete('my_module_field_info')
|
|
|
|
->condition('id', $field['id'])
|
|
|
|
->execute();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Acts when a field instance is being purged.
|
|
|
|
*
|
2013-09-02 20:26:08 +00:00
|
|
|
* In field_purge_instance(), after the instance definition has been removed
|
|
|
|
* from the the system, the entity storage has purged stored field data, and the
|
|
|
|
* field info cache has been cleared, this hook is invoked on all modules to
|
|
|
|
* allow them to respond to the field instance being purged.
|
2010-04-22 22:51:54 +00:00
|
|
|
*
|
|
|
|
* @param $instance
|
|
|
|
* The instance being purged.
|
|
|
|
*/
|
2011-10-25 08:11:30 +00:00
|
|
|
function hook_field_purge_instance($instance) {
|
2010-04-22 22:51:54 +00:00
|
|
|
db_delete('my_module_field_instance_info')
|
|
|
|
->condition('id', $instance['id'])
|
|
|
|
->execute();
|
|
|
|
}
|
|
|
|
|
2009-02-05 03:42:58 +00:00
|
|
|
/**
|
2012-05-17 12:58:49 +00:00
|
|
|
* @} End of "addtogroup field_crud".
|
2009-02-05 03:42:58 +00:00
|
|
|
*/
|
|
|
|
|
2011-11-25 03:35:12 +00:00
|
|
|
/**
|
2012-05-17 12:58:49 +00:00
|
|
|
* @} End of "addtogroup hooks".
|
2011-11-25 03:35:12 +00:00
|
|
|
*/
|