diff --git a/core/includes/form.inc b/core/includes/form.inc index 9e0b7c7..ae60c90 100644 --- a/core/includes/form.inc +++ b/core/includes/form.inc @@ -685,27 +685,6 @@ function form_type_select_value($element, $input = FALSE) { } /** - * Determines the value for a textfield form element. - * - * @param $element - * The form element whose value is being populated. - * @param $input - * The incoming input to populate the form element. If this is FALSE, - * the element's default value should be returned. - * - * @return - * The data that will appear in the $element_state['values'] collection - * for this element. Return nothing to use the default. - */ -function form_type_textfield_value($element, $input = FALSE) { - if ($input !== FALSE && $input !== NULL) { - // Equate $input to the form value to ensure it's marked for - // validation. - return str_replace(array("\r", "\n"), '', $input); - } -} - -/** * Determines the value for form's token value. * * @param $element diff --git a/core/lib/Drupal/Core/Form/FormBuilder.php b/core/lib/Drupal/Core/Form/FormBuilder.php index c150c29..5885eaa 100644 --- a/core/lib/Drupal/Core/Form/FormBuilder.php +++ b/core/lib/Drupal/Core/Form/FormBuilder.php @@ -1042,7 +1042,14 @@ protected function handleInputElement($form_id, &$element, &$form_state) { // Set the element's #value property. if (!isset($element['#value']) && !array_key_exists('#value', $element)) { + // @todo Once all elements are converted to plugins in + // https://www.drupal.org/node/2311393, rely on + // $element['#value_callback'] directly. $value_callable = !empty($element['#value_callback']) ? $element['#value_callback'] : 'form_type_' . $element['#type'] . '_value'; + if (!is_callable($value_callable)) { + $value_callable = '\Drupal\Core\Render\Element\FormElement::valueCallback'; + } + if ($process_input) { // Get the input for the current element. NULL values in the input need // to be explicitly distinguished from missing input. (see below) @@ -1066,9 +1073,8 @@ protected function handleInputElement($form_id, &$element, &$form_state) { // If we have input for the current element, assign it to the #value // property, optionally filtered through $value_callback. if ($input_exists) { - if (is_callable($value_callable)) { - $element['#value'] = call_user_func_array($value_callable, array(&$element, $input, &$form_state)); - } + $element['#value'] = call_user_func_array($value_callable, array(&$element, $input, &$form_state)); + if (!isset($element['#value']) && isset($input)) { $element['#value'] = $input; } @@ -1082,9 +1088,8 @@ protected function handleInputElement($form_id, &$element, &$form_state) { if (!isset($element['#value'])) { // Call #type_value without a second argument to request default_value // handling. - if (is_callable($value_callable)) { - $element['#value'] = call_user_func_array($value_callable, array(&$element, FALSE, &$form_state)); - } + $element['#value'] = call_user_func_array($value_callable, array(&$element, FALSE, &$form_state)); + // Final catch. If we haven't set a value yet, use the explicit default // value. Avoid image buttons (which come with garbage value), so we // only get value for the button actually clicked. diff --git a/core/lib/Drupal/Core/Render/Element/FormElement.php b/core/lib/Drupal/Core/Render/Element/FormElement.php index a118f0a..82a4bd2 100644 --- a/core/lib/Drupal/Core/Render/Element/FormElement.php +++ b/core/lib/Drupal/Core/Render/Element/FormElement.php @@ -19,6 +19,24 @@ abstract class FormElement extends RenderElement { /** + * Determines how user input is mapped to an element's #value property. + * + * @param array $element + * An associative array containing the properties of the element. + * @param mixed $input + * The incoming input to populate the form element. If this is FALSE, + * the element's default value should be returned. + * @param array $form_state + * An associative array containing the current state of the form. + * + * @return mixed + * The value to assign to the element. + */ + public static function valueCallback(&$element, $input, &$form_state) { + return NULL; + } + + /** * Form element processing handler for the #ajax form property. * * @param array $element diff --git a/core/lib/Drupal/Core/Render/Element/MachineName.php b/core/lib/Drupal/Core/Render/Element/MachineName.php index 457bb62..f318262 100644 --- a/core/lib/Drupal/Core/Render/Element/MachineName.php +++ b/core/lib/Drupal/Core/Render/Element/MachineName.php @@ -51,6 +51,13 @@ public function getInfo() { } /** + * {@inheritdoc} + */ + public static function valueCallback(&$element, $input, &$form_state) { + return NULL; + } + + /** * Processes a machine-readable name form element. * * @param array $element diff --git a/core/lib/Drupal/Core/Render/Element/Textfield.php b/core/lib/Drupal/Core/Render/Element/Textfield.php index 7799a03..75b4c4c 100644 --- a/core/lib/Drupal/Core/Render/Element/Textfield.php +++ b/core/lib/Drupal/Core/Render/Element/Textfield.php @@ -42,6 +42,17 @@ public function getInfo() { } /** + * {@inheritdoc} + */ + public static function valueCallback(&$element, $input, &$form_state) { + if ($input !== FALSE && $input !== NULL) { + // Equate $input to the form value to ensure it's marked for + // validation. + return str_replace(array("\r", "\n"), '', $input); + } + } + + /** * Prepares a #type 'textfield' render element for theme_input(). * * @param array $element diff --git a/core/lib/Drupal/Core/Render/ElementInfoManager.php b/core/lib/Drupal/Core/Render/ElementInfoManager.php index a60e54d..1d65fb08 100644 --- a/core/lib/Drupal/Core/Render/ElementInfoManager.php +++ b/core/lib/Drupal/Core/Render/ElementInfoManager.php @@ -10,6 +10,7 @@ use Drupal\Core\Cache\CacheBackendInterface; use Drupal\Core\Extension\ModuleHandlerInterface; use Drupal\Core\Plugin\DefaultPluginManager; +use Drupal\Core\Render\Element\FormElement; /** * Provides a plugin manager for element plugins. @@ -64,7 +65,16 @@ protected function buildInfo() { $info = $this->moduleHandler->invokeAll('element_info'); foreach ($this->getDefinitions() as $element_type => $definition) { - $info[$element_type] = $this->createInstance($element_type)->getInfo(); + $element = $this->createInstance($element_type); + $element_info = $element->getInfo(); + + // If this is element is to be used exclusively in a form, denote that it + // will receive input, and assign the value callback. + if ($element instanceof FormElement) { + $element_info['#input'] = TRUE; + $element_info['#value_callback'] = array(get_class($element), 'valueCallback'); + } + $info[$element_type] = $element_info; } foreach ($info as $element_type => $element) { $info[$element_type]['#type'] = $element_type;