diff --git a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php index b46d9f7..1e931f5 100644 --- a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php +++ b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php @@ -161,9 +161,17 @@ class EntityType extends Plugin { public $translatable = FALSE; /** - * @todo content_translation_entity_info_alter() uses this but it is undocumented. + * Array marking the entity type as translatable. + * + * This is used to register field translation handlers and thus mark the + * entity type as translatable. Additionally it could be used to provide + * translation-handler specific data. * * @var array + * + * @deprecated The entire concept of field translation handler has been + * removed. This will no longer be used. Use the "translatable" property + * instead. */ public $translation = array(); @@ -237,37 +245,6 @@ class EntityType extends Plugin { public $route_base_path; /** - * The base menu router path to which the entity admin user interface responds. - * - * It can be used to generate UI links and to attach additional router items - * to the entity UI in a generic fashion. - * - * @var string (optional) - */ - public $menu_base_path; - - /** - * The menu router path to be used to view the entity. - * - * @var string (optional) - */ - public $menu_view_path; - - /** - * The menu router path to be used to edit the entity. - * - * @var string (optional) - */ - public $menu_edit_path; - - /** - * A string identifying the menu loader in the router path. - * - * @var string (optional) - */ - public $menu_path_wildcard; - - /** * Link templates using the URI template syntax. * * Links are an array of standard link relations to the URI template that diff --git a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php index 2baf1fe..426b479 100644 --- a/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php +++ b/core/modules/block/custom_block/lib/Drupal/custom_block/Entity/CustomBlock.php @@ -37,8 +37,10 @@ * base_table = "custom_block", * revision_table = "custom_block_revision", * route_base_path = "admin/structure/block/custom-blocks/manage/{bundle}", - * menu_base_path = "block/%custom_block", - * menu_edit_path = "block/%custom_block", + * links = { + * "canonical" = "/block/{custom_block}", + * "edit-form" = "/block/{custom_block}" + * }, * fieldable = TRUE, * translatable = TRUE, * entity_keys = { @@ -177,19 +179,6 @@ protected function init() { /** * {@inheritdoc} */ - public function uri() { - return array( - 'path' => 'block/' . $this->id(), - 'options' => array( - 'entity_type' => $this->entityType, - 'entity' => $this, - ) - ); - } - - /** - * {@inheritdoc} - */ public function preSave(EntityStorageControllerInterface $storage_controller) { parent::preSave($storage_controller); diff --git a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php index 7944fdd..a90be4a 100644 --- a/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php +++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTranslationUITest.php @@ -68,7 +68,7 @@ function setupBundle() { * Overrides \Drupal\content_translation\Tests\ContentTranslationUITest::getTranslatorPermission(). */ protected function getTranslatorPermissions() { - return array_merge(parent::getTranslatorPermissions(), array('post comments', 'administer comments')); + return array_merge(parent::getTranslatorPermissions(), array('post comments', 'administer comments', 'access comments')); } /** @@ -134,11 +134,11 @@ protected function assertPublishedStatus() { $languages = language_list(); // Check that simple users cannot see unpublished field translations. - $path = $this->controller->getViewPath($entity); + $uri = $entity->uri(); foreach ($this->langcodes as $index => $langcode) { $translation = $this->getTranslation($entity, $langcode); $value = $this->getValue($translation, 'comment_body', $langcode); - $this->drupalGet($path, array('language' => $languages[$langcode])); + $this->drupalGet($uri['path'], array('language' => $languages[$langcode])); if ($index > 0) { $this->assertNoRaw($value, 'Unpublished field translation is not shown.'); } diff --git a/core/modules/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index b31b8d8..25f1e00 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -82,31 +82,22 @@ function content_translation_entity_info_alter(array &$entity_info) { continue; } - if (!isset($info['translation']['content_translation'])) { - $info['translation']['content_translation'] = array(); - } - // Every fieldable entity type must have a translation controller class, no // matter if it is enabled for translation or not. As a matter of fact we // might need it to correctly switch field translatability when a field is // shared accross different entities. $info['controllers'] += array('translation' => 'Drupal\content_translation\ContentTranslationController'); - // If no menu base path is provided we default to the usual - // "entity_type/%entity_type" pattern. - if (!isset($info['menu_base_path'])) { - $path = "$entity_type/%$entity_type"; - $info['menu_base_path'] = $path; - } - - $path = $info['menu_base_path']; - - $info += array( - 'menu_view_path' => $path, - 'menu_edit_path' => "$path/edit", - 'menu_path_wildcard' => "%$entity_type", + // Provide default links for the translation paths. + $info['links'] += array( + 'drupal:content-translation-overview' => $info['links']['canonical'] . '/translations', ); + if (!isset($info['translation']['content_translation'])) { + $info['translation']['content_translation'] = array(); + } + + $path = _content_translation_link_to_router_path($entity_type, $info['links']['canonical']); $entity_position = count(explode('/', $path)) - 1; $info['translation']['content_translation'] += array( 'access_callback' => 'content_translation_translate_access', @@ -156,6 +147,9 @@ function content_translation_entity_field_info_alter(&$info, $entity_type) { /** * Implements hook_menu(). + * + * @todo Split this into route definition and menu link definition. See + * https://drupal.org/node/1987882 and https://drupal.org/node/2047633. */ function content_translation_menu() { $items = array(); @@ -164,7 +158,7 @@ function content_translation_menu() { foreach (entity_get_info() as $entity_type => $info) { // Provide the translation UI only for enabled types. if (content_translation_enabled($entity_type)) { - $path = $info['menu_base_path']; + $path = _content_translation_link_to_router_path($entity_type, $info['links']['canonical']); $entity_position = count(explode('/', $path)) - 1; $keys = array_flip(array('theme_callback', 'theme_arguments', 'access_callback', 'access_arguments', 'load_arguments')); $menu_info = array_intersect_key($info['translation']['content_translation'], $keys) + array('file' => 'content_translation.pages.inc'); @@ -228,6 +222,9 @@ function content_translation_menu() { /** * Implements hook_menu_alter(). + * + * @todo Split this into route definition and menu link definition. See + * https://drupal.org/node/1987882 and https://drupal.org/node/2047633. */ function content_translation_menu_alter(array &$items) { // Clarify where translation settings are located. @@ -237,7 +234,7 @@ function content_translation_menu_alter(array &$items) { // Check that the declared menu base paths are actually valid. foreach (entity_get_info() as $entity_type => $info) { if (content_translation_enabled($entity_type)) { - $path = $info['menu_base_path']; + $path = _content_translation_link_to_router_path($entity_type, $info['links']['canonical']); // If the base path is not defined we cannot provide the translation UI // for this entity type. In some cases the actual base path might not have @@ -255,7 +252,7 @@ function content_translation_menu_alter(array &$items) { } else { $entity_position = count(explode('/', $path)) - 1; - $edit_path = $info['menu_edit_path']; + $edit_path = $path . '/edit'; if (isset($items[$edit_path])) { // If the edit path is a default local task we need to find the parent @@ -287,6 +284,24 @@ function content_translation_local_tasks_alter(&$local_tasks) { } /** + * Convert an entity canonical link to a router path. + * + * @param string $link + * The entity link to be converted. + * + * @return string + * The resulting router path. For instance "/node/{node}" is turned into + * "node/%node". + * + * @todo Remove this and use the actual link values when all the Content + * Translation code is adapted to the new routing system. + */ +function _content_translation_link_to_router_path($entity_type, $link) { + $path = preg_replace('|{([^}]+)}|', '%$1', trim($link, '/')); + return str_replace('%id', '%' . $entity_type, $path); +} + +/** * Strips out menu loaders from the given path. * * @param string $path @@ -477,9 +492,9 @@ function content_translation_set_config($entity_type, $bundle, $setting, $value) */ function content_translation_enabled($entity_type, $bundle = NULL) { $enabled = FALSE; - $info = entity_get_info($entity_type); + $entity_info = entity_get_info($entity_type); - if (!empty($info['translatable'])) { + if (content_translation_supported($entity_type)) { $bundles = !empty($bundle) ? array($bundle) : array_keys(entity_get_bundles($entity_type)); foreach ($bundles as $bundle) { if (content_translation_get_config($entity_type, $bundle, 'enabled')) { @@ -493,31 +508,17 @@ function content_translation_enabled($entity_type, $bundle = NULL) { } /** - * Returns all the translatable entity types. + * Checks whether an entity type supports translation. + * + * @param string $entity_type + * The entity type. * - * @return array - * An array of entity types keyed by entity type. + * @return bool + * TRUE if an entity type is supported, FALSE otherwise. */ -function content_translation_types_translatable() { - $entity_types = &drupal_static(__FUNCTION__, array()); - - foreach (entity_get_info() as $entity_type => $info) { - if (content_translation_enabled($entity_type)) { - // Lazy load router items. - if (!isset($items)) { - $items = menu_get_router(); - } - // Check whether the required paths are defined. We need to strip out the - // menu loader and replace it with a plain "%" as router items have no - // menu loader in them. - $path = _content_translation_menu_strip_loaders($info['menu_base_path']); - if (!empty($items[$path]) && !empty($items[$path . '/translations'])) { - $entity_types[$entity_type] = $entity_type; - } - } - } - - return $entity_types; +function content_translation_supported($entity_type) { + $info = entity_get_info($entity_type); + return !empty($info['translatable']) && !empty($info['links']['canonical']); } /** diff --git a/core/modules/content_translation/content_translation.pages.inc b/core/modules/content_translation/content_translation.pages.inc index f64599f..b6473ae 100644 --- a/core/modules/content_translation/content_translation.pages.inc +++ b/core/modules/content_translation/content_translation.pages.inc @@ -25,14 +25,21 @@ function content_translation_overview(EntityInterface $entity) { $translations = $entity->getTranslationLanguages(); $field_ui = \Drupal::moduleHandler()->moduleExists('field_ui') && user_access('administer ' . $entity->entityType() . ' fields'); - $path = $controller->getViewPath($entity); - $base_path = $controller->getBasePath($entity); - $edit_path = $controller->getEditPath($entity); + $rel = array(); + foreach (array('canonical', 'edit-form', 'drupal:content-translation-overview') as $name) { + $rel[$name] = $entity->uri($name); + } $header = array(t('Language'), t('Translation'), t('Source language'), t('Status'), t('Operations')); $rows = array(); if (language_multilingual()) { + // If we have a view path defined for the current entity get the switch + // links based on it. + if (!empty($rel['canonical'])) { + $links = _content_translation_get_switch_links($rel['canonical']['path']); + } + // Determine whether the current entity is translatable. $translatable = FALSE; foreach (field_info_instances($entity->entityType(), $entity->bundle()) as $instance) { @@ -45,16 +52,14 @@ function content_translation_overview(EntityInterface $entity) { foreach ($languages as $language) { $language_name = $language->name; $langcode = $language->id; - $add_path = $base_path . '/translations/add/' . $original . '/' . $langcode; - $translate_path = $base_path . '/translations/edit/' . $langcode; - $delete_path = $base_path . '/translations/delete/' . $langcode; - - if ($base_path) { - $add_links = _content_translation_get_switch_links($add_path); - $edit_links = _content_translation_get_switch_links($edit_path); - $translate_links = _content_translation_get_switch_links($translate_path); - $delete_links = _content_translation_get_switch_links($delete_path); - } + + $add_path = $rel['drupal:content-translation-overview']['path'] . '/add/' . $original . '/' . $langcode; + $translate_path = $rel['drupal:content-translation-overview']['path'] . '/edit/' . $langcode; + + $add_links = _content_translation_get_switch_links($add_path); + $edit_links = _content_translation_get_switch_links($rel['edit-form']['path']); + $translate_links = _content_translation_get_switch_links($translate_path); + $delete_links = _content_translation_get_switch_links($rel['drupal:content-translation-overview']['path'] . '/delete/' . $langcode); $operations = array( 'data' => array( @@ -69,7 +74,7 @@ function content_translation_overview(EntityInterface $entity) { $source = isset($entity->translation[$langcode]['source']) ? $entity->translation[$langcode]['source'] : ''; $is_original = $langcode == $original; $label = $entity->getTranslation($langcode)->label(); - $link = isset($links->links[$langcode]['href']) ? $links->links[$langcode] : array('href' => $path, 'language' => $language); + $link = isset($links->links[$langcode]['href']) ? $links->links[$langcode] : array('href' => $rel['canonical']['path'], 'language' => $language); $row_title = l($label, $link['href'], $link); if (empty($link['href'])) { @@ -79,8 +84,8 @@ function content_translation_overview(EntityInterface $entity) { // If the user is allowed to edit the entity we point the edit link to // the entity form, otherwise if we are not dealing with the original // language we point the link to the translation form. - if ($edit_path && $entity->access('update')) { - $links['edit'] = isset($edit_links->links[$langcode]['href']) ? $edit_links->links[$langcode] : array('href' => $edit_path, 'language' => $language); + if ($entity->access('update')) { + $links['edit'] = isset($edit_links->links[$langcode]['href']) ? $edit_links->links[$langcode] : array('href' => $rel['edit-form']['path'], 'language' => $language); } elseif (!$is_original && $controller->getTranslationAccess($entity, 'update')) { $links['edit'] = isset($translate_links->links[$langcode]['href']) ? $translate_links->links[$langcode] : array('href' => $translate_path, 'language' => $language); @@ -246,11 +251,12 @@ function content_translation_prepare_translation(EntityInterface $entity, Langua */ function content_translation_delete_confirm(array $form, array $form_state, EntityInterface $entity, Language $language) { $controller = content_translation_controller($entity->entityType()); + $uri = $entity->uri('drupal:content-translation-overview'); return confirm_form( $form, t('Are you sure you want to delete the @language translation of %label?', array('@language' => $language->name, '%label' => $entity->label())), - $controller->getEditPath($entity), + $uri['path'], t('This action cannot be undone.'), t('Delete'), t('Cancel') @@ -271,9 +277,11 @@ function content_translation_delete_confirm_submit(array $form, array &$form_sta // Remove any existing path alias for the removed translation. // @todo This should be taken care of by the Path module. if (\Drupal::moduleHandler()->moduleExists('path')) { - $conditions = array('source' => $controller->getViewPath($entity), 'langcode' => $language->id); + $uri = $entity->uri(); + $conditions = array('source' => $uri['path'], 'langcode' => $language->id); \Drupal::service('path.crud')->delete($conditions); } - $form_state['redirect'] = $controller->getBasePath($entity) . '/translations'; + $uri = $entity->uri('drupal:content-translation-overview'); + $form_state['redirect'] = $uri['path']; } diff --git a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php index c499806..a639f30 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php @@ -54,27 +54,6 @@ public function retranslate(EntityInterface $entity, $langcode = NULL) { } /** - * Implements ContentTranslationControllerInterface::getBasePath(). - */ - public function getBasePath(EntityInterface $entity) { - return $this->getPathInstance($this->entityInfo['menu_base_path'], $entity->id()); - } - - /** - * Implements ContentTranslationControllerInterface::getEditPath(). - */ - public function getEditPath(EntityInterface $entity) { - return isset($this->entityInfo['menu_edit_path']) ? $this->getPathInstance($this->entityInfo['menu_edit_path'], $entity->id()) : FALSE; - } - - /** - * Implements ContentTranslationControllerInterface::getViewPath(). - */ - public function getViewPath(EntityInterface $entity) { - return isset($this->entityInfo['menu_view_path']) ? $this->getPathInstance($this->entityInfo['menu_view_path'], $entity->id()) : FALSE; - } - - /** * Implements ContentTranslationControllerInterface::getTranslationAccess(). */ public function getTranslationAccess(EntityInterface $entity, $op) { @@ -446,7 +425,9 @@ public function entityFormSourceChange($form, &$form_state) { $form_controller = content_translation_form_controller($form_state); $entity = $form_controller->getEntity(); $source = $form_state['values']['source_langcode']['source']; - $path = $this->getBasePath($entity) . '/translations/add/' . $source . '/' . $form_controller->getFormLangcode($form_state); + + $uri = $entity->uri('drupal:content-translation-overview'); + $path = $uri['path'] . '/add/' . $source . '/' . $form_controller->getFormLangcode($form_state); $form_state['redirect'] = $path; $languages = language_list(); drupal_set_message(t('Source language set to: %language', array('%language' => $languages[$source]->name))); @@ -473,9 +454,9 @@ function entityFormDelete($form, &$form_state) { function entityFormDeleteTranslation($form, &$form_state) { $form_controller = content_translation_form_controller($form_state); $entity = $form_controller->getEntity(); - $base_path = $this->getBasePath($entity); + $uri = $entity->uri('drupal:content-translation-overview'); $form_langcode = $form_controller->getFormLangcode($form_state); - $form_state['redirect'] = $base_path . '/translations/delete/' . $form_langcode; + $form_state['redirect'] = $uri['path'] . '/delete/' . $form_langcode; } /** @@ -488,17 +469,4 @@ protected function entityFormTitle(EntityInterface $entity) { return $entity->label(); } - /** - * Returns an instance of the given path. - * - * @param $path - * An internal path containing the entity id wildcard. - * - * @return string - * The instantiated path. - */ - protected function getPathInstance($path, $entity_id) { - $wildcard = $this->entityInfo['menu_path_wildcard']; - return str_replace($wildcard, $entity_id, $path); - } } diff --git a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationControllerInterface.php b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationControllerInterface.php index d2d3c2c..ed68e8f 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationControllerInterface.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationControllerInterface.php @@ -22,96 +22,27 @@ * To make Content Translation automatically support an entity type some keys * may need to be defined, but none of them is required unless the entity path * is different from ENTITY_TYPE/%ENTITY_TYPE (e.g. taxonomy/term/1), in which - * case at least the 'menu_base_path' key must be defined. This is used to - * determine the view and edit paths if they follow the standard path patterns. - * Otherwise the 'menu_view_path' and 'menu_edit_path' keys must be defined. If - * an entity type is enabled for translation and no menu path key is defined, - * the following defaults will be assumed: - * - menu_base_path: ENTITY_TYPE/%ENTITY_TYPE - * - menu_view_path: ENTITY_TYPE/%ENTITY_TYPE - * - menu_edit_path: ENTITY_TYPE/%ENTITY_TYPE/edit - * The menu base path is also used to reliably alter menu router information to - * provide the translation overview page for any entity. - * If the entity uses a menu loader different from %ENTITY_TYPE also the 'menu - * path wildcard' info key needs to be defined. + * case at least the 'canonical' key in the 'links' entity info property must be + * defined. * * Every entity type needs a translation controller to be translated. This can * be specified through the "controllers['translation']" key in the entity * info. If an entity type is enabled for translation and no translation - * controller is defined, Drupal\content_translation\ContentTranslationController - * will be assumed. Every translation controller class must implement - * Drupal\content_translation\ContentTranslationControllerInterface. + * controller is defined, + * \Drupal\content_translation\ContentTranslationController will be assumed. + * Every translation controller class must implement + * \Drupal\content_translation\ContentTranslationControllerInterface. * * If the entity paths match the default patterns above and there is no need for * an entity-specific translation controller class, Content Translation will * provide built-in support for the entity. It will still be required to enable * translation for each translatable bundle. * - * Additionally some more entity info keys can be defined to further customize - * the translation UI. The content translation info is an associative array that - * has to match the following structure. Two nested arrays keyed respectively - * by the 'translation' key and the 'content_translation' key. Elements: - * - access callback: The access callback for the translation pages. Defaults to - * 'entity_translation_translate_access'. - * - access arguments: The access arguments for the translation pages. By - * default only the entity object is passed to the access callback. - * - * This is how entity info would look for a module defining a new translatable - * entity type: - * @code - * function mymodule_entity_info_alter(array &$info) { - * $info['myentity'] += array( - * 'menu_base_path' => 'mymodule/myentity/%my_entity_loader', - * 'menu_path_wildcard' => '%my_entity_loader', - * 'translation' => array( - * 'content_translation' => array( - * 'access_callback' => 'mymodule_myentity_translate_access', - * 'access_arguments' => array(2), - * ), - * ), - * ); - * $info['myentity']['controllers'] += array('translation' => 'Drupal\mymodule\MyContentTranslationController'); - * } - * @endcode - * * @see \Drupal\Core\Entity\EntityManagerInterface */ interface ContentTranslationControllerInterface { /** - * Returns the base path for the current entity. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity to the path should refer to. - * - * @return string - * The entity base path. - */ - public function getBasePath(EntityInterface $entity); - - /** - * Returns the path of the entity edit form. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity to the path should refer to. - * - * @return string - * The entity edit path. - */ - public function getEditPath(EntityInterface $entity); - - /** - * Returns the path of the entity view page. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity to the path should refer to. - * - * @return string - * The entity view path. - */ - public function getViewPath(EntityInterface $entity); - - /** * Checks if the user can perform the given operation on translations of the * wrapped entity. * diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Plugin/Derivative/ContentTranslationLocalTasks.php b/core/modules/content_translation/lib/Drupal/content_translation/Plugin/Derivative/ContentTranslationLocalTasks.php index 21c352a..f7da9a7 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/Plugin/Derivative/ContentTranslationLocalTasks.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/Plugin/Derivative/ContentTranslationLocalTasks.php @@ -72,7 +72,7 @@ public static function create(ContainerInterface $container, $base_plugin_id) { public function getDerivativeDefinitions(array $base_plugin_definition) { // Create tabs for all possible entity types. foreach ($this->entityManager->getDefinitions() as $entity_type => $entity_info) { - if ($entity_info['translatable'] && isset($entity_info['translation'])) { + if (!empty($entity_info['translatable'])) { // Find the route name for the translation overview. $translation_route_name = "content_translation.translation_overview_$entity_type"; $translation_tab = $translation_route_name; @@ -92,8 +92,8 @@ public function getDerivativeDefinitions(array $base_plugin_definition) { */ public function alterLocalTasks(array &$local_tasks) { foreach ($this->entityManager->getDefinitions() as $entity_type => $entity_info) { - if ($entity_info['translatable'] && isset($entity_info['translation'])) { - $path = '/' . preg_replace('/%(.*)/', '{$1}', $entity_info['menu_base_path']); + if (!empty($entity_info['translatable']) && !empty($entity_info['links']['canonical'])) { + $path = $entity_info['links']['canonical']; if ($routes = $this->routeProvider->getRoutesByPattern($path)->all()) { // Find the route name for the entity page. $entity_route_name = key($routes); diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Routing/ContentTranslationRouteSubscriber.php b/core/modules/content_translation/lib/Drupal/content_translation/Routing/ContentTranslationRouteSubscriber.php index 63033d4..368dc27 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/Routing/ContentTranslationRouteSubscriber.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/Routing/ContentTranslationRouteSubscriber.php @@ -39,8 +39,9 @@ public function __construct(EntityManagerInterface $entityManager) { */ protected function routes(RouteCollection $collection) { foreach ($this->entityManager->getDefinitions() as $entity_type => $entity_info) { - if ($entity_info['translatable'] && isset($entity_info['translation'])) { - $path = '/' . str_replace($entity_info['menu_path_wildcard'], '{' . $entity_type . '}', $entity_info['menu_base_path']) . '/translations'; + if (!empty($entity_info['translatable']) && !empty($entity_info['links']['drupal:content-translation-overview'])) { + $path = $entity_info['links']['drupal:content-translation-overview']; + $route = new Route( $path, array( diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php index 21c8465..212d427 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php @@ -52,6 +52,9 @@ protected function assertBasicTranslation() { $this->entityId = $this->createEntity($values[$default_langcode], $default_langcode); $entity = entity_load($this->entityType, $this->entityId, TRUE); $this->assertTrue($entity, 'Entity found in the database.'); + $uri = $entity->uri(); + $this->drupalGet($uri['path']); + $this->assertResponse(200, 'Entity URL is valid.'); $translation = $this->getTranslation($entity, $default_langcode); foreach ($values[$default_langcode] as $property => $value) { @@ -65,8 +68,8 @@ protected function assertBasicTranslation() { $langcode = 'it'; $values[$langcode] = $this->getNewEntityValues($langcode); - $base_path = $this->controller->getBasePath($entity); - $path = $langcode . '/' . $base_path . '/translations/add/' . $default_langcode . '/' . $langcode; + $uri = $entity->uri('drupal:content-translation-overview'); + $path = $langcode . '/' . $uri['path'] . '/add/' . $default_langcode . '/' . $langcode; $this->drupalPostForm($path, $this->getEditValues($values, $langcode), $this->getFormSubmitAction($entity)); if ($this->testLanguageSelector) { $this->assertNoFieldByXPath('//select[@id="edit-langcode"]', NULL, 'Language selector correclty disabled on translations.'); @@ -77,7 +80,7 @@ protected function assertBasicTranslation() { $langcode = 'fr'; $source_langcode = 'it'; $edit = array('source_langcode[source]' => $source_langcode); - $path = $langcode . '/' . $base_path . '/translations/add/' . $default_langcode . '/' . $langcode; + $path = $langcode . '/' . $uri['path'] . '/add/' . $default_langcode . '/' . $langcode; $this->drupalPostForm($path, $edit, t('Change')); $this->assertFieldByXPath("//input[@name=\"{$this->fieldName}[0][value]\"]", $values[$source_langcode][$this->fieldName][0]['value'], 'Source language correctly switched.'); @@ -104,8 +107,8 @@ protected function assertBasicTranslation() { */ protected function doTestTranslationOverview() { $entity = entity_load($this->entityType, $this->entityId, TRUE); - $path = $this->controller->getBasePath($entity) . '/translations'; - $this->drupalGet($path); + $uri = $entity->uri('drupal:content-translation-overview'); + $this->drupalGet($uri['path']); foreach ($this->langcodes as $langcode) { if ($entity->hasTranslation($langcode)) { @@ -124,13 +127,14 @@ protected function assertOutdatedStatus() { // Mark translations as outdated. $edit = array('content_translation[retranslate]' => TRUE); - $this->drupalPostForm($langcode . '/' . $this->controller->getEditPath($entity), $edit, $this->getFormSubmitAction($entity)); + $uri = $entity->uri('edit-form'); + $this->drupalPostForm($langcode . '/' . $uri['path'], $edit, $this->getFormSubmitAction($entity)); $entity = entity_load($this->entityType, $this->entityId, TRUE); // Check that every translation has the correct "outdated" status. foreach ($this->langcodes as $enabled_langcode) { $prefix = $enabled_langcode != $default_langcode ? $enabled_langcode . '/' : ''; - $path = $prefix . $this->controller->getEditPath($entity); + $path = $prefix . $uri['path']; $this->drupalGet($path); if ($enabled_langcode == $langcode) { $this->assertFieldByXPath('//input[@name="content_translation[retranslate]"]', FALSE, 'The retranslate flag is not checked by default.'); @@ -152,7 +156,8 @@ protected function assertOutdatedStatus() { */ protected function assertPublishedStatus() { $entity = entity_load($this->entityType, $this->entityId, TRUE); - $path = $this->controller->getEditPath($entity); + $uri = $entity->uri('edit-form'); + $path = $uri['path']; // Unpublish translations. foreach ($this->langcodes as $index => $langcode) { @@ -174,7 +179,8 @@ protected function assertPublishedStatus() { */ protected function assertAuthoringInfo() { $entity = entity_load($this->entityType, $this->entityId, TRUE); - $path = $this->controller->getEditPath($entity); + $uri = $entity->uri('edit-form'); + $path = $uri['path']; $values = array(); // Post different authoring information for each translation. @@ -218,7 +224,8 @@ protected function assertTranslationDeletion() { // Confirm and delete a translation. $langcode = 'fr'; $entity = entity_load($this->entityType, $this->entityId, TRUE); - $this->drupalPostForm($langcode . '/' . $this->controller->getEditPath($entity), array(), t('Delete translation')); + $uri = $entity->uri('edit-form'); + $this->drupalPostForm($langcode . '/' . $uri['path'], array(), t('Delete translation')); $this->drupalPostForm(NULL, array(), t('Delete')); $entity = entity_load($this->entityType, $this->entityId, TRUE); if ($this->assertTrue(is_object($entity), 'Entity found')) { diff --git a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationWorkflowsTest.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationWorkflowsTest.php index c523900..0b3da77 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationWorkflowsTest.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationWorkflowsTest.php @@ -67,7 +67,8 @@ protected function setupEntity() { // Create a translation. $this->drupalLogin($this->translator); - $add_translation_path = $this->controller->getBasePath($this->entity) . "/translations/add/$default_langcode/{$this->langcodes[2]}"; + $uri = $this->entity->uri('drupal:content-translation-overview'); + $add_translation_path = $uri['path'] . "/add/$default_langcode/{$this->langcodes[2]}"; $this->drupalPostForm($add_translation_path, array(), t('Save')); $this->rebuildContainer(); } @@ -90,7 +91,8 @@ function testWorkflows() { // Check that translation permissions governate the associated operations. $ops = array('create' => t('Add'), 'update' => t('Edit'), 'delete' => t('Delete')); - $translations_path = $this->controller->getBasePath($this->entity) . "/translations"; + $uri = $this->entity->uri('drupal:content-translation-overview'); + $translations_path = $uri['path']; foreach ($ops as $current_op => $label) { $user = $this->drupalCreateUser(array($this->getTranslatePermission(), "$current_op content translations")); $this->drupalLogin($user); @@ -123,14 +125,16 @@ protected function assertWorkflows(UserInterface $user, $expected_status) { $this->drupalLogin($user); // Check whether the user is allowed to access the entity form in edit mode. - $edit_path = $this->controller->getEditPath($this->entity); + $uri = $this->entity->uri('edit-form'); + $edit_path = $uri['path']; $options = array('language' => $languages[$default_langcode]); $this->drupalGet($edit_path, $options); $this->assertResponse($expected_status['edit'], format_string('The @user_label has the expected edit access.', $args)); // Check whether the user is allowed to access the translation overview. $langcode = $this->langcodes[1]; - $translations_path = $this->controller->getBasePath($this->entity) . "/translations"; + $uri = $this->entity->uri('drupal:content-translation-overview'); + $translations_path = $uri['path']; $options = array('language' => $languages[$langcode]); $this->drupalGet($translations_path, $options); $this->assertResponse($expected_status['overview'], format_string('The @user_label has the expected translation overview access.', $args)); diff --git a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php index 6a2608c..3f5f147 100644 --- a/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php +++ b/core/modules/node/lib/Drupal/node/Tests/NodeTranslationUITest.php @@ -74,7 +74,7 @@ protected function getFormSubmitAction(EntityInterface $entity) { */ protected function assertPublishedStatus() { $entity = entity_load($this->entityType, $this->entityId, TRUE); - $path = $this->controller->getEditPath($entity); + $uri = $entity->uri('edit-form'); $languages = language_list(); $actions = array( @@ -89,7 +89,7 @@ protected function assertPublishedStatus() { if (!empty($status_actions)) { $action = array_shift($status_actions); } - $this->drupalPostForm($path, array(), $action, array('language' => $languages[$langcode])); + $this->drupalPostForm($uri['path'], array(), $action, array('language' => $languages[$langcode])); } $entity = entity_load($this->entityType, $this->entityId, TRUE); foreach ($this->langcodes as $langcode) { @@ -106,7 +106,7 @@ protected function assertPublishedStatus() { */ protected function assertAuthoringInfo() { $entity = entity_load($this->entityType, $this->entityId, TRUE); - $path = $this->controller->getEditPath($entity); + $uri = $entity->uri('edit-form'); $languages = language_list(); $values = array(); @@ -122,7 +122,7 @@ protected function assertAuthoringInfo() { 'date[date]' => format_date($values[$langcode]['created'], 'custom', 'Y-m-d'), 'date[time]' => format_date($values[$langcode]['created'], 'custom', 'H:i:s'), ); - $this->drupalPostForm($path, $edit, $this->getFormSubmitAction($entity), array('language' => $languages[$langcode])); + $this->drupalPostForm($uri['path'], $edit, $this->getFormSubmitAction($entity), array('language' => $languages[$langcode])); } $entity = entity_load($this->entityType, $this->entityId, TRUE); diff --git a/core/modules/system/tests/modules/entity_test/entity_test.module b/core/modules/system/tests/modules/entity_test/entity_test.module index c8f868e..2348856 100644 --- a/core/modules/system/tests/modules/entity_test/entity_test.module +++ b/core/modules/system/tests/modules/entity_test/entity_test.module @@ -62,9 +62,6 @@ function entity_test_entity_types($filter = NULL) { */ function entity_test_entity_info_alter(&$info) { foreach (entity_test_entity_types() as $entity_type) { - // Ensure these test entity types use their base path as their edit path. - $info[$entity_type]['menu_edit_path'] = $info[$entity_type]['menu_base_path']; - // Optionally specify a translation handler for testing translations. if (\Drupal::state()->get('entity_test.translation')) { $info[$entity_type]['translation'][$entity_type] = TRUE; diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php index 8695b11..eabcb5a 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTest.php @@ -37,7 +37,6 @@ * "bundle" = "type", * "label" = "name" * }, - * menu_base_path = "entity_test/manage/%entity_test", * route_base_path = "admin/structure/entity-test/manage/{bundle}", * links = { * "canonical" = "/entity_test/{entity_test}", diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php index 55a7b5e..48d345e 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestCache.php @@ -32,8 +32,7 @@ * "id" = "id", * "uuid" = "uuid", * "bundle" = "type" - * }, - * menu_base_path = "entity-test/manage/%entity_test" + * } * ) */ class EntityTestCache extends EntityTest { diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php index d3e0fb3..85cad2e 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMul.php @@ -35,8 +35,11 @@ * "bundle" = "type", * "label" = "name" * }, - * menu_base_path = "entity_test_mul/manage/%entity_test_mul", - * route_base_path = "entity_test_mul/structure/{bundle}" + * route_base_path = "entity_test_mul/structure/{bundle}", + * links = { + * "canonical" = "/entity_test_mul/manage/{entity_test_mul}", + * "edit-form" = "/entity_test_mul/manage/{entity_test_mul}" + * } * ) */ class EntityTestMul extends EntityTest { diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php index 3d8df50..25887a5 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestMulRev.php @@ -37,7 +37,10 @@ * "revision" = "revision_id", * "bundle" = "type" * }, - * menu_base_path = "entity_test_mulrev/manage/%entity_test_mulrev" + * links = { + * "canonical" = "/entity_test_mulrev/manage/{entity_test_mulrev}", + * "edit-form" = "/entity_test_mulrev/manage/{entity_test_mulrev}" + * } * ) */ class EntityTestMulRev extends EntityTestRev { diff --git a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php index 19760e8..fb6d42c 100644 --- a/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php +++ b/core/modules/system/tests/modules/entity_test/lib/Drupal/entity_test/Entity/EntityTestRev.php @@ -34,7 +34,10 @@ * "revision" = "revision_id", * "bundle" = "type" * }, - * menu_base_path = "entity_test_rev/manage/%entity_test_rev" + * links = { + * "canonical" = "/entity_test_rev/manage/{entity_test_rev}", + * "edit-form" = "/entity_test_rev/manage/{entity_test_rev}" + * } * ) */ class EntityTestRev extends EntityTest { diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php index 033c5f1..7c9e9c3 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/Entity/Term.php @@ -48,7 +48,6 @@ * "canonical" = "/taxonomy/term/{taxonomy_term}", * "edit-form" = "/taxonomy/term/{taxonomy_term}/edit" * }, - * menu_base_path = "taxonomy/term/%taxonomy_term", * route_base_path = "admin/structure/taxonomy/manage/{bundle}", * permission_granularity = "bundle" * ) diff --git a/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php b/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php index f7c704a..ba951a1 100644 --- a/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php +++ b/core/modules/taxonomy/lib/Drupal/taxonomy/TermTranslationController.php @@ -36,7 +36,8 @@ function entityFormSave(array $form, array &$form_state) { // We need a redirect here, otherwise we would get an access denied page, // since the current URL would be preserved and we would try to add a // translation for a language that already has a translation. - $form_state['redirect'] = $this->getEditPath($entity); + $uri = $entity->uri('edit-form'); + $form_state['redirect'] = $uri['path']; } } diff --git a/core/modules/user/lib/Drupal/user/ProfileTranslationController.php b/core/modules/user/lib/Drupal/user/ProfileTranslationController.php index 499f28c..9667170 100644 --- a/core/modules/user/lib/Drupal/user/ProfileTranslationController.php +++ b/core/modules/user/lib/Drupal/user/ProfileTranslationController.php @@ -36,7 +36,8 @@ function entityFormSave(array $form, array &$form_state) { // We need a redirect here, otherwise we would get an access denied page // since the current URL would be preserved and we would try to add a // translation for a language that already has a translation. - $form_state['redirect'] = $this->getViewPath($entity); + $uri = $entity->uri(); + $form_state['redirect'] = $uri['path']; } } }