3 namespace Drupal\Core\Controller;
5 use Drupal\Core\DependencyInjection\DependencySerializationTrait;
6 use Drupal\Core\Form\FormBuilderInterface;
7 use Drupal\Core\Form\FormState;
8 use Drupal\Core\Routing\RouteMatchInterface;
9 use Symfony\Component\HttpFoundation\Request;
10 use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
13 * Common base class for form interstitial controllers.
15 * @todo Make this a trait in PHP 5.4.
17 abstract class FormController {
18 use DependencySerializationTrait;
21 * The argument resolver.
23 * @var \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface
25 protected $argumentResolver;
28 * The controller resolver.
30 * @var \Drupal\Core\Controller\ControllerResolverInterface
33 * Deprecated property that is only assigned when the 'controller_resolver'
34 * service is used as the first parameter to FormController::__construct().
36 * @see https://www.drupal.org/node/2959408
37 * @see \Drupal\Core\Controller\FormController::__construct()
39 protected $controllerResolver;
44 * @var \Drupal\Core\Form\FormBuilderInterface
46 protected $formBuilder;
49 * Constructs a new \Drupal\Core\Controller\FormController object.
51 * @param \Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface $argument_resolver
52 * The argument resolver.
53 * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
56 public function __construct(ArgumentResolverInterface $argument_resolver, FormBuilderInterface $form_builder) {
57 $this->argumentResolver = $argument_resolver;
58 if ($argument_resolver instanceof ControllerResolverInterface) {
59 @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);
60 $this->controllerResolver = $argument_resolver;
62 $this->formBuilder = $form_builder;
66 * Invokes the form and returns the result.
68 * @param \Symfony\Component\HttpFoundation\Request $request
70 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
74 * The render array that results from invoking the controller.
76 public function getContentResult(Request $request, RouteMatchInterface $route_match) {
77 $form_arg = $this->getFormArgument($route_match);
78 $form_object = $this->getFormObject($route_match, $form_arg);
80 // Add the form and form_state to trick the getArguments method of the
81 // controller resolver.
82 $form_state = new FormState();
83 $request->attributes->set('form', []);
84 $request->attributes->set('form_state', $form_state);
85 $args = $this->argumentResolver->getArguments($request, [$form_object, 'buildForm']);
86 $request->attributes->remove('form');
87 $request->attributes->remove('form_state');
89 // Remove $form and $form_state from the arguments, and re-index them.
90 unset($args[0], $args[1]);
91 $form_state->addBuildInfo('args', array_values($args));
93 return $this->formBuilder->buildForm($form_object, $form_state);
97 * Extracts the form argument string from a request.
99 * Depending on the type of form the argument string may be stored in a
100 * different request attribute.
102 * One example of a route definition is given below.
105 * _form: Drupal\example\Form\ExampleForm
108 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
109 * The route match object from which to extract a form definition string.
112 * The form definition string.
114 abstract protected function getFormArgument(RouteMatchInterface $route_match);
117 * Returns the object used to build the form.
119 * @param \Drupal\Core\Routing\RouteMatchInterface $route_match
121 * @param string $form_arg
122 * Either a class name or a service ID.
124 * @return \Drupal\Core\Form\FormInterface
125 * The form object to use.
127 abstract protected function getFormObject(RouteMatchInterface $route_match, $form_arg);