Drupal 8.0.0 beta 12. More info: https://www.drupal.org/node/2514176

This commit is contained in:
Pantheon Automation 2015-08-17 17:00:26 -07:00 committed by Greg Anderson
commit 9921556621
13277 changed files with 1459781 additions and 0 deletions

View file

@ -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;
}
}

View 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;
}
}

View file

@ -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');
}
}

View file

@ -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);
}

View 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;
}
}

View file

@ -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);
}

View file

@ -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 {
}