diff --git a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php index b8e4061..720c3ad 100644 --- a/core/lib/Drupal/Core/Entity/Annotation/EntityType.php +++ b/core/lib/Drupal/Core/Entity/Annotation/EntityType.php @@ -222,7 +222,7 @@ class EntityType extends Plugin { public $bundle_prefix; /** - * The base menu router path to which the entity admin user interface responds. + * The base menu router path to which the entity 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. @@ -232,27 +232,6 @@ class EntityType extends Plugin { 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/content_translation/content_translation.module b/core/modules/content_translation/content_translation.module index 2de5947..7bdd358 100644 --- a/core/modules/content_translation/content_translation.module +++ b/core/modules/content_translation/content_translation.module @@ -79,16 +79,18 @@ 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'); + // Provide default links for the translation paths. + $canonical = $info['links']['canonical']; + $info['links'] += array( + 'translation-overview' => $canonical . '/translations', + ); + // If no menu base path is provided we default to the usual // "entity_type/%entity_type" pattern. if (!isset($info['menu_base_path'])) { @@ -96,15 +98,11 @@ function content_translation_entity_info_alter(array &$entity_info) { $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", - ); + if (!isset($info['translation']['content_translation'])) { + $info['translation']['content_translation'] = array(); + } - $entity_position = count(explode('/', $path)) - 1; + $entity_position = count(explode('/', $info['menu_base_path'])) - 1; $info['translation']['content_translation'] += array( 'access_callback' => 'content_translation_translate_access', 'access_arguments' => array($entity_position), @@ -236,7 +234,7 @@ function content_translation_menu_alter(array &$items) { } else { $entity_position = count(explode('/', $path)) - 1; - $edit_path = $info['menu_edit_path']; + $edit_path = $info['menu_base_path'] . '/edit'; if (isset($items[$edit_path])) { // If the edit path is a default local task we need to find the parent diff --git a/core/modules/content_translation/content_translation.pages.inc b/core/modules/content_translation/content_translation.pages.inc index 5bc9501..d729ce8 100644 --- a/core/modules/content_translation/content_translation.pages.inc +++ b/core/modules/content_translation/content_translation.pages.inc @@ -22,10 +22,13 @@ function content_translation_overview(EntityInterface $entity) { $original = $entity->language()->langcode; $translations = $entity->getTranslationLanguages(); $field_ui = module_exists('field_ui') && user_access('administer ' . $entity->entityType() . ' fields'); + $generator = Drupal::urlGenerator(); - $path = $controller->getViewPath($entity); - $base_path = $controller->getBasePath($entity); - $edit_path = $controller->getEditPath($entity); + $rel = array(); + foreach (array('canonical', 'edit-form', 'translation-overview') as $name) { + $rel[$name] = $entity->uri($name); + } + $base_path = $rel['translation-overview']['path']; $header = array(t('Language'), t('Translation'), t('Source language'), t('Status'), t('Operations')); $rows = array(); @@ -33,8 +36,8 @@ function content_translation_overview(EntityInterface $entity) { if (language_multilingual()) { // If we have a view path defined for the current entity get the switch // links based on it. - if ($path) { - $links = _content_translation_get_switch_links($path); + if (!empty($rel['canonical'])) { + $links = _content_translation_get_switch_links($rel['canonical']['path']); } // Determine whether the current entity is translatable. @@ -51,13 +54,13 @@ function content_translation_overview(EntityInterface $entity) { foreach ($languages as $language) { $language_name = $language->name; $langcode = $language->langcode; - $add_path = $base_path . '/translations/add/' . $original . '/' . $langcode; - $translate_path = $base_path . '/translations/edit/' . $langcode; - $delete_path = $base_path . '/translations/delete/' . $langcode; + $add_path = $base_path . '/add/' . $original . '/' . $langcode; + $translate_path = $base_path . '/edit/' . $langcode; + $delete_path = $base_path . '/delete/' . $langcode; if ($base_path) { $add_links = _content_translation_get_switch_links($add_path); - $edit_links = _content_translation_get_switch_links($edit_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($delete_path); } @@ -76,7 +79,7 @@ function content_translation_overview(EntityInterface $entity) { $is_original = $langcode == $original; $translation = $translations[$langcode]; $label = $entity->label($langcode); - $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'])) { @@ -86,8 +89,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 ($controller->getAccess($entity, 'update')) { // TODO: was $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); @@ -268,11 +271,12 @@ function content_translation_prepare_translation(EntityInterface $entity, Langua function content_translation_delete_confirm(array $form, array $form_state, EntityInterface $entity, Language $language) { $langcode = $language->langcode; $controller = content_translation_controller($entity->entityType()); + $uri = $entity->uri('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') @@ -293,9 +297,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 (module_exists('path')) { - $conditions = array('source' => $controller->getViewPath($entity), 'langcode' => $language->langcode); + $uri = $entity->uri(); + $conditions = array('source' => $uri['path'], 'langcode' => $language->langcode); Drupal::service('path.crud')->delete($conditions); } - $form_state['redirect'] = $controller->getBasePath($entity) . '/translations'; + $uri = $entity->uri('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 5e4ad79..2b819a4 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationController.php @@ -70,27 +70,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) { @@ -461,7 +440,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('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))); @@ -488,9 +469,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('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; } /** @@ -503,17 +484,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 b28dd8d..f840e87 100644 --- a/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationControllerInterface.php +++ b/core/modules/content_translation/lib/Drupal/content_translation/ContentTranslationControllerInterface.php @@ -22,14 +22,8 @@ * 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 + * case at least the 'menu_base_path' key must be defined. + * * 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 @@ -62,7 +56,6 @@ * 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', @@ -79,39 +72,6 @@ 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/Tests/ContentTranslationUITest.php b/core/modules/content_translation/lib/Drupal/content_translation/Tests/ContentTranslationUITest.php index 6ffad4f..a1c949c 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 @@ -65,8 +65,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('translation-overview'); + $path = $langcode . '/' . $uri['path'] . '/add/' . $default_langcode . '/' . $langcode; $this->drupalPost($path, $this->getEditValues($values, $langcode), $this->getFormSubmitAction($entity)); if ($this->testLanguageSelector) { $this->assertNoFieldByXPath('//select[@id="edit-langcode"]', NULL, 'Language selector correclty disabled on translations.'); @@ -109,13 +109,14 @@ protected function assertOutdatedStatus() { // Mark translations as outdated. $edit = array('content_translation[retranslate]' => TRUE); - $this->drupalPost($langcode . '/' . $this->controller->getEditPath($entity), $edit, $this->getFormSubmitAction($entity)); + $uri = $entity->uri('edit-form'); + $this->drupalPost($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.'); @@ -137,7 +138,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) { @@ -159,7 +161,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. @@ -203,7 +206,8 @@ protected function assertTranslationDeletion() { // Confirm and delete a translation. $langcode = 'fr'; $entity = entity_load($this->entityType, $this->entityId, TRUE); - $this->drupalPost($langcode . '/' . $this->controller->getEditPath($entity), array(), t('Delete translation')); + $uri = $entity->uri('edit-form'); + $this->drupalPost($langcode . '/' . $uri['path'], array(), t('Delete translation')); $this->drupalPost(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 4930283..ee556a2 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 @@ -66,7 +66,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 = $entity->uri('translation-overview'); + $add_translation_path = $uri['path'] . "/add/$default_langcode/{$this->langcodes[2]}"; $this->drupalPost($add_translation_path, array(), t('Save')); $this->rebuildContainer(); } @@ -89,7 +90,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 = $entity->uri('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); @@ -122,14 +124,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 = $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 = $entity->uri('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));