Issue #2257835 by tim.plunkett, sun, Jalandhar: Move form submission logic out of FormBuilder into a new class.
parent
5f79a75cbc
commit
120a1da34c
|
@ -119,10 +119,13 @@ services:
|
|||
arguments: [default]
|
||||
form_builder:
|
||||
class: Drupal\Core\Form\FormBuilder
|
||||
arguments: ['@form_validator', '@module_handler', '@keyvalue.expirable', '@event_dispatcher', '@url_generator', '@request_stack', '@?csrf_token', '@?http_kernel']
|
||||
arguments: ['@form_validator', '@form_submitter', '@module_handler', '@keyvalue.expirable', '@event_dispatcher', '@request_stack', '@?csrf_token', '@?http_kernel']
|
||||
form_validator:
|
||||
class: Drupal\Core\Form\FormValidator
|
||||
arguments: ['@request_stack', '@string_translation', '@csrf_token']
|
||||
form_submitter:
|
||||
class: Drupal\Core\Form\FormSubmitter
|
||||
arguments: ['@request_stack', '@url_generator']
|
||||
keyvalue:
|
||||
class: Drupal\Core\KeyValueStore\KeyValueFactory
|
||||
arguments: ['@service_container', '@settings']
|
||||
|
|
|
@ -334,27 +334,27 @@ function drupal_validate_form($form_id, &$form, &$form_state) {
|
|||
* Redirects the user to a URL after a form has been processed.
|
||||
*
|
||||
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
|
||||
* Use \Drupal::formBuilder()->redirectForm().
|
||||
* Use \Drupal::service('form_submitter')->redirectForm().
|
||||
*
|
||||
* @see \Drupal\Core\Form\FormBuilderInterface::redirectForm().
|
||||
* @see \Drupal\Core\Form\FormSubmitterInterface::redirectForm().
|
||||
*/
|
||||
function drupal_redirect_form($form_state) {
|
||||
return \Drupal::formBuilder()->redirectForm($form_state);
|
||||
return \Drupal::service('form_submitter')->redirectForm($form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes custom validation and submission handlers for a given form.
|
||||
*
|
||||
* @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
|
||||
* Use either \Drupal::formBuilder()->executeSubmitHandlers() or
|
||||
* Use either \Drupal::service('form_submitter')->executeSubmitHandlers() or
|
||||
* \Drupal::service('form_validator')->executeValidateHandlers().
|
||||
*
|
||||
* @see \Drupal\Core\Form\FormBuilderInterface::executeSubmitHandlers()
|
||||
* @see \Drupal\Core\Form\FormSubmitterInterface::executeSubmitHandlers()
|
||||
* @see \Drupal\Core\Form\FormValidatorInterface::executeValidateHandlers()
|
||||
*/
|
||||
function form_execute_handlers($type, &$form, &$form_state) {
|
||||
if ($type == 'submit') {
|
||||
\Drupal::formBuilder()->executeSubmitHandlers($form, $form_state);
|
||||
\Drupal::service('form_submitter')->executeSubmitHandlers($form, $form_state);
|
||||
}
|
||||
elseif ($type == 'validate') {
|
||||
\Drupal::service('form_validator')->executeValidateHandlers($form, $form_state);
|
||||
|
|
|
@ -15,11 +15,8 @@ use Drupal\Core\Extension\ModuleHandlerInterface;
|
|||
use Drupal\Core\HttpKernel;
|
||||
use Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface;
|
||||
use Drupal\Core\Render\Element;
|
||||
use Drupal\Core\Routing\UrlGeneratorInterface;
|
||||
use Drupal\Core\Site\Settings;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
|
@ -29,7 +26,7 @@ use Symfony\Component\HttpKernel\KernelEvents;
|
|||
/**
|
||||
* Provides form building and processing.
|
||||
*/
|
||||
class FormBuilder implements FormBuilderInterface, FormValidatorInterface {
|
||||
class FormBuilder implements FormBuilderInterface, FormValidatorInterface, FormSubmitterInterface {
|
||||
|
||||
/**
|
||||
* The module handler.
|
||||
|
@ -52,13 +49,6 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface {
|
|||
*/
|
||||
protected $eventDispatcher;
|
||||
|
||||
/**
|
||||
* The URL generator.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
*
|
||||
|
@ -92,19 +82,24 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface {
|
|||
*/
|
||||
protected $formValidator;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Form\FormSubmitterInterface
|
||||
*/
|
||||
protected $formSubmitter;
|
||||
|
||||
/**
|
||||
* Constructs a new FormBuilder.
|
||||
*
|
||||
* @param \Drupal\Core\Form\FormValidatorInterface $form_validator
|
||||
* The form validator.
|
||||
* @param \Drupal\Core\Form\FormSubmitterInterface $form_submitter
|
||||
* The form submission processor.
|
||||
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
|
||||
* The module handler.
|
||||
* @param \Drupal\Core\KeyValueStore\KeyValueExpirableFactoryInterface $key_value_expirable_factory
|
||||
* The keyvalue expirable factory.
|
||||
* @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $event_dispatcher
|
||||
* The event dispatcher.
|
||||
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
|
||||
* The URL generator.
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
||||
* The request stack.
|
||||
* @param \Drupal\Core\Access\CsrfTokenGenerator $csrf_token
|
||||
|
@ -112,12 +107,12 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface {
|
|||
* @param \Drupal\Core\HttpKernel $http_kernel
|
||||
* The HTTP kernel.
|
||||
*/
|
||||
public function __construct(FormValidatorInterface $form_validator, ModuleHandlerInterface $module_handler, KeyValueExpirableFactoryInterface $key_value_expirable_factory, EventDispatcherInterface $event_dispatcher, UrlGeneratorInterface $url_generator, RequestStack $request_stack, CsrfTokenGenerator $csrf_token = NULL, HttpKernel $http_kernel = NULL) {
|
||||
public function __construct(FormValidatorInterface $form_validator, FormSubmitterInterface $form_submitter, ModuleHandlerInterface $module_handler, KeyValueExpirableFactoryInterface $key_value_expirable_factory, EventDispatcherInterface $event_dispatcher, RequestStack $request_stack, CsrfTokenGenerator $csrf_token = NULL, HttpKernel $http_kernel = NULL) {
|
||||
$this->formValidator = $form_validator;
|
||||
$this->formSubmitter = $form_submitter;
|
||||
$this->moduleHandler = $module_handler;
|
||||
$this->keyValueExpirableFactory = $key_value_expirable_factory;
|
||||
$this->eventDispatcher = $event_dispatcher;
|
||||
$this->urlGenerator = $url_generator;
|
||||
$this->requestStack = $request_stack;
|
||||
$this->csrfToken = $csrf_token;
|
||||
$this->httpKernel = $http_kernel;
|
||||
|
@ -555,53 +550,9 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface {
|
|||
$this->drupalStaticReset('drupal_html_id');
|
||||
}
|
||||
|
||||
// @todo Move into a dedicated class in https://drupal.org/node/2257835.
|
||||
if ($form_state['submitted'] && !$this->getAnyErrors() && !$form_state['rebuild']) {
|
||||
// Execute form submit handlers.
|
||||
$this->executeSubmitHandlers($form, $form_state);
|
||||
|
||||
// If batches were set in the submit handlers, we process them now,
|
||||
// possibly ending execution. We make sure we do not react to the batch
|
||||
// that is already being processed (if a batch operation performs a
|
||||
// self::submitForm).
|
||||
if ($batch = &$this->batchGet() && !isset($batch['current_set'])) {
|
||||
// Store $form_state information in the batch definition.
|
||||
// We need the full $form_state when either:
|
||||
// - Some submit handlers were saved to be called during batch
|
||||
// processing. See self::executeSubmitHandlers().
|
||||
// - The form is multistep.
|
||||
// In other cases, we only need the information expected by
|
||||
// self::redirectForm().
|
||||
if ($batch['has_form_submits'] || !empty($form_state['rebuild'])) {
|
||||
$batch['form_state'] = $form_state;
|
||||
}
|
||||
else {
|
||||
$batch['form_state'] = array_intersect_key($form_state, array_flip(array('programmed', 'rebuild', 'storage', 'no_redirect', 'redirect', 'redirect_route')));
|
||||
}
|
||||
|
||||
$batch['progressive'] = !$form_state['programmed'];
|
||||
$response = batch_process();
|
||||
if ($batch['progressive']) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Execution continues only for programmatic forms.
|
||||
// For 'regular' forms, we get redirected to the batch processing
|
||||
// page. Form redirection will be handled in _batch_finished(),
|
||||
// after the batch is processed.
|
||||
}
|
||||
|
||||
// Set a flag to indicate the the form has been processed and executed.
|
||||
$form_state['executed'] = TRUE;
|
||||
|
||||
// If no response has been set, process the form redirect.
|
||||
if (!isset($form_state['response']) && $redirect = $this->redirectForm($form_state)) {
|
||||
$form_state['response'] = $redirect;
|
||||
}
|
||||
|
||||
// If there is a response was set, return it instead of continuing.
|
||||
if (isset($form_state['response']) && $form_state['response'] instanceof Response) {
|
||||
return $form_state['response'];
|
||||
if (!$form_state['rebuild'] && !$this->formValidator->getAnyErrors()) {
|
||||
if ($submit_response = $this->formSubmitter->doSubmitForm($form, $form_state)) {
|
||||
return $submit_response;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -793,78 +744,7 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function redirectForm($form_state) {
|
||||
// Skip redirection for form submissions invoked via self::submitForm().
|
||||
if (!empty($form_state['programmed'])) {
|
||||
return;
|
||||
}
|
||||
// Skip redirection if rebuild is activated.
|
||||
if (!empty($form_state['rebuild'])) {
|
||||
return;
|
||||
}
|
||||
// Skip redirection if it was explicitly disallowed.
|
||||
if (!empty($form_state['no_redirect'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow using redirect responses directly if needed.
|
||||
if (isset($form_state['redirect']) && $form_state['redirect'] instanceof RedirectResponse) {
|
||||
return $form_state['redirect'];
|
||||
}
|
||||
|
||||
// Check for a route-based redirection.
|
||||
if (isset($form_state['redirect_route'])) {
|
||||
// @todo Remove once all redirects are converted to Url.
|
||||
if (!($form_state['redirect_route'] instanceof Url)) {
|
||||
$form_state['redirect_route'] += array(
|
||||
'route_parameters' => array(),
|
||||
'options' => array(),
|
||||
);
|
||||
$form_state['redirect_route'] = new Url($form_state['redirect_route']['route_name'], $form_state['redirect_route']['route_parameters'], $form_state['redirect_route']['options']);
|
||||
}
|
||||
|
||||
$form_state['redirect_route']->setAbsolute();
|
||||
return new RedirectResponse($form_state['redirect_route']->toString());
|
||||
}
|
||||
|
||||
// Only invoke a redirection if redirect value was not set to FALSE.
|
||||
if (!isset($form_state['redirect']) || $form_state['redirect'] !== FALSE) {
|
||||
if (isset($form_state['redirect'])) {
|
||||
if (is_array($form_state['redirect'])) {
|
||||
if (isset($form_state['redirect'][1])) {
|
||||
$options = $form_state['redirect'][1];
|
||||
}
|
||||
else {
|
||||
$options = array();
|
||||
}
|
||||
// Redirections should always use absolute URLs.
|
||||
$options['absolute'] = TRUE;
|
||||
if (isset($form_state['redirect'][2])) {
|
||||
$status_code = $form_state['redirect'][2];
|
||||
}
|
||||
else {
|
||||
$status_code = 302;
|
||||
}
|
||||
return new RedirectResponse($this->urlGenerator->generateFromPath($form_state['redirect'][0], $options), $status_code);
|
||||
}
|
||||
else {
|
||||
// This function can be called from the installer, which guarantees
|
||||
// that $redirect will always be a string, so catch that case here
|
||||
// and use the appropriate redirect function.
|
||||
if ($this->drupalInstallationAttempted()) {
|
||||
install_goto($form_state['redirect']);
|
||||
}
|
||||
else {
|
||||
return new RedirectResponse($this->urlGenerator->generateFromPath($form_state['redirect'], array('absolute' => TRUE)));
|
||||
}
|
||||
}
|
||||
}
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
$url = $this->urlGenerator->generateFromPath($request->attributes->get('_system_path'), array(
|
||||
'query' => $request->query->all(),
|
||||
'absolute' => TRUE,
|
||||
));
|
||||
return new RedirectResponse($url);
|
||||
}
|
||||
return $this->formSubmitter->redirectForm($form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -878,33 +758,14 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface {
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function executeSubmitHandlers(&$form, &$form_state) {
|
||||
// If there was a button pressed, use its handlers.
|
||||
if (isset($form_state['submit_handlers'])) {
|
||||
$handlers = $form_state['submit_handlers'];
|
||||
}
|
||||
// Otherwise, check for a form-level handler.
|
||||
elseif (isset($form['#submit'])) {
|
||||
$handlers = $form['#submit'];
|
||||
}
|
||||
else {
|
||||
$handlers = array();
|
||||
}
|
||||
$this->formSubmitter->executeSubmitHandlers($form, $form_state);
|
||||
}
|
||||
|
||||
foreach ($handlers as $function) {
|
||||
// Check if a previous _submit handler has set a batch, but make sure we
|
||||
// do not react to a batch that is already being processed (for instance
|
||||
// if a batch operation performs a self::submitForm()).
|
||||
if (($batch = &$this->batchGet()) && !isset($batch['id'])) {
|
||||
// Some previous submit handler has set a batch. To ensure correct
|
||||
// execution order, store the call in a special 'control' batch set.
|
||||
// See _batch_next_set().
|
||||
$batch['sets'][] = array('form_submit' => $function);
|
||||
$batch['has_form_submits'] = TRUE;
|
||||
}
|
||||
else {
|
||||
call_user_func_array($function, array(&$form, &$form_state));
|
||||
}
|
||||
}
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function doSubmitForm(&$form, &$form_state) {
|
||||
throw new \LogicException('Use FormBuilderInterface::processForm() instead.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1378,15 +1239,6 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface {
|
|||
return element_info($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps drupal_installation_attempted().
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function drupalInstallationAttempted() {
|
||||
return drupal_installation_attempted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps drupal_html_class().
|
||||
*
|
||||
|
@ -1430,11 +1282,4 @@ class FormBuilder implements FormBuilderInterface, FormValidatorInterface {
|
|||
return $this->currentUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps batch_get().
|
||||
*/
|
||||
protected function &batchGet() {
|
||||
return batch_get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -385,83 +385,6 @@ interface FormBuilderInterface extends FormErrorInterface {
|
|||
*/
|
||||
public function prepareForm($form_id, &$form, &$form_state);
|
||||
|
||||
/**
|
||||
* Redirects the user to a URL after a form has been processed.
|
||||
*
|
||||
* After a form is submitted and processed, normally the user should be
|
||||
* redirected to a new destination page. This function figures out what that
|
||||
* destination should be, based on the $form_state array and the 'destination'
|
||||
* query string in the request URL, and redirects the user there.
|
||||
*
|
||||
* Usually (for exceptions, see below) $form_state['redirect'] determines
|
||||
* where to redirect the user. This can be set either to a string (the path to
|
||||
* redirect to), or an array of arguments for url(). If
|
||||
* $form_state['redirect'] is missing, the user is usually (again, see below
|
||||
* for exceptions) redirected back to the page they came from, where they
|
||||
* should see a fresh, unpopulated copy of the form.
|
||||
*
|
||||
* Here is an example of how to set up a form to redirect to the path 'node':
|
||||
* @code
|
||||
* $form_state['redirect'] = 'node';
|
||||
* @endcode
|
||||
* And here is an example of how to redirect to 'node/123?foo=bar#baz':
|
||||
* @code
|
||||
* $form_state['redirect'] = array(
|
||||
* 'node/123',
|
||||
* array(
|
||||
* 'query' => array(
|
||||
* 'foo' => 'bar',
|
||||
* ),
|
||||
* 'fragment' => 'baz',
|
||||
* ),
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
* There are several exceptions to the "usual" behavior described above:
|
||||
* - If $form_state['programmed'] is TRUE, the form submission was usually
|
||||
* invoked via self::submitForm(), so any redirection would break the script
|
||||
* that invoked self::submitForm() and no redirection is done.
|
||||
* - If $form_state['rebuild'] is TRUE, the form is being rebuilt, and no
|
||||
* redirection is done.
|
||||
* - If $form_state['no_redirect'] is TRUE, redirection is disabled. This is
|
||||
* set, for instance, by \Drupal\system\FormAjaxController::getForm() to
|
||||
* prevent redirection in Ajax callbacks. $form_state['no_redirect'] should
|
||||
* never be set or altered by form builder functions or form validation
|
||||
* or submit handlers.
|
||||
* - If $form_state['redirect'] is set to FALSE, redirection is disabled.
|
||||
* - If none of the above conditions has prevented redirection, then the
|
||||
* redirect is accomplished by returning a RedirectResponse, passing in the
|
||||
* value of $form_state['redirect'] if it is set, or the current path if it
|
||||
* is not. RedirectResponse preferentially uses the value of
|
||||
* \Drupal::request->query->get('destination') (the 'destination' URL query
|
||||
* string) if it is present, so this will override any values set by
|
||||
* $form_state['redirect'].
|
||||
*
|
||||
* @param $form_state
|
||||
* An associative array containing the current state of the form.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|null
|
||||
*
|
||||
* @see self::processForm()
|
||||
* @see self::buildForm()
|
||||
*/
|
||||
public function redirectForm($form_state);
|
||||
|
||||
/**
|
||||
* Executes custom submission handlers for a given form.
|
||||
*
|
||||
* Button-specific handlers are checked first. If none exist, the function
|
||||
* falls back to form-level handlers.
|
||||
*
|
||||
* @param $form
|
||||
* An associative array containing the structure of the form.
|
||||
* @param $form_state
|
||||
* A keyed array containing the current state of the form. If the user
|
||||
* submitted the form by clicking a button with custom handler functions
|
||||
* defined, those handlers will be stored here.
|
||||
*/
|
||||
public function executeSubmitHandlers(&$form, &$form_state);
|
||||
|
||||
/**
|
||||
* Builds and processes all elements in the structured form array.
|
||||
*
|
||||
|
|
|
@ -0,0 +1,232 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Form\FormSubmitter.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Form;
|
||||
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Drupal\Core\Routing\UrlGeneratorInterface;
|
||||
|
||||
/**
|
||||
* Provides submission processing for forms.
|
||||
*/
|
||||
class FormSubmitter implements FormSubmitterInterface {
|
||||
|
||||
/**
|
||||
* The URL generator.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\RequestStack
|
||||
*/
|
||||
protected $requestStack;
|
||||
|
||||
/**
|
||||
* Constructs a new FormValidator.
|
||||
*
|
||||
* @param \Symfony\Component\HttpFoundation\RequestStack $request_stack
|
||||
* The request stack.
|
||||
* @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator
|
||||
*/
|
||||
public function __construct(RequestStack $request_stack, UrlGeneratorInterface $url_generator) {
|
||||
$this->requestStack = $request_stack;
|
||||
$this->urlGenerator = $url_generator;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function doSubmitForm(&$form, &$form_state) {
|
||||
if (!$form_state['submitted']) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute form submit handlers.
|
||||
$this->executeSubmitHandlers($form, $form_state);
|
||||
|
||||
// If batches were set in the submit handlers, we process them now,
|
||||
// possibly ending execution. We make sure we do not react to the batch
|
||||
// that is already being processed (if a batch operation performs a
|
||||
// \Drupal\Core\Form\FormBuilderInterface::submitForm).
|
||||
if ($batch = &$this->batchGet() && !isset($batch['current_set'])) {
|
||||
// Store $form_state information in the batch definition.
|
||||
// We need the full $form_state when either:
|
||||
// - Some submit handlers were saved to be called during batch
|
||||
// processing. See self::executeSubmitHandlers().
|
||||
// - The form is multistep.
|
||||
// In other cases, we only need the information expected by
|
||||
// self::redirectForm().
|
||||
if ($batch['has_form_submits'] || !empty($form_state['rebuild'])) {
|
||||
$batch['form_state'] = $form_state;
|
||||
}
|
||||
else {
|
||||
$batch['form_state'] = array_intersect_key($form_state, array_flip(array('programmed', 'rebuild', 'storage', 'no_redirect', 'redirect', 'redirect_route')));
|
||||
}
|
||||
|
||||
$batch['progressive'] = !$form_state['programmed'];
|
||||
$response = batch_process();
|
||||
if ($batch['progressive']) {
|
||||
return $response;
|
||||
}
|
||||
|
||||
// Execution continues only for programmatic forms.
|
||||
// For 'regular' forms, we get redirected to the batch processing
|
||||
// page. Form redirection will be handled in _batch_finished(),
|
||||
// after the batch is processed.
|
||||
}
|
||||
|
||||
// Set a flag to indicate the the form has been processed and executed.
|
||||
$form_state['executed'] = TRUE;
|
||||
|
||||
// If no response has been set, process the form redirect.
|
||||
if (!isset($form_state['response']) && $redirect = $this->redirectForm($form_state)) {
|
||||
$form_state['response'] = $redirect;
|
||||
}
|
||||
|
||||
// If there is a response was set, return it instead of continuing.
|
||||
if (isset($form_state['response']) && $form_state['response'] instanceof Response) {
|
||||
return $form_state['response'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function executeSubmitHandlers(&$form, &$form_state) {
|
||||
// If there was a button pressed, use its handlers.
|
||||
if (isset($form_state['submit_handlers'])) {
|
||||
$handlers = $form_state['submit_handlers'];
|
||||
}
|
||||
// Otherwise, check for a form-level handler.
|
||||
elseif (isset($form['#submit'])) {
|
||||
$handlers = $form['#submit'];
|
||||
}
|
||||
else {
|
||||
$handlers = array();
|
||||
}
|
||||
|
||||
foreach ($handlers as $function) {
|
||||
// Check if a previous _submit handler has set a batch, but make sure we
|
||||
// do not react to a batch that is already being processed (for instance
|
||||
// if a batch operation performs a
|
||||
// \Drupal\Core\Form\FormBuilderInterface::submitForm()).
|
||||
if (($batch = &$this->batchGet()) && !isset($batch['id'])) {
|
||||
// Some previous submit handler has set a batch. To ensure correct
|
||||
// execution order, store the call in a special 'control' batch set.
|
||||
// See _batch_next_set().
|
||||
$batch['sets'][] = array('form_submit' => $function);
|
||||
$batch['has_form_submits'] = TRUE;
|
||||
}
|
||||
else {
|
||||
call_user_func_array($function, array(&$form, &$form_state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function redirectForm($form_state) {
|
||||
// Skip redirection for form submissions invoked via
|
||||
// \Drupal\Core\Form\FormBuilderInterface::submitForm().
|
||||
if (!empty($form_state['programmed'])) {
|
||||
return;
|
||||
}
|
||||
// Skip redirection if rebuild is activated.
|
||||
if (!empty($form_state['rebuild'])) {
|
||||
return;
|
||||
}
|
||||
// Skip redirection if it was explicitly disallowed.
|
||||
if (!empty($form_state['no_redirect'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Allow using redirect responses directly if needed.
|
||||
if (isset($form_state['redirect']) && $form_state['redirect'] instanceof RedirectResponse) {
|
||||
return $form_state['redirect'];
|
||||
}
|
||||
|
||||
// Check for a route-based redirection.
|
||||
if (isset($form_state['redirect_route'])) {
|
||||
// @todo Remove once all redirects are converted to Url.
|
||||
if (!($form_state['redirect_route'] instanceof Url)) {
|
||||
$form_state['redirect_route'] += array(
|
||||
'route_parameters' => array(),
|
||||
'options' => array(),
|
||||
);
|
||||
$form_state['redirect_route'] = new Url($form_state['redirect_route']['route_name'], $form_state['redirect_route']['route_parameters'], $form_state['redirect_route']['options']);
|
||||
}
|
||||
|
||||
$form_state['redirect_route']->setAbsolute();
|
||||
return new RedirectResponse($form_state['redirect_route']->toString());
|
||||
}
|
||||
|
||||
// Only invoke a redirection if redirect value was not set to FALSE.
|
||||
if (!isset($form_state['redirect']) || $form_state['redirect'] !== FALSE) {
|
||||
if (isset($form_state['redirect'])) {
|
||||
if (is_array($form_state['redirect'])) {
|
||||
if (isset($form_state['redirect'][1])) {
|
||||
$options = $form_state['redirect'][1];
|
||||
}
|
||||
else {
|
||||
$options = array();
|
||||
}
|
||||
// Redirections should always use absolute URLs.
|
||||
$options['absolute'] = TRUE;
|
||||
if (isset($form_state['redirect'][2])) {
|
||||
$status_code = $form_state['redirect'][2];
|
||||
}
|
||||
else {
|
||||
$status_code = 302;
|
||||
}
|
||||
return new RedirectResponse($this->urlGenerator->generateFromPath($form_state['redirect'][0], $options), $status_code);
|
||||
}
|
||||
else {
|
||||
// This function can be called from the installer, which guarantees
|
||||
// that $redirect will always be a string, so catch that case here
|
||||
// and use the appropriate redirect function.
|
||||
if ($this->drupalInstallationAttempted()) {
|
||||
install_goto($form_state['redirect']);
|
||||
}
|
||||
else {
|
||||
return new RedirectResponse($this->urlGenerator->generateFromPath($form_state['redirect'], array('absolute' => TRUE)));
|
||||
}
|
||||
}
|
||||
}
|
||||
$request = $this->requestStack->getCurrentRequest();
|
||||
$url = $this->urlGenerator->generateFromPath($request->attributes->get('_system_path'), array(
|
||||
'query' => $request->query->all(),
|
||||
'absolute' => TRUE,
|
||||
));
|
||||
return new RedirectResponse($url);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps drupal_installation_attempted().
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function drupalInstallationAttempted() {
|
||||
return drupal_installation_attempted();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps batch_get().
|
||||
*/
|
||||
protected function &batchGet() {
|
||||
return batch_get();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\Form\FormSubmitterInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\Form;
|
||||
|
||||
/**
|
||||
* Provides an interface for processing form submissions.
|
||||
*/
|
||||
interface FormSubmitterInterface {
|
||||
|
||||
/**
|
||||
* Handles the submitted form, executing callbacks and processing responses.
|
||||
*
|
||||
* @param array $form
|
||||
* An associative array containing the structure of the form.
|
||||
* @param array $form_state
|
||||
* An associative array containing the current state of the form.
|
||||
*
|
||||
* @return null|\Symfony\Component\HttpFoundation\Response
|
||||
* If a response was set by a submit handler, or if the form needs to
|
||||
* redirect, a Response object will be returned.
|
||||
*/
|
||||
public function doSubmitForm(&$form, &$form_state);
|
||||
|
||||
/**
|
||||
* Executes custom submission handlers for a given form.
|
||||
*
|
||||
* Button-specific handlers are checked first. If none exist, the function
|
||||
* falls back to form-level handlers.
|
||||
*
|
||||
* @param $form
|
||||
* An associative array containing the structure of the form.
|
||||
* @param $form_state
|
||||
* A keyed array containing the current state of the form. If the user
|
||||
* submitted the form by clicking a button with custom handler functions
|
||||
* defined, those handlers will be stored here.
|
||||
*/
|
||||
public function executeSubmitHandlers(&$form, &$form_state);
|
||||
|
||||
/**
|
||||
* Redirects the user to a URL after a form has been processed.
|
||||
*
|
||||
* After a form is submitted and processed, normally the user should be
|
||||
* redirected to a new destination page. This function figures out what that
|
||||
* destination should be, based on the $form_state array and the 'destination'
|
||||
* query string in the request URL, and redirects the user there.
|
||||
*
|
||||
* Usually (for exceptions, see below) $form_state['redirect'] determines
|
||||
* where to redirect the user. This can be set either to a string (the path to
|
||||
* redirect to), or an array of arguments for url(). If
|
||||
* $form_state['redirect'] is missing, the user is usually (again, see below
|
||||
* for exceptions) redirected back to the page they came from, where they
|
||||
* should see a fresh, unpopulated copy of the form.
|
||||
*
|
||||
* Here is an example of how to set up a form to redirect to the path 'node':
|
||||
* @code
|
||||
* $form_state['redirect'] = 'node';
|
||||
* @endcode
|
||||
* And here is an example of how to redirect to 'node/123?foo=bar#baz':
|
||||
* @code
|
||||
* $form_state['redirect'] = array(
|
||||
* 'node/123',
|
||||
* array(
|
||||
* 'query' => array(
|
||||
* 'foo' => 'bar',
|
||||
* ),
|
||||
* 'fragment' => 'baz',
|
||||
* ),
|
||||
* );
|
||||
* @endcode
|
||||
*
|
||||
* There are several exceptions to the "usual" behavior described above:
|
||||
* - If $form_state['programmed'] is TRUE, the form submission was usually
|
||||
* invoked via self::submitForm(), so any redirection would break the script
|
||||
* that invoked self::submitForm() and no redirection is done.
|
||||
* - If $form_state['rebuild'] is TRUE, the form is being rebuilt, and no
|
||||
* redirection is done.
|
||||
* - If $form_state['no_redirect'] is TRUE, redirection is disabled. This is
|
||||
* set, for instance, by \Drupal\system\FormAjaxController::getForm() to
|
||||
* prevent redirection in Ajax callbacks. $form_state['no_redirect'] should
|
||||
* never be set or altered by form builder functions or form validation
|
||||
* or submit handlers.
|
||||
* - If $form_state['redirect'] is set to FALSE, redirection is disabled.
|
||||
* - If none of the above conditions has prevented redirection, then the
|
||||
* redirect is accomplished by returning a RedirectResponse, passing in the
|
||||
* value of $form_state['redirect'] if it is set, or the current path if it
|
||||
* is not. RedirectResponse preferentially uses the value of
|
||||
* \Drupal::request->query->get('destination') (the 'destination' URL query
|
||||
* string) if it is present, so this will override any values set by
|
||||
* $form_state['redirect'].
|
||||
*
|
||||
* @param $form_state
|
||||
* An associative array containing the current state of the form.
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\RedirectResponse|null
|
||||
*
|
||||
* @see \Drupal\Core\Form\FormBuilderInterface::processForm()
|
||||
* @see \Drupal\Core\Form\FormBuilderInterface::buildForm()
|
||||
*/
|
||||
public function redirectForm($form_state);
|
||||
|
||||
}
|
|
@ -7,12 +7,9 @@
|
|||
|
||||
namespace Drupal\Tests\Core\Form {
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\DependencyInjection\ContainerInjectionInterface;
|
||||
use Drupal\Core\Form\FormInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
|
||||
/**
|
||||
* Tests the form builder.
|
||||
|
@ -35,17 +32,6 @@ class FormBuilderTest extends FormTestBase {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('url_generator', $this->urlGenerator);
|
||||
\Drupal::setContainer($container);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getFormId() method with a string based form ID.
|
||||
*/
|
||||
|
@ -219,140 +205,6 @@ class FormBuilderTest extends FormTestBase {
|
|||
}
|
||||
$this->assertSame($response, $form_state['response']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the redirectForm() method when a redirect is expected.
|
||||
*
|
||||
* @param array $form_state
|
||||
* An array of form state data to use for the redirect.
|
||||
* @param string $result
|
||||
* The URL the redirect is targeting.
|
||||
* @param int $status
|
||||
* (optional) The HTTP status code for the redirect.
|
||||
*
|
||||
* @dataProvider providerTestRedirectWithResult
|
||||
*/
|
||||
public function testRedirectWithResult($form_state, $result, $status = 302) {
|
||||
$this->urlGenerator->expects($this->once())
|
||||
->method('generateFromPath')
|
||||
->will($this->returnValueMap(array(
|
||||
array(NULL, array('query' => array(), 'absolute' => TRUE), '<front>'),
|
||||
array('foo', array('absolute' => TRUE), 'foo'),
|
||||
array('bar', array('query' => array('foo' => 'baz'), 'absolute' => TRUE), 'bar'),
|
||||
array('baz', array('absolute' => TRUE), 'baz'),
|
||||
))
|
||||
);
|
||||
|
||||
$form_state += $this->formBuilder->getFormStateDefaults();
|
||||
$redirect = $this->formBuilder->redirectForm($form_state);
|
||||
$this->assertSame($result, $redirect->getTargetUrl());
|
||||
$this->assertSame($status, $redirect->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the redirectForm() with redirect_route when a redirect is expected.
|
||||
*
|
||||
* @param array $form_state
|
||||
* An array of form state data to use for the redirect.
|
||||
* @param string $result
|
||||
* The URL the redirect is targeting.
|
||||
* @param int $status
|
||||
* (optional) The HTTP status code for the redirect.
|
||||
*
|
||||
* @dataProvider providerTestRedirectWithRouteWithResult
|
||||
*/
|
||||
public function testRedirectWithRouteWithResult($form_state, $result, $status = 302) {
|
||||
$this->urlGenerator->expects($this->once())
|
||||
->method('generateFromRoute')
|
||||
->will($this->returnValueMap(array(
|
||||
array('test_route_a', array(), array('absolute' => TRUE), 'test-route'),
|
||||
array('test_route_b', array('key' => 'value'), array('absolute' => TRUE), 'test-route/value'),
|
||||
))
|
||||
);
|
||||
|
||||
$form_state += $this->formBuilder->getFormStateDefaults();
|
||||
$redirect = $this->formBuilder->redirectForm($form_state);
|
||||
$this->assertSame($result, $redirect->getTargetUrl());
|
||||
$this->assertSame($status, $redirect->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the redirectForm() method with a response object.
|
||||
*/
|
||||
public function testRedirectWithResponseObject() {
|
||||
$redirect = new RedirectResponse('/example');
|
||||
$form_state['redirect'] = $redirect;
|
||||
|
||||
$form_state += $this->formBuilder->getFormStateDefaults();
|
||||
$result_redirect = $this->formBuilder->redirectForm($form_state);
|
||||
|
||||
$this->assertSame($redirect, $result_redirect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the redirectForm() method when no redirect is expected.
|
||||
*
|
||||
* @param array $form_state
|
||||
* An array of form state data to use for the redirect.
|
||||
*
|
||||
* @dataProvider providerTestRedirectWithoutResult
|
||||
*/
|
||||
public function testRedirectWithoutResult($form_state) {
|
||||
$this->urlGenerator->expects($this->never())
|
||||
->method('generateFromPath');
|
||||
$this->urlGenerator->expects($this->never())
|
||||
->method('generateFromRoute');
|
||||
$form_state += $this->formBuilder->getFormStateDefaults();
|
||||
$redirect = $this->formBuilder->redirectForm($form_state);
|
||||
$this->assertNull($redirect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing the redirectForm() method with a redirect.
|
||||
*
|
||||
* @return array
|
||||
* Returns some test data.
|
||||
*/
|
||||
public function providerTestRedirectWithResult() {
|
||||
return array(
|
||||
array(array(), '<front>'),
|
||||
array(array('redirect' => 'foo'), 'foo'),
|
||||
array(array('redirect' => array('foo')), 'foo'),
|
||||
array(array('redirect' => array('foo')), 'foo'),
|
||||
array(array('redirect' => array('bar', array('query' => array('foo' => 'baz')))), 'bar'),
|
||||
array(array('redirect' => array('baz', array(), 301)), 'baz', 301),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing the redirectForm() method with a route name.
|
||||
*
|
||||
* @return array
|
||||
* Returns some test data.
|
||||
*/
|
||||
public function providerTestRedirectWithRouteWithResult() {
|
||||
return array(
|
||||
array(array('redirect_route' => array('route_name' => 'test_route_a')), 'test-route'),
|
||||
array(array('redirect_route' => array('route_name' => 'test_route_b', 'route_parameters' => array('key' => 'value'))), 'test-route/value'),
|
||||
array(array('redirect_route' => new Url('test_route_b', array('key' => 'value'))), 'test-route/value'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing the redirectForm() method with no redirect.
|
||||
*
|
||||
* @return array
|
||||
* Returns some test data.
|
||||
*/
|
||||
public function providerTestRedirectWithoutResult() {
|
||||
return array(
|
||||
array(array('programmed' => TRUE)),
|
||||
array(array('rebuild' => TRUE)),
|
||||
array(array('no_redirect' => TRUE)),
|
||||
array(array('redirect' => FALSE)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the getForm() method with a string based form ID.
|
||||
*/
|
||||
|
@ -554,9 +406,6 @@ class FormBuilderTest extends FormTestBase {
|
|||
$form_id = 'test_form_id';
|
||||
$expected_form = $form_id();
|
||||
$expected_form['test']['#required'] = TRUE;
|
||||
$this->formValidator->expects($this->exactly(4))
|
||||
->method('getAnyErrors')
|
||||
->will($this->returnValue(TRUE));
|
||||
|
||||
// Mock a form object that will be built two times.
|
||||
$form_arg = $this->getMock('Drupal\Core\Form\FormInterface');
|
||||
|
|
|
@ -0,0 +1,291 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Tests\Core\Form\FormSubmitterTest.
|
||||
*/
|
||||
|
||||
namespace Drupal\Tests\Core\Form;
|
||||
|
||||
use Drupal\Core\DependencyInjection\ContainerBuilder;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Tests\UnitTestCase;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RequestStack;
|
||||
|
||||
/**
|
||||
* Tests the form submission handler.
|
||||
*
|
||||
* @coversDefaultClass \Drupal\Core\Form\FormSubmitter
|
||||
*
|
||||
* @group Drupal
|
||||
* @group Form
|
||||
*/
|
||||
class FormSubmitterTest extends UnitTestCase {
|
||||
|
||||
/**
|
||||
* The mocked URL generator.
|
||||
*
|
||||
* @var \PHPUnit_Framework_MockObject_MockObject|\Drupal\Core\Routing\UrlGeneratorInterface
|
||||
*/
|
||||
protected $urlGenerator;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function getInfo() {
|
||||
return array(
|
||||
'name' => 'Form submission test',
|
||||
'description' => 'Tests the form submission handler.',
|
||||
'group' => 'Form API',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
$this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::doSubmitForm
|
||||
*/
|
||||
public function testHandleFormSubmissionNotSubmitted() {
|
||||
$form_submitter = $this->getFormSubmitter();
|
||||
$form = array();
|
||||
$form_state = $this->getFormStateDefaults();
|
||||
|
||||
$return = $form_submitter->doSubmitForm($form, $form_state);
|
||||
$this->assertFalse($form_state['executed']);
|
||||
$this->assertNull($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::doSubmitForm
|
||||
*/
|
||||
public function testHandleFormSubmissionNoRedirect() {
|
||||
$form_submitter = $this->getFormSubmitter();
|
||||
$form = array();
|
||||
$form_state = $this->getFormStateDefaults();
|
||||
$form_state['submitted'] = TRUE;
|
||||
$form_state['no_redirect'] = TRUE;
|
||||
|
||||
$return = $form_submitter->doSubmitForm($form, $form_state);
|
||||
$this->assertTrue($form_state['executed']);
|
||||
$this->assertNull($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::doSubmitForm
|
||||
*
|
||||
* @dataProvider providerTestHandleFormSubmissionWithResponses
|
||||
*/
|
||||
public function testHandleFormSubmissionWithResponses($class, $form_state_key) {
|
||||
$response = $this->getMockBuilder($class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$response->expects($this->any())
|
||||
->method('prepare')
|
||||
->will($this->returnValue($response));
|
||||
|
||||
$form_state = $this->getFormStateDefaults();
|
||||
$form_state['submitted'] = TRUE;
|
||||
$form_state[$form_state_key] = $response;
|
||||
|
||||
$form_submitter = $this->getFormSubmitter();
|
||||
$form = array();
|
||||
$return = $form_submitter->doSubmitForm($form, $form_state);
|
||||
|
||||
$this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $return);
|
||||
}
|
||||
|
||||
public function providerTestHandleFormSubmissionWithResponses() {
|
||||
return array(
|
||||
array('Symfony\Component\HttpFoundation\Response', 'response'),
|
||||
array('Symfony\Component\HttpFoundation\RedirectResponse', 'redirect'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the redirectForm() method when a redirect is expected.
|
||||
*
|
||||
* @covers ::redirectForm
|
||||
*
|
||||
* @dataProvider providerTestRedirectWithResult
|
||||
*/
|
||||
public function testRedirectWithResult($form_state, $result, $status = 302) {
|
||||
$form_submitter = $this->getFormSubmitter();
|
||||
$this->urlGenerator->expects($this->once())
|
||||
->method('generateFromPath')
|
||||
->will($this->returnValueMap(array(
|
||||
array(NULL, array('query' => array(), 'absolute' => TRUE), '<front>'),
|
||||
array('foo', array('absolute' => TRUE), 'foo'),
|
||||
array('bar', array('query' => array('foo' => 'baz'), 'absolute' => TRUE), 'bar'),
|
||||
array('baz', array('absolute' => TRUE), 'baz'),
|
||||
))
|
||||
);
|
||||
|
||||
$form_state += $this->getFormStateDefaults();
|
||||
$redirect = $form_submitter->redirectForm($form_state);
|
||||
$this->assertSame($result, $redirect->getTargetUrl());
|
||||
$this->assertSame($status, $redirect->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the redirectForm() with redirect_route when a redirect is expected.
|
||||
*
|
||||
* @covers ::redirectForm
|
||||
*
|
||||
* @dataProvider providerTestRedirectWithRouteWithResult
|
||||
*/
|
||||
public function testRedirectWithRouteWithResult($form_state, $result, $status = 302) {
|
||||
$container = new ContainerBuilder();
|
||||
$container->set('url_generator', $this->urlGenerator);
|
||||
\Drupal::setContainer($container);
|
||||
$form_submitter = $this->getFormSubmitter();
|
||||
$this->urlGenerator->expects($this->once())
|
||||
->method('generateFromRoute')
|
||||
->will($this->returnValueMap(array(
|
||||
array('test_route_a', array(), array('absolute' => TRUE), 'test-route'),
|
||||
array('test_route_b', array('key' => 'value'), array('absolute' => TRUE), 'test-route/value'),
|
||||
))
|
||||
);
|
||||
|
||||
$form_state += $this->getFormStateDefaults();
|
||||
$redirect = $form_submitter->redirectForm($form_state);
|
||||
$this->assertSame($result, $redirect->getTargetUrl());
|
||||
$this->assertSame($status, $redirect->getStatusCode());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the redirectForm() method with a response object.
|
||||
*
|
||||
* @covers ::redirectForm
|
||||
*/
|
||||
public function testRedirectWithResponseObject() {
|
||||
$form_submitter = $this->getFormSubmitter();
|
||||
$redirect = new RedirectResponse('/example');
|
||||
$form_state['redirect'] = $redirect;
|
||||
|
||||
$form_state += $this->getFormStateDefaults();
|
||||
$result_redirect = $form_submitter->redirectForm($form_state);
|
||||
|
||||
$this->assertSame($redirect, $result_redirect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the redirectForm() method when no redirect is expected.
|
||||
*
|
||||
* @covers ::redirectForm
|
||||
*
|
||||
* @dataProvider providerTestRedirectWithoutResult
|
||||
*/
|
||||
public function testRedirectWithoutResult($form_state) {
|
||||
$form_submitter = $this->getFormSubmitter();
|
||||
$this->urlGenerator->expects($this->never())
|
||||
->method('generateFromPath');
|
||||
$this->urlGenerator->expects($this->never())
|
||||
->method('generateFromRoute');
|
||||
$form_state += $this->getFormStateDefaults();
|
||||
$redirect = $form_submitter->redirectForm($form_state);
|
||||
$this->assertNull($redirect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing the redirectForm() method with a redirect.
|
||||
*
|
||||
* @return array
|
||||
* Returns some test data.
|
||||
*/
|
||||
public function providerTestRedirectWithResult() {
|
||||
return array(
|
||||
array(array(), '<front>'),
|
||||
array(array('redirect' => 'foo'), 'foo'),
|
||||
array(array('redirect' => array('foo')), 'foo'),
|
||||
array(array('redirect' => array('foo')), 'foo'),
|
||||
array(array('redirect' => array('bar', array('query' => array('foo' => 'baz')))), 'bar'),
|
||||
array(array('redirect' => array('baz', array(), 301)), 'baz', 301),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing the redirectForm() method with a route name.
|
||||
*
|
||||
* @return array
|
||||
* Returns some test data.
|
||||
*/
|
||||
public function providerTestRedirectWithRouteWithResult() {
|
||||
return array(
|
||||
array(array('redirect_route' => array('route_name' => 'test_route_a')), 'test-route'),
|
||||
array(array('redirect_route' => array('route_name' => 'test_route_b', 'route_parameters' => array('key' => 'value'))), 'test-route/value'),
|
||||
array(array('redirect_route' => new Url('test_route_b', array('key' => 'value'))), 'test-route/value'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides test data for testing the redirectForm() method with no redirect.
|
||||
*
|
||||
* @return array
|
||||
* Returns some test data.
|
||||
*/
|
||||
public function providerTestRedirectWithoutResult() {
|
||||
return array(
|
||||
array(array('programmed' => TRUE)),
|
||||
array(array('rebuild' => TRUE)),
|
||||
array(array('no_redirect' => TRUE)),
|
||||
array(array('redirect' => FALSE)),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers ::executeSubmitHandlers
|
||||
*/
|
||||
public function testExecuteSubmitHandlers() {
|
||||
$form_submitter = $this->getFormSubmitter();
|
||||
$mock = $this->getMock('stdClass', array('submit_handler', 'hash_submit'));
|
||||
$mock->expects($this->once())
|
||||
->method('submit_handler')
|
||||
->with($this->isType('array'), $this->isType('array'));
|
||||
$mock->expects($this->once())
|
||||
->method('hash_submit')
|
||||
->with($this->isType('array'), $this->isType('array'));
|
||||
|
||||
$form = array();
|
||||
$form_state = $this->getFormStateDefaults();
|
||||
$form_submitter->executeSubmitHandlers($form, $form_state);
|
||||
|
||||
$form['#submit'][] = array($mock, 'hash_submit');
|
||||
$form_submitter->executeSubmitHandlers($form, $form_state);
|
||||
|
||||
// $form_state submit handlers will supersede $form handlers.
|
||||
$form_state['submit_handlers'][] = array($mock, 'submit_handler');
|
||||
$form_submitter->executeSubmitHandlers($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array()
|
||||
*/
|
||||
protected function getFormStateDefaults() {
|
||||
$form_builder = $this->getMockBuilder('Drupal\Core\Form\FormBuilder')
|
||||
->disableOriginalConstructor()
|
||||
->setMethods(NULL)
|
||||
->getMock();
|
||||
return $form_builder->getFormStateDefaults();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Drupal\Core\Form\FormSubmitterInterface
|
||||
*/
|
||||
protected function getFormSubmitter() {
|
||||
$request_stack = new RequestStack();
|
||||
$request_stack->push(new Request());
|
||||
return $this->getMockBuilder('Drupal\Core\Form\FormSubmitter')
|
||||
->setConstructorArgs(array($request_stack, $this->urlGenerator))
|
||||
->setMethods(array('batchGet', 'drupalInstallationAttempted'))
|
||||
->getMock();
|
||||
}
|
||||
|
||||
}
|
|
@ -34,6 +34,11 @@ abstract class FormTestBase extends UnitTestCase {
|
|||
*/
|
||||
protected $formValidator;
|
||||
|
||||
/**
|
||||
* @var \Drupal\Core\Form\FormSubmitterInterface|\PHPUnit_Framework_MockObject_MockObject
|
||||
*/
|
||||
protected $formSubmitter;
|
||||
|
||||
/**
|
||||
* The mocked URL generator.
|
||||
*
|
||||
|
@ -83,6 +88,13 @@ abstract class FormTestBase extends UnitTestCase {
|
|||
*/
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
* The request stack.
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\RequestStack
|
||||
*/
|
||||
protected $requestStack;
|
||||
|
||||
/**
|
||||
* The event dispatcher.
|
||||
*
|
||||
|
@ -117,8 +129,6 @@ abstract class FormTestBase extends UnitTestCase {
|
|||
array('form_state', $this->formStateCache),
|
||||
)));
|
||||
|
||||
$this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$this->formValidator = $this->getMock('Drupal\Core\Form\FormValidatorInterface');
|
||||
$this->urlGenerator = $this->getMock('Drupal\Core\Routing\UrlGeneratorInterface');
|
||||
$this->csrfToken = $this->getMockBuilder('Drupal\Core\Access\CsrfTokenGenerator')
|
||||
->disableOriginalConstructor()
|
||||
|
@ -126,10 +136,22 @@ abstract class FormTestBase extends UnitTestCase {
|
|||
$this->httpKernel = $this->getMockBuilder('Drupal\Core\HttpKernel')
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->request = new Request();
|
||||
$this->account = $this->getMock('Drupal\Core\Session\AccountInterface');
|
||||
$this->request = new Request();
|
||||
$this->eventDispatcher = $this->getMock('Symfony\Component\EventDispatcher\EventDispatcherInterface');
|
||||
$this->requestStack = new RequestStack();
|
||||
$this->requestStack->push($this->request);
|
||||
$this->formValidator = $this->getMockBuilder('Drupal\Core\Form\FormValidator')
|
||||
->setConstructorArgs(array($this->requestStack, $this->getStringTranslationStub(), $this->csrfToken))
|
||||
->setMethods(array('drupalSetMessage'))
|
||||
->getMock();
|
||||
$this->formSubmitter = $this->getMockBuilder('Drupal\Core\Form\FormSubmitter')
|
||||
->setConstructorArgs(array($this->requestStack, $this->urlGenerator))
|
||||
->setMethods(array('batchGet', 'drupalInstallationAttempted'))
|
||||
->getMock();
|
||||
|
||||
$this->setupFormBuilder();
|
||||
$this->formBuilder = new TestFormBuilder($this->formValidator, $this->formSubmitter, $this->moduleHandler, $this->keyValueExpirableFactory, $this->eventDispatcher, $this->requestStack, $this->csrfToken, $this->httpKernel);
|
||||
$this->formBuilder->setCurrentUser($this->account);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,16 +161,6 @@ abstract class FormTestBase extends UnitTestCase {
|
|||
$this->formBuilder->drupalStaticReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up a new form builder object to test.
|
||||
*/
|
||||
protected function setupFormBuilder() {
|
||||
$request_stack = new RequestStack();
|
||||
$request_stack->push($this->request);
|
||||
$this->formBuilder = new TestFormBuilder($this->formValidator, $this->moduleHandler, $this->keyValueExpirableFactory, $this->eventDispatcher, $this->urlGenerator, $request_stack, $this->csrfToken, $this->httpKernel);
|
||||
$this->formBuilder->setCurrentUser($this->account);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a mocked form object.
|
||||
*
|
||||
|
@ -276,13 +288,6 @@ class TestFormBuilder extends FormBuilder {
|
|||
return $types[$type];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function drupalInstallationAttempted() {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@ -310,14 +315,6 @@ class TestFormBuilder extends FormBuilder {
|
|||
static::$seenIds = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function &batchGet() {
|
||||
$batch = array();
|
||||
return $batch;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue