Commit 1deffa83 authored by alexpott's avatar alexpott

Issue #2040265 by larowlan: Add a _entity_view() routing default for viewing an entity.

parent 0643e0a6
<?php
/**
* @file
* Contains \Drupal\Core\Entity\Controller\EntityViewController.
*/
namespace Drupal\Core\Entity\Controller;
use Drupal\Core\Controller\ControllerInterface;
use Drupal\Core\Entity\EntityManager;
use Drupal\Core\Entity\EntityInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Defines a generic controller to render a single entity.
*/
class EntityViewController 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')
);
}
/**
* Provides a page to render a single entity.
*
* @param \Drupal\Core\Entity\EntityInterface $_entity
* The Entity to be rendered. Note this variable is named $_entity rather
* than $entity to prevent collisions with other named placeholders in the
* route.
* @param string $view_mode
* (optional) The view mode that should be used to display the entity.
* Defaults to 'full'.
* @param string $langcode
* (optional) For which language the entity should be rendered, defaults to
* the current content language.
*
* @return array
* A render array as expected by drupal_render().
*/
public function view(EntityInterface $_entity, $view_mode = 'full', $langcode = NULL) {
return $this->entityManager
->getRenderController($_entity->entityType())
->view($_entity, $view_mode, $langcode);
}
}
......@@ -9,6 +9,7 @@
use Symfony\Component\HttpFoundation\Request;
use Symfony\Cmf\Component\Routing\Enhancer\RouteEnhancerInterface;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Drupal\Core\ContentNegotiation;
/**
......@@ -47,6 +48,54 @@ public function enhance(array $defaults, Request $request) {
$defaults['entity_type'] = $defaults['_entity_list'];
unset($defaults['_entity_list']);
}
elseif (!empty($defaults['_entity_view'])) {
$defaults['_controller'] = 'controller.page:content';
$defaults['_content'] = '\Drupal\Core\Entity\Controller\EntityViewController::view';
if (strpos($defaults['_entity_view'], '.') !== FALSE) {
// The _entity_view entry is of the form entity_type.view_mode.
list($entity_type, $view_mode) = explode('.', $defaults['_entity_view']);
$defaults['view_mode'] = $view_mode;
}
else {
// Only the entity type is nominated, the view mode will use the
// default.
$entity_type = $defaults['_entity_view'];
}
// Set by reference so that we get the upcast value.
if (!empty($defaults[$entity_type])) {
$defaults['_entity'] = &$defaults[$entity_type];
}
else {
// The entity is not keyed by its entity_type. Attempt to find it
// using a converter.
$route = $defaults[RouteObjectInterface::ROUTE_OBJECT];
if ($route && is_object($route)) {
$options = $route->getOptions();
if (isset($options['parameters'])) {
foreach ($options['parameters'] as $name => $details) {
if (!empty($details['type'])) {
$type = $details['type'];
// Type is of the form entity:{entity_type}.
$parameter_entity_type = substr($type, strlen('entity:'));
if ($entity_type == $parameter_entity_type) {
// We have the matching entity type. Set the '_entity' key
// to point to this named placeholder. The entity in this
// position is the one being rendered.
$defaults['_entity'] = &$defaults[$name];
}
}
}
}
else {
throw new \RuntimeException(sprintf('Failed to find entity of type %s in route named %s', $entity_type, $defaults[RouteObjectInterface::ROUTE_NAME]));
}
}
else {
throw new \RuntimeException(sprintf('Failed to find entity of type %s in route named %s', $entity_type, $defaults[RouteObjectInterface::ROUTE_NAME]));
}
}
unset($defaults['_entity_view']);
}
}
return $defaults;
}
......
<?php
/**
* @file
* Contains \Drupal\system\Tests\Entity\EntityViewControllerTest.
*/
namespace Drupal\system\Tests\Entity;
use Drupal\simpletest\WebTestBase;
use Drupal\Core\Language\Language;
/**
* Tests \Drupal\Core\Entity\Controller\EntityViewController.
*/
class EntityViewControllerTest extends WebTestBase {
/**
* Modules to enable.
*
* @var array
*/
public static $modules = array('entity_test');
/**
* Array of test entities.
*
* @var array
*/
protected $entities = array();
public static function getInfo() {
return array(
'name' => 'Entity View Controller',
'description' => 'Tests EntityViewController functionality.',
'group' => 'Entity API',
);
}
function setUp() {
parent::setUp();
// Create some dummy entity_test_render entities.
for ($i = 0; $i < 2; $i++) {
$random_label = $this->randomName();
$data = array('bundle' => 'entity_test_render', 'name' => $random_label);
$entity_test = $this->container->get('plugin.manager.entity')->getStorageController('entity_test_render')->create($data);
$entity_test->save();
$this->entities[] = $entity_test;
}
}
/**
* Tests EntityViewController.
*/
function testEntityViewController() {
foreach ($this->entities as $entity) {
$this->drupalGet('entity-test-render/' . $entity->id());
$this->assertRaw($entity->label());
$this->assertRaw('full');
$this->drupalGet('entity-test-render-converter/' . $entity->id());
$this->assertRaw($entity->label());
$this->assertRaw('full');
$this->drupalGet('entity-test-render-no-view-mode/' . $entity->id());
$this->assertRaw($entity->label());
$this->assertRaw('full');
}
}
}
entity_test_render:
pattern: '/entity-test-render/{entity_test_render}'
defaults:
_entity_view: 'entity_test_render.full'
requirements:
_access: 'TRUE'
entity_test_render_options:
pattern: '/entity-test-render-converter/{foo}'
options:
parameters:
foo:
type: 'entity:entity_test_render'
defaults:
_entity_view: 'entity_test_render.full'
requirements:
_access: 'TRUE'
entity_test_render_no_view_mode:
pattern: '/entity-test-render-no-view-mode/{entity_test_render}'
defaults:
_entity_view: 'entity_test_render'
requirements:
_access: 'TRUE'
<?php
/**
* @file
* Contains \Drupal\Tests\Core\Entity\Controller\EntityViewControllerTest.
*/
namespace Drupal\Core\Tests\Entity\Controller;
use Drupal\Core\Entity\Controller\EntityViewController;
use Drupal\Tests\UnitTestCase;
/**
* Tests the entity view controller.
*
* @see \Drupal\Core\Entity\Controller\EntityViewController
*/
class EntityViewControllerTest extends UnitTestCase{
public static function getInfo() {
return array(
'name' => 'Entity route enhancer test',
'description' => 'Tests the entity route enhancer.',
'group' => 'Entity'
);
}
/**
* Tests the enhancer method.
*
* @see \Drupal\Core\Entity\Controller\EntityViewController::view()
*/
public function testView() {
// Mock a render controller.
$render_controller = $this->getMockBuilder('Drupal\entity_test\EntityTestRenderController')
->disableOriginalConstructor()
->getMock();
$render_controller->expects($this->any())
->method('view')
->will($this->returnValue('Output from rendering the entity'));
// Mock an entity manager.
$entity_manager = $this->getMockBuilder('Drupal\Core\Entity\EntityManager')
->disableOriginalConstructor()
->getMock();
$entity_manager->expects($this->any())
->method('getRenderController')
->will($this->returnValue($render_controller));
// Mock an 'entity_test_render' entity.
$entity = $this->getMockBuilder('Drupal\entity_test\Plugin\Core\Entity\EntityTestRender')
->disableOriginalConstructor()
->getMock();
// Initialize the controller to test.
$controller = new EntityViewController($entity_manager);
// Test the view method.
$this->assertEquals($controller->view($entity, 'full'), 'Output from rendering the entity');
}
}
......@@ -10,6 +10,7 @@
use Drupal\Core\ContentNegotiation;
use Drupal\Core\Entity\Enhancer\EntityRouteEnhancer;
use Drupal\Tests\UnitTestCase;
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
use Symfony\Component\HttpFoundation\Request;
/**
......@@ -62,6 +63,52 @@ public function testEnhancer() {
$this->assertEquals('\Drupal\Core\Entity\Controller\EntityListController::listing', $defaults['_content'], 'The entity list controller was not set.');
$this->assertEquals('entity_test.default', $defaults['entity_type']);
$this->assertFalse(isset($defaults['_entity_list']));
// Set _entity_view and ensure that the entity view controller is set.
$defaults = array();
$defaults['_entity_view'] = 'entity_test.full';
$defaults['entity_test'] = 'Mock entity';
$defaults = $route_enhancer->enhance($defaults, $request);
$this->assertEquals('controller.page:content', $defaults['_controller']);
$this->assertEquals('\Drupal\Core\Entity\Controller\EntityViewController::view', $defaults['_content'], 'The entity view controller was not set.');
$this->assertEquals($defaults['_entity'], 'Mock entity');
$this->assertEquals($defaults['view_mode'], 'full');
$this->assertFalse(isset($defaults['_entity_view']));
// Set _entity_view and ensure that the entity view controller is set using
// a converter.
$defaults = array();
$defaults['_entity_view'] = 'entity_test.full';
$defaults['foo'] = 'Mock entity';
// Add a converter.
$options['parameters']['foo'] = array('type' => 'entity:entity_test');
// Set the route.
$route = $this->getMockBuilder('Symfony\Component\Routing\Route')
->disableOriginalConstructor()
->getMock();
$route->expects($this->any())
->method('getOptions')
->will($this->returnValue($options));
$defaults[RouteObjectInterface::ROUTE_OBJECT] = $route;
$defaults = $route_enhancer->enhance($defaults, $request);
$this->assertEquals('controller.page:content', $defaults['_controller']);
$this->assertEquals('\Drupal\Core\Entity\Controller\EntityViewController::view', $defaults['_content'], 'The entity view controller was not set.');
$this->assertEquals($defaults['_entity'], 'Mock entity');
$this->assertEquals($defaults['view_mode'], 'full');
$this->assertFalse(isset($defaults['_entity_view']));
// Set _entity_view without a view mode.
$defaults = array();
$defaults['_entity_view'] = 'entity_test';
$defaults['entity_test'] = 'Mock entity';
$defaults = $route_enhancer->enhance($defaults, $request);
$this->assertEquals('controller.page:content', $defaults['_controller']);
$this->assertEquals('\Drupal\Core\Entity\Controller\EntityViewController::view', $defaults['_content'], 'The entity view controller was not set.');
$this->assertEquals($defaults['_entity'], 'Mock entity');
$this->assertTrue(empty($defaults['view_mode']));
$this->assertFalse(isset($defaults['_entity_view']));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment