diff --git a/core/modules/content_translation/content_translation.pages.inc b/core/modules/content_translation/content_translation.pages.inc deleted file mode 100644 index 989867864870404e3ebc1716443696bda61cb3ae..0000000000000000000000000000000000000000 --- a/core/modules/content_translation/content_translation.pages.inc +++ /dev/null @@ -1,251 +0,0 @@ -getEntityTypeId()); - $languages = \Drupal::languageManager()->getLanguages(); - $original = $entity->getUntranslated()->language()->id; - $translations = $entity->getTranslationLanguages(); - $administrator = \Drupal::currentUser()->hasPermission('administer languages'); - - $rel = array(); - foreach (array('canonical', 'edit-form', 'drupal:content-translation-overview') as $name) { - $rel[$name] = $entity->getSystemPath($name); - } - - $rows = array(); - $show_source_column = FALSE; - - if (\Drupal::languageManager()->isMultilingual()) { - // Determine whether the current entity is translatable. - $translatable = FALSE; - foreach (\Drupal::entityManager()->getFieldDefinitions($entity->getEntityTypeId(), $entity->bundle()) as $field_definition) { - if ($field_definition->isTranslatable()) { - $translatable = TRUE; - break; - } - } - - // Show source-language column if there are non-original source langcodes. - $additional_source_langcodes = array_filter($entity->translation, function ($translation) use ($original) { - return !empty($translation['source']) && $translation['source'] != $original; - }); - $show_source_column = !empty($additional_source_langcodes); - - foreach ($languages as $language) { - $language_name = $language->name; - $langcode = $language->id; - - $add_path = $rel['drupal:content-translation-overview'] . '/add/' . $original . '/' . $langcode; - $translate_path = $rel['drupal:content-translation-overview'] . '/edit/' . $langcode; - - $add_links = _content_translation_get_switch_links($add_path); - $edit_links = _content_translation_get_switch_links($rel['edit-form']); - $translate_links = _content_translation_get_switch_links($translate_path); - $delete_links = _content_translation_get_switch_links($rel['drupal:content-translation-overview'] . '/delete/' . $langcode); - - $operations = array( - 'data' => array( - '#type' => 'operations', - '#links' => array(), - ), - ); - $links = &$operations['data']['#links']; - - if (isset($translations[$langcode])) { - // Existing translation in the translation set: display status. - $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' => $rel['canonical'], 'language' => $language); - $row_title = l($label, $link['href'], $link); - - if (empty($link['href'])) { - $row_title = $is_original ? $label : t('n/a'); - } - - // 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 ($entity->access('update')) { - $links['edit'] = isset($edit_links->links[$langcode]['href']) ? $edit_links->links[$langcode] : array('href' => $rel['edit-form'], '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); - } - - if (isset($links['edit'])) { - $links['edit']['title'] = t('Edit'); - } - - $translation = $entity->translation[$langcode]; - $status = !empty($translation['status']) ? t('Published') : t('Not published'); - // @todo Add a theming function here. - $status = '' . $status . '' . (!empty($translation['outdated']) ? ' ' . t('outdated') . '' : ''); - - if ($is_original) { - $language_name = t('@language_name (Original language)', array('@language_name' => $language_name)); - $source_name = t('n/a'); - } - else { - $source_name = isset($languages[$source]) ? $languages[$source]->name : t('n/a'); - if ($controller->getTranslationAccess($entity, 'delete')) { - $links['delete'] = isset($delete_links->links[$langcode]['href']) ? $delete_links->links[$langcode] : array('href' => $delete_links, 'language' => $language); - $links['delete']['title'] = t('Delete'); - } - } - } - else { - // No such translation in the set yet: help user to create it. - $row_title = $source_name = t('n/a'); - $source = $entity->language()->id; - - if ($source != $langcode && $controller->getTranslationAccess($entity, 'create')) { - if ($translatable) { - $links['add'] = isset($add_links->links[$langcode]['href']) ? $add_links->links[$langcode] : array('href' => $add_path, 'language' => $language); - $links['add']['title'] = t('Add'); - } - elseif ($administrator) { - $links['nofields'] = array('title' => t('No translatable fields'), 'route_name' => 'language.content_settings_page', 'language' => $language); - } - } - - $status = t('Not translated'); - } - - if ($show_source_column) { - $rows[] = array($language_name, $row_title, $source_name, $status, $operations); - } - else { - $rows[] = array($language_name, $row_title, $status, $operations); - } - } - } - - $build['#title'] = t('Translations of %label', array('%label' => $entity->label())); - - // Add metadata to the build render array to let other modules know about - // which entity this is. - $build['#entity'] = $entity; - - if ($show_source_column) { - $header = array(t('Language'), t('Translation'), t('Source language'), t('Status'), t('Operations')); - } - else { - $header = array(t('Language'), t('Translation'), t('Status'), t('Operations')); - } - - $build['content_translation_overview'] = array( - '#type' => 'table', - '#header' => $header, - '#rows' => $rows, - ); - - return $build; -} - -/** - * Returns the localized links for the given path. - * - * @param string $path - * The path for which language switch links should be provided. - * - * @returns - * A renderable array of language switch links. - */ -function _content_translation_get_switch_links($path) { - $links = \Drupal::languageManager()->getLanguageSwitchLinks(LanguageInterface::TYPE_CONTENT, $path); - if (empty($links)) { - // If content language is set up to fall back to the interface language, - // then there will be no switch links for LanguageInterface::TYPE_CONTENT, - // ergo we also need to use interface switch links. - $links = \Drupal::languageManager()->getLanguageSwitchLinks(LanguageInterface::TYPE_INTERFACE, $path); - } - return $links; -} - -/** - * Page callback for the translation addition page. - * - * @param EntityInterface $entity - * The entity being translated. - * @param \Drupal\Core\Language\LanguageInterface $source - * (optional) The language of the values being translated. Defaults to the - * entity language. - * @param \Drupal\Core\Language\LanguageInterface $target - * (optional) The language of the translated values. Defaults to the current - * content language. - * - * @return array - * A processed form array ready to be rendered. - * - * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. - * Use \Drupal\content_translation\Controller\ContentTranslationController::add(). - */ -function content_translation_add_page(EntityInterface $entity, LanguageInterface $source = NULL, LanguageInterface $target = NULL) { - $source = !empty($source) ? $source : $entity->language(); - $target = !empty($target) ? $target : \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); - // @todo Exploit the upcoming hook_entity_prepare() when available. - content_translation_prepare_translation($entity, $source, $target); - $form_state['langcode'] = $target->id; - $form_state['content_translation']['source'] = $source; - $form_state['content_translation']['target'] = $target; - $form_state['content_translation']['translation_form'] = !$entity->access('update'); - return \Drupal::service('entity.form_builder')->getForm($entity, 'default', $form_state); -} - -/** - * Page callback for the translation edit page. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entity being translated. - * @param \Drupal\Core\Language\LanguageInterface $language - * (optional) The language of the translated values. Defaults to the current - * content language. - * - * @return array - * A processed form array ready to be rendered. - * - * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0. - * Use \Drupal\content_translation\Controller\ContentTranslationController::edit(). - */ -function content_translation_edit_page(EntityInterface $entity, LanguageInterface $language = NULL) { - $language = !empty($language) ? $language : \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); - $form_state['langcode'] = $language->id; - $form_state['content_translation']['translation_form'] = TRUE; - return \Drupal::service('entity.form_builder')->getForm($entity, 'default', $form_state); -} - -/** - * Populates target values with the source values. - * - * @param \Drupal\Core\Entity\EntityInterface $entity - * The entitiy being translated. - * @param \Drupal\Core\Language\LanguageInterface $source - * The language to be used as source. - * @param \Drupal\Core\Language\LanguageInterface $target - * The language to be used as target. - */ -function content_translation_prepare_translation(EntityInterface $entity, LanguageInterface $source, LanguageInterface $target) { - if ($entity instanceof ContentEntityInterface) { - $source_translation = $entity->getTranslation($source->id); - $entity->addTranslation($target->id, $source_translation->toArray()); - } -} diff --git a/core/modules/content_translation/content_translation.services.yml b/core/modules/content_translation/content_translation.services.yml index da2acb274c47813483cb0b9ad0b159c989eb8c55..8d4740ffde23616afe055221e9d63be0b566611f 100644 --- a/core/modules/content_translation/content_translation.services.yml +++ b/core/modules/content_translation/content_translation.services.yml @@ -17,7 +17,7 @@ services: content_translation.manage_access: class: Drupal\content_translation\Access\ContentTranslationManageAccessCheck - arguments: ['@entity.manager'] + arguments: ['@entity.manager', '@language_manager'] tags: - { name: access_check, applies_to: _access_content_translation_manage } diff --git a/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php b/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php index 137b52e1e3277a3c3b21dfb399d3d076f4bf5f11..116c99290f9c4949087bad4d74fdbddaa34afcbf 100644 --- a/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php +++ b/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php @@ -9,10 +9,11 @@ use Drupal\Core\Entity\EntityManagerInterface; use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Language\LanguageManagerInterface; use Drupal\Core\Routing\Access\AccessInterface; use Drupal\Core\Session\AccountInterface; -use Symfony\Component\Routing\Route; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Route; /** * Access check for entity translation CRUD operation. @@ -26,14 +27,24 @@ class ContentTranslationManageAccessCheck implements AccessInterface { */ protected $entityManager; + /** + * The language manager. + * + * @var \Drupal\Core\Language\LanguageManagerInterface + */ + protected $languageManager; + /** * Constructs a ContentTranslationManageAccessCheck object. * * @param \Drupal\Core\Entity\EntityManagerInterface $manager * The entity type manager. + * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager + * The language manager. */ - public function __construct(EntityManagerInterface $manager) { + public function __construct(EntityManagerInterface $manager, LanguageManagerInterface $language_manager) { $this->entityManager = $manager; + $this->languageManager = $language_manager; } /** @@ -52,39 +63,43 @@ public function __construct(EntityManagerInterface $manager) { * @param string $language * (optional) For an update or delete operation, the language code of the * translation being updated or deleted. + * @param string $entity_type_id + * (optional) The entity type ID. * * @return string * A \Drupal\Core\Access\AccessInterface constant value. */ - public function access(Route $route, Request $request, AccountInterface $account, $source = NULL, $target = NULL, $language = NULL) { - $entity_type = $request->attributes->get('_entity_type_id'); - /** @var $entity \Drupal\Core\Entity\EntityInterface */ - if ($entity = $request->attributes->get($entity_type)) { + public function access(Route $route, Request $request, AccountInterface $account, $source = NULL, $target = NULL, $language = NULL, $entity_type_id = NULL) { + /* @var \Drupal\Core\Entity\ContentEntityInterface $entity */ + if ($entity = $request->attributes->get($entity_type_id)) { + $operation = $route->getRequirement('_access_content_translation_manage'); - $controller = content_translation_controller($entity_type, $account); + + /* @var \Drupal\content_translation\ContentTranslationHandlerInterface $handler */ + $handler = $this->entityManager->getController($entity->getEntityTypeId(), 'translation'); // Load translation. $translations = $entity->getTranslationLanguages(); - $languages = language_list(); + $languages = $this->languageManager->getLanguages(); switch ($operation) { case 'create': - $source = language_load($source) ?: $entity->language(); - $target = language_load($target) ?: \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); - return ($source->id != $target->id - && isset($languages[$source->id]) - && isset($languages[$target->id]) - && !isset($translations[$target->id]) - && $controller->getTranslationAccess($entity, $operation)) + $source_language = $this->languageManager->getLanguage($source) ?: $entity->language(); + $target_language = $this->languageManager->getLanguage($target) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); + return ($source_language->getId() != $target_language->getId() + && isset($languages[$source_language->getId()]) + && isset($languages[$target_language->getId()]) + && !isset($translations[$target_language->getId()]) + && $handler->getTranslationAccess($entity, $operation)) ? static::ALLOW : static::DENY; case 'update': case 'delete': - $language = language_load($language) ?: \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); - return isset($languages[$language->id]) - && $language->id != $entity->getUntranslated()->language()->id - && isset($translations[$language->id]) - && $controller->getTranslationAccess($entity, $operation) + $language = $this->languageManager->getLanguage($language) ?: $this->languageManager->getCurrentLanguage(LanguageInterface::TYPE_CONTENT); + return isset($languages[$language->getId()]) + && $language->getId() != $entity->getUntranslated()->language()->getId() + && isset($translations[$language->getId()]) + && $handler->getTranslationAccess($entity, $operation) ? static::ALLOW : static::DENY; } } diff --git a/core/modules/content_translation/src/Access/ContentTranslationOverviewAccess.php b/core/modules/content_translation/src/Access/ContentTranslationOverviewAccess.php index fabd61b954a8969618559ccd804b1ba4a838b630..5104db7ce96c97b9a1c948b8721c56f16310f578 100644 --- a/core/modules/content_translation/src/Access/ContentTranslationOverviewAccess.php +++ b/core/modules/content_translation/src/Access/ContentTranslationOverviewAccess.php @@ -46,7 +46,7 @@ public function __construct(EntityManagerInterface $manager) { * A \Drupal\Core\Access\AccessInterface constant value. */ public function access(Request $request, AccountInterface $account) { - $entity_type = $request->attributes->get('_entity_type_id'); + $entity_type = $request->attributes->get('entity_type_id'); if ($entity = $request->attributes->get($entity_type)) { // Get entity base info. $bundle = $entity->bundle(); diff --git a/core/modules/content_translation/src/ContentTranslationHandler.php b/core/modules/content_translation/src/ContentTranslationHandler.php index 734ee5d7e55830353544fb6e7ced32511ddba2e5..cba41ae4e60898f72df2a0af38ee3cef64f6dcaf 100644 --- a/core/modules/content_translation/src/ContentTranslationHandler.php +++ b/core/modules/content_translation/src/ContentTranslationHandler.php @@ -201,8 +201,12 @@ public function entityFormAlter(array &$form, FormStateInterface $form_state, En // A new translation is not available in the translation metadata, hence // it should count as one more. $published = $new_translation; - foreach ($entity->translation as $translation) { - $published += $translation['status']; + // When creating a brand new translation, $entity->translation is not + // set. + if (!$new_translation) { + foreach ($entity->translation as $translation) { + $published += $translation['status']; + } } $enabled = $published > 1; } @@ -467,7 +471,7 @@ function entityFormDeleteTranslation($form, FormStateInterface $form_state) { $form_controller = content_translation_form_controller($form_state); $entity = $form_controller->getEntity(); $entity_type_id = $entity->getEntityTypeId(); - $form_state->setRedirect('content_translation.delete_' . $entity_type_id, array( + $form_state->setRedirect('content_translation.translation_delete_' . $entity_type_id, array( $entity_type_id => $entity->id(), 'language' => $form_controller->getFormLangcode($form_state), )); diff --git a/core/modules/content_translation/src/Controller/ContentTranslationController.php b/core/modules/content_translation/src/Controller/ContentTranslationController.php index 31a33d2eb51d553c25c0b335da24803af5a8ec24..8d5a306253d38b4d7f491d5c3ab0fbf4c87252ac 100644 --- a/core/modules/content_translation/src/Controller/ContentTranslationController.php +++ b/core/modules/content_translation/src/Controller/ContentTranslationController.php @@ -7,41 +7,288 @@ namespace Drupal\content_translation\Controller; +use Drupal\Core\Controller\ControllerBase; +use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\Url; use Symfony\Component\HttpFoundation\Request; /** * Base class for entity translation controllers. */ -class ContentTranslationController { +class ContentTranslationController extends ControllerBase { /** - * @todo Remove content_translation_overview(). + * Populates target values with the source values. + * + * @param \Drupal\Core\Entity\ContentEntityInterface $entity + * The entity being translated. + * @param \Drupal\Core\Language\LanguageInterface $source + * The language to be used as source. + * @param \Drupal\Core\Language\LanguageInterface $target + * The language to be used as target. */ - public function overview(Request $request) { - $entity = $request->attributes->get($request->attributes->get('_entity_type_id')); - module_load_include('pages.inc', 'content_translation'); - return content_translation_overview($entity); + public function prepareTranslation(ContentEntityInterface $entity, LanguageInterface $source, LanguageInterface $target) { + /* @var \Drupal\Core\Entity\ContentEntityInterface $source_translation */ + $source_translation = $entity->getTranslation($source->getId()); + $entity->addTranslation($target->getId(), $source_translation->toArray()); } /** - * @todo Remove content_translation_add_page(). + * Builds the translations overview page. + * + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object from which to extract the entity type. + * @param string $entity_type_id + * (optional) The entity type ID. + * + * @return array + * Array of page elements to render. */ - public function add(Request $request, $source, $target) { - $entity = $request->attributes->get($request->attributes->get('_entity_type_id')); - module_load_include('pages.inc', 'content_translation'); - $source = language_load($source); - $target = language_load($target); - return content_translation_add_page($entity, $source, $target); + public function overview(Request $request, $entity_type_id = NULL) { + $entity = $request->attributes->get($entity_type_id); + $account = $this->currentUser(); + $handler = $this->entityManager()->getController($entity_type_id, 'translation'); + + $languages = $this->languageManager()->getLanguages(); + $original = $entity->getUntranslated()->language()->getId(); + $translations = $entity->getTranslationLanguages(); + $field_ui = $this->moduleHandler()->moduleExists('field_ui') && $account->hasPermission('administer ' . $entity_type_id . ' fields'); + + $rows = array(); + $show_source_column = FALSE; + + if ($this->languageManager()->isMultilingual()) { + // Determine whether the current entity is translatable. + $translatable = FALSE; + foreach ($this->entityManager->getFieldDefinitions($entity_type_id, $entity->bundle()) as $instance) { + if ($instance->isTranslatable()) { + $translatable = TRUE; + break; + } + } + + // Show source-language column if there are non-original source langcodes. + $additional_source_langcodes = array_filter($entity->translation, function ($translation) use ($original) { + return !empty($translation['source']) && $translation['source'] != $original; + }); + $show_source_column = !empty($additional_source_langcodes); + + foreach ($languages as $language) { + $language_name = $language->name; + $langcode = $language->getId(); + + $add_url = new Url( + 'content_translation.translation_add_' . $entity_type_id, + array( + 'source' => $original, + 'target' => $language->getId(), + $entity_type_id => $entity->id(), + ) + ); + $edit_url = new Url( + 'content_translation.translation_edit_' . $entity_type_id, + array( + 'language' => $language->getId(), + $entity_type_id => $entity->id(), + ) + ); + $delete_url = new Url( + 'content_translation.translation_delete_' . $entity_type_id, + array( + 'language' => $language->getId(), + $entity_type_id => $entity->id(), + ) + ); + $operations = array( + 'data' => array( + '#type' => 'operations', + '#links' => array(), + ), + ); + + $links = &$operations['data']['#links']; + if (array_key_exists($langcode, $translations)) { + // Existing translation in the translation set: display status. + $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' => $entity->getSystemPath()); + $row_title = l($label, $link['href'], $link); + + if (empty($link['href'])) { + $row_title = $is_original ? $label : $this->t('n/a'); + } + + // 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 ($entity->access('update')) { + $links['edit'] = array( + 'href' => $entity->getSystemPath('edit-form'), + ); + } + elseif (!$is_original && $handler->getTranslationAccess($entity, 'update')) { + $links['edit'] = $edit_url->toArray(); + } + + if (isset($links['edit'])) { + $links['edit']['title'] = $this->t('Edit'); + } + $translation = $entity->translation[$langcode]; + $status = !empty($translation['status']) ? $this->t('Published') : $this->t('Not published'); + // @todo Remove as part of https://drupal.org/node/2250841. + $status = '' . $status . '' . (!empty($translation['outdated']) ? ' ' . $this->t('outdated') . '' : ''); + + if ($is_original) { + $language_name = $this->t('@language_name (Original language)', array('@language_name' => $language_name)); + $source_name = $this->t('n/a'); + } + else { + $source_name = isset($languages[$source]) ? $languages[$source]->name : $this->t('n/a'); + if ($handler->getTranslationAccess($entity, 'delete')) { + $links['delete'] = array( + 'title' => $this->t('Delete'), + ) + $delete_url->toArray(); + } + } + } + else { + // No such translation in the set yet: help user to create it. + $row_title = $source_name = $this->t('n/a'); + $source = $entity->language()->getId(); + + if ($source != $langcode && $handler->getTranslationAccess($entity, 'create')) { + if ($translatable) { + $links['add'] = array( + 'title' => $this->t('Add'), + ) + $add_url->toArray(); + } + elseif ($field_ui) { + $url = new Url('language.content_settings_page'); + + // Link directly to the fields tab to make it easier to find the + // setting to enable translation on fields. + $links['nofields'] = array( + 'title' => $this->t('No translatable fields'), + ) + $url->toArray(); + } + } + + $status = $this->t('Not translated'); + } + if ($show_source_column) { + $rows[] = array( + $language_name, + $row_title, + $source_name, + $status, + $operations, + ); + } + else { + $rows[] = array($language_name, $row_title, $status, $operations); + } + } + } + if ($show_source_column) { + $header = array( + $this->t('Language'), + $this->t('Translation'), + $this->t('Source language'), + $this->t('Status'), + $this->t('Operations'), + ); + } + else { + $header = array( + $this->t('Language'), + $this->t('Translation'), + $this->t('Status'), + $this->t('Operations'), + ); + } + + $build['#title'] = $this->t('Translations of %label', array('%label' => $entity->label())); + + // Add metadata to the build render array to let other modules know about + // which entity this is. + $build['#entity'] = $entity; + + $build['content_translation_overview'] = array( + '#theme' => 'table', + '#header' => $header, + '#rows' => $rows, + ); + + return $build; + } + + /** + * Builds an add translation page. + * + * @param \Drupal\Core\Language\LanguageInterface $source + * The language of the values being translated. Defaults to the entity + * language. + * @param \Drupal\Core\Language\LanguageInterface $target + * The language of the translated values. Defaults to the current content + * language. + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object from which to extract the entity type. + * @param string $entity_type_id + * (optional) The entity type ID. + * + * @return array + * A processed form array ready to be rendered. + */ + public function add(LanguageInterface $source, LanguageInterface $target, Request $request, $entity_type_id = NULL) { + $entity = $request->attributes->get($entity_type_id); + + // @todo Exploit the upcoming hook_entity_prepare() when available. + // See https://www.drupal.org/node/1810394. + $this->prepareTranslation($entity, $source, $target); + + // @todo Provide a way to figure out the default form operation. Maybe like + // $operation = isset($info['default_operation']) ? $info['default_operation'] : 'default'; + // See https://www.drupal.org/node/2006348. + $operation = 'default'; + + $form_state_additions = array(); + $form_state_additions['langcode'] = $target->getId(); + $form_state_additions['content_translation']['source'] = $source; + $form_state_additions['content_translation']['target'] = $target; + $form_state_additions['content_translation']['translation_form'] = !$entity->access('update'); + + return $this->entityFormBuilder()->getForm($entity, $operation, $form_state_additions); } /** - * @todo Remove content_translation_edit_page(). + * Builds the edit translation page. + * + * @param \Drupal\Core\Language\LanguageInterface $language + * The language of the translated values. Defaults to the current content + * language. + * @param \Symfony\Component\HttpFoundation\Request $request + * The request object from which to extract the entity type. + * @param string $entity_type_id + * (optional) The entity type ID. + * + * @return array + * A processed form array ready to be rendered. */ - public function edit(Request $request, $language) { - $entity = $request->attributes->get($request->attributes->get('_entity_type_id')); - module_load_include('pages.inc', 'content_translation'); - $language = language_load($language); - return content_translation_edit_page($entity, $language); + public function edit(LanguageInterface $language, Request $request, $entity_type_id = NULL) { + $entity = $request->attributes->get($entity_type_id); + + // @todo Provide a way to figure out the default form operation. Maybe like + // $operation = isset($info['default_operation']) ? $info['default_operation'] : 'default'; + // See https://www.drupal.org/node/2006348. + $operation = 'default'; + + $form_state_additions = array(); + $form_state_additions['langcode'] = $language->getId(); + $form_state_additions['content_translation']['translation_form'] = TRUE; + + return $this->entityFormBuilder()->getForm($entity, $operation, $form_state_additions); } } diff --git a/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php b/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php index c27b5e8dd98200a41f333d433caa68f4580ac1ee..1b723ce761ec8da23d86b3fe0b002e6e33c77003 100644 --- a/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php +++ b/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php @@ -40,8 +40,8 @@ public function getFormId() { /** * {@inheritdoc} */ - public function buildForm(array $form, FormStateInterface $form_state, $_entity_type_id = NULL, $language = NULL) { - $this->entity = $this->getRequest()->attributes->get($_entity_type_id); + public function buildForm(array $form, FormStateInterface $form_state, $entity_type_id = NULL, $language = NULL) { + $this->entity = $this->getRequest()->attributes->get($entity_type_id); $this->language = language_load($language); return parent::buildForm($form, $form_state); } diff --git a/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php b/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php index d46b8d63db5deaf1f49bf85f93137fb5169f4ea6..b5124ef2f371a9a2091931e33e5bf73f213ac665 100644 --- a/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php +++ b/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php @@ -57,7 +57,7 @@ protected function alterRoutes(RouteCollection $collection) { $path, array( '_content' => '\Drupal\content_translation\Controller\ContentTranslationController::overview', - '_entity_type_id' => $entity_type_id, + 'entity_type_id' => $entity_type_id, ), array( '_access_content_translation_overview' => $entity_type_id, @@ -66,9 +66,6 @@ protected function alterRoutes(RouteCollection $collection) { array( '_access_mode' => AccessManagerInterface::ACCESS_MODE_ANY, 'parameters' => array( - 'entity' => array( - 'type' => 'entity:' . $entity_type_id, - ), $entity_type_id => array( 'type' => 'entity:' . $entity_type_id, ), @@ -85,7 +82,7 @@ protected function alterRoutes(RouteCollection $collection) { 'source' => NULL, 'target' => NULL, '_title' => 'Add', - '_entity_type_id' => $entity_type_id, + 'entity_type_id' => $entity_type_id, ), array( @@ -95,8 +92,11 @@ protected function alterRoutes(RouteCollection $collection) { array( '_access_mode' => AccessManagerInterface::ACCESS_MODE_ANY, 'parameters' => array( - 'entity' => array( - 'type' => 'entity:' . $entity_type_id, + 'source' => array( + 'type' => 'language', + ), + 'target' => array( + 'type' => 'language', ), $entity_type_id => array( 'type' => 'entity:' . $entity_type_id, @@ -113,7 +113,7 @@ protected function alterRoutes(RouteCollection $collection) { '_content' => '\Drupal\content_translation\Controller\ContentTranslationController::edit', 'language' => NULL, '_title' => 'Edit', - '_entity_type_id' => $entity_type_id, + 'entity_type_id' => $entity_type_id, ), array( '_permission' => 'translate any entity', @@ -122,8 +122,8 @@ protected function alterRoutes(RouteCollection $collection) { array( '_access_mode' => AccessManagerInterface::ACCESS_MODE_ANY, 'parameters' => array( - 'entity' => array( - 'type' => 'entity:' . $entity_type_id, + 'language' => array( + 'type' => 'language', ), $entity_type_id => array( 'type' => 'entity:' . $entity_type_id, @@ -140,7 +140,7 @@ protected function alterRoutes(RouteCollection $collection) { '_form' => '\Drupal\content_translation\Form\ContentTranslationDeleteForm', 'language' => NULL, '_title' => 'Delete', - '_entity_type_id' => $entity_type_id, + 'entity_type_id' => $entity_type_id, ), array( '_permission' => 'translate any entity', @@ -148,8 +148,8 @@ protected function alterRoutes(RouteCollection $collection) { ), array( 'parameters' => array( - 'entity' => array( - 'type' => 'entity:' . $entity_type_id, + 'language' => array( + 'type' => 'language', ), $entity_type_id => array( 'type' => 'entity:' . $entity_type_id, @@ -159,7 +159,7 @@ protected function alterRoutes(RouteCollection $collection) { '_admin_route' => $is_admin, ) ); - $collection->add("content_translation.delete_$entity_type_id", $route); + $collection->add("content_translation.translation_delete_$entity_type_id", $route); } } diff --git a/core/modules/content_translation/tests/src/Access/ContentTranslationManageAccessCheckTest.php b/core/modules/content_translation/tests/src/Access/ContentTranslationManageAccessCheckTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cc6d15e93aa499e7f9d94c0ee50c1bb0904896f6 --- /dev/null +++ b/core/modules/content_translation/tests/src/Access/ContentTranslationManageAccessCheckTest.php @@ -0,0 +1,94 @@ +getMock('\Drupal\content_translation\ContentTranslationHandlerInterface'); + $translation_handler->expects($this->once()) + ->method('getTranslationAccess') + ->will($this->returnValue(TRUE)); + + $entity_manager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface'); + $entity_manager->expects($this->once()) + ->method('getController') + ->withAnyParameters() + ->will($this->returnValue($translation_handler)); + + // Set our source and target languages. + $source = 'en'; + $target = 'it'; + + // Set the mock language manager. + $language_manager = $this->getMock('Drupal\Core\Language\LanguageManagerInterface'); + $language_manager->expects($this->at(0)) + ->method('getLanguages') + ->will($this->returnValue(array('en' => array(), 'it' => array()))); + $language_manager->expects($this->at(1)) + ->method('getLanguage') + ->with($this->equalTo($source)) + ->will($this->returnValue(new Language(array('id' => 'en')))); + $language_manager->expects($this->at(2)) + ->method('getLanguage') + ->with($this->equalTo($target)) + ->will($this->returnValue(new Language(array('id' => 'it')))); + + // Set the mock entity. We need to use ContentEntityBase for mocking due to + // issues with phpunit and multiple interfaces. + $entity = $this->getMockBuilder('Drupal\Core\Entity\ContentEntityBase') + ->disableOriginalConstructor() + ->getMock(); + $entity->expects($this->once()) + ->method('getEntityTypeId'); + $entity->expects($this->once()) + ->method('getTranslationLanguages') + ->with() + ->will($this->returnValue(array())); + + // Set the route requirements. + $route = new Route('test_route'); + $route->setRequirement('_access_content_translation_manage', 'create'); + + // Set the request attributes. + $request = Request::create('node/1'); + $request->attributes->set('node', $entity); + + // Set the mock account. + $account = $this->getMock('Drupal\Core\Session\AccountInterface'); + + // The access check under test. + $check = new ContentTranslationManageAccessCheck($entity_manager, $language_manager); + + // The request params. + $language = 'en'; + $entity_type_id = 'node'; + + $this->assertEquals($check->access($route, $request, $account, $source, $target, $language, $entity_type_id), AccessInterface::ALLOW, "The access check matches"); + } + +} diff --git a/core/modules/language/language.services.yml b/core/modules/language/language.services.yml index 9b5b2f474c7b2e052bd45ac36431581bee3721ef..1eeb59773232b70fde669d0f8365d0ca643dbb5e 100644 --- a/core/modules/language/language.services.yml +++ b/core/modules/language/language.services.yml @@ -17,3 +17,8 @@ services: tags: - { name: config.factory.override, priority: -254 } - { name: event_subscriber } + language_converter: + class: Drupal\language\LanguageConverter + arguments: ['@language_manager'] + tags: + - { name: paramconverter } diff --git a/core/modules/language/src/LanguageConverter.php b/core/modules/language/src/LanguageConverter.php new file mode 100644 index 0000000000000000000000000000000000000000..0bcc265ee7541798b94055dc6b49e8d949d0fb5e --- /dev/null +++ b/core/modules/language/src/LanguageConverter.php @@ -0,0 +1,54 @@ +languageManager = $language_manager; + } + + /** + * {@inheritdoc} + */ + public function convert($value, $definition, $name, array $defaults, Request $request) { + if (!empty($value)) { + return $this->languageManager->getLanguage($value); + } + return NULL; + } + + /** + * {@inheritdoc} + */ + public function applies($definition, $name, Route $route) { + return (!empty($definition['type']) && $definition['type'] == 'language'); + } + +}