Code Coverage |
||||||||||
Classes and Traits |
Functions and Methods |
Lines |
||||||||
Total | |
0.00% |
0 / 1 |
|
25.00% |
1 / 4 |
CRAP | |
3.70% |
1 / 27 |
FormElement | |
0.00% |
0 / 1 |
|
25.00% |
1 / 4 |
140.59 | |
3.70% |
1 / 27 |
valueCallback | |
100.00% |
1 / 1 |
1 | |
100.00% |
1 / 1 |
|||
processPattern | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 4 |
|||
validatePattern | |
0.00% |
0 / 1 |
12 | |
0.00% |
0 / 5 |
|||
processAutocomplete | |
0.00% |
0 / 1 |
30 | |
0.00% |
0 / 17 |
<?php | |
/** | |
* @file | |
* Contains \Drupal\Core\Render\Element\FormElement. | |
*/ | |
namespace Drupal\Core\Render\Element; | |
use Drupal\Core\Form\FormStateInterface; | |
use Drupal\Core\Render\BubbleableMetadata; | |
use Drupal\Core\Url; | |
/** | |
* Provides a base class for form element plugins. | |
* | |
* Form elements are a subset of render elements, representing elements for | |
* HTML forms, which can be referenced in form arrays. See the | |
* @link theme_render Render API topic @endlink for an overview of render | |
* arrays and render elements, and the @link form_api Form API topic @endlink | |
* for an overview of forms and form arrays. | |
* | |
* The elements of form arrays are divided up into properties (whose keys | |
* start with #) and children (whose keys do not start with #). The properties | |
* provide data or settings that are used in rendering and form processing. | |
* Some properties are specific to a particular type of form/render element, | |
* some are available for any render element, and some are available for any | |
* form input element. A list of the properties that are available for all form | |
* elements follows; see \Drupal\Core\Render\Element\RenderElement for some | |
* additional information, as well as a list of properties that are common to | |
* all render elements (including form elements). Properties specific to a | |
* particular element are documented on that element's class. | |
* | |
* Here is a list of properties that are used during the rendering and form | |
* processing of form elements: | |
* - #after_build: (array) Array of callables or function names, which are | |
* called after the element is built. Arguments: $element, $form_state. | |
* - #ajax: (array) Array of elements to specify Ajax behavior. See | |
* the @link ajax Ajax API topic @endlink for more information. | |
* - #array_parents: (string[], read-only) Array of names of all the element's | |
* parents (including itself) in the render array. See also #parents, #tree. | |
* - #default_value: Default value for the element. See also #value. | |
* - #description: (string) Help or description text for the element. In an | |
* ideal user interface, the #title should be enough to describe the element, | |
* so most elements should not have a description; if you do need one, make | |
* sure it is translated. If it is not already wrapped in a safe markup | |
* object, it will be filtered for XSS safety. | |
* - #disabled: (bool) If TRUE, the element is shown but does not accept | |
* user input. | |
* - #element_validate: (array) Array of callables or function names, which | |
* are called to validate the input. Arguments: $element, $form_state, $form. | |
* - #field_prefix: (string) Prefix to display before the HTML input element. | |
* Should be translated, normally. If it is not already wrapped in a safe | |
* markup object, will be filtered for XSS safety. | |
* - #field_suffix: (string) Suffix to display after the HTML input element. | |
* Should be translated, normally. If it is not already wrapped in a safe | |
* markup object, will be filtered for XSS safety. | |
* - #input: (bool, internal) Whether or not the element accepts input. | |
* - #parents: (string[], read-only) Array of names of the element's parents | |
* for purposes of getting values out of $form_state. See also | |
* #array_parents, #tree. | |
* - #process: (array) Array of callables or function names, which are | |
* called during form building. Arguments: $element, $form_state, $form. | |
* - #processed: (bool, internal) Set to TRUE when the element is processed. | |
* - #required: (bool) Whether or not input is required on the element. | |
* - #states: (array) Information about JavaScript states, such as when to | |
* hide or show the element based on input on other elements. | |
* See drupal_process_states() for documentation. | |
* - #title: (string) Title of the form element. Should be translated. | |
* - #title_display: (string) Where and how to display the #title. Possible | |
* values: | |
* - before: Label goes before the element (default for most elements). | |
* - after: Label goes after the element (default for radio elements). | |
* - invisible: Label is there but is made invisible using CSS. | |
* - attribute: Make it the title attribute (hover tooltip). | |
* - #tree: (bool) TRUE if the values of this element and its children should | |
* be hierarchical in $form_state; FALSE if the values should be flat. | |
* See also #parents, #array_parents. | |
* - #value_callback: (callable) Callable or function name, which is called | |
* to transform the raw user input to the element's value. Arguments: | |
* $element, $input, $form_state. | |
* | |
* @see \Drupal\Core\Render\Annotation\FormElement | |
* @see \Drupal\Core\Render\Element\FormElementInterface | |
* @see \Drupal\Core\Render\ElementInfoManager | |
* @see plugin_api | |
* | |
* @ingroup theme_render | |
*/ | |
abstract class FormElement extends RenderElement implements FormElementInterface { | |
/** | |
* {@inheritdoc} | |
*/ | |
public static function valueCallback(&$element, $input, FormStateInterface $form_state) { | |
return NULL; | |
} | |
/** | |
* #process callback for #pattern form element property. | |
* | |
* @param array $element | |
* An associative array containing the properties and children of the | |
* generic input element. | |
* @param \Drupal\Core\Form\FormStateInterface $form_state | |
* The current state of the form. | |
* @param array $complete_form | |
* The complete form structure. | |
* | |
* @return array | |
* The processed element. | |
*/ | |
public static function processPattern(&$element, FormStateInterface $form_state, &$complete_form) { | |
if (isset($element['#pattern']) && !isset($element['#attributes']['pattern'])) { | |
$element['#attributes']['pattern'] = $element['#pattern']; | |
$element['#element_validate'][] = array(get_called_class(), 'validatePattern'); | |
} | |
return $element; | |
} | |
/** | |
* #element_validate callback for #pattern form element property. | |
* | |
* @param $element | |
* An associative array containing the properties and children of the | |
* generic form element. | |
* @param $form_state | |
* The current state of the form. | |
* @param array $complete_form | |
* The complete form structure. | |
*/ | |
public static function validatePattern(&$element, FormStateInterface $form_state, &$complete_form) { | |
if ($element['#value'] !== '') { | |
// The pattern must match the entire string and should have the same | |
// behavior as the RegExp object in ECMA 262. | |
// - Use bracket-style delimiters to avoid introducing a special delimiter | |
// character like '/' that would have to be escaped. | |
// - Put in brackets so that the pattern can't interfere with what's | |
// prepended and appended. | |
$pattern = '{^(?:' . $element['#pattern'] . ')$}'; | |
if (!preg_match($pattern, $element['#value'])) { | |
$form_state->setError($element, t('%name field is not in the right format.', array('%name' => $element['#title']))); | |
} | |
} | |
} | |
/** | |
* Adds autocomplete functionality to elements. | |
* | |
* This sets up autocomplete functionality for elements with an | |
* #autocomplete_route_name property, using the #autocomplete_route_parameters | |
* property if present. | |
* | |
* For example, suppose your autocomplete route name is | |
* 'mymodule.autocomplete' and its path is | |
* '/mymodule/autocomplete/{a}/{b}'. In a form array, you would create a text | |
* field with properties: | |
* @code | |
* '#autocomplete_route_name' => 'mymodule.autocomplete', | |
* '#autocomplete_route_parameters' => array('a' => $some_key, 'b' => $some_id), | |
* @endcode | |
* If the user types "keywords" in that field, the full path called would be: | |
* 'mymodule_autocomplete/$some_key/$some_id?q=keywords' | |
* | |
* @param array $element | |
* The form element to process. Properties used: | |
* - #autocomplete_route_name: A route to be used as callback URL by the | |
* autocomplete JavaScript library. | |
* - #autocomplete_route_parameters: The parameters to be used in | |
* conjunction with the route name. | |
* @param \Drupal\Core\Form\FormStateInterface $form_state | |
* The current state of the form. | |
* @param array $complete_form | |
* The complete form structure. | |
* | |
* @return array | |
* The form element. | |
*/ | |
public static function processAutocomplete(&$element, FormStateInterface $form_state, &$complete_form) { | |
$url = NULL; | |
$access = FALSE; | |
if (!empty($element['#autocomplete_route_name'])) { | |
$parameters = isset($element['#autocomplete_route_parameters']) ? $element['#autocomplete_route_parameters'] : array(); | |
$url = Url::fromRoute($element['#autocomplete_route_name'], $parameters)->toString(TRUE); | |
/** @var \Drupal\Core\Access\AccessManagerInterface $access_manager */ | |
$access_manager = \Drupal::service('access_manager'); | |
$access = $access_manager->checkNamedRoute($element['#autocomplete_route_name'], $parameters, \Drupal::currentUser(), TRUE); | |
} | |
if ($access) { | |
$metadata = BubbleableMetadata::createFromRenderArray($element); | |
if ($access->isAllowed()) { | |
$element['#attributes']['class'][] = 'form-autocomplete'; | |
$metadata->addAttachments(['library' => ['core/drupal.autocomplete']]); | |
// Provide a data attribute for the JavaScript behavior to bind to. | |
$element['#attributes']['data-autocomplete-path'] = $url->getGeneratedUrl(); | |
$metadata = $metadata->merge($url); | |
} | |
$metadata | |
->merge(BubbleableMetadata::createFromObject($access)) | |
->applyTo($element); | |
} | |
return $element; | |
} | |
} |