diff --git a/core/lib/Drupal/Core/Controller/ControllerBase.php b/core/lib/Drupal/Core/Controller/ControllerBase.php index fae15e9..fb0f1d4 100644 --- a/core/lib/Drupal/Core/Controller/ControllerBase.php +++ b/core/lib/Drupal/Core/Controller/ControllerBase.php @@ -8,12 +8,26 @@ namespace Drupal\Core\Controller; use Symfony\Component\DependencyInjection\ContainerAware; +use Symfony\Component\HttpFoundation\RedirectResponse; /** - * Defines a base class for 'thin' route controllers that don't need injected - * dependencies. + * Utility base class for thin controllers. * - * @todo Clarify the definition of 'thin' :) + * Controllers that use this base class have access to a number of utility + * methods and to the Container, which can greatly reduce boilerplate dependency + * handling code. However, it also renders the class impossible to unit test. + * Therefore this base class should only be used by controller classes that + * contain only trivial glue code. Controllers that contain sufficiently + * complex logic that it's worth testing should not use this base class but + * use ControllerInterface instead, or even better be refactored to be trivial + * glue code. + * + * The services exposed here are those that it is reasonable for a well-behaved + * controller to leverage. A controller that needs other other services may + * need to be refactored into a thin controller and a dependent unit-testable + * service. + * + * @see \Drupal\Core\Controller\ControllerInterface */ abstract class ControllerBase extends ContainerAware { @@ -58,7 +72,7 @@ protected function keyValueExpirable($collection) { * Retrieves a configuration object. * * This is the main entry point to the configuration API. Calling - * @code Drupal::config('book.admin') @endcode will return a configuration + * @code $this->config('book.admin') @endcode will return a configuration * object in which the book module can store its administrative settings. * * @param string $name @@ -152,4 +166,20 @@ protected function languageManager() { return $this->container->get('language_manager'); } + /** + * Returns a redirect response object for the specified + * + * @param string $route_name + * The name of the route to which to redirect. + * @param array $parameters + * Parameters for the route. + * @param int $status + * The HTTP redirect status code for the redirect. The default is 302 Found. + * @return \Symfony\Component\HttpFoundation\RedirectResponse + * A redirect response object that may be returned by the controller. + */ + public function redirect($route_name, array $parameters = array(), $status = 302) { + $url = $this->container->get('url_generator')->generate($route_name, $parameters, TRUE); + return new RedirectResponse($url, $status); + } } diff --git a/core/lib/Drupal/Core/Controller/ControllerInterface.php b/core/lib/Drupal/Core/Controller/ControllerInterface.php index f87ae12..c490f9c 100644 --- a/core/lib/Drupal/Core/Controller/ControllerInterface.php +++ b/core/lib/Drupal/Core/Controller/ControllerInterface.php @@ -11,6 +11,14 @@ /** * Defines a common interface for route controllers. + * + * This interface gives controller classes a factory method for instantiation + * rather than relying on a services.yml entry. However, it may result in + * a lot of boilerplate code in the class. As an alternative, controllers that + * contain only limited glue code ("thin" controllers) should instead extend + * ControllerBase as that allows direct access to the container. That renders + * the controller un-unit-testable so should only be used for controllers that + * are trivial in complexity. */ interface ControllerInterface {