diff --git a/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php b/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php index 2a5851f..a897d30 100644 --- a/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php +++ b/core/lib/Drupal/Core/Entity/EntityAccessControllerInterface.php @@ -45,8 +45,8 @@ public function access(EntityInterface $entity, $operation, $langcode = Language * Checks access to create an entity. * * @param string $entity_bundle - * (optional) The bundle of the entity. Required if the entity supports - * bundles, defaults to NULL otherwise. + * (optional) The bundle of the entity. If no bundle has been given, access + * is checked for any available bundle. * @param \Drupal\Core\Session\AccountInterface $account * (optional) The user session for which to check access, or NULL to check * access for the current user. Defaults to NULL. diff --git a/core/lib/Drupal/Core/Entity/EntityListBuilder.php b/core/lib/Drupal/Core/Entity/EntityListBuilder.php index 16a0849..32ef3e1 100644 --- a/core/lib/Drupal/Core/Entity/EntityListBuilder.php +++ b/core/lib/Drupal/Core/Entity/EntityListBuilder.php @@ -8,6 +8,8 @@ namespace Drupal\Core\Entity; use Drupal\Core\Extension\ModuleHandlerInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\Utility\LinkGeneratorInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\Component\Utility\String; @@ -183,16 +185,19 @@ public function buildOperations(EntityInterface $entity) { * {@inheritdoc} * * Builds the entity listing as renderable array for theme_table(). - * - * @todo Add a link to add a new item to the #empty text. */ public function render() { + $empty_text = $this->getEmptyText(); + $add_link = $this->createAddLink(); + if ($add_link) { + $empty_text .= ' ' . $add_link; + } $build = array( '#type' => 'table', '#header' => $this->buildHeader(), '#title' => $this->getTitle(), '#rows' => array(), - '#empty' => $this->t('There is no @label yet.', array('@label' => $this->entityType->getLabel())), + '#empty' => $empty_text, ); foreach ($this->load() as $entity) { if ($row = $this->buildRow($entity)) { @@ -203,6 +208,44 @@ public function render() { } /** + * Gets the text to display when the list is empty. + * + * @return string + */ + protected function getEmptyText() { + return $this->t('There is no @label yet.', array( + '@label' => $this->entityType->getLabel(), + )); + } + + /** + * Gets the text for the "Add new entity" link. + * + * @return string + */ + protected function getAddLinkText() { + return $this->t('Add one.'); + } + + /** + * Creates a link to add a new entity. + * + * @return string|false + * The HTML link or FALSE if no link is available. + */ + protected function createAddLink() { + if ($this->entityType->hasLinkTemplate('add-entity-form') && \Drupal::entityManager()->getAccessController($this->entityTypeId)->createAccess()) { + return \Drupal::linkGenerator()->generate( + $this->getAddLinkText(), + $this->entityType->getLinkTemplate('add-entity-form') + ); + } + else { + return FALSE; + } + } + + /** * Returns the title of the page. * * @return string diff --git a/core/modules/block_content/src/Entity/BlockContent.php b/core/modules/block_content/src/Entity/BlockContent.php index 630fe51..4f725dd 100644 --- a/core/modules/block_content/src/Entity/BlockContent.php +++ b/core/modules/block_content/src/Entity/BlockContent.php @@ -40,7 +40,8 @@ * "canonical" = "block_content.edit", * "delete-form" = "block_content.delete", * "edit-form" = "block_content.edit", - * "admin-form" = "block_content.type_edit" + * "admin-form" = "block_content.type_edit", + * "add-entity-form" = "block_content.add_page" * }, * fieldable = TRUE, * translatable = TRUE, diff --git a/core/modules/block_content/src/Entity/BlockContentType.php b/core/modules/block_content/src/Entity/BlockContentType.php index 17a358e..279c99f 100644 --- a/core/modules/block_content/src/Entity/BlockContentType.php +++ b/core/modules/block_content/src/Entity/BlockContentType.php @@ -36,7 +36,8 @@ * }, * links = { * "delete-form" = "block_content.type_delete", - * "edit-form" = "block_content.type_edit" + * "edit-form" = "block_content.type_edit", + * "add-entity-form" = "block_content.type_add" * } * ) */ diff --git a/core/modules/field_ui/src/FieldInstanceConfigListBuilder.php b/core/modules/field_ui/src/FieldInstanceConfigListBuilder.php index b801f4c..623c186 100644 --- a/core/modules/field_ui/src/FieldInstanceConfigListBuilder.php +++ b/core/modules/field_ui/src/FieldInstanceConfigListBuilder.php @@ -9,9 +9,6 @@ use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Entity\EntityInterface; -use Drupal\Core\Entity\EntityManagerInterface; -use Drupal\Core\Entity\EntityTypeInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; /** * Provides lists of field instance config entities. @@ -19,33 +16,6 @@ class FieldInstanceConfigListBuilder extends ConfigEntityListBuilder { /** - * The entity manager. - * - * @var \Drupal\Core\Entity\EntityManagerInterface - */ - protected $entityManager; - - /** - * Constructs a new class instance. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type definition. - * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager - * The entity manager. - */ - public function __construct(EntityTypeInterface $entity_type, EntityManagerInterface $entity_manager) { - parent::__construct($entity_type, $entity_manager->getStorage($entity_type->id())); - $this->entityManager = $entity_manager; - } - - /** - * {@inheritdoc} - */ - public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { - return new static($entity_type, $container->get('entity.manager')); - } - - /** * {@inheritdoc} */ public function render() { diff --git a/core/modules/image/src/Entity/ImageStyle.php b/core/modules/image/src/Entity/ImageStyle.php index ad415a9..833c0d4 100644 --- a/core/modules/image/src/Entity/ImageStyle.php +++ b/core/modules/image/src/Entity/ImageStyle.php @@ -43,7 +43,8 @@ * links = { * "flush-form" = "image.style_flush", * "edit-form" = "image.style_edit", - * "delete-form" = "image.style_delete" + * "delete-form" = "image.style_delete", + * "add-entity-form" = "image.style_add" * } * ) */ diff --git a/core/modules/node/src/Entity/Node.php b/core/modules/node/src/Entity/Node.php index 90ab790..5bc891e 100644 --- a/core/modules/node/src/Entity/Node.php +++ b/core/modules/node/src/Entity/Node.php @@ -56,7 +56,8 @@ * "delete-form" = "node.delete_confirm", * "edit-form" = "node.page_edit", * "version-history" = "node.revision_overview", - * "admin-form" = "node.type_edit" + * "admin-form" = "node.type_edit", + * "add-entity-form" = "node.add_page" * } * ) */ diff --git a/core/modules/node/src/Entity/NodeType.php b/core/modules/node/src/Entity/NodeType.php index ecc21ea..7cb99da 100644 --- a/core/modules/node/src/Entity/NodeType.php +++ b/core/modules/node/src/Entity/NodeType.php @@ -37,7 +37,8 @@ * links = { * "add-form" = "node.add", * "edit-form" = "node.type_edit", - * "delete-form" = "node.type_delete_confirm" + * "delete-form" = "node.type_delete_confirm", + * "add-entity-form" = "node.type_add" * } * ) */ diff --git a/core/modules/node/src/NodeListBuilder.php b/core/modules/node/src/NodeListBuilder.php index 4ddc56e..d3a3d02 100644 --- a/core/modules/node/src/NodeListBuilder.php +++ b/core/modules/node/src/NodeListBuilder.php @@ -49,8 +49,7 @@ public function __construct(EntityTypeInterface $entity_type, EntityStorageInter /** * {@inheritdoc} */ - public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { - return new static( + public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { return new static( $entity_type, $container->get('entity.manager')->getStorage($entity_type->id()), $container->get('date') @@ -60,6 +59,20 @@ public static function createInstance(ContainerInterface $container, EntityTypeI /** * {@inheritdoc} */ + protected function getEmptyText() { + return $this->t('There is no content yet.'); + } + + /** + * {@inheritdoc} + */ + protected function getAddLinkText() { + return $this->t('Add new content.'); + } + + /** + * {@inheritdoc} + */ public function buildHeader() { // Enable language column and filter if multiple languages are added. $header = array( diff --git a/core/modules/node/src/NodeTypeListBuilder.php b/core/modules/node/src/NodeTypeListBuilder.php index 779672a..a2389e9 100644 --- a/core/modules/node/src/NodeTypeListBuilder.php +++ b/core/modules/node/src/NodeTypeListBuilder.php @@ -8,13 +8,8 @@ namespace Drupal\node; use Drupal\Core\Config\Entity\ConfigEntityListBuilder; -use Drupal\Core\Entity\EntityTypeInterface; -use Symfony\Component\DependencyInjection\ContainerInterface; -use Drupal\Core\Entity\EntityStorageInterface; -use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Component\Utility\Xss; -use Drupal\Component\Utility\String; /** * Defines a class to build a listing of node type entities. @@ -24,39 +19,6 @@ class NodeTypeListBuilder extends ConfigEntityListBuilder { /** - * The url generator service. - * - * @var \Drupal\Core\Routing\UrlGeneratorInterface - */ - protected $urlGenerator; - - /** - * Constructs a NodeTypeForm object. - * - * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type - * The entity type definition. - * @param \Drupal\Core\Entity\EntityStorageInterface $storage - * The entity storage class. - * @param \Drupal\Core\Routing\UrlGeneratorInterface $url_generator - * The url generator service. - */ - public function __construct(EntityTypeInterface $entity_type, EntityStorageInterface $storage, UrlGeneratorInterface $url_generator) { - parent::__construct($entity_type, $storage); - $this->urlGenerator = $url_generator; - } - - /** - * {@inheritdoc} - */ - public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type) { - return new static( - $entity_type, - $container->get('entity.manager')->getStorage($entity_type->id()), - $container->get('url_generator') - ); - } - - /** * {@inheritdoc} */ public function buildHeader() { @@ -96,12 +58,15 @@ public function getDefaultOperations(EntityInterface $entity) { /** * {@inheritdoc} */ - public function render() { - $build = parent::render(); - $build['#empty'] = t('No content types available. Add content type.', array( - '@link' => $this->urlGenerator->generateFromPath('admin/structure/types/add'), - )); - return $build; + protected function getEmptyText() { + return $this->t('There are no content types yet.'); + } + + /** + * {@inheritdoc} + */ + protected function getAddLinkText() { + return $this->t('Add new content type.'); } } diff --git a/core/modules/responsive_image/src/Entity/ResponsiveImageMapping.php b/core/modules/responsive_image/src/Entity/ResponsiveImageMapping.php index 7c37818..9e76fc9 100644 --- a/core/modules/responsive_image/src/Entity/ResponsiveImageMapping.php +++ b/core/modules/responsive_image/src/Entity/ResponsiveImageMapping.php @@ -35,7 +35,8 @@ * }, * links = { * "edit-form" = "responsive_image.mapping_page_edit", - * "duplicate-form" = "responsive_image.mapping_page_duplicate" + * "duplicate-form" = "responsive_image.mapping_page_duplicate", + * "add-entity-form" = "responsive_image.mapping_page_add" * } * ) */ diff --git a/core/modules/system/src/Entity/DateFormat.php b/core/modules/system/src/Entity/DateFormat.php index a7d689d..3cb690e 100644 --- a/core/modules/system/src/Entity/DateFormat.php +++ b/core/modules/system/src/Entity/DateFormat.php @@ -34,7 +34,8 @@ * admin_permission = "administer site configuration", * links = { * "delete-form" = "system.date_format_delete", - * "edit-form" = "system.date_format_edit" + * "edit-form" = "system.date_format_edit", + * "add-entity-form" = "system.date_format_add" * } * ) */ diff --git a/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php b/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php index 121d745..29c7f4c 100644 --- a/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php +++ b/core/tests/Drupal/Tests/Core/Entity/EntityListBuilderTest.php @@ -23,6 +23,20 @@ class EntityListBuilderTest extends UnitTestCase { /** + * The entity access controller. + * + * @var \Drupal\Core\Entity\EntityAccessControllerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $entityAccess; + + /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $entityManager; + + /** * The entity type used for testing. * * @var \Drupal\Core\Entity\EntityTypeInterface|\PHPUnit_Framework_MockObject_MockObject @@ -30,6 +44,13 @@ class EntityListBuilderTest extends UnitTestCase { protected $entityType; /** + * The link generator. + * + * @var \Drupal\Core\Utility\LinkGeneratorInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $linkGenerator; + + /** * The module handler used for testing. * * @var \Drupal\Core\Extension\ModuleHandlerInterface|\PHPUnit_Framework_MockObject_MockObject @@ -87,11 +108,16 @@ protected function setUp() { $this->role = $this->getMock('Drupal\user\RoleInterface'); $this->roleStorage = $this->getMock('\Drupal\user\RoleStorageInterface'); + $this->entityAccess = $this->getMock('\Drupal\Core\Entity\EntityAccessControllerInterface'); + $this->entityManager = $this->getMock('\Drupal\Core\Entity\EntityManagerInterface'); + $this->linkGenerator = $this->getMock('\Drupal\Core\Utility\LinkGeneratorInterface'); $this->moduleHandler = $this->getMock('\Drupal\Core\Extension\ModuleHandlerInterface'); $this->entityType = $this->getMock('\Drupal\Core\Entity\EntityTypeInterface'); $this->translationManager = $this->getMock('\Drupal\Core\StringTranslation\TranslationInterface'); $this->entityListBuilder = new TestEntityListBuilder($this->entityType, $this->roleStorage, $this->moduleHandler); $this->container = new ContainerBuilder(); + $this->container->set('entity.manager', $this->entityManager); + $this->container->set('link_generator', $this->linkGenerator); \Drupal::setContainer($this->container); }