Apply the field states to a form element.
Due to various form elements having different array structure, the states array has to be put in a different spot for different widgets. Most common locations are `value` and `target_id` or for multiple value forms, on the wrapper.
Parameters
array $element: The field widget form elements as constructed by \Drupal\Core\Field\WidgetBase::formMultipleElements().
\Drupal\Core\Form\FormStateInterface $form_state: The current state of the form.
array $context: An associative array containing the following key-value pairs:
- 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.
- widget: The widget plugin instance.
- items: The field values, as a \Drupal\Core\Field\FieldItemListInterface object.
- default: A boolean indicating whether the form is being shown as a dummy form to set default values.
See also
hook_field_widget_multivalue_form_alter().
File
-
src/
FieldStateManager.php, line 81
Class
- FieldStateManager
- Manages field state plugins.
Namespace
Drupal\field_states_uiCode
public function apply(&$element, FormStateInterface $form_state, $context) {
/** @var \Drupal\Core\Field\PluginSettingsInterface $plugin */
$plugin = $context['widget'];
// Check that it is enabled for this field.
if (empty($plugin->getThirdPartySettings('field_states_ui')['field_states'])) {
return;
}
$states = $plugin->getThirdPartySettings('field_states_ui')['field_states'];
/** @var \Drupal\Core\Field\FieldItemListInterface $field_item */
$field_item = $context['items'];
$field_definition = $field_item->getFieldDefinition();
$type = $field_definition->getType();
$plugin_id = $plugin->getPluginId();
// Handle the type of field appropriately.
switch ($type) {
case 'entity_reference':
switch ($plugin_id) {
case 'chosen_select':
case 'options_select':
case 'options_buttons':
case 'media_library_widget':
$target =& $element;
break;
case 'entity_browser_entity_reference':
if (!isset($element[0])) {
$target =& $element;
}
else {
$target =& $element[0];
}
break;
case 'entity_reference_autocomplete':
case 'entity_reference_autocomplete_tags':
if (!isset($element[0])) {
$target =& $element['target_id'];
}
else {
$target =& $element[0]['target_id'];
}
break;
default:
// Log a notice so that user(s) can report unrecognized field
// plugin_id.
$this->logger
->notice(t('Field type: "@type" with plugin_id "@id" was unrecognized. Please report on the @link. For quickest resolution, please include what module it comes from.', [
'@type' => $type,
'@id' => $plugin_id,
'@link' => Link::fromTextAndUrl(t('Field States UI Issue Queue'), Url::fromUri('https://www.drupal.org/project/issues/field_states_ui'))->toString(),
]));
if (isset($element[0]['target_id'])) {
$target =& $element[0]['target_id'];
}
elseif (isset($element['target_id'])) {
$target =& $element['target_id'];
}
else {
$target =& $element;
}
break;
}
break;
case 'boolean':
switch ($plugin_id) {
case 'options_buttons':
$target =& $element[0];
break;
case 'boolean_checkbox':
$target =& $element['value'];
break;
default:
$target =& $element[0]['value'];
break;
}
break;
case 'address_country':
case 'decimal':
case 'float':
case 'integer':
case 'string':
case 'string_long':
$target =& $element[0]['value'];
break;
case 'text_with_summary':
case 'text_long':
case 'list_float':
case 'list_integer':
case 'list_string':
case 'link':
case 'entity_reference_revisions':
case 'datetime':
case 'color_field_type':
case 'address_zone':
case 'address':
if (!isset($element[0])) {
$target =& $element;
}
else {
$target =& $element[0];
}
break;
case 'name':
$target =& $element[0];
$container = TRUE;
break;
default:
// Log a notice so that user(s) can report unrecognized field types.
$this->logger
->notice(t('Field type: "@type" was unrecognized. Please report on the @link. For quickest resolution, please include the element details: @details', [
'@type' => $type,
'@link' => Link::fromTextAndUrl(t('Field States UI Issue Queue'), Url::fromUri('https://www.drupal.org/project/issues/field_states_ui'))->toString(),
'@details' => var_export(array_keys($element[0]), TRUE),
]));
$target =& $element[0];
$container = TRUE;
break;
}
if (!isset($target['#field_parents'])) {
$parents = [];
$this->logger
->notice(t('#field_parents key not found. This will may cause problems. If so, please report on the @link. For quickest resolution, please include the element details: @details', [
'@link' => Link::fromTextAndUrl(t('Field States UI Issue Queue'), Url::fromUri('https://www.drupal.org/project/issues/field_states_ui'))->toString(),
'@details' => var_export(array_keys($element[0]), TRUE),
]));
}
else {
$parents = $target['#field_parents'];
}
if (isset($element['#cardinality_multiple']) && $element['#cardinality_multiple']) {
// Multiple widget field. Put states on the wrapper.
$element = [
'element' => $element,
'#type' => 'container',
'#states' => $this->getStates($states, $form_state, $context, $element, $parents),
];
}
elseif (isset($container)) {
// Add a container element and set states on that to ensure it works.
// This increases divitis which is already common on Drupal forms so
// it is better to handle the element properly. There are elements that it
// does make sense to do this to (ie name) but avoid if possible.
$element = [
'element' => $element,
'#type' => 'container',
'#states' => $this->getStates($states, $form_state, $context, $element, $parents),
];
}
else {
$target['#states'] = $this->getStates($states, $form_state, $context, $element, $parents);
}
}