diff --git a/core/lib/Drupal/Core/Entity/Controller/EntityController.php b/core/lib/Drupal/Core/Entity/Controller/EntityController.php new file mode 100644 index 0000000000000000000000000000000000000000..0af9638f54c50f9811cf321a1942f66f129d9572 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Controller/EntityController.php @@ -0,0 +1,143 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Entity\Controller\EntityController. + */ + +namespace Drupal\Core\Entity\Controller; + +use Drupal\Core\Entity\EntityManagerInterface; +use Drupal\Core\Routing\RouteMatchInterface; +use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\DependencyInjection\ContainerInjectionInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\Core\StringTranslation\TranslationInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Provides generic entity title callbacks for use in routing. + * + * It provides: + * - A view title callback. + * - An edit title callback. + * - A delete title callback. + */ +class EntityController implements ContainerInjectionInterface { + + use StringTranslationTrait; + + /** + * The entity manager. + * + * @var \Drupal\Core\Entity\EntityManagerInterface + */ + protected $entityManager; + + /** + * Constructs a new EntityController. + * + * @param \Drupal\Core\Entity\EntityManagerInterface $entity_manager + * The entity manager. + * @param \Drupal\Core\StringTranslation\TranslationInterface $string_translation + * The string translation. + */ + public function __construct(EntityManagerInterface $entity_manager, TranslationInterface $string_translation) { + $this->entityManager = $entity_manager; + $this->stringTranslation = $string_translation; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity.manager'), + $container->get('string_translation') + ); + } + + /** + * 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 + * The title for the entity view page. + */ + 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 + * The title for the entity edit page. + */ + 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 delete entity 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 ($entity) { + return $this->entityManager->getTranslationFromContext($entity); + } + } + +} diff --git a/core/lib/Drupal/Core/Entity/Routing/AdminHtmlRouteProvider.php b/core/lib/Drupal/Core/Entity/Routing/AdminHtmlRouteProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..39c1c6ebccac220471d90173746e41fc06d9f131 --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Routing/AdminHtmlRouteProvider.php @@ -0,0 +1,44 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Entity\Routing\AdminHtmlRouteProvider. + */ + +namespace Drupal\Core\Entity\Routing; + +use Drupal\Core\Entity\EntityTypeInterface; + +/** + * Provides HTML routes for entities with administrative edit/delete pages. + * + * Use this class if the edit and delete form routes should use the + * administrative theme. + * + * @see \Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider. + * + * @internal + */ +class AdminHtmlRouteProvider extends DefaultHtmlRouteProvider { + + /** + * {@inheritdoc} + */ + protected function getEditFormRoute(EntityTypeInterface $entity_type) { + if ($route = parent::getEditFormRoute($entity_type)) { + $route->setOption('_admin_route', TRUE); + return $route; + } + } + + /** + * {@inheritdoc} + */ + protected function getDeleteFormRoute(EntityTypeInterface $entity_type) { + if ($route = parent::getDeleteFormRoute($entity_type)) { + $route->setOption('_admin_route', TRUE); + return $route; + } + } + +} diff --git a/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..f0b5907de3f026f56f271a7ce8523679261487df --- /dev/null +++ b/core/lib/Drupal/Core/Entity/Routing/DefaultHtmlRouteProvider.php @@ -0,0 +1,135 @@ +<?php + +/** + * @file + * Contains \Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider. + */ + +namespace Drupal\Core\Entity\Routing; + +use Drupal\Core\Entity\EntityTypeInterface; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * Provides HTML routes for entities. + * + * This class provides the following routes for entities, with title and access + * callbacks: + * - canonical + * - edit-form + * - delete-form + * + * @see \Drupal\Core\Entity\Routing\AdminHtmlRouteProvider. + * + * @internal + */ +class DefaultHtmlRouteProvider implements EntityRouteProviderInterface { + + /** + * {@inheritdoc} + */ + public function getRoutes(EntityTypeInterface $entity_type) { + $collection = new RouteCollection(); + + $entity_type_id = $entity_type->id(); + + if ($edit_route = $this->getEditFormRoute($entity_type)) { + $collection->add("entity.{$entity_type_id}.edit_form", $edit_route); + } + + if ($canonical_route = $this->getCanonicalRoute($entity_type)) { + $collection->add("entity.{$entity_type_id}.canonical", $canonical_route); + } + + if ($delete_route = $this->getDeleteFormRoute($entity_type)) { + $collection->add("entity.{$entity_type_id}.delete_form", $delete_route); + } + + return $collection; + } + + /** + * Gets the canonical route. + * + * @param \Drupal\Core\Entity\EntityTypeInterface $entity_type + * The entity type. + * + * @return \Symfony\Component\Routing\Route|null + * The generated route, if available. + */ + protected function getCanonicalRoute(EntityTypeInterface $entity_type) { + if ($entity_type->hasLinkTemplate('canonical') && $entity_type->hasViewBuilderClass()) { + $entity_type_id = $entity_type->id(); + $route = new Route($entity_type->getLinkTemplate('canonical')); + $route + ->addDefaults([ + '_entity_view' => "{$entity_type_id}.full", + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::title', + ]) + ->setRequirement('_entity_access', "{$entity_type_id}.view") + ->setOption('parameters', [ + $entity_type_id => ['type' => 'entity:' . $entity_type_id], + ]); + return $route; + } + } + + /** + * Gets the edit-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 getEditFormRoute(EntityTypeInterface $entity_type) { + if ($entity_type->hasLinkTemplate('edit-form')) { + $entity_type_id = $entity_type->id(); + $route = new Route($entity_type->getLinkTemplate('edit-form')); + // Use the edit form handler, if available, otherwise default. + $operation = 'default'; + if ($entity_type->getFormClass('edit')) { + $operation = 'edit'; + } + $route + ->setDefaults([ + '_entity_form' => "{$entity_type_id}.{$operation}", + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::editTitle' + ]) + ->setRequirement('_entity_access', "{$entity_type_id}.update") + ->setOption('parameters', [ + $entity_type_id => ['type' => 'entity:' . $entity_type_id], + ]); + return $route; + } + } + + /** + * Gets the delete-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 getDeleteFormRoute(EntityTypeInterface $entity_type) { + if ($entity_type->hasLinkTemplate('delete-form')) { + $entity_type_id = $entity_type->id(); + $route = new Route($entity_type->getLinkTemplate('delete-form')); + $route + ->addDefaults([ + '_entity_form' => "{$entity_type_id}.delete", + '_title_callback' => '\Drupal\Core\Entity\Controller\EntityController::deleteTitle', + ]) + ->setRequirement('_entity_access', "{$entity_type_id}.delete") + ->setOption('parameters', [ + $entity_type_id => ['type' => 'entity:' . $entity_type_id], + ]); + return $route; + } + } + +} diff --git a/core/lib/Drupal/Core/Entity/entity.api.php b/core/lib/Drupal/Core/Entity/entity.api.php index 3a3d61c6b80d10ad87473e7fe10ccc21e957f7d8..8883f78d038ec21afb7ce5f8d08fdd9a9db4f3b6 100644 --- a/core/lib/Drupal/Core/Entity/entity.api.php +++ b/core/lib/Drupal/Core/Entity/entity.api.php @@ -324,7 +324,9 @@ * also need to add a corresponding route to your module's routing.yml file; * see the entity.node.canonical route in node.routing.yml for an example, and see * @ref sec_routes below for some notes. - * - Define routes and links for the various URLs associated with the entity. + * - Optionally, instead of defining routes, routes can be auto generated by + * providing a route handler. See @ref sec_routes. Otherwise, define routes + * and links for the various URLs associated with the entity. * These go into the 'links' annotation, with the link type as the key, and * the path of this link template as the value. The corresponding route * requires the following route name: @@ -358,8 +360,10 @@ * * @section sec_routes Entity routes * Entity routes, like other routes, are defined in *.routing.yml files; see - * the @link menu Menu and routing @endlink topic for more information. Here - * is a typical entry, for the block configure form: + * the @link routing Routing API @endlink topic for more information. Entities + * may alternatively use an auto route provider class; there is an example of + * this at the end of this section. If providing routes directly, here is a + * typical entry, for the block configure form: * @code * entity.block.edit_form: * path: '/admin/structure/block/manage/{block}' @@ -386,6 +390,19 @@ * "form" = { * "default" = "Drupal\block\BlockForm", * @endcode + * - Instead of putting the routes for your entity in a *.routing.yml file, you + * can instead use a route provider class. + * \Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider provides canonical, + * edit-form, and delete-form routes; + * \Drupal\Core\Entity\Routing\AdminHtmlRouteProvider provides the same + * routes, set up to use the administrative theme for edit and delete pages. + * You can also create your own class. To use a route provider class, add + * lines like the following to your entity annotation: + * @code + * handlers = { + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * @endcode * * @section bundle Defining a content entity bundle * For entity types that use bundles, such as Node (bundles are content types) diff --git a/core/lib/Drupal/Core/EventSubscriber/EntityRouteProviderSubscriber.php b/core/lib/Drupal/Core/EventSubscriber/EntityRouteProviderSubscriber.php index d5c4def45017314c1cb9ce64313734755382bd1c..326c9984c4339dbde92993dc6cd80108adcb2317 100644 --- a/core/lib/Drupal/Core/EventSubscriber/EntityRouteProviderSubscriber.php +++ b/core/lib/Drupal/Core/EventSubscriber/EntityRouteProviderSubscriber.php @@ -48,12 +48,14 @@ public function onDynamicRouteEvent(RouteBuildEvent $event) { foreach ($this->entityManager->getRouteProviders($entity_type->id()) as $route_provider) { // Allow to both return an array of routes or a route collection, // like route_callbacks in the routing.yml file. + $routes = $route_provider->getRoutes($entity_type); if ($routes instanceof RouteCollection) { - $route_collection->addCollection($routes); + $routes = $routes->all(); } - elseif (is_array($routes)) { - foreach ($routes as $route_name => $route) { + foreach ($routes as $route_name => $route) { + // Don't override existing routes. + if (!$route_collection->get($route_name)) { $route_collection->add($route_name, $route); } } diff --git a/core/modules/aggregator/aggregator.routing.yml b/core/modules/aggregator/aggregator.routing.yml index 2f2d5536c8f98ddeb8e45cf6a0997e0e00ead58d..941f6934350327697777ae9e59a37e7701babc53 100644 --- a/core/modules/aggregator/aggregator.routing.yml +++ b/core/modules/aggregator/aggregator.routing.yml @@ -49,34 +49,6 @@ aggregator.feed_add: options: _admin_route: TRUE -entity.aggregator_feed.canonical: - path: '/aggregator/sources/{aggregator_feed}' - defaults: - _entity_view: 'aggregator_feed' - _title_callback: '\Drupal\aggregator\Controller\AggregatorController::feedTitle' - requirements: - _permission: 'access news feeds' - -entity.aggregator_feed.edit_form: - path: '/aggregator/sources/{aggregator_feed}/configure' - defaults: - _entity_form: 'aggregator_feed.default' - _title: 'Configure' - requirements: - _permission: 'administer news feeds' - options: - _admin_route: TRUE - -entity.aggregator_feed.delete_form: - path: '/aggregator/sources/{aggregator_feed}/delete' - defaults: - _entity_form: 'aggregator_feed.delete' - _title: 'Delete feed' - requirements: - _permission: 'administer news feeds' - options: - _admin_route: TRUE - aggregator.page_last: path: '/aggregator' defaults: diff --git a/core/modules/aggregator/src/Entity/Feed.php b/core/modules/aggregator/src/Entity/Feed.php index 68494e1a771b289706a3217fed4c49a32b38f89b..f478d1cc3d902768dd80c6ed20756021aa1edfe2 100644 --- a/core/modules/aggregator/src/Entity/Feed.php +++ b/core/modules/aggregator/src/Entity/Feed.php @@ -29,7 +29,10 @@ * "default" = "Drupal\aggregator\FeedForm", * "delete" = "Drupal\aggregator\Form\FeedDeleteForm", * "delete_items" = "Drupal\aggregator\Form\FeedItemsDeleteForm", - * } + * }, + * "route_provider" = { + * "html" = "Drupal\aggregator\FeedHtmlRouteProvider", + * }, * }, * links = { * "canonical" = "/aggregator/sources/{aggregator_feed}", diff --git a/core/modules/aggregator/src/FeedHtmlRouteProvider.php b/core/modules/aggregator/src/FeedHtmlRouteProvider.php new file mode 100644 index 0000000000000000000000000000000000000000..ad168ee1a1f66dbe83de2215be27c7120f9fa889 --- /dev/null +++ b/core/modules/aggregator/src/FeedHtmlRouteProvider.php @@ -0,0 +1,39 @@ +<?php + +/** + * @file + * Contains Drupal\aggregator\FeedHtmlRouteProvider. + */ + +namespace Drupal\aggregator; + +use Drupal\Core\Entity\EntityTypeInterface; +use Drupal\Core\Entity\Routing\AdminHtmlRouteProvider; + +/** + * Provides HTML routes for the feed entity type. + */ +class FeedHtmlRouteProvider extends AdminHtmlRouteProvider { + + /** + * {@inheritdoc} + */ + protected function getCanonicalRoute(EntityTypeInterface $entity_type) { + $route = parent::getCanonicalRoute($entity_type); + $route->setDefault('_title_controller', '\Drupal\aggregator\Controller\AggregatorController::feedTitle'); + + return $route; + } + + /** + * {@inheritdoc} + */ + protected function getEditFormRoute(EntityTypeInterface $entity_type) { + $route = parent::getEditFormRoute($entity_type); + + $route->setDefault('_title', 'Configure'); + + return $route; + } + +} diff --git a/core/modules/aggregator/src/Tests/AddFeedTest.php b/core/modules/aggregator/src/Tests/AddFeedTest.php index 94f315b6e12e1b59813bc34d4d77be8a75ad71db..56f5586349a847a879f3b5ff7aa903eff8cdbbf5 100644 --- a/core/modules/aggregator/src/Tests/AddFeedTest.php +++ b/core/modules/aggregator/src/Tests/AddFeedTest.php @@ -61,8 +61,8 @@ public function testFeedLabelEscaping() { $this->drupalGet('aggregator/sources/' . $feed->id()); $this->assertResponse(200); - $result = $this->xpath('//h1'); - $this->assertEqual((string) $result[0], 'Test feed title alert(123);'); + $this->assertEscaped('Test feed title <script>alert(123);</script>'); + $this->assertNoRaw('Test feed title <script>alert(123);</script>'); // Ensure the feed icon title is escaped. $this->assertTrue(strpos(str_replace(["\n", "\r"], '', $this->getRawContent()), 'class="feed-icon"> Subscribe to Test feed title <script>alert(123);</script> feed</a>') !== FALSE); diff --git a/core/modules/comment/src/Tests/CommentNonNodeTest.php b/core/modules/comment/src/Tests/CommentNonNodeTest.php index 98099fb85065f22ee5789927c163875704e13188..c7f3e71a5ab8e16e8b6ea55c856da38a80862f1a 100644 --- a/core/modules/comment/src/Tests/CommentNonNodeTest.php +++ b/core/modules/comment/src/Tests/CommentNonNodeTest.php @@ -435,7 +435,7 @@ function testCommentFunctionality() { $data = array('bundle' => 'entity_test', 'name' => $random_label); $new_entity = entity_create('entity_test', $data); $new_entity->save(); - $this->drupalGet('entity_test/manage/' . $new_entity->id()); + $this->drupalGet('entity_test/manage/' . $new_entity->id() . '/edit'); $this->assertNoFieldChecked('edit-field-foobar-0-status-1'); $this->assertFieldChecked('edit-field-foobar-0-status-2'); $this->assertNoField('edit-field-foobar-0-status-0'); diff --git a/core/modules/content_translation/src/Tests/ContentTestTranslationUITest.php b/core/modules/content_translation/src/Tests/ContentTestTranslationUITest.php index ce9237cc31f4d9c69d9399877c30628a4c7de062..3569a457d3c6f6c89cfdc91b3f07fb52b8cc2d00 100644 --- a/core/modules/content_translation/src/Tests/ContentTestTranslationUITest.php +++ b/core/modules/content_translation/src/Tests/ContentTestTranslationUITest.php @@ -26,19 +26,6 @@ class ContentTestTranslationUITest extends ContentTranslationUITestBase { */ public static $modules = array('language', 'content_translation', 'entity_test'); - /** - * {@inheritdoc} - */ - protected $defaultCacheContexts = [ - 'languages:language_interface', - 'session', - 'theme', - 'url.path', - 'url.query_args', - 'user.permissions', - 'user.roles:authenticated', - ]; - /** * Overrides \Drupal\simpletest\WebTestBase::setUp(). */ diff --git a/core/modules/field/src/Tests/EntityReference/EntityReferenceIntegrationTest.php b/core/modules/field/src/Tests/EntityReference/EntityReferenceIntegrationTest.php index e73d4897313798d65d39e829229dc6fe708a4365..4d678f8a50428a1531135af3e2bb5c35cf1a0e09 100644 --- a/core/modules/field/src/Tests/EntityReference/EntityReferenceIntegrationTest.php +++ b/core/modules/field/src/Tests/EntityReference/EntityReferenceIntegrationTest.php @@ -87,7 +87,7 @@ public function testSupportedEntityTypesAndWidgets() { // Try to post the form again with no modification and check if the field // values remain the same. $entity = current(entity_load_multiple_by_properties($this->entityType, array('name' => $entity_name))); - $this->drupalGet($this->entityType . '/manage/' . $entity->id()); + $this->drupalGet($this->entityType . '/manage/' . $entity->id() . '/edit'); $this->assertFieldByName($this->fieldName . '[0][target_id]', $referenced_entities[0]->label() . ' (' . $referenced_entities[0]->id() . ')'); $this->assertFieldByName($this->fieldName . '[1][target_id]', $referenced_entities[1]->label() . ' (' . $referenced_entities[1]->id() . ')'); @@ -113,7 +113,7 @@ public function testSupportedEntityTypesAndWidgets() { // Try to post the form again with no modification and check if the field // values remain the same. $entity = current(entity_load_multiple_by_properties($this->entityType, array('name' => $entity_name))); - $this->drupalGet($this->entityType . '/manage/' . $entity->id()); + $this->drupalGet($this->entityType . '/manage/' . $entity->id() . '/edit'); $this->assertFieldByName($this->fieldName . '[target_id]', $target_id . ' (' . $referenced_entities[1]->id() . ')'); $this->drupalPostForm(NULL, array(), t('Save')); @@ -132,7 +132,7 @@ public function testSupportedEntityTypesAndWidgets() { 'type' => $widget_type, ))->save(); - $this->drupalPostForm($this->entityType . '/manage/' . $entity->id(), array(), t('Save')); + $this->drupalPostForm($this->entityType . '/manage/' . $entity->id() . '/edit', array(), t('Save')); $this->assertFieldValues($entity_name, $referenced_entities); } diff --git a/core/modules/field/src/Tests/FormTest.php b/core/modules/field/src/Tests/FormTest.php index ed56dceb4c5f44b11bf026f0e8d4cf2d155582f0..dbdc71a4f7636c5f5a386b7d3580df5238a3d379 100644 --- a/core/modules/field/src/Tests/FormTest.php +++ b/core/modules/field/src/Tests/FormTest.php @@ -139,7 +139,7 @@ function testFieldFormSingle() { $this->assertEqual($entity->{$field_name}->value, $value, 'Field value was saved'); // Display edit form. - $this->drupalGet('entity_test/manage/' . $id); + $this->drupalGet('entity_test/manage/' . $id . '/edit'); $this->assertFieldByName("{$field_name}[0][value]", $value, 'Widget is displayed with the correct default value'); $this->assertNoField("{$field_name}[1][value]", 'No extraneous widget is displayed'); @@ -159,7 +159,7 @@ function testFieldFormSingle() { $edit = array( "{$field_name}[0][value]" => $value ); - $this->drupalPostForm('entity_test/manage/' . $id, $edit, t('Save')); + $this->drupalPostForm('entity_test/manage/' . $id . '/edit', $edit, t('Save')); $this->assertText(t('entity_test @id has been updated.', array('@id' => $id)), 'Entity was updated'); $this->container->get('entity.manager')->getStorage('entity_test')->resetCache(array($id)); $entity = entity_load('entity_test', $id); @@ -231,7 +231,7 @@ function testFieldFormSingleRequired() { $edit = array( "{$field_name}[0][value]" => $value, ); - $this->drupalPostForm('entity_test/manage/' . $id, $edit, t('Save')); + $this->drupalPostForm('entity_test/manage/' . $id . '/edit', $edit, t('Save')); $this->assertRaw(t('@name field is required.', array('@name' => $this->field['label'])), 'Required field with no value fails validation'); } @@ -491,7 +491,7 @@ function testFieldFormMultipleWidget() { $this->assertFieldValues($entity_init, $field_name, array(1, 2, 3)); // Display the form, check that the values are correctly filled in. - $this->drupalGet('entity_test/manage/' . $id); + $this->drupalGet('entity_test/manage/' . $id . '/edit'); $this->assertFieldByName($field_name, '1, 2, 3', 'Widget is displayed.'); // Submit the form with more values than the field accepts. @@ -574,7 +574,7 @@ function testFieldFormAccess() { "{$field_name}[0][value]" => 2, 'revision' => TRUE, ); - $this->drupalPostForm($entity_type . '/manage/' . $id, $edit, t('Save')); + $this->drupalPostForm($entity_type . '/manage/' . $id . '/edit', $edit, t('Save')); // Check that the new revision has the expected values. $this->container->get('entity.manager')->getStorage($entity_type)->resetCache(array($id)); @@ -630,7 +630,7 @@ function testHiddenField() { ->save(); // Display edit form. - $this->drupalGet($entity_type . '/manage/' . $id); + $this->drupalGet($entity_type . '/manage/' . $id . '/edit'); $this->assertFieldByName("{$field_name}[0][value]", 99, 'Widget is displayed with the correct default value'); // Update the entity. @@ -649,7 +649,7 @@ function testHiddenField() { // Create a new revision. $edit = array('revision' => TRUE); - $this->drupalPostForm($entity_type . '/manage/' . $id, $edit, t('Save')); + $this->drupalPostForm($entity_type . '/manage/' . $id . '/edit', $edit, t('Save')); // Check that the expected value has been carried over to the new revision. \Drupal::entityManager()->getStorage($entity_type)->resetCache(array($id)); diff --git a/core/modules/field/src/Tests/TranslationWebTest.php b/core/modules/field/src/Tests/TranslationWebTest.php index 4aa8c4893071104116566af5c3e446d70e7637d0..8350285c152c564ae005e6a988f6c724418ce0e8 100644 --- a/core/modules/field/src/Tests/TranslationWebTest.php +++ b/core/modules/field/src/Tests/TranslationWebTest.php @@ -114,7 +114,7 @@ function testFieldFormTranslationRevisions() { "{$field_name}[0][value]" => $entity->{$field_name}->value, 'revision' => TRUE, ); - $this->drupalPostForm($this->entityTypeId . '/manage/' . $entity->id(), $edit, t('Save')); + $this->drupalPostForm($this->entityTypeId . '/manage/' . $entity->id() . '/edit', $edit, t('Save')); // Check translation revisions. $this->checkTranslationRevisions($entity->id(), $entity->getRevisionId(), $available_langcodes); diff --git a/core/modules/link/src/Tests/LinkFieldTest.php b/core/modules/link/src/Tests/LinkFieldTest.php index 4b61f730a021b2a43ce850b192da9b08eab3c484..494936a09c24159d132520c0d730eb580ec9fc6d 100644 --- a/core/modules/link/src/Tests/LinkFieldTest.php +++ b/core/modules/link/src/Tests/LinkFieldTest.php @@ -318,7 +318,7 @@ function testLinkTitle() { $edit = array( "{$field_name}[0][title]" => $title, ); - $this->drupalPostForm("entity_test/manage/$id", $edit, t('Save')); + $this->drupalPostForm("entity_test/manage/$id/edit", $edit, t('Save')); $this->assertText(t('entity_test @id has been updated.', array('@id' => $id))); $this->renderTestEntity($id); diff --git a/core/modules/options/src/Tests/OptionsSelectDynamicValuesTest.php b/core/modules/options/src/Tests/OptionsSelectDynamicValuesTest.php index f6a661a70a39ab682c1728e33cddb0d0e65d357f..2b9c0bb531be3a9d9f27e8b2963d3fb2580081d4 100644 --- a/core/modules/options/src/Tests/OptionsSelectDynamicValuesTest.php +++ b/core/modules/options/src/Tests/OptionsSelectDynamicValuesTest.php @@ -25,7 +25,7 @@ function testSelectListDynamic() { $this->drupalLogin($web_user); // Display form. - $this->drupalGet('entity_test_rev/manage/' . $this->entity->id()); + $this->drupalGet('entity_test_rev/manage/' . $this->entity->id() . '/edit'); $options = $this->xpath('//select[@id="edit-test-options"]/option'); $this->assertEqual(count($options), count($this->test) + 1); foreach ($options as $option) { diff --git a/core/modules/options/src/Tests/OptionsWidgetsTest.php b/core/modules/options/src/Tests/OptionsWidgetsTest.php index f1d2ca327c999a20e62e42e3dcb8d1941f6686f2..93293cac3873873367f2b610c3d066e2da52e048 100644 --- a/core/modules/options/src/Tests/OptionsWidgetsTest.php +++ b/core/modules/options/src/Tests/OptionsWidgetsTest.php @@ -108,7 +108,7 @@ function testRadioButtons() { $entity_init = clone $entity; // With no field data, no buttons are checked. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertNoFieldChecked('edit-card-1-0'); $this->assertNoFieldChecked('edit-card-1-1'); $this->assertNoFieldChecked('edit-card-1-2'); @@ -121,7 +121,7 @@ function testRadioButtons() { $this->assertFieldValues($entity_init, 'card_1', array(0)); // Check that the selected button is checked. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertFieldChecked('edit-card-1-0'); $this->assertNoFieldChecked('edit-card-1-1'); $this->assertNoFieldChecked('edit-card-1-2'); @@ -136,7 +136,7 @@ function testRadioButtons() { $this->card1->save(); $field->setRequired(TRUE); $field->save(); - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertFieldChecked('edit-card-1-99'); } @@ -165,7 +165,7 @@ function testCheckBoxes() { $entity_init = clone $entity; // Display form: with no field data, nothing is checked. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertNoFieldChecked('edit-card-2-0'); $this->assertNoFieldChecked('edit-card-2-1'); $this->assertNoFieldChecked('edit-card-2-2'); @@ -181,7 +181,7 @@ function testCheckBoxes() { $this->assertFieldValues($entity_init, 'card_2', array(0, 2)); // Display form: check that the right options are selected. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertFieldChecked('edit-card-2-0'); $this->assertNoFieldChecked('edit-card-2-1'); $this->assertFieldChecked('edit-card-2-2'); @@ -196,7 +196,7 @@ function testCheckBoxes() { $this->assertFieldValues($entity_init, 'card_2', array(0)); // Display form: check that the right options are selected. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertFieldChecked('edit-card-2-0'); $this->assertNoFieldChecked('edit-card-2-1'); $this->assertNoFieldChecked('edit-card-2-2'); @@ -225,7 +225,7 @@ function testCheckBoxes() { $this->card2->save(); $field->setRequired(TRUE); $field->save(); - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertFieldChecked('edit-card-2-99'); } @@ -255,7 +255,7 @@ function testSelectListSingle() { $entity_init = clone $entity; // Display form. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); // A required field without any value has a "none" option. $this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1', ':label' => t('- Select a value -'))), 'A required select list has a "Select a value" choice.'); @@ -277,7 +277,7 @@ function testSelectListSingle() { $this->assertFieldValues($entity_init, 'card_1', array(0)); // Display form: check that the right options are selected. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); // A required field with a value has no 'none' option. $this->assertFalse($this->xpath('//select[@id=:id]//option[@value="_none"]', array(':id' => 'edit-card-1')), 'A required select list with an actual value has no "none" choice.'); $this->assertOptionSelected('edit-card-1', 0); @@ -289,12 +289,12 @@ function testSelectListSingle() { $field->save(); // Display form. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); // A non-required field has a 'none' option. $this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1', ':label' => t('- None -'))), 'A non-required select list has a "None" choice.'); // Submit form: Unselect the option. $edit = array('card_1' => '_none'); - $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); + $this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_1', array()); // Test optgroups. @@ -304,7 +304,7 @@ function testSelectListSingle() { $this->card1->save(); // Display form: with no field data, nothing is selected - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertNoOptionSelected('edit-card-1', 0); $this->assertNoOptionSelected('edit-card-1', 1); $this->assertNoOptionSelected('edit-card-1', 2); @@ -318,14 +318,14 @@ function testSelectListSingle() { $this->assertFieldValues($entity_init, 'card_1', array(0)); // Display form: check that the right options are selected. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertOptionSelected('edit-card-1', 0); $this->assertNoOptionSelected('edit-card-1', 1); $this->assertNoOptionSelected('edit-card-1', 2); // Submit form: Unselect the option. $edit = array('card_1' => '_none'); - $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); + $this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_1', array()); } @@ -354,7 +354,7 @@ function testSelectListMultiple() { $entity_init = clone $entity; // Display form: with no field data, nothing is selected. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertOptionSelected("edit-card-2", '_none'); $this->assertNoOptionSelected('edit-card-2', 0); $this->assertNoOptionSelected('edit-card-2', 1); @@ -367,7 +367,7 @@ function testSelectListMultiple() { $this->assertFieldValues($entity_init, 'card_2', array(0, 2)); // Display form: check that the right options are selected. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertOptionSelected('edit-card-2', 0); $this->assertNoOptionSelected('edit-card-2', 1); $this->assertOptionSelected('edit-card-2', 2); @@ -378,7 +378,7 @@ function testSelectListMultiple() { $this->assertFieldValues($entity_init, 'card_2', array(0)); // Display form: check that the right options are selected. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertOptionSelected('edit-card-2', 0); $this->assertNoOptionSelected('edit-card-2', 1); $this->assertNoOptionSelected('edit-card-2', 2); @@ -398,18 +398,18 @@ function testSelectListMultiple() { // Check that the 'none' option has no effect if actual options are selected // as well. $edit = array('card_2[]' => array('_none' => '_none', 0 => 0)); - $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); + $this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_2', array(0)); // Check that selecting the 'none' option empties the field. $edit = array('card_2[]' => array('_none' => '_none')); - $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); + $this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_2', array()); // A required select list does not have an empty key. $field->setRequired(TRUE); $field->save(); - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertFalse($this->xpath('//select[@id=:id]//option[@value=""]', array(':id' => 'edit-card-2')), 'A required select list does not have an empty key.'); // We do not have to test that a required select list with one option is @@ -425,7 +425,7 @@ function testSelectListMultiple() { $field->save(); // Display form: with no field data, nothing is selected. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertNoOptionSelected('edit-card-2', 0); $this->assertNoOptionSelected('edit-card-2', 1); $this->assertNoOptionSelected('edit-card-2', 2); @@ -439,14 +439,14 @@ function testSelectListMultiple() { $this->assertFieldValues($entity_init, 'card_2', array(0)); // Display form: check that the right options are selected. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertOptionSelected('edit-card-2', 0); $this->assertNoOptionSelected('edit-card-2', 1); $this->assertNoOptionSelected('edit-card-2', 2); // Submit form: Unselect the option. $edit = array('card_2[]' => array('_none' => '_none')); - $this->drupalPostForm('entity_test/manage/' . $entity->id(), $edit, t('Save')); + $this->drupalPostForm('entity_test/manage/' . $entity->id() . '/edit', $edit, t('Save')); $this->assertFieldValues($entity_init, 'card_2', array()); } @@ -476,7 +476,7 @@ function testEmptyValue() { $entity->save(); // Display form: check that _none options are present and has label. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); $this->assertTrue($this->xpath('//div[@id=:id]//input[@value=:value]', array(':id' => 'edit-card-1', ':value' => '_none')), 'A test radio button has a "None" choice.'); $this->assertTrue($this->xpath('//div[@id=:id]//label[@for=:for and text()=:label]', array(':id' => 'edit-card-1', ':for' => 'edit-card-1-none', ':label' => 'N/A')), 'A test radio button has a "N/A" choice.'); @@ -488,7 +488,7 @@ function testEmptyValue() { ->save(); // Display form: check that _none options are present and has label. - $this->drupalGet('entity_test/manage/' . $entity->id()); + $this->drupalGet('entity_test/manage/' . $entity->id() . '/edit'); // A required field without any value has a "none" option. $this->assertTrue($this->xpath('//select[@id=:id]//option[@value="_none" and text()=:label]', array(':id' => 'edit-card-1', ':label' => t('- None -'))), 'A test select has a "None" choice.'); } diff --git a/core/modules/system/src/Tests/Entity/EntityFormTest.php b/core/modules/system/src/Tests/Entity/EntityFormTest.php index ffa5cca84ac37da4e46e346f4ae723e753fc45dd..4b2647a5fa4d7a8bc3dbfb7691d078a6b42ba40a 100644 --- a/core/modules/system/src/Tests/Entity/EntityFormTest.php +++ b/core/modules/system/src/Tests/Entity/EntityFormTest.php @@ -26,7 +26,7 @@ class EntityFormTest extends WebTestBase { protected function setUp() { parent::setUp(); - $web_user = $this->drupalCreateUser(array('administer entity_test content')); + $web_user = $this->drupalCreateUser(array('administer entity_test content', 'view test entity')); $this->drupalLogin($web_user); // Add a language. @@ -84,14 +84,14 @@ protected function doTestFormCRUD($entity_type) { $this->assertTrue($entity, format_string('%entity_type: Entity found in the database.', array('%entity_type' => $entity_type))); $edit['name[0][value]'] = $name2; - $this->drupalPostForm($entity_type . '/manage/' . $entity->id(), $edit, t('Save')); + $this->drupalPostForm($entity_type . '/manage/' . $entity->id() . '/edit', $edit, t('Save')); $entity = $this->loadEntityByName($entity_type, $name1); $this->assertFalse($entity, format_string('%entity_type: The entity has been modified.', array('%entity_type' => $entity_type))); $entity = $this->loadEntityByName($entity_type, $name2); $this->assertTrue($entity, format_string('%entity_type: Modified entity found in the database.', array('%entity_type' => $entity_type))); $this->assertNotEqual($entity->name->value, $name1, format_string('%entity_type: The entity name has been modified.', array('%entity_type' => $entity_type))); - $this->drupalGet($entity_type . '/manage/' . $entity->id()); + $this->drupalGet($entity_type . '/manage/' . $entity->id() . '/edit'); $this->clickLink(t('Delete')); $this->drupalPostForm(NULL, array(), t('Delete')); $entity = $this->loadEntityByName($entity_type, $name2); @@ -125,12 +125,12 @@ protected function doTestMultilingualFormCRUD($entity_type_id) { $this->assertEqual($translated_entity->name->value, $name1_ro, format_string('%entity_type: The translation has been added.', array('%entity_type' => $entity_type_id))); $edit['name[0][value]'] = $name2_ro; - $this->drupalPostForm('ro/' . $entity_type_id . '/manage/' . $entity->id(), $edit, t('Save')); + $this->drupalPostForm('ro/' . $entity_type_id . '/manage/' . $entity->id() . '/edit', $edit, t('Save')); $translated_entity = $this->loadEntityByName($entity_type_id, $name1)->getTranslation('ro'); $this->assertTrue($translated_entity, format_string('%entity_type: Modified translation found in the database.', array('%entity_type' => $entity_type_id))); $this->assertEqual($translated_entity->name->value, $name2_ro, format_string('%entity_type: The name of the translation has been modified.', array('%entity_type' => $entity_type_id))); - $this->drupalGet('ro/' . $entity_type_id . '/manage/' . $entity->id()); + $this->drupalGet('ro/' . $entity_type_id . '/manage/' . $entity->id() . '/edit'); $this->clickLink(t('Delete')); $this->drupalPostForm(NULL, array(), t('Delete Romanian translation')); $entity = $this->loadEntityByName($entity_type_id, $name1); diff --git a/core/modules/system/src/Tests/Entity/EntityRevisionsTest.php b/core/modules/system/src/Tests/Entity/EntityRevisionsTest.php index 53f5288e2847fd50e7554385ba435caa761ddd52..39f04c32d728e3d9cb14853e6551176c2b0cfc5c 100644 --- a/core/modules/system/src/Tests/Entity/EntityRevisionsTest.php +++ b/core/modules/system/src/Tests/Entity/EntityRevisionsTest.php @@ -37,6 +37,7 @@ protected function setUp() { // Create and login user. $this->webUser = $this->drupalCreateUser(array( 'administer entity_test content', + 'view test entity', )); $this->drupalLogin($this->webUser); } @@ -110,7 +111,7 @@ protected function runRevisionsTests($entity_type) { // Confirm the correct revision text appears in the edit form. $entity = entity_load($entity_type, $entity->id->value); - $this->drupalGet($entity_type . '/manage/' . $entity->id->value); + $this->drupalGet($entity_type . '/manage/' . $entity->id->value . '/edit'); $this->assertFieldById('edit-name-0-value', $entity->name->value, format_string('%entity_type: Name matches in UI.', array('%entity_type' => $entity_type))); $this->assertFieldById('edit-field-test-text-0-value', $entity->field_test_text->value, format_string('%entity_type: Text matches in UI.', array('%entity_type' => $entity_type))); } diff --git a/core/modules/system/tests/modules/entity_test/src/Controller/EntityTestController.php b/core/modules/system/tests/modules/entity_test/src/Controller/EntityTestController.php index 1d6e4e82af49eaa2ad7718f874ab1c4db2119b3f..b44c7ebeb221889574173c5a4bf6651ed6c2b9fc 100644 --- a/core/modules/system/tests/modules/entity_test/src/Controller/EntityTestController.php +++ b/core/modules/system/tests/modules/entity_test/src/Controller/EntityTestController.php @@ -62,26 +62,6 @@ public function testAdd($entity_type_id) { return $form; } - /** - * Displays the 'Edit existing entity_test' form. - * - * @param \Drupal\Core\Routing\RouteMatchInterface $route_match - * The route match object to get entity type from. - * @param string $entity_type_id - * The entity type ID. - * - * @return array - * The processed form for the edited entity. - * - * @see \Drupal\entity_test\Routing\EntityTestRoutes::routes() - */ - public function testEdit(RouteMatchInterface $route_match, $entity_type_id) { - $entity = $route_match->getParameter($entity_type_id); - $form = $this->entityFormBuilder()->getForm($entity); - $form['#title'] = $entity->label(); - return $form; - } - /** * Returns an empty page. * diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php index 89b4c20405124e7638cabc54383456dcb1bd3c0c..1197c2cd34aa93ef80a09cee190acbb9c4dd8e6f 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTest.php @@ -28,10 +28,14 @@ * "default" = "Drupal\entity_test\EntityTestForm", * "delete" = "Drupal\entity_test\EntityTestDeleteForm" * }, + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * }, * "translation" = "Drupal\content_translation\ContentTranslationHandler", * "views_data" = "Drupal\entity_test\EntityTestViewsData" * }, * base_table = "entity_test", + * admin_permission = "administer entity_test content", * persistent_cache = FALSE, * list_cache_contexts = { "entity_test_view_grants" }, * entity_keys = { @@ -43,7 +47,7 @@ * }, * links = { * "canonical" = "/entity_test/{entity_test}", - * "edit-form" = "/entity_test/manage/{entity_test}", + * "edit-form" = "/entity_test/manage/{entity_test}/edit", * "delete-form" = "/entity_test/delete/entity_test/{entity_test}", * }, * field_ui_base_route = "entity.entity_test.admin_form", diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestAdminRoutes.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestAdminRoutes.php new file mode 100644 index 0000000000000000000000000000000000000000..2660412acb01e4a5ae7e41e36a70cca8ae813d08 --- /dev/null +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestAdminRoutes.php @@ -0,0 +1,49 @@ +<?php + +/** + * @file + * Contains \Drupal\entity_test\Entity\EntityTestAdminRoutes. + */ + +namespace Drupal\entity_test\Entity; + +/** + * Defines a test entity type with administrative routes. + * + * @ContentEntityType( + * id = "entity_test_admin_routes", + * label = @Translation("Test entity - admin routes"), + * handlers = { + * "view_builder" = "Drupal\entity_test\EntityTestViewBuilder", + * "access" = "Drupal\entity_test\EntityTestAccessControlHandler", + * "form" = { + * "default" = "Drupal\entity_test\EntityTestForm", + * "delete" = "Drupal\entity_test\EntityTestDeleteForm" + * }, + * "translation" = "Drupal\content_translation\ContentTranslationHandler", + * "views_data" = "Drupal\views\EntityViewsData", + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\AdminHtmlRouteProvider", + * }, + * }, + * base_table = "entity_test_admin_routes", + * data_table = "entity_test_admin_routes_property_data", + * admin_permission = "administer entity_test content", + * translatable = TRUE, + * entity_keys = { + * "id" = "id", + * "uuid" = "uuid", + * "bundle" = "type", + * "label" = "name", + * "langcode" = "langcode", + * }, + * links = { + * "canonical" = "/entity_test_admin_routes/manage/{entity_test_admin_routes}", + * "edit-form" = "/entity_test_admin_routes/manage/{entity_test_admin_routes}/edit", + * "delete-form" = "/entity_test/delete/entity_test_admin_routes/{entity_test_admin_routes}", + * }, + * ) + */ +class EntityTestAdminRoutes extends EntityTest { + +} diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestBaseFieldDisplay.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestBaseFieldDisplay.php index 915f057c864f55372aabe6168579ddefc89447f3..d2f83780a4a6a0be8432738db89f971a07ddf60f 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestBaseFieldDisplay.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestBaseFieldDisplay.php @@ -22,9 +22,13 @@ * "form" = { * "default" = "Drupal\entity_test\EntityTestForm" * }, - * "translation" = "Drupal\content_translation\ContentTranslationHandler" + * "translation" = "Drupal\content_translation\ContentTranslationHandler", + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * }, * }, * base_table = "entity_test_base_field_display", + * admin_permission = "administer entity_test content", * entity_keys = { * "id" = "id", * "label" = "name", @@ -32,7 +36,9 @@ * "bundle" = "type" * }, * links = { + * "canonical" = "/entity_test_base_field_display/{entity_test_base_field_display}/edit", * "edit-form" = "/entity_test_base_field_display/manage/{entity_test_base_field_display}", + * "delete-form" = "/entity_test/delete/entity_test_base_field_display/{entity_test_base_field_display}/edit", * }, * field_ui_base_route = "entity.entity_test_base_field_display.admin_form", * ) diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMul.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMul.php index e821272150ffa9d6a36b4e0def726cdb738d665c..d1908d35be9b44008038c301e08e1ab7f5d4d885 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMul.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMul.php @@ -21,10 +21,14 @@ * "delete" = "Drupal\entity_test\EntityTestDeleteForm" * }, * "translation" = "Drupal\content_translation\ContentTranslationHandler", - * "views_data" = "Drupal\views\EntityViewsData" + * "views_data" = "Drupal\views\EntityViewsData", + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * }, * }, * base_table = "entity_test_mul", * data_table = "entity_test_mul_property_data", + * admin_permission = "administer entity_test content", * translatable = TRUE, * entity_keys = { * "id" = "id", @@ -35,7 +39,7 @@ * }, * links = { * "canonical" = "/entity_test_mul/manage/{entity_test_mul}", - * "edit-form" = "/entity_test_mul/manage/{entity_test_mul}", + * "edit-form" = "/entity_test_mul/manage/{entity_test_mul}/edit", * "delete-form" = "/entity_test/delete/entity_test_mul/{entity_test_mul}", * }, * field_ui_base_route = "entity.entity_test_mul.admin_form", diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php index 67811ac925463c17419153aca254839aae1a6484..055e2906c5a19be63fadc79c69ce1450927f25c7 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulChanged.php @@ -25,6 +25,9 @@ * "default" = "Drupal\entity_test\EntityTestForm", * "delete" = "Drupal\entity_test\EntityTestDeleteForm" * }, + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * }, * "translation" = "Drupal\content_translation\ContentTranslationHandler", * "views_data" = "Drupal\views\EntityViewsData" * }, @@ -40,7 +43,7 @@ * }, * links = { * "canonical" = "/entity_test_mul_changed/manage/{entity_test_mul_changed}", - * "edit-form" = "/entity_test_mul_changed/manage/{entity_test_mul_changed}", + * "edit-form" = "/entity_test_mul_changed/manage/{entity_test_mul_changed}/edit", * "delete-form" = "/entity_test/delete/entity_test_mul_changed/{entity_test_mul_changed}", * }, * field_ui_base_route = "entity.entity_test_mul_changed.admin_form", diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulLangcodeKey.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulLangcodeKey.php index 3be6a903e9ee4e1d798769e543dfaba5097fd108..3f794e5b0b18ab1a768ee146db12abc8c0ed0036 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulLangcodeKey.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulLangcodeKey.php @@ -23,10 +23,14 @@ * "delete" = "Drupal\entity_test\EntityTestDeleteForm" * }, * "translation" = "Drupal\content_translation\ContentTranslationHandler", - * "views_data" = "Drupal\views\EntityViewsData" + * "views_data" = "Drupal\views\EntityViewsData", + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * }, * }, * base_table = "entity_test_mul_langcode_key", * data_table = "entity_test_mul_langcode_key_field_data", + * admin_permission = "administer entity_test content", * translatable = TRUE, * entity_keys = { * "id" = "id", @@ -38,7 +42,7 @@ * }, * links = { * "canonical" = "/entity_test_mul_langcode_key/manage/{entity_test_mul_langcode_key}", - * "edit-form" = "/entity_test_mul_langcode_key/manage/{entity_test_mul_langcode_key}", + * "edit-form" = "/entity_test_mul_langcode_key/manage/{entity_test_mul_langcode_key}/edit", * "delete-form" = "/entity_test/delete/entity_test_mul_langcode_key/{entity_test_mul_langcode_key}", * }, * field_ui_base_route = "entity.entity_test_mul_langcode_key.admin_form", diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRev.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRev.php index a29dbbf424a584713eb1d843e6113e38a90768b1..1eb7715cf397fd42009610e8ac295e0b9a699c06 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRev.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRev.php @@ -21,12 +21,16 @@ * "delete" = "Drupal\entity_test\EntityTestDeleteForm" * }, * "translation" = "Drupal\content_translation\ContentTranslationHandler", - * "views_data" = "Drupal\views\EntityViewsData" + * "views_data" = "Drupal\views\EntityViewsData", + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * }, * }, * base_table = "entity_test_mulrev", * data_table = "entity_test_mulrev_property_data", * revision_table = "entity_test_mulrev_revision", * revision_data_table = "entity_test_mulrev_property_revision", + * admin_permission = "administer entity_test content", * translatable = TRUE, * entity_keys = { * "id" = "id", @@ -39,7 +43,7 @@ * links = { * "canonical" = "/entity_test_mulrev/manage/{entity_test_mulrev}", * "delete-form" = "/entity_test/delete/entity_test_mulrev/{entity_test_mulrev}", - * "edit-form" = "/entity_test_mulrev/manage/{entity_test_mulrev}", + * "edit-form" = "/entity_test_mulrev/manage/{entity_test_mulrev}/edit", * "revision" = "/entity_test_mulrev/{entity_test_mulrev}/revision/{entity_test_mulrev_revision}/view", * } * ) diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRevChanged.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRevChanged.php index 933e55adbc4b5cdd4cc00d1e92bc5f7d3c7c90d3..f2a9667d2e8f3697105e77dadbb7daf8e3933a8a 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRevChanged.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestMulRevChanged.php @@ -23,6 +23,9 @@ * "default" = "Drupal\entity_test\EntityTestForm", * "delete" = "Drupal\entity_test\EntityTestDeleteForm" * }, + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * }, * "translation" = "Drupal\content_translation\ContentTranslationHandler", * "views_data" = "Drupal\views\EntityViewsData" * }, @@ -42,7 +45,7 @@ * links = { * "canonical" = "/entity_test_mulrev_changed/manage/{entity_test_mulrev_changed}", * "delete-form" = "/entity_test/delete/entity_test_mulrev_changed/{entity_test_mulrev_changed}", - * "edit-form" = "/entity_test_mulrev_changed/manage/{entity_test_mulrev_changed}", + * "edit-form" = "/entity_test_mulrev_changed/manage/{entity_test_mulrev_changed}/edit", * "revision" = "/entity_test_mulrev_changed/{entity_test_mulrev_changed}/revision/{entity_test_mulrev_changed_revision}/view", * } * ) diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php index 7a4fefde876ce9b68c234cc034a971b874f5947a..047b85dc7fc50ba678dc5cbd853645434558d6c6 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestRev.php @@ -18,16 +18,21 @@ * label = @Translation("Test entity - revisions"), * handlers = { * "access" = "Drupal\entity_test\EntityTestAccessControlHandler", + * "view_builder" = "Drupal\entity_test\EntityTestViewBuilder", * "form" = { * "default" = "Drupal\entity_test\EntityTestForm", * "delete" = "Drupal\entity_test\EntityTestDeleteForm" * }, * "view_builder" = "Drupal\entity_test\EntityTestViewBuilder", * "translation" = "Drupal\content_translation\ContentTranslationHandler", - * "views_data" = "Drupal\views\EntityViewsData" + * "views_data" = "Drupal\views\EntityViewsData", + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * }, * }, * base_table = "entity_test_rev", * revision_table = "entity_test_rev_revision", + * admin_permission = "administer entity_test content", * entity_keys = { * "id" = "id", * "uuid" = "uuid", @@ -39,7 +44,7 @@ * links = { * "canonical" = "/entity_test_rev/manage/{entity_test_rev}", * "delete-form" = "/entity_test/delete/entity_test_rev/{entity_test_rev}", - * "edit-form" = "/entity_test_rev/manage/{entity_test_rev}", + * "edit-form" = "/entity_test_rev/manage/{entity_test_rev}/edit", * "revision" = "/entity_test_rev/{entity_test_rev}/revision/{entity_test_rev_revision}/view", * } * ) diff --git a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestStringId.php b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestStringId.php index d6b6c59ea129e29ec06acf09036de0bcac5caad3..1f53e044f40a09fdfa0c20871b96d1b06dab6c90 100644 --- a/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestStringId.php +++ b/core/modules/system/tests/modules/entity_test/src/Entity/EntityTestStringId.php @@ -20,9 +20,13 @@ * "form" = { * "default" = "Drupal\entity_test\EntityTestForm" * }, - * "translation" = "Drupal\content_translation\ContentTranslationHandler" + * "translation" = "Drupal\content_translation\ContentTranslationHandler", + * "route_provider" = { + * "html" = "Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider", + * }, * }, * base_table = "entity_test_string", + * admin_permission = "administer entity_test content", * entity_keys = { * "id" = "id", * "uuid" = "uuid", diff --git a/core/modules/system/tests/modules/entity_test/src/Routing/EntityTestRoutes.php b/core/modules/system/tests/modules/entity_test/src/Routing/EntityTestRoutes.php index 09d677f1864e34b6cff00fb06b75d849d8f8df8f..8992550f31693fc10edabe09e052b0c0bc8f48e3 100644 --- a/core/modules/system/tests/modules/entity_test/src/Routing/EntityTestRoutes.php +++ b/core/modules/system/tests/modules/entity_test/src/Routing/EntityTestRoutes.php @@ -33,30 +33,6 @@ public function routes() { array('_permission' => 'administer entity_test content') ); - $routes["entity.$entity_type_id.canonical"] = new Route( - $entity_type_id . '/manage/{' . $entity_type_id . '}', - array('_controller' => '\Drupal\entity_test\Controller\EntityTestController::testEdit', 'entity_type_id' => $entity_type_id), - array('_permission' => 'administer entity_test content'), - array('parameters' => array( - $entity_type_id => array('type' => 'entity:' . $entity_type_id), - )) - ); - - $routes["entity.$entity_type_id.edit_form"] = new Route( - $entity_type_id . '/manage/{' . $entity_type_id . '}', - array('_controller' => '\Drupal\entity_test\Controller\EntityTestController::testEdit', 'entity_type_id' => $entity_type_id), - array('_permission' => 'administer entity_test content'), - array('parameters' => array( - $entity_type_id => array('type' => 'entity:' . $entity_type_id), - )) - ); - - $routes["entity.$entity_type_id.delete_form"] = new Route( - 'entity_test/delete/' . $entity_type_id . '/{' . $entity_type_id . '}', - array('_entity_form' => $entity_type_id . '.delete'), - array('_permission' => 'administer entity_test content') - ); - $routes["entity.$entity_type_id.admin_form"] = new Route( "$entity_type_id/structure/{bundle}", array('_controller' => '\Drupal\entity_test\Controller\EntityTestController::testAdmin'), diff --git a/core/modules/text/src/Tests/TextFieldTest.php b/core/modules/text/src/Tests/TextFieldTest.php index a1c9ec32678f09bd2209deae0d0e78ff0bb24a43..8279a6ded7e414e66dcc034180814f5fabd4fc9e 100644 --- a/core/modules/text/src/Tests/TextFieldTest.php +++ b/core/modules/text/src/Tests/TextFieldTest.php @@ -223,7 +223,7 @@ function _testTextfieldWidgetsFormatted($field_type, $widget_type) { // Display edition form. // We should now have a 'text format' selector. - $this->drupalGet('entity_test/manage/' . $id); + $this->drupalGet('entity_test/manage/' . $id . '/edit'); $this->assertFieldByName("{$field_name}[0][value]", NULL, 'Widget is displayed'); $this->assertFieldByName("{$field_name}[0][format]", NULL, 'Format selector is displayed'); diff --git a/core/tests/Drupal/KernelTests/Core/Entity/RouteProviderTest.php b/core/tests/Drupal/KernelTests/Core/Entity/RouteProviderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3b7af4156c265aab1190596d7018c8dd7b3f74bf --- /dev/null +++ b/core/tests/Drupal/KernelTests/Core/Entity/RouteProviderTest.php @@ -0,0 +1,148 @@ +<?php + +/** + * @file + * Contains \Drupal\KernelTests\Core\Entity\RouteProviderTest. + */ + +namespace Drupal\KernelTests\Core\Entity; + +use Drupal\entity_test\Entity\EntityTestAdminRoutes; +use Drupal\entity_test\Entity\EntityTestMul; +use Drupal\KernelTests\KernelTestBase; +use Drupal\user\Entity\Role; +use Drupal\user\RoleInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * Tests route providers for entity types. + * + * @group Entity + */ +class RouteProviderTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['entity_test', 'user', 'system']; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->installEntitySchema('user'); + $this->installEntitySchema('entity_test_mul'); + $this->installEntitySchema('entity_test_admin_routes'); + $this->installSchema('system', 'router'); + + $router_builder = \Drupal::service('router.builder'); + $router_builder->rebuild(); + + /** @var \Drupal\Core\Routing\RouteBuilderInterface $router_builder */ + $router_builder = \Drupal::service('router.builder'); + $router_builder->rebuild(); + + /** @var \Drupal\user\RoleInterface $role */ + $role = Role::create([ + 'id' => RoleInterface::ANONYMOUS_ID + ]); + $role + ->grantPermission('administer entity_test content') + ->grantPermission('view test entity'); + $role->save(); + } + + protected function httpKernelHandle($url) { + $request = Request::create($url); + /** @var \Symfony\Component\HttpKernel\HttpKernelInterface $http_kernel */ + $http_kernel = \Drupal::service('http_kernel'); + return $http_kernel->handle($request, HttpKernelInterface::SUB_REQUEST)->getContent(); + } + + /** + * @covers \Drupal\Core\Entity\Routing\DefaultHtmlRouteProvider::getRoutes + */ + public function testHtmlRoutes() { + /** @var \Drupal\Core\Routing\RouteProviderInterface $route_provider */ + $route_provider = \Drupal::service('router.route_provider'); + + $route = $route_provider->getRouteByName('entity.entity_test_mul.canonical'); + $this->assertEquals('entity_test_mul.full', $route->getDefault('_entity_view')); + $this->assertEquals('\Drupal\Core\Entity\Controller\EntityController::title', $route->getDefault('_title_callback')); + $this->assertEquals('entity_test_mul.view', $route->getRequirement('_entity_access')); + $this->assertFalse($route->hasOption('_admin_route')); + + $route = $route_provider->getRouteByName('entity.entity_test_mul.edit_form'); + $this->assertEquals('entity_test_mul.default', $route->getDefault('_entity_form')); + $this->assertEquals('\Drupal\Core\Entity\Controller\EntityController::editTitle', $route->getDefault('_title_callback')); + $this->assertEquals('entity_test_mul.update', $route->getRequirement('_entity_access')); + $this->assertFalse($route->hasOption('_admin_route')); + + $route = $route_provider->getRouteByName('entity.entity_test_mul.delete_form'); + $this->assertEquals('entity_test_mul.delete', $route->getDefault('_entity_form')); + $this->assertEquals('\Drupal\Core\Entity\Controller\EntityController::deleteTitle', $route->getDefault('_title_callback')); + $this->assertEquals('entity_test_mul.delete', $route->getRequirement('_entity_access')); + $this->assertFalse($route->hasOption('_admin_route')); + + $entity = EntityTestMul::create([ + 'name' => 'Test title', + ]); + $entity->save(); + + $this->setRawContent($this->httpKernelHandle($entity->url())); + $this->assertTitle('Test title | '); + + $this->setRawContent($this->httpKernelHandle($entity->url('edit-form'))); + $this->assertTitle('Edit Test title | '); + + $this->setRawContent($this->httpKernelHandle($entity->url('delete-form'))); + $this->assertTitle('Are you sure you want to delete the test entity - data table Test title? | '); + } + + /** + * @covers \Drupal\Core\Entity\Routing\AdminHtmlRouteProvider::getEditFormRoute + * @covers \Drupal\Core\Entity\Routing\AdminHtmlRouteProvider::getDeleteFormRoute + */ + public function testAdminHtmlRoutes() { + /** @var \Drupal\Core\Routing\RouteProviderInterface $route_provider */ + $route_provider = \Drupal::service('router.route_provider'); + + $route = $route_provider->getRouteByName('entity.entity_test_admin_routes.canonical'); + $this->assertEquals('entity_test_admin_routes.full', $route->getDefault('_entity_view')); + $this->assertEquals('\Drupal\Core\Entity\Controller\EntityController::title', $route->getDefault('_title_callback')); + $this->assertEquals('entity_test_admin_routes.view', $route->getRequirement('_entity_access')); + $this->assertFalse($route->hasOption('_admin_route')); + + $route = $route_provider->getRouteByName('entity.entity_test_admin_routes.edit_form'); + $this->assertEquals('entity_test_admin_routes.default', $route->getDefault('_entity_form')); + $this->assertEquals('\Drupal\Core\Entity\Controller\EntityController::editTitle', $route->getDefault('_title_callback')); + $this->assertEquals('entity_test_admin_routes.update', $route->getRequirement('_entity_access')); + $this->assertTrue($route->hasOption('_admin_route')); + $this->assertTrue($route->getOption('_admin_route')); + + $route = $route_provider->getRouteByName('entity.entity_test_admin_routes.delete_form'); + $this->assertEquals('entity_test_admin_routes.delete', $route->getDefault('_entity_form')); + $this->assertEquals('\Drupal\Core\Entity\Controller\EntityController::deleteTitle', $route->getDefault('_title_callback')); + $this->assertEquals('entity_test_admin_routes.delete', $route->getRequirement('_entity_access')); + $this->assertTrue($route->hasOption('_admin_route')); + $this->assertTrue($route->getOption('_admin_route')); + + $entity = EntityTestAdminRoutes::create([ + 'name' => 'Test title', + ]); + $entity->save(); + + $this->setRawContent($this->httpKernelHandle($entity->url())); + $this->assertTitle('Test title | '); + + $this->setRawContent($this->httpKernelHandle($entity->url('edit-form'))); + $this->assertTitle('Edit Test title | '); + + $this->setRawContent($this->httpKernelHandle($entity->url('delete-form'))); + $this->assertTitle('Are you sure you want to delete the test entity - admin routes Test title? | '); + } + +}