entityTypeManager = $entity_type_manager; $this->entityTypeBundleInfo = $entity_type_bundle_info; $this->entityRepository = $entity_repository; $this->renderer = $renderer; $this->stringTranslation = $string_translation; $this->urlGenerator = $url_generator; } /** * {@inheritdoc} */ public static function create(ContainerInterface $container) { return new static( $container->get('entity_type.manager'), $container->get('entity_type.bundle.info'), $container->get('entity.repository'), $container->get('renderer'), $container->get('string_translation'), $container->get('url_generator') ); } /** * 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. * * @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) { $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id); $bundle_key = $entity_type->getKey('bundle'); $bundle_entity_type_id = $entity_type->getBundleEntityType(); $build = [ '#theme' => 'entity_add_list', '#bundles' => [], ]; if ($bundle_entity_type_id) { $bundle_argument = $bundle_entity_type_id; $bundle_entity_type = $this->entityTypeManager->getDefinition($bundle_entity_type_id); $bundle_entity_type_label = $bundle_entity_type->getLowercaseLabel(); $build['#cache']['tags'] = $bundle_entity_type->getListCacheTags(); // Build the message shown when there are no bundles. $link_text = $this->t('Add a new @entity_type.', ['@entity_type' => $bundle_entity_type_label]); $link_route_name = 'entity.' . $bundle_entity_type->id() . '.add_form'; $build['#add_bundle_message'] = $this->t('There is no @entity_type yet. @add_link', [ '@entity_type' => $bundle_entity_type_label, '@add_link' => Link::createFromRoute($link_text, $link_route_name)->toString(), ]); // Filter out the bundles the user doesn't have access to. $access_control_handler = $this->entityTypeManager->getAccessControlHandler($entity_type_id); foreach ($bundles as $bundle_name => $bundle_info) { $access = $access_control_handler->createAccess($bundle_name, NULL, [], TRUE); if (!$access->isAllowed()) { unset($bundles[$bundle_name]); } $this->renderer->addCacheableDependency($build, $access); } // Add descriptions from the bundle entities. $bundles = $this->loadBundleDescriptions($bundles, $bundle_entity_type); } else { $bundle_argument = $bundle_key; } $form_route_name = 'entity.' . $entity_type_id . '.add_form'; // Redirect if there's only one bundle available. if (count($bundles) == 1) { $bundle_names = array_keys($bundles); $bundle_name = reset($bundle_names); return $this->redirect($form_route_name, [$bundle_argument => $bundle_name]); } // Prepare the #bundles array for the template. foreach ($bundles as $bundle_name => $bundle_info) { $build['#bundles'][$bundle_name] = [ 'label' => $bundle_info['label'], 'description' => isset($bundle_info['description']) ? $bundle_info['description'] : '', 'add_link' => Link::createFromRoute($bundle_info['label'], $form_route_name, [$bundle_argument => $bundle_name]), ]; } return $build; } /** * Provides a generic add title callback for an entity type. * * @param string $entity_type_id * The entity type ID. * * @return string * The title for the entity add page. */ public function addTitle($entity_type_id) { $entity_type = $this->entityTypeManager->getDefinition($entity_type_id); return $this->t('Add @entity-type', ['@entity-type' => $entity_type->getLowercaseLabel()]); } /** * Provides a generic add title callback for entities with bundles. * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The route match. * @param string $entity_type_id * The entity type ID. * @param string $bundle_parameter * The name of the route parameter that holds the bundle. * * @return string * The title for the entity add page, if the bundle was found. */ public function addBundleTitle(RouteMatchInterface $route_match, $entity_type_id, $bundle_parameter) { $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type_id); // If the entity has bundle entities, the parameter might have been upcasted // so fetch the raw parameter. $bundle = $route_match->getRawParameter($bundle_parameter); if ((count($bundles) > 1) && isset($bundles[$bundle])) { return $this->t('Add @bundle', ['@bundle' => $bundles[$bundle]['label']]); } // If the entity supports bundles generally, but only has a single bundle, // the bundle is probably something like 'Default' so that it preferable to // use the entity type label. else { return $this->addTitle($entity_type_id); } } /** * Provides a generic title callback for a single entity. * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The route match. * @param \Drupal\Core\Entity\EntityInterface $_entity * (optional) An entity, passed in directly from the request attributes. * * @return string|null * The title for the entity view page, if an entity was found. */ public function title(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) { if ($entity = $this->doGetEntity($route_match, $_entity)) { return $entity->label(); } } /** * Provides a generic edit title callback. * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The route match. * @param \Drupal\Core\Entity\EntityInterface $_entity * (optional) An entity, passed in directly from the request attributes. * * @return string|null * The title for the entity edit page, if an entity was found. */ public function editTitle(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) { if ($entity = $this->doGetEntity($route_match, $_entity)) { return $this->t('Edit %label', ['%label' => $entity->label()]); } } /** * Provides a generic delete title callback. * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The route match. * @param \Drupal\Core\Entity\EntityInterface $_entity * (optional) An entity, passed in directly from the request attributes, and * set in \Drupal\Core\Entity\Enhancer\EntityRouteEnhancer. * * @return string * The title for the entity delete page. */ public function deleteTitle(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) { if ($entity = $this->doGetEntity($route_match, $_entity)) { return $this->t('Delete %label', ['%label' => $entity->label()]); } } /** * Determines the entity. * * @param \Drupal\Core\Routing\RouteMatchInterface $route_match * The route match. * @param \Drupal\Core\Entity\EntityInterface $_entity * (optional) The entity, set in * \Drupal\Core\Entity\Enhancer\EntityRouteEnhancer. * * @return \Drupal\Core\Entity\EntityInterface|null * The entity, if it is passed in directly or if the first parameter of the * active route is an entity; otherwise, NULL. */ protected function doGetEntity(RouteMatchInterface $route_match, EntityInterface $_entity = NULL) { if ($_entity) { $entity = $_entity; } else { // Let's look up in the route object for the name of upcasted values. foreach ($route_match->getParameters() as $parameter) { if ($parameter instanceof EntityInterface) { $entity = $parameter; break; } } } if (isset($entity)) { return $this->entityRepository->getTranslationFromContext($entity); } } /** * Expands the bundle information with descriptions, if known. * * @param array $bundles * An array of bundle information. * @param \Drupal\Core\Entity\EntityTypeInterface $bundle_entity_type * The bundle entity type definition. * * @return array * The expanded array of bundle information. */ protected function loadBundleDescriptions(array $bundles, EntityTypeInterface $bundle_entity_type) { if (!$bundle_entity_type->entityClassImplements(EntityDescriptionInterface::class)) { return $bundles; } $bundle_names = array_keys($bundles); $storage = $this->entityTypeManager->getStorage($bundle_entity_type->id()); /** @var \Drupal\Core\Entity\EntityDescriptionInterface[] $bundle_entities */ $bundle_entities = $storage->loadMultiple($bundle_names); foreach ($bundles as $bundle_name => &$bundle_info) { if (isset($bundle_entities[$bundle_name])) { $bundle_info['description'] = $bundle_entities[$bundle_name]->getDescription(); } } return $bundles; } }