Issue #2049159 by amateescu, Crell: Create a ControllerBase class to stop the boilerplate code madness.

8.0.x
Alex Pott 2013-08-07 01:32:39 +02:00
parent 17c92fbf00
commit 7412e6f58b
8 changed files with 204 additions and 206 deletions

View File

@ -251,7 +251,7 @@ class Drupal {
/**
* Returns a key/value storage collection.
*
* @param $collection
* @param string $collection
* Name of the key/value collection to return.
*
* @return \Drupal\Core\KeyValueStore\KeyValueStoreInterface
@ -305,10 +305,10 @@ class Drupal {
/**
* Returns the entity query aggregate object for this entity type.
*
* @param $entity_type
* @param string $entity_type
* The entity type, e.g. node, for which the query object should be
* returned.
* @param $conjunction
* @param string $conjunction
* AND if all conditions in the query need to apply, OR if any of them is
* enough. Optional, defaults to AND.
*
@ -331,7 +331,7 @@ class Drupal {
/**
* Returns the module handler.
*
* @return \Drupal\Core\Extension\ModuleHandler
* @return \Drupal\Core\Extension\ModuleHandlerInterface
*/
public static function moduleHandler() {
return static::$container->get('module_handler');
@ -364,7 +364,7 @@ class Drupal {
/**
* Returns the url generator service.
*
* @return \Drupal\Core\Routing\UrlGenerator
* @return \Drupal\Core\Routing\PathBasedGeneratorInterface
* The url generator service.
*/
public static function urlGenerator() {

View File

@ -0,0 +1,172 @@
<?php
/**
* @file
* Contains \Drupal\Core\Controller\ControllerBase.
*/
namespace Drupal\Core\Controller;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\RedirectResponse;
/**
* Utility base class for thin controllers.
*
* 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 makes the class considerably more
* difficult 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 {
/**
* Retrieves the entity manager service.
*
* @return \Drupal\Core\Entity\EntityManager
* The entity manager service.
*/
protected function entityManager() {
return $this->container->get('plugin.manager.entity');
}
/**
* Returns the requested cache bin.
*
* @param string $bin
* (optional) The cache bin for which the cache object should be returned,
* defaults to 'cache'.
*
* @return \Drupal\Core\Cache\CacheBackendInterface
* The cache object associated with the specified bin.
*/
protected function cache($bin = 'cache') {
return $this->container->get('cache.' . $bin);
}
/**
* Retrieves a configuration object.
*
* This is the main entry point to the configuration API. Calling
* @code $this->config('book.admin') @endcode will return a configuration
* object in which the book module can store its administrative settings.
*
* @param string $name
* The name of the configuration object to retrieve. The name corresponds to
* a configuration file. For @code config('book.admin') @endcode, the config
* object returned will contain the contents of book.admin configuration file.
*
* @return \Drupal\Core\Config\Config
* A configuration object.
*/
protected function config($name) {
return $this->container->get('config.factory')->get($name);
}
/**
* Returns a key/value storage collection.
*
* @param string $collection
* Name of the key/value collection to return.
*
* @return \Drupal\Core\KeyValueStore\KeyValueStoreInterface
*/
protected function keyValue($collection) {
return $this->container->get('keyvalue')->get($collection);
}
/**
* Returns the state storage service.
*
* Use this to store machine-generated data, local to a specific environment
* that does not need deploying and does not need human editing; for example,
* the last time cron was run. Data which needs to be edited by humans and
* needs to be the same across development, production, etc. environments
* (for example, the system maintenance message) should use config() instead.
*
* @return \Drupal\Core\KeyValueStore\KeyValueStoreInterface
*/
protected function state() {
return $this->container->get('state');
}
/**
* Returns the module handler.
*
* @return \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected function moduleHandler() {
return $this->container->get('module_handler');
}
/**
* Returns the url generator service.
*
* @return \Drupal\Core\Routing\PathBasedGeneratorInterface
* The url generator service.
*/
protected function urlGenerator() {
return $this->container->get('url_generator');
}
/**
* Translates a string to the current language or to a given language using
* the string translation service.
*
* @param string $string
* A string containing the English string to translate.
* @param array $args
* An associative array of replacements to make after translation. Based
* on the first character of the key, the value is escaped and/or themed.
* See \Drupal\Core\Utility\String::format() for details.
* @param array $options
* An associative array of additional options, with the following elements:
* - 'langcode': The language code to translate to a language other than
* what is used to display the page.
* - 'context': The context the source string belongs to.
*
* @return string
* The translated string.
*/
protected function t($string, array $args = array(), array $options = array()) {
return $this->container->get('string_translation')->translate($string, $args, $options);
}
/**
* Returns the language manager service.
*
* @return \Drupal\Core\Language\LanguageManager
* The language manager.
*/
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);
}
}

View File

@ -11,6 +11,14 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* 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 very difficult to unit test so should only be used for
* controllers that are trivial in complexity.
*/
interface ControllerInterface {

View File

@ -7,40 +7,13 @@
namespace Drupal\Core\Entity\Controller;
use Drupal\Core\Controller\ControllerInterface;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Defines a generic controller to list entities.
*/
class EntityListController implements ControllerInterface {
/**
* The entity manager
*
* @var \Drupal\Core\Entity\EntityManager
*/
protected $entityManager;
/**
* Creates an EntityListController object.
*
* @param \Drupal\Core\Entity\EntityManager $entity_manager
* The entity manager.
*/
public function __construct(EntityManager $entity_manager) {
$this->entityManager = $entity_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.entity')
);
}
class EntityListController extends ControllerBase {
/**
* Provides the listing page for any entity type.
@ -52,7 +25,7 @@ class EntityListController implements ControllerInterface {
* A render array as expected by drupal_render().
*/
public function listing($entity_type) {
return $this->entityManager->getListController($entity_type)->render();
return $this->entityManager()->getListController($entity_type)->render();
}
}

View File

@ -7,33 +7,13 @@
namespace Drupal\block\Controller;
use Drupal\Core\Controller\ControllerInterface;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Controller for building the block instance add form.
*/
class BlockAddController implements ControllerInterface {
/**
* Constructs a Block object.
*
* @param \Drupal\Core\Entity\EntityManager $entity_manager
* Entity manager service.
*/
public function __construct(EntityManager $entity_manager) {
$this->entityManager = $entity_manager;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.entity')
);
}
class BlockAddController extends ControllerBase {
/**
* Build the block instance add form.
@ -51,8 +31,9 @@ class BlockAddController implements ControllerInterface {
drupal_set_title(t('Configure block'));
// Create a block entity.
$entity = $this->entityManager->getStorageController('block')->create(array('plugin' => $plugin_id, 'theme' => $theme));
$entity = $this->entityManager()->getStorageController('block')->create(array('plugin' => $plugin_id, 'theme' => $theme));
return $this->entityManager->getForm($entity);
return $this->entityManager()->getForm($entity);
}
}

View File

@ -9,45 +9,12 @@ namespace Drupal\block\Controller;
use Drupal\Core\Entity\Controller\EntityListController;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Entity\EntityManager;
/**
* Defines a controller to list blocks.
*/
class BlockListController extends EntityListController {
/**
* The configuration factory object.
*
* @var \Drupal\Core\Config\ConfigFactory
*/
protected $configFactory;
/**
* Creates an BlockListController object.
*
* @param \Drupal\Core\Entity\EntityManager $entity_manager
* The entity manager.
* @param \Drupal\Core\Config\ConfigFactory $config_factory
* Configuration factory object.
*/
public function __construct(EntityManager $entity_manager, ConfigFactory $config_factory) {
$this->entityManager = $entity_manager;
$this->configFactory = $config_factory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.entity'),
$container->get('config.factory')
);
}
/**
* Shows the block administration page.
*
@ -60,8 +27,8 @@ class BlockListController extends EntityListController {
* A render array as expected by drupal_render().
*/
public function listing($entity_type, $theme = NULL) {
$default_theme = $theme ?: $this->configFactory->get('system.theme')->get('default');
return $this->entityManager->getListController($entity_type)->render($default_theme);
$default_theme = $theme ?: $this->config('system.theme')->get('default');
return $this->entityManager()->getListController($entity_type)->render($default_theme);
}
}

View File

@ -7,10 +7,7 @@
namespace Drupal\shortcut\Controller;
use Drupal\Core\Controller\ControllerInterface;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Routing\PathBasedGeneratorInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\shortcut\ShortcutSetInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
@ -20,55 +17,7 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
/**
* Builds the page for administering shortcut sets.
*/
class ShortcutSetController implements ControllerInterface {
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* Stores the entity manager.
*
* @var \Drupal\Core\Entity\EntityManager
*/
protected $entityManager;
/**
* The URL generator.
*
* @var \Drupal\Core\Routing\PathBasedGeneratorInterface
*/
protected $urlGenerator;
/**
* Constructs a new \Drupal\shortcut\Controller\ShortCutController object.
*
* @param \Drupal\Core\Entity\EntityManager $entity_manager
* The entity manager.
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Routing\PathBasedGeneratorInterface $url_generator
* The URL generator.
*/
public function __construct(EntityManager $entity_manager, ModuleHandlerInterface $module_handler, PathBasedGeneratorInterface $url_generator) {
$this->entityManager = $entity_manager;
$this->moduleHandler = $module_handler;
$this->urlGenerator = $url_generator;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('plugin.manager.entity'),
$container->get('module_handler'),
$container->get('url_generator')
);
}
class ShortcutSetController extends ControllerBase {
/**
* Creates a new link in the provided shortcut set.
@ -93,7 +42,7 @@ class ShortcutSetController implements ControllerInterface {
'link_title' => $title,
'link_path' => $link,
);
$this->moduleHandler->loadInclude('shortcut', 'admin.inc');
$this->moduleHandler()->loadInclude('shortcut', 'admin.inc');
shortcut_admin_add_link($link, $shortcut_set);
if ($shortcut_set->save() == SAVED_UPDATED) {
drupal_set_message(t('Added a shortcut for %title.', array('%title' => $link['link_title'])));
@ -101,7 +50,7 @@ class ShortcutSetController implements ControllerInterface {
else {
drupal_set_message(t('Unable to add a shortcut for %title.', array('%title' => $link['link_title'])));
}
return new RedirectResponse($this->urlGenerator->generateFromPath('<front>', array('absolute' => TRUE)));
return new RedirectResponse($this->urlGenerator()->generateFromPath('<front>', array('absolute' => TRUE)));
}
throw new AccessDeniedHttpException();

View File

@ -7,66 +7,14 @@
namespace Drupal\taxonomy\Controller;
use Drupal\Core\Controller\ControllerInterface;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\taxonomy\TermStorageControllerInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\taxonomy\VocabularyInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides route responses for taxonomy.module.
*/
class TaxonomyController implements ControllerInterface {
/**
* The module handler.
*
* @var \Drupal\Core\Extension\ModuleHandlerInterface
*/
protected $moduleHandler;
/**
* The entity manager.
*
* @var \Drupal\Core\Entity\EntityManager
*/
protected $entityManager;
/**
* The taxonomy term storage.
*
* @var \Drupal\taxonomy\TermStorageControllerInterface
*/
protected $termStorage;
/**
* Constructs a new TaxonomyController.
*
* @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
* The module handler.
* @param \Drupal\Core\Entity\EntityManager $entity_manager
* The entity manager.
* @param \Drupal\taxonomy\TermStorageControllerInterface $term_storage
* The taxonomy term storage.
*/
public function __construct(ModuleHandlerInterface $module_handler, EntityManager $entity_manager, TermStorageControllerInterface $term_storage) {
$this->moduleHandler = $module_handler;
$this->entityManager = $entity_manager;
$this->termStorage = $term_storage;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$entity_manager = $container->get('plugin.manager.entity');
return new static(
$container->get('module_handler'),
$entity_manager,
$entity_manager->getStorageController('taxonomy_term')
);
}
class TaxonomyController extends ControllerBase {
/**
* Returns a rendered edit form to create a new term associated to the given vocabulary.
@ -78,11 +26,11 @@ class TaxonomyController implements ControllerInterface {
* The taxonomy term add form.
*/
public function addForm(VocabularyInterface $taxonomy_vocabulary) {
$term = $this->termStorage->create(array('vid' => $taxonomy_vocabulary->id()));
if ($this->moduleHandler->moduleExists('language')) {
$term = $this->entityManager()->getStorageController('taxonomy_term')->create(array('vid' => $taxonomy_vocabulary->id()));
if ($this->moduleHandler()->moduleExists('language')) {
$term->langcode = language_get_default_langcode('taxonomy_term', $taxonomy_vocabulary->id());
}
return $this->entityManager->getForm($term);
return $this->entityManager()->getForm($term);
}
}