Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176
This commit is contained in:
commit
9921556621
13277 changed files with 1459781 additions and 0 deletions
|
@ -0,0 +1,109 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\ParamConverter\AdminPathConfigEntityConverter.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\ParamConverter;
|
||||
|
||||
use Drupal\Core\Routing\AdminContext;
|
||||
use Symfony\Component\Routing\Route;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
|
||||
/**
|
||||
* Makes sure the unmodified ConfigEntity is loaded on admin pages.
|
||||
*
|
||||
* Converts entity route arguments to unmodified entities as opposed to
|
||||
* converting to entities with overrides, such as the negotiated language.
|
||||
*
|
||||
* This converter applies only if the path is an admin path, the entity is
|
||||
* a config entity, and the "with_config_overrides" element is not set to TRUE
|
||||
* on the parameter definition.
|
||||
*
|
||||
* Due to this converter having a higher weight than the default
|
||||
* EntityConverter, every time this applies, it takes over the conversion duty
|
||||
* from EntityConverter. As we only allow a single converter per route
|
||||
* argument, EntityConverter is ignored when this converter applies.
|
||||
*/
|
||||
class AdminPathConfigEntityConverter extends EntityConverter {
|
||||
|
||||
/**
|
||||
* The config factory.
|
||||
*
|
||||
* @var \Drupal\Core\Config\ConfigFactoryInterface
|
||||
*/
|
||||
protected $configFactory;
|
||||
|
||||
/**
|
||||
* The route admin context to determine whether a route is an admin one.
|
||||
*
|
||||
* @var \Drupal\Core\Routing\AdminContext
|
||||
*/
|
||||
protected $adminContext;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityConverter.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
* @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
|
||||
* The config factory.
|
||||
* @param \Drupal\Core\Routing\AdminContext $admin_context
|
||||
* The route admin context service.
|
||||
*
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager, ConfigFactoryInterface $config_factory, AdminContext $admin_context) {
|
||||
parent::__construct($entity_manager);
|
||||
|
||||
$this->configFactory = $config_factory;
|
||||
$this->adminContext = $admin_context;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function convert($value, $definition, $name, array $defaults) {
|
||||
$entity_type_id = $this->getEntityTypeFromDefaults($definition, $name, $defaults);
|
||||
|
||||
// If the entity type is dynamic, confirm it to be a config entity. Static
|
||||
// entity types will have performed this check in self::applies().
|
||||
if (strpos($definition['type'], 'entity:{') === 0) {
|
||||
$entity_type = $this->entityManager->getDefinition($entity_type_id);
|
||||
if (!$entity_type->isSubclassOf('\Drupal\Core\Config\Entity\ConfigEntityInterface')) {
|
||||
return parent::convert($value, $definition, $name, $defaults);
|
||||
}
|
||||
}
|
||||
|
||||
if ($storage = $this->entityManager->getStorage($entity_type_id)) {
|
||||
// Make sure no overrides are loaded.
|
||||
return $storage->loadOverrideFree($value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applies($definition, $name, Route $route) {
|
||||
if (isset($definition['with_config_overrides']) && $definition['with_config_overrides']) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (parent::applies($definition, $name, $route)) {
|
||||
$entity_type_id = substr($definition['type'], strlen('entity:'));
|
||||
// If the entity type is dynamic, defer checking to self::convert().
|
||||
if (strpos($entity_type_id, '{') === 0) {
|
||||
return TRUE;
|
||||
}
|
||||
// As we only want to override EntityConverter for ConfigEntities, find
|
||||
// out whether the current entity is a ConfigEntity.
|
||||
$entity_type = $this->entityManager->getDefinition($entity_type_id);
|
||||
if ($entity_type->isSubclassOf('\Drupal\Core\Config\Entity\ConfigEntityInterface')) {
|
||||
return $this->adminContext->isAdminRoute($route);
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
}
|
124
core/lib/Drupal/Core/ParamConverter/EntityConverter.php
Normal file
124
core/lib/Drupal/Core/ParamConverter/EntityConverter.php
Normal file
|
@ -0,0 +1,124 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\ParamConverter\EntityConverter.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\ParamConverter;
|
||||
|
||||
use Drupal\Core\Entity\EntityInterface;
|
||||
use Drupal\Core\Entity\EntityManagerInterface;
|
||||
use Drupal\Core\TypedData\TranslatableInterface;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @var \Drupal\Core\Entity\EntityManagerInterface
|
||||
*/
|
||||
protected $entityManager;
|
||||
|
||||
/**
|
||||
* Constructs a new EntityConverter.
|
||||
*
|
||||
* @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager
|
||||
* The entity manager.
|
||||
*/
|
||||
public function __construct(EntityManagerInterface $entity_manager) {
|
||||
$this->entityManager = $entity_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function convert($value, $definition, $name, array $defaults) {
|
||||
$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) {
|
||||
$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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\ParamConverter\MenuLinkPluginConverter.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\ParamConverter;
|
||||
|
||||
use Drupal\Core\Menu\MenuLinkManagerInterface;
|
||||
use Drupal\Component\Plugin\Exception\PluginException;
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* Parameter converter for upcasting entity ids to full objects.
|
||||
*/
|
||||
class MenuLinkPluginConverter implements ParamConverterInterface {
|
||||
|
||||
/**
|
||||
* Plugin manager which creates the instance from the value.
|
||||
*
|
||||
* @var \Drupal\Core\Menu\MenuLinkManagerInterface
|
||||
*/
|
||||
protected $menuLinkManager;
|
||||
|
||||
/**
|
||||
* Constructs a new MenuLinkPluginConverter.
|
||||
*
|
||||
* @param \Drupal\Core\Menu\MenuLinkManagerInterface $menu_link_manager
|
||||
* The menu link plugin manager.
|
||||
*/
|
||||
public function __construct(MenuLinkManagerInterface $menu_link_manager) {
|
||||
$this->menuLinkManager = $menu_link_manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function convert($value, $definition, $name, array $defaults) {
|
||||
if ($value) {
|
||||
try {
|
||||
return $this->menuLinkManager->createInstance($value);
|
||||
}
|
||||
catch (PluginException $e) {
|
||||
// Suppress the error.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function applies($definition, $name, Route $route) {
|
||||
return (!empty($definition['type']) && $definition['type'] === 'menu_link_plugin');
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\ParamConverter\ParamConverterInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\ParamConverter;
|
||||
|
||||
use Symfony\Component\Routing\Route;
|
||||
|
||||
/**
|
||||
* Interface for parameter converters.
|
||||
*
|
||||
* Classes implementing this interface are responsible for converting a path
|
||||
* parameter to the object it represents.
|
||||
*
|
||||
* Here is an example path: /admin/structure/block/manage/{block}
|
||||
*
|
||||
* In this case, '{block}' would be the path parameter which should be turned
|
||||
* into a block object representing the block in question.
|
||||
*
|
||||
* ParamConverters are defined as services tagged with 'paramconverter', and are
|
||||
* managed by the 'paramconverter_manager' service.
|
||||
*
|
||||
* @see menu
|
||||
* @see \Drupal\Core\ParamConverter\ParamConverterManagerInterface
|
||||
* @see \Drupal\Core\ParamConverter\EntityConverter
|
||||
*/
|
||||
interface ParamConverterInterface {
|
||||
|
||||
/**
|
||||
* Converts path variables to their corresponding objects.
|
||||
*
|
||||
* @param mixed $value
|
||||
* The raw value.
|
||||
* @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.
|
||||
*
|
||||
* @return mixed|null
|
||||
* The converted parameter value.
|
||||
*/
|
||||
public function convert($value, $definition, $name, array $defaults);
|
||||
|
||||
/**
|
||||
* Determines if the converter applies to a specific route and variable.
|
||||
*
|
||||
* @param mixed $definition
|
||||
* The parameter definition provided in the route options.
|
||||
* @param string $name
|
||||
* The name of the parameter.
|
||||
* @param \Symfony\Component\Routing\Route $route
|
||||
* The route to consider attaching to.
|
||||
*
|
||||
* @return bool
|
||||
* TRUE if the converter applies to the passed route and parameter, FALSE
|
||||
* otherwise.
|
||||
*/
|
||||
public function applies($definition, $name, Route $route);
|
||||
|
||||
}
|
115
core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
Normal file
115
core/lib/Drupal/Core/ParamConverter/ParamConverterManager.php
Normal file
|
@ -0,0 +1,115 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\ParamConverter\ParamConverterManager.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\ParamConverter;
|
||||
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
|
||||
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
|
||||
use Symfony\Cmf\Component\Routing\RouteObjectInterface;
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* Manages converter services for converting request parameters to full objects.
|
||||
*
|
||||
* A typical use case for this would be upcasting (converting) a node id to a
|
||||
* node entity.
|
||||
*/
|
||||
class ParamConverterManager implements ParamConverterManagerInterface {
|
||||
|
||||
/**
|
||||
* Array of loaded converter services keyed by their ids.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $converters = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function addConverter(ParamConverterInterface $param_converter, $id) {
|
||||
$this->converters[$id] = $param_converter;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getConverter($converter) {
|
||||
if (isset($this->converters[$converter])) {
|
||||
return $this->converters[$converter];
|
||||
}
|
||||
else {
|
||||
throw new \InvalidArgumentException(sprintf('No converter has been registered for %s', $converter));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function setRouteParameterConverters(RouteCollection $routes) {
|
||||
foreach ($routes->all() as $route) {
|
||||
if (!$parameters = $route->getOption('parameters')) {
|
||||
// Continue with the next route if no parameters have been defined.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Loop over all defined parameters and look up the right converter.
|
||||
foreach ($parameters as $name => &$definition) {
|
||||
if (isset($definition['converter'])) {
|
||||
// Skip parameters that already have a manually set converter.
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach (array_keys($this->converters) as $converter) {
|
||||
if ($this->getConverter($converter)->applies($definition, $name, $route)) {
|
||||
$definition['converter'] = $converter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Override the parameters array.
|
||||
$route->setOption('parameters', $parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function convert(array $defaults) {
|
||||
/** @var $route \Symfony\Component\Routing\Route */
|
||||
$route = $defaults[RouteObjectInterface::ROUTE_OBJECT];
|
||||
|
||||
// Skip this enhancer if there are no parameter definitions.
|
||||
if (!$parameters = $route->getOption('parameters')) {
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
// Invoke the registered converter for each parameter.
|
||||
foreach ($parameters as $name => $definition) {
|
||||
if (!isset($defaults[$name])) {
|
||||
// Do not try to convert anything that is already set to NULL.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!isset($definition['converter'])) {
|
||||
// Continue if no converter has been specified.
|
||||
continue;
|
||||
}
|
||||
|
||||
// If a converter returns NULL it means that the parameter could not be
|
||||
// converted.
|
||||
$defaults[$name] = $this->getConverter($definition['converter'])->convert($defaults[$name], $definition, $name, $defaults);
|
||||
if (!isset($defaults[$name])) {
|
||||
throw new ParamNotConvertedException(sprintf('The "%s" parameter was not converted for the path "%s" (route name: "%s")', $name, $route->getPath(), $defaults[RouteObjectInterface::ROUTE_NAME]));
|
||||
}
|
||||
}
|
||||
|
||||
return $defaults;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\ParamConverter\ParamConverterManagerInterface.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\ParamConverter;
|
||||
|
||||
use Symfony\Component\Routing\RouteCollection;
|
||||
|
||||
/**
|
||||
* Provides an interface for a parameter converter manager.
|
||||
*/
|
||||
interface ParamConverterManagerInterface {
|
||||
|
||||
/**
|
||||
* Registers a parameter converter with the manager.
|
||||
*
|
||||
* @param \Drupal\Core\ParamConverter\ParamConverterInterface $param_converter
|
||||
* The added param converter instance.
|
||||
* @param string $id
|
||||
* The parameter converter service id to register.
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function addConverter(ParamConverterInterface $param_converter, $id);
|
||||
|
||||
/**
|
||||
* Lazy-loads converter services.
|
||||
*
|
||||
* @param string $id
|
||||
* The service id of converter service to load.
|
||||
*
|
||||
* @return \Drupal\Core\ParamConverter\ParamConverterInterface
|
||||
* The loaded converter service identified by the given service id.
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* If the given service id is not a registered converter.
|
||||
*/
|
||||
public function getConverter($id);
|
||||
|
||||
/**
|
||||
* Saves a list of applicable converters to each route.
|
||||
*
|
||||
* @param \Symfony\Component\Routing\RouteCollection $routes
|
||||
* A collection of routes to apply converters to.
|
||||
*/
|
||||
public function setRouteParameterConverters(RouteCollection $routes);
|
||||
|
||||
/**
|
||||
* Invokes the registered converter for each defined parameter on a route.
|
||||
*
|
||||
* @param array $defaults
|
||||
* The route defaults array.
|
||||
*
|
||||
* @throws \Drupal\Core\ParamConverter\ParamNotConvertedException
|
||||
* If one of the assigned converters returned NULL because the given
|
||||
* variable could not be converted.
|
||||
*
|
||||
* @return array
|
||||
* The modified defaults.
|
||||
*/
|
||||
public function convert(array $defaults);
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Contains \Drupal\Core\ParamConverter\ParamNotConvertedException.
|
||||
*/
|
||||
|
||||
namespace Drupal\Core\ParamConverter;
|
||||
|
||||
/**
|
||||
* Provides an exception class for a request parameter that was not converted.
|
||||
*/
|
||||
class ParamNotConvertedException extends \Exception {
|
||||
|
||||
}
|
Reference in a new issue