FormBuilderInterface.php 15.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
<?php

/**
 * @file
 * Contains \Drupal\Core\Form\FormBuilderInterface.
 */

namespace Drupal\Core\Form;

/**
 * Provides an interface for form building and processing.
 */
13
interface FormBuilderInterface {
14 15

  /**
16
   * Determines the ID of a form.
17 18
   *
   * @param \Drupal\Core\Form\FormInterface|string $form_arg
19
   *   The value is identical to that of self::getForm()'s $form_arg argument.
20 21
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
22 23 24 25
   *
   * @return string
   *   The unique string identifying the desired form.
   */
26
  public function getFormId($form_arg, FormStateInterface &$form_state);
27 28

  /**
29
   * Gets a renderable form array.
30 31 32 33 34 35
   *
   * This function should be used instead of self::buildForm() when $form_state
   * is not needed (i.e., when initially rendering the form) and is often
   * used as a menu callback.
   *
   * @param \Drupal\Core\Form\FormInterface|string $form_arg
36 37 38
   *   The value must be one of the following:
   *   - The name of a class that implements \Drupal\Core\Form\FormInterface.
   *   - An instance of a class that implements \Drupal\Core\Form\FormInterface.
39 40
   * @param ...
   *   Any additional arguments are passed on to the functions called by
41 42 43 44
   *   \Drupal::formBuilder()->getForm(), including the unique form constructor
   *   function. For example, the node_edit form requires that a node object is
   *   passed in here when it is called. These are available to implementations
   *   of hook_form_alter() and hook_form_FORM_ID_alter() as the array
45
   *   $form_state->getBuildInfo()['args'].
46 47 48 49
   *
   * @return array
   *   The form array.
   *
50
   * @see \Drupal\Core\Form\FormBuilderInterface::buildForm()
51 52 53 54 55 56 57 58 59 60
   */
  public function getForm($form_arg);

  /**
   * Builds and processes a form for a given form ID.
   *
   * The form may also be retrieved from the cache if the form was built in a
   * previous page-load. The form is then passed on for processing, validation
   * and submission if there is proper input.
   *
61
   * @param \Drupal\Core\Form\FormInterface|string $form_id
62 63 64
   *   The value must be one of the following:
   *   - The name of a class that implements \Drupal\Core\Form\FormInterface.
   *   - An instance of a class that implements \Drupal\Core\Form\FormInterface.
65 66
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
67 68 69 70 71 72 73
   *
   * @return array
   *   The rendered form. This function may also perform a redirect and hence
   *   may not return at all depending upon the $form_state flags that were set.
   *
   * @see self::redirectForm()
   */
74
  public function buildForm($form_id, FormStateInterface &$form_state);
75 76 77 78 79 80 81

  /**
   * Constructs a new $form from the information in $form_state.
   *
   * This is the key function for making multi-step forms advance from step to
   * step. It is called by self::processForm() when all user input processing,
   * including calling validation and submission handlers, for the request is
82 83 84 85
   * finished. If a validate or submit handler set $form_state->isRebuilding()
   * to TRUE, and if other conditions don't preempt a rebuild from happening,
   * then this function is called to generate a new $form, the next step in the
   * form workflow, to be returned for rendering.
86 87 88 89 90 91 92 93
   *
   * Ajax form submissions are almost always multi-step workflows, so that is
   * one common use-case during which form rebuilding occurs. See
   * Drupal\system\FormAjaxController::content() for more information about
   * creating Ajax-enabled forms.
   *
   * @param string $form_id
   *   The unique string identifying the desired form. If a function with that
94
   *   name exists, it is called to build the form array.
95 96
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form.
97 98 99 100
   * @param array|null $old_form
   *   (optional) A previously built $form. Used to retain the #build_id and
   *   #action properties in Ajax callbacks and similar partial form rebuilds.
   *   The only properties copied from $old_form are the ones which both exist
101
   *   in $old_form and for which $form_state->getRebuildInfo()['copy'][PROPERTY]
102 103 104 105 106 107 108 109 110 111
   *   is TRUE. If $old_form is not passed, the entire $form is rebuilt freshly.
   *   'rebuild_info' needs to be a separate top-level property next to
   *   'build_info', since the contained data must not be cached.
   *
   * @return array
   *   The newly built form.
   *
   * @see self::processForm()
   * @see \Drupal\system\FormAjaxController::content()
   */
112
  public function rebuildForm($form_id, FormStateInterface &$form_state, $old_form = NULL);
113 114 115 116 117 118 119 120 121

  /**
   * Retrieves, populates, and processes a form.
   *
   * This function allows you to supply values for form elements and submit a
   * form for processing. Compare to self::getForm(), which also builds and
   * processes a form, but does not allow you to supply values.
   *
   * There is no return value, but you can check to see if there are errors
122
   * by calling $form_state->getErrors().
123 124 125 126
   *
   * @param \Drupal\Core\Form\FormInterface|string $form_arg
   *   A form object to use to build the form, or the unique string identifying
   *   the desired form. If $form_arg is a string and a function with that
127
   *   name exists, it is called to build the form array.
128
   * @param $form_state
129
   *   The current state of the form. Most important is the
130
   *   $form_state->getValues() collection, a tree of data used to simulate the
131
   *   incoming \Drupal::request()->request information from a user's form
132
   *   submission. If a key is not filled in $form_state->getValues(), then the
133 134 135 136
   *   default value of the respective element is used. To submit an unchecked
   *   checkbox or other control that browsers submit by not having a
   *   \Drupal::request()->request entry, include the key, but set the value to
   *   NULL.
137 138 139 140 141 142 143 144 145
   * @param ...
   *   Any additional arguments are passed on to the functions called by
   *   self::submitForm(), including the unique form constructor function.
   *   For example, the node_edit form requires that a node object be passed
   *   in here when it is called. Arguments that need to be passed by reference
   *   should not be included here, but rather placed directly in the
   *   $form_state build info array so that the reference can be preserved. For
   *   example, a form builder function with the following signature:
   *   @code
146
   *   function mymodule_form($form, FormStateInterface &$form_state, &$object) {
147 148 149 150
   *   }
   *   @endcode
   *   would be called via self::submitForm() as follows:
   *   @code
151 152
   *   $form_state->setValues($my_form_values);
   *   $form_state->addBuildInfo('args', [&$object]);
153 154 155 156 157
   *   drupal_form_submit('mymodule_form', $form_state);
   *   @endcode
   * For example:
   * @code
   * // register a new user
158
   * $form_state = new FormState();
159 160 161 162 163
   * $values['name'] = 'robo-user';
   * $values['mail'] = 'robouser@example.com';
   * $values['pass']['pass1'] = 'password';
   * $values['pass']['pass2'] = 'password';
   * $values['op'] = t('Create new account');
164
   * $form_state->setValues($values);
165 166 167
   * drupal_form_submit('user_register_form', $form_state);
   * @endcode
   */
168
  public function submitForm($form_arg, FormStateInterface &$form_state);
169 170 171 172 173 174 175

  /**
   * Retrieves the structured array that defines a given form.
   *
   * @param string $form_id
   *   The unique string identifying the desired form. If a function
   *   with that name exists, it is called to build the form array.
176 177 178 179
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form, including the additional arguments to
   *   self::getForm() or self::submitForm() in the 'args' component of the
   *   array.
180 181 182
   *
   * @return mixed|\Symfony\Component\HttpFoundation\Response
   */
183
  public function retrieveForm($form_id, FormStateInterface &$form_state);
184 185 186 187 188 189 190 191 192 193 194

  /**
   * Processes a form submission.
   *
   * This function is the heart of form API. The form gets built, validated and
   * in appropriate cases, submitted and rebuilt.
   *
   * @param string $form_id
   *   The unique string identifying the current form.
   * @param array $form
   *   An associative array containing the structure of the form.
195 196 197 198 199
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form. This includes the current persistent
   *   storage data for the form, and any data passed along by earlier steps
   *   when displaying a multi-step form. Additional information, like the
   *   sanitized \Drupal::request()->request data, is also accumulated here.
200 201 202
   *
   * @return \Symfony\Component\HttpFoundation\RedirectResponse|null
   */
203
  public function processForm($form_id, &$form, FormStateInterface &$form_state);
204 205 206 207 208 209 210 211 212 213 214 215

  /**
   * Prepares a structured form array.
   *
   * Adds required elements, executes any hook_form_alter functions, and
   * optionally inserts a validation token to prevent tampering.
   *
   * @param string $form_id
   *   A unique string identifying the form for validation, submission,
   *   theming, and hook_form_alter functions.
   * @param array $form
   *   An associative array containing the structure of the form.
216 217 218
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form. Passed in here so that hook_form_alter()
   *   calls can use it, as well.
219
   */
220
  public function prepareForm($form_id, &$form, FormStateInterface &$form_state);
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235

  /**
   * Builds and processes all elements in the structured form array.
   *
   * Adds any required properties to each element, maps the incoming input data
   * to the proper elements, and executes any #process handlers attached to a
   * specific element.
   *
   * This is one of the three primary functions that recursively iterates a form
   * array. This one does it for completing the form building process. The other
   * two are self::doValidateForm() (invoked via self::validateForm() and used
   * to invoke validation logic for each element) and drupal_render() (for
   * rendering each element). Each of these three pipelines provides ample
   * opportunity for modules to customize what happens. For example, during this
   * function's life cycle, the following functions get called for each element:
236
   * - $element['#value_callback']: A callable that implements how user input is
237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
   *   mapped to an element's #value property. This defaults to a function named
   *   'form_type_TYPE_value' where TYPE is $element['#type'].
   * - $element['#process']: An array of functions called after user input has
   *   been mapped to the element's #value property. These functions can be used
   *   to dynamically add child elements: for example, for the 'date' element
   *   type, one of the functions in this array is form_process_datetime(),
   *   which adds the individual 'date', and 'time'. child elements. These
   *   functions can also be used to set additional properties or implement
   *   special logic other than adding child elements: for example, for the
   *   'details' element type, one of the functions in this array is
   *   form_process_details(), which adds the attributes and JavaScript needed
   *   to make the details work in older browsers. The #process functions are
   *   called in preorder traversal, meaning they are called for the parent
   *   element first, then for the child elements.
   * - $element['#after_build']: An array of callables called after
   *   self::doBuildForm() is done with its processing of the element. These are
   *   called in postorder traversal, meaning they are called for the child
   *   elements first, then for the parent element.
   * There are similar properties containing callback functions invoked by
   * self::doValidateForm() and drupal_render(), appropriate for those
   * operations.
   *
   * Developers are strongly encouraged to integrate the functionality needed by
   * their form or module within one of these three pipelines, using the
   * appropriate callback property, rather than implementing their own recursive
   * traversal of a form array. This facilitates proper integration between
   * multiple modules. For example, module developers are familiar with the
   * relative order in which hook_form_alter() implementations and #process
   * functions run. A custom traversal function that affects the building of a
   * form is likely to not integrate with hook_form_alter() and #process in the
   * expected way. Also, deep recursion within PHP is both slow and memory
   * intensive, so it is best to minimize how often it's done.
   *
   * As stated above, each element's #process functions are executed after its
   * #value has been set. This enables those functions to execute conditional
   * logic based on the current value. However, all of self::doBuildForm() runs
   * before self::validateForm() is called, so during #process function
   * execution, the element's #value has not yet been validated, so any code
   * that requires validated values must reside within a submit handler.
   *
   * As a security measure, user input is used for an element's #value only if
   * the element exists within $form, is not disabled (as per the #disabled
   * property), and can be accessed (as per the #access property, except that
   * forms submitted using self::submitForm() bypass #access restrictions). When
   * user input is ignored due to #disabled and #access restrictions, the
   * element's default value is used.
   *
   * Because of the preorder traversal, where #process functions of an element
   * run before user input for its child elements is processed, and because of
   * the Form API security of user input processing with respect to #access and
   * #disabled described above, this generally means that #process functions
   * should not use an element's (unvalidated) #value to affect the #disabled or
   * #access of child elements. Use-cases where a developer may be tempted to
   * implement such conditional logic usually fall into one of two categories:
   * - Where user input from the current submission must affect the structure of
   *   a form, including properties like #access and #disabled that affect how
   *   the next submission needs to be processed, a multi-step workflow is
   *   needed. This is most commonly implemented with a submit handler setting
   *   persistent data within $form_state based on *validated* values in
296 297
   *   $form_state->getValues() and checking $form_state->isRebuilding(). The
   *   form building functions must then be implemented to use the $form_state
298 299 300 301 302 303 304 305 306 307 308
   *   to rebuild the form with the structure appropriate for the new state.
   * - Where user input must affect the rendering of the form without affecting
   *   its structure, the necessary conditional rendering logic should reside
   *   within functions that run during the rendering phase (#pre_render,
   *   #theme, #theme_wrappers, and #post_render).
   *
   * @param string $form_id
   *   A unique string identifying the form for validation, submission,
   *   theming, and hook_form_alter functions.
   * @param array $element
   *   An associative array containing the structure of the current element.
309 310 311 312
   * @param \Drupal\Core\Form\FormStateInterface $form_state
   *   The current state of the form. In this context, it is used to accumulate
   *   information about which button was clicked when the form was submitted,
   *   as well as the sanitized \Drupal::request()->request data.
313 314 315
   *
   * @return array
   */
316
  public function doBuildForm($form_id, &$element, FormStateInterface &$form_state);
317 318

}