public static function WebformElementStates::processWebformStates in Webform 6.x
Same name and namespace in other branches
- 8.5 src/Element/WebformElementStates.php \Drupal\webform\Element\WebformElementStates::processWebformStates()
Expand an email confirm field into two HTML5 email elements.
File
- src/
Element/ WebformElementStates.php, line 70
Class
- WebformElementStates
- Provides a webform element to edit an element's #states.
Namespace
Drupal\webform\ElementCode
public static function processWebformStates(&$element, FormStateInterface $form_state, &$complete_form) {
// Define default #state_options and #trigger_options.
// There are also defined by \Drupal\webform\Plugin\WebformElementBase::form.
$element += [
'#state_options' => static::getStateOptions(),
'#trigger_options' => static::getTriggerOptions(),
];
$element['#state_options_flattened'] = OptGroup::flattenOptions($element['#state_options']);
$element['#selector_options_flattened'] = OptGroup::flattenOptions($element['#selector_options']);
$element['#tree'] = TRUE;
$edit_source = $form_state
->get(static::getStorageKey($element, 'edit_source'));
// Add validate callback that extracts the associative array of states.
$element += [
'#element_validate' => [],
];
array_unshift($element['#element_validate'], [
get_called_class(),
'validateWebformElementStates',
]);
// For customized #states display a CodeMirror YAML editor.
$warning_message = static::isDefaultValueCustomizedFormApiStates($element);
if ($warning_message || $edit_source) {
if ($warning_message) {
$warning_message .= ' ' . t('Form API #states must be manually entered.');
$element['warning_messages'] = [
'#type' => 'webform_message',
'#message_type' => 'warning',
'#message_message' => $warning_message,
];
}
if ($edit_source) {
$element['edit_source_message'] = [
'#type' => 'webform_message',
'#message_message' => t('Creating custom conditional logic (Form API #states) with nested conditions or custom selectors will disable the conditional logic builder. This will require that Form API #states be manually entered.'),
'#message_type' => 'info',
'#message_close' => TRUE,
'#message_storage' => WebformMessage::STORAGE_SESSION,
];
}
$element['states'] = [
'#type' => 'webform_codemirror',
'#title' => t('Conditional Logic (YAML)'),
'#title_display' => 'invisible',
'#mode' => 'yaml',
'#default_value' => WebformYaml::encode($element['#default_value']),
'#description' => t('Learn more about Drupal\'s <a href=":href">Form API #states</a>.', [
':href' => 'https://www.lullabot.com/articles/form-api-states',
]),
'#webform_element' => TRUE,
'#more_title' => t('Help'),
'#more' => static::buildSourceHelp($element),
];
return $element;
}
$table_id = implode('_', $element['#parents']) . '_table';
// Store the number of rows.
$storage_key = static::getStorageKey($element, 'number_of_rows');
if ($form_state
->get($storage_key) === NULL) {
if (empty($element['#default_value']) || !is_array($element['#default_value'])) {
$number_of_rows = 2;
}
else {
$number_of_rows = count($element['#default_value']);
}
$form_state
->set($storage_key, $number_of_rows);
}
$number_of_rows = $form_state
->get($storage_key);
// DEBUG: Disable Ajax callback by commenting out the below callback and
// wrapper.
$ajax_settings = [
'callback' => [
get_called_class(),
'ajaxCallback',
],
'wrapper' => $table_id,
'progress' => [
'type' => 'none',
],
];
// Build header.
$header = [
[
'data' => t('State'),
'width' => '25%',
],
[
'data' => t('Element'),
'width' => '50%',
],
[
'data' => t('Trigger/Value'),
'width' => '25%',
],
[
'data' => WebformAccessibilityHelper::buildVisuallyHidden(t('Operations')),
],
];
// Get states and number of rows.
if ($form_state
->isRebuilding()) {
$states = $element['#value'];
}
else {
$states = isset($element['#default_value']) ? static::convertFormApiStatesToStatesArray($element['#default_value']) : [];
}
// Track state row indexes for disable/enabled warning message.
$state_row_indexes = [];
// Build state and conditions rows.
$row_index = 0;
$rows = [];
foreach ($states as $state_settings) {
$rows[$row_index] = static::buildStateRow($element, $state_settings, $table_id, $row_index, $ajax_settings);
$state_row_indexes[] = $row_index;
$row_index++;
foreach ($state_settings['conditions'] as $condition) {
$rows[$row_index] = static::buildConditionRow($element, $condition, $table_id, $row_index, $ajax_settings);
$row_index++;
}
}
// Generator empty state with conditions rows.
if ($row_index < $number_of_rows) {
$rows[$row_index] = static::buildStateRow($element, [], $table_id, $row_index, $ajax_settings);
$state_row_indexes[] = $row_index;
$row_index++;
while ($row_index < $number_of_rows) {
$rows[$row_index] = static::buildConditionRow($element, [], $table_id, $row_index, $ajax_settings);
$row_index++;
}
}
// Add wrapper to the element.
$element += [
'#prefix' => '',
'#suffix' => '',
];
$element['#prefix'] = '<div id="' . $table_id . '">' . $element['#prefix'];
$element['#suffix'] .= '</div>';
// Build table.
$element['states'] = [
'#type' => 'table',
'#header' => $header,
'#attributes' => [
'class' => [
'webform-states-table',
],
],
] + $rows;
$element['actions'] = [
'#type' => 'container',
];
// Build add state action.
if ($element['#multiple']) {
$element['actions']['add'] = [
'#type' => 'submit',
'#value' => t('Add another state'),
'#limit_validation_errors' => [],
'#submit' => [
[
get_called_class(),
'addStateSubmit',
],
],
'#ajax' => $ajax_settings,
'#name' => $table_id . '_add',
];
}
// Edit source.
if (\Drupal::currentUser()
->hasPermission('edit webform source')) {
$element['actions']['source'] = [
'#type' => 'submit',
'#value' => t('Edit source'),
'#limit_validation_errors' => [],
'#submit' => [
[
get_called_class(),
'editSourceSubmit',
],
],
'#ajax' => $ajax_settings,
'#attributes' => [
'class' => [
'button',
'button--danger',
],
],
'#name' => $table_id . '_source',
];
}
// Display a warning message when any state is set to disabled or enabled.
if (!empty($element['#disabled_message'])) {
$total_state_row_indexes = count($state_row_indexes);
$triggers = [];
foreach ($state_row_indexes as $index => $row_index) {
$id = Html::getId('edit-' . implode('-', $element['#parents']) . '-states-' . $row_index . '-state');
$triggers[] = [
':input[data-drupal-selector="' . $id . '"]' => [
'value' => [
'pattern' => '^(disabled|enabled)$',
],
],
];
if ($index + 1 < $total_state_row_indexes) {
$triggers[] = 'or';
}
}
if ($triggers) {
$element['disabled_message'] = [
'#type' => 'webform_message',
'#message_message' => t('<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-disabled">Disabled</a> elements do not submit data back to the server and the element\'s server-side default or current value will be preserved and saved to the database.'),
'#message_type' => 'warning',
'#states' => [
'visible' => $triggers,
],
];
}
}
$element['#attached']['library'][] = 'webform/webform.element.states';
// Convert #options to jQuery autocomplete source format.
// @see http://api.jqueryui.com/autocomplete/#option-source
$selectors = [];
$sources = [];
if ($element['#selector_sources']) {
foreach ($element['#selector_sources'] as $selector => $values) {
$sources_key = Crypt::hashBase64(serialize($values));
$selectors[$selector] = $sources_key;
if (!isset($sources[$sources_key])) {
foreach ($values as $key => $value) {
$sources[$sources_key][] = [
'label' => (string) $value . ($value !== $key ? ' (' . $key . ')' : ''),
'value' => (string) $key,
];
}
}
}
}
$element['#attached']['drupalSettings']['webformElementStates'] = [
'selectors' => $selectors,
'sources' => $sources,
];
return $element;
}