Newer
Older
<?php
/**
* @file
* Contains Drupal\Core\ParamConverter\EntityConverter.
*/
namespace Drupal\Core\ParamConverter;
use Drupal\Core\Entity\EntityInterface;
Angie Byron
committed
use Drupal\Core\Entity\EntityManagerInterface;
use Drupal\Core\TypedData\TranslatableInterface;
use Symfony\Component\Routing\Route;
/**
Angie Byron
committed
* Parameter converter for upcasting entity IDs to full objects.
*
* This is useful in cases where the dynamic elements of the path can't be
* auto-determined; for example, if your path refers to multiple of the same
* type of entity ("example/{node1}/foo/{node2}") or if the path can act on any
* entity type ("example/{entity_type}/{entity}/foo").
*
* In order to use it you should specify some additional options in your route:
* @code
* example.route:
* path: foo/{example}
* options:
* parameters:
* example:
* type: entity:node
* @endcode
*
* If you want to have the entity type itself dynamic in the url you can
* specify it like the following:
* @code
* example.route:
* path: foo/{entity_type}/{example}
* options:
* parameters:
* example:
* type: entity:{entity_type}
* @endcode
*/
class EntityConverter implements ParamConverterInterface {
/**
* Entity manager which performs the upcasting in the end.
*
Angie Byron
committed
* @var \Drupal\Core\Entity\EntityManagerInterface
*/
protected $entityManager;
/**
* Constructs a new EntityConverter.
*
Angie Byron
committed
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
* The entity manager.
*/
Angie Byron
committed
public function __construct(EntityManagerInterface $entity_manager) {
$this->entityManager = $entity_manager;
}
/**
* {@inheritdoc}
*/
public function convert($value, $definition, $name, array $defaults) {
Angie Byron
committed
$entity_type_id = $this->getEntityTypeFromDefaults($definition, $name, $defaults);
if ($storage = $this->entityManager->getStorage($entity_type_id)) {
$entity = $storage->load($value);
// If the entity type is translatable, ensure we return the proper
// translation object for the current context.
if ($entity instanceof EntityInterface && $entity instanceof TranslatableInterface) {
$entity = $this->entityManager->getTranslationFromContext($entity, NULL, array('operation' => 'entity_upcast'));
}
return $entity;
/**
* {@inheritdoc}
*/
public function applies($definition, $name, Route $route) {
if (!empty($definition['type']) && strpos($definition['type'], 'entity:') === 0) {
Angie Byron
committed
$entity_type_id = substr($definition['type'], strlen('entity:'));
if (strpos($definition['type'], '{') !== FALSE) {
$entity_type_slug = substr($entity_type_id, 1, -1);
return $name != $entity_type_slug && in_array($entity_type_slug, $route->compile()->getVariables(), TRUE);
}
return $this->entityManager->hasDefinition($entity_type_id);
return FALSE;
Angie Byron
committed
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
/**
* Determines the entity type ID given a route definition and route defaults.
*
* @param mixed $definition
* The parameter definition provided in the route options.
* @param string $name
* The name of the parameter.
* @param array $defaults
* The route defaults array.
*
* @throws \Drupal\Core\ParamConverter\ParamNotConvertedException
* Thrown when the dynamic entity type is not found in the route defaults.
*
* @return string
* The entity type ID.
*/
protected function getEntityTypeFromDefaults($definition, $name, array $defaults) {
$entity_type_id = substr($definition['type'], strlen('entity:'));
// If the entity type is dynamic, it will be pulled from the route defaults.
if (strpos($entity_type_id, '{') === 0) {
$entity_type_slug = substr($entity_type_id, 1, -1);
if (!isset($defaults[$entity_type_slug])) {
throw new ParamNotConvertedException(sprintf('The "%s" parameter was not converted because the "%s" parameter is missing', $name, $entity_type_slug));
}
$entity_type_id = $defaults[$entity_type_slug];
}
return $entity_type_id;
}