1<?php 2 3namespace Drupal\Core\Controller; 4 5use Drupal\Core\DependencyInjection\DependencySerializationTrait; 6use Drupal\Core\Form\FormBuilderInterface; 7use Drupal\Core\Form\FormState; 8use Drupal\Core\Routing\RouteMatchInterface; 9use Symfony\Component\HttpFoundation\Request; 10use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; 11 12/** 13 * Common base class for form interstitial controllers. 14 */ 15abstract class FormController { 16 use DependencySerializationTrait; 17 18 /** 19 * The argument resolver. 20 * 21 * @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface 22 */ 23 protected $argumentResolver; 24 25 /** 26 * The controller resolver. 27 * 28 * @var \Drupal\Core\Controller\ControllerResolverInterface 29 * 30 * @deprecated 31 * Deprecated property that is only assigned when the 'controller_resolver' 32 * service is used as the first parameter to FormController::__construct(). 33 * 34 * @see https://www.drupal.org/node/2959408 35 * @see \Drupal\Core\Controller\FormController::__construct() 36 */ 37 protected $controllerResolver; 38 39 /** 40 * The form builder. 41 * 42 * @var \Drupal\Core\Form\FormBuilderInterface 43 */ 44 protected $formBuilder; 45 46 /** 47 * Constructs a new \Drupal\Core\Controller\FormController object. 48 * 49 * @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver 50 * The argument resolver. 51 * @param \Drupal\Core\Form\FormBuilderInterface $form_builder 52 * The form builder. 53 */ 54 public function __construct(ArgumentResolverInterface $argument_resolver, FormBuilderInterface $form_builder) { 55 $this->argumentResolver = $argument_resolver; 56 if ($argument_resolver instanceof ControllerResolverInterface) { 57 @trigger_error("Using the 'controller_resolver' service as the first argument is deprecated, use the 'http_kernel.controller.argument_resolver' instead. If your subclass requires the 'controller_resolver' service add it as an additional argument. See https://www.drupal.org/node/2959408.", E_USER_DEPRECATED); 58 $this->controllerResolver = $argument_resolver; 59 } 60 $this->formBuilder = $form_builder; 61 } 62 63 /** 64 * Invokes the form and returns the result. 65 * 66 * @param \Symfony\Component\HttpFoundation\Request $request 67 * The request object. 68 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match 69 * The route match. 70 * 71 * @return array 72 * The render array that results from invoking the controller. 73 */ 74 public function getContentResult(Request $request, RouteMatchInterface $route_match) { 75 $form_arg = $this->getFormArgument($route_match); 76 $form_object = $this->getFormObject($route_match, $form_arg); 77 78 // Add the form and form_state to trick the getArguments method of the 79 // controller resolver. 80 $form_state = new FormState(); 81 $request->attributes->set('form', []); 82 $request->attributes->set('form_state', $form_state); 83 $args = $this->argumentResolver->getArguments($request, [$form_object, 'buildForm']); 84 $request->attributes->remove('form'); 85 $request->attributes->remove('form_state'); 86 87 // Remove $form and $form_state from the arguments, and re-index them. 88 unset($args[0], $args[1]); 89 $form_state->addBuildInfo('args', array_values($args)); 90 91 return $this->formBuilder->buildForm($form_object, $form_state); 92 } 93 94 /** 95 * Extracts the form argument string from a request. 96 * 97 * Depending on the type of form the argument string may be stored in a 98 * different request attribute. 99 * 100 * One example of a route definition is given below. 101 * @code 102 * defaults: 103 * _form: Drupal\example\Form\ExampleForm 104 * @endcode 105 * 106 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match 107 * The route match object from which to extract a form definition string. 108 * 109 * @return string 110 * The form definition string. 111 */ 112 abstract protected function getFormArgument(RouteMatchInterface $route_match); 113 114 /** 115 * Returns the object used to build the form. 116 * 117 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match 118 * The route match. 119 * @param string $form_arg 120 * Either a class name or a service ID. 121 * 122 * @return \Drupal\Core\Form\FormInterface 123 * The form object to use. 124 */ 125 abstract protected function getFormObject(RouteMatchInterface $route_match, $form_arg); 126 127} 128