/** * Form validation handler for updating components. */ public function validateComponentsForm($form, &$form_state) { // Check that no two components end up with the same form key. $duplicates = []; $parents = []; $components = $form_state->getValue('components'); unset($components['add']); if ($components) { foreach ($components as $cid => $component) { $form_key = $form['#node']->webform['components'][$cid]['form_key']; if (isset($parents[$component['pid']]) && ($existing = array_search($form_key, $parents[$component['pid']])) && $existing !== FALSE) { if (!isset($duplicates[$form_key])) { $duplicates[$form_key] = [$existing]; } $duplicates[$form_key][] = $cid; } $parents[$component['pid']][$cid] = $form_key; } } if (!empty($duplicates)) { $items = []; foreach ($duplicates as $form_key => $cids) { foreach ($cids as $cid) { $items[] = webform_filter_xss($form['#node']->webform['components'][$cid]['name']); } } $list = ['#theme' => 'item_list', '#items' => $items]; $form_state->setErrorByName('', $this->t('The form order failed to save because the following elements have same form keys and are under the same parent. Edit each component and give them a unique form key, then try moving them again. !list_components', ['!list_components' => drupal_render($list)])); } }
/** * Render a Webform component to be part of a form. * * @param $component * A Webform component array. * @param $value * If editing an existing submission or resuming a draft, this will contain * an array of values to be shown instead of the default in the component * configuration. This value will always be an array, keyed numerically for * each value saved in this field. * @param $filter * Whether or not to filter the contents of descriptions and values when * rendering the component. Values need to be unfiltered to be editable by * Form Builder. * * @see _webform_client_form_add_component() */ function _webform_render_component($component, $value = NULL, $filter = TRUE) { $form_item = array('#type' => 'textfield', '#title' => $filter ? webform_filter_xss($component['name']) : $component['name'], '#required' => $component['required'], '#weight' => $component['weight'], '#description' => $filter ? webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'], '#default_value' => $filter ? webform_replace_tokens($component['value']) : $component['value'], '#prefix' => '<div class="webform-component-textfield" id="webform-component-' . $component['form_key'] . '">', '#suffix' => '</div>'); if (isset($value)) { $form_item['#default_value'] = $value[0]; } return $form_item; }
/** * Render a Webform component to be part of a form. * * @param $component * A Webform component array. * @param $value * If editing an existing submission or resuming a draft, this will contain * an array of values to be shown instead of the default in the component * configuration. This value will always be an array, keyed numerically for * each value saved in this field. * @param $filter * Whether or not to filter the contents of descriptions and values when * rendering the component. Values need to be unfiltered to be editable by * Form Builder. * @param $submission * The submission from which this component is being rendered. Usually not * needed. Used by _webform_render_date() to validate using the submission's * completion date. * * @see _webform_client_form_add_component() */ function _webform_render_component($component, $value = NULL, $filter = TRUE, $submission = NULL) { $form_item = array('#type' => 'textfield', '#title' => $filter ? webform_filter_xss($component['name']) : $component['name'], '#required' => $component['required'], '#weight' => $component['weight'], '#description' => $filter ? webform_filter_descriptions($component['extra']['description']) : $component['extra']['description'], '#default_value' => $filter ? webform_replace_tokens($component['value']) : $component['value'], '#theme_wrappers' => array('webform_element')); if (isset($value)) { $form_item['#default_value'] = $value[0]; } return $form_item; }