123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- <?php
- 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\Core\Form\FormHelper::processStates() 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'][] = [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.', ['%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'] : [];
- $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;
- }
- }
|