Skip to content
Snippets Groups Projects
Commit e71cd2c1 authored by Bojan Zivanovic's avatar Bojan Zivanovic
Browse files

Add a route provider and controller for add page/form.

parent 16567a01
No related branches found
No related tags found
No related merge requests found
<?php
/**
* @file
* Provides expanded entity APIs.
*/
use Drupal\Core\Url;
/**
* Implements hook_theme().
*/
function entity_theme() {
return [
'entity_add_list' => [
'variables' => [
'bundles' => [],
'bundle_type' => NULL,
'form_route_name' => NULL,
],
'template' => 'entity-add-list',
],
];
}
/**
* Prepares variables for the list of available bundles.
*
* Default template: entity-add-list.html.twig.
*
* @param array $variables
* An associative array containing:
* - bundle_type: The entity type of the bundles.
* - bundles: An array of bundles.
* - form_route_name: The add form route.
*/
function template_preprocess_entity_add_list(&$variables) {
$bundle_type = \Drupal::entityTypeManager()->getDefinition($variables['bundle_type']);
$variables += [
'class' => str_replace('_', '-', $bundle_type->getBundleOf()) . '-add-list',
'create_bundle_url' => Url::fromRoute('entity.' . $bundle_type->id() . '.add_form'),
'bundle_type_label' => $bundle_type->getLowercaseLabel(),
];
foreach ($variables['bundles'] as $bundle) {
$url = Url::fromRoute($variables['form_route_name'], [$bundle->getEntityTypeId() => $bundle->id()]);
$variables['bundles'][$bundle->id()] = [
'bundle' => $bundle->id(),
'add_link' => \Drupal::l($bundle->label(), $url),
'description' => [
'#markup' => $bundle->getDescription(),
],
];
}
}
<?php
/**
* @file
* Contains \Drupal\entity\Controller\EntityCreateController.
*/
namespace Drupal\entity\Controller;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Render\RendererInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\Core\Url;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
/**
* A generic controller for creating entities.
*/
class EntityCreateController extends ControllerBase {
/**
* The entity type bundle info.
*
* @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
*/
protected $entityTypeBundleInfo;
/**
* The renderer service.
*
* @var \Drupal\Core\Render\RendererInterface
*/
protected $renderer;
/**
* Constructs a new EntityCreateController object.
*
* @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
* The entity type bundle info.
* @param \Drupal\Core\Render\RendererInterface $renderer
* The renderer.
*/
public function __construct(EntityTypeBundleInfoInterface $entity_type_bundle_info, RendererInterface $renderer) {
$this->entityTypeBundleInfo = $entity_type_bundle_info;
$this->renderer = $renderer;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
return new static(
$container->get('entity_type.bundle.info'),
$container->get('renderer')
);
}
/**
* Displays add links for the available bundles.
*
* Redirects to the add form if there's only one bundle available.
*
* @param string $entity_type_id
* The entity type ID.
* @param \Symfony\Component\HttpFoundation\Request $request
* The request.
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse|array
* If there's only one available bundle, a redirect response.
* Otherwise, a render array with the add links for each bundle.
*/
public function addPage($entity_type_id, Request $request) {
$entity_type = $this->entityTypeManager()->getDefinition($entity_type_id);
$bundle_type = $entity_type->getBundleEntityType();
$form_route_name = 'entity.' . $entity_type_id . '.add_form';
$build = [
'#theme' => 'entity_add_list',
'#cache' => [
'tags' => $entity_type->getListCacheTags(),
],
'#bundle_type' => $bundle_type,
'#form_route_name' => $form_route_name,
];
$bundles = array_keys($this->entityTypeBundleInfo->getBundleInfo($entity_type_id));
// Filter out the bundles the user doesn't have access to.
$access_control_handler = $this->entityTypeManager()->getAccessControlHandler($bundle_type);
foreach ($bundles as $index => $bundle_name) {
$access = $access_control_handler->createAccess($bundle_name, NULL, [], TRUE);
if (!$access->isAllowed()) {
unset($bundles[$index]);
}
$this->renderer->addCacheableDependency($build, $access);
}
// Redirect if there's only one bundle available.
if (count($bundles) == 1) {
$bundle_name = reset($bundles);
return $this->redirect($form_route_name, [$bundle_type => $bundle_name]);
}
// The theme function needs the full bundle entities.
$build['#bundles'] = $this->entityTypeManager->getStorage($bundle_type)->loadMultiple($bundles);
return $build;
}
/**
* The title callback for the add page.
*
* @param string $entity_type_id
* The entity type ID.
*
* @return string
* The page title.
*/
public function addPageTitle($entity_type_id) {
$entity_type = $this->entityTypeManager()->getDefinition($entity_type_id);
return $this->t('Add @entity-type', ['@entity-type' => $entity_type->getLowercaseLabel()]);
}
/**
* Provides the add form for an entity of a specific bundle.
*
* @param string $entity_type_id
* The entity type ID.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*
* @return array
* The add form.
*/
public function addForm($entity_type_id, RouteMatchInterface $route_match) {
$entity_type = $this->entityTypeManager()->getDefinition($entity_type_id);
$bundle_type = $entity_type->getBundleEntityType();
$bundle_key = $entity_type->getKey('bundle');
$bundle_name = $route_match->getRawParameter($bundle_type);
$entity = $this->entityTypeManager()->getStorage($entity_type_id)->create([
$bundle_key => $bundle_name,
]);
return $this->entityFormBuilder()->getForm($entity, 'add');
}
/**
* The title callback for the add form.
*
* @param string $entity_type_id
* The entity type ID.
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*
* @return string
* The page title.
*/
public function addFormTitle($entity_type_id, RouteMatchInterface $route_match) {
$entity_type = $this->entityTypeManager()->getDefinition($entity_type_id);
$bundle_type = $entity_type->getBundleEntityType();
$bundle_name = $route_match->getRawParameter($bundle_type);
$bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id);
if (count($bundles) == 1) {
$title = $this->t('Add @entity-type', ['@entity-type' => $entity_type->getLowercaseLabel()]);
}
else {
$title = $this->t('Add @bundle', ['@bundle' => $bundles[$bundle_name]['label']]);
}
return $title;
}
}
<?php
/**
* @file
* Contains \Drupal\entity\Routing\CreateUIRouteProvider.
*/
namespace Drupal\entity\Routing;
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Entity\Routing\EntityRouteProviderInterface;
use Symfony\Component\Routing\Route;
use Symfony\Component\Routing\RouteCollection;
/**
* Provides HTML routes for creating entities.
*
* This class provides the following routes for entities, with title callbacks:
* - add-page
* - add-form
*/
class CreateUIRouteProvider implements EntityRouteProviderInterface {
/**
* {@inheritdoc}
*/
public function getRoutes(EntityTypeInterface $entity_type) {
$routes = new RouteCollection();
if ($route = $this->addPageRoute($entity_type)) {
$routes->add('entity.' . $entity_type->id() . '.add_page', $route);
}
if ($route = $this->addFormRoute($entity_type)) {
$routes->add('entity.' . $entity_type->id() . '.add_form', $route);
}
return $routes;
}
/**
* Returns the add page route.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type.
*
* @return \Symfony\Component\Routing\Route|null
* The generated route, if available.
*/
protected function addPageRoute(EntityTypeInterface $entity_type) {
if ($entity_type->hasLinkTemplate('add-page')) {
$route = new Route($entity_type->getLinkTemplate('add-page'));
$route->setDefault('_controller', '\Drupal\entity\Controller\EntityCreateController::addPage');
$route->setDefault('_title_callback', '\Drupal\entity\Controller\EntityCreateController::addPageTitle');
$route->setDefault('entity_type_id', $entity_type->id());
$route->setRequirement('_entity_create_access', $entity_type->id());
return $route;
}
}
/**
* Returns the add form route.
*
* @param \Drupal\Core\Entity\EntityTypeInterface $entity_type
* The entity type.
*
* @return \Symfony\Component\Routing\Route|null
* The generated route, if available.
*/
protected function addFormRoute(EntityTypeInterface $entity_type) {
if ($entity_type->hasLinkTemplate('add-form')) {
$bundle_type = $entity_type->getBundleEntityType();
$route = new Route($entity_type->getLinkTemplate('add-form'));
$route->setDefault('_controller', '\Drupal\entity\Controller\EntityCreateController::addForm');
$route->setDefault('_title_callback', '\Drupal\entity\Controller\EntityCreateController::addFormTitle');
$route->setDefault('entity_type_id', $entity_type->id());
$route->setOption('parameters', [
$bundle_type => ['type' => 'entity:' . $bundle_type],
]);
$route->setRequirement('_entity_create_access', $entity_type->id());
return $route;
}
}
}
{#
/**
* @file
* Default theme implementation to present a list of available bundles.
*
* Available variables:
* - class: The entity type specific class. E.g. 'node-add-list'.
* - create_bundle_url: The url to the bundle creation page.
* - bundle_type_label: The lowercase label of the bundle entity type.
* - bundles: A list of bundles, each with the following properties:
* - add_link: link to create an entity of this bundle.
* - description: Bundle description.
*
* @see template_preprocess_entity_add_list()
*
* @ingroup themeable
*/
#}
{% if bundles is not empty %}
<dl class="entity-add-list {{ class }}">
{% for bundle in bundles %}
<dt>{{ bundle.add_link }}</dt>
<dd>{{ bundle.description }}</dd>
{% endfor %}
</dl>
{% else %}
<p>
{% trans %}
Go to the <a href="{{ create_bundle_url }}">{{ bundle_type_label }} creation page</a> to add a new {{ bundle_type_label }}.
{% endtrans %}
</p>
{% endif %}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment