summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex Pott2014-08-20 14:05:31 (GMT)
committerAlex Pott2014-08-20 14:40:29 (GMT)
commit77c666c39ac2e5d1e81b42f50b0d00406288d85c (patch)
tree116dd30620c6f339a0b2a902e6d33a190e08832d
parentf485925f181b82c73e7a7614364d22cb4e580e98 (diff)
Issue #1987882 by disasm, vijaycs85, penyaskito, kim.pepper, likin, YesCT, InternetDevels, dawehner, wamilton, Letharion, katbailey, googletorp, tim.plunkett, acrollet, neetu morwani: Convert content_translation routes to a new style controller.
-rw-r--r--core/modules/content_translation/content_translation.pages.inc251
-rw-r--r--core/modules/content_translation/content_translation.services.yml2
-rw-r--r--core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php55
-rw-r--r--core/modules/content_translation/src/Access/ContentTranslationOverviewAccess.php2
-rw-r--r--core/modules/content_translation/src/ContentTranslationHandler.php10
-rw-r--r--core/modules/content_translation/src/Controller/ContentTranslationController.php285
-rw-r--r--core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php4
-rw-r--r--core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php28
-rw-r--r--core/modules/content_translation/tests/src/Access/ContentTranslationManageAccessCheckTest.php94
-rw-r--r--core/modules/language/language.services.yml5
-rw-r--r--core/modules/language/src/LanguageConverter.php54
11 files changed, 479 insertions, 311 deletions
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 9898678..0000000
--- a/core/modules/content_translation/content_translation.pages.inc
+++ /dev/null
@@ -1,251 +0,0 @@
-<?php
-
-/**
- * @file
- * The content translation user interface.
- */
-
-use Drupal\Core\Language\LanguageInterface;
-use Drupal\Core\Entity\EntityInterface;
-use Drupal\Core\Entity\ContentEntityInterface;
-
-/**
- * Translations overview page callback.
- *
- * @param \Drupal\Core\Entity\EntityInterface $entity
- * The entity whose translation overview should be displayed.
- *
- * @deprecated in Drupal 8.x-dev, will be removed before Drupal 8.0.
- * Use \Drupal\content_translation\Controller\ContentTranslationController::overview().
- */
-function content_translation_overview(EntityInterface $entity) {
- $controller = content_translation_controller($entity->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 = '<span class="status">' . $status . '</span>' . (!empty($translation['outdated']) ? ' <span class="marker">' . t('outdated') . '</span>' : '');
-
- if ($is_original) {
- $language_name = t('<strong>@language_name (Original language)</strong>', 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 da2acb2..8d4740f 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 137b52e..116c992 100644
--- a/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php
+++ b/core/modules/content_translation/src/Access/ContentTranslationManageAccessCheck.php
@@ -9,10 +9,11 @@ namespace Drupal\content_translation\Access;
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.
@@ -27,13 +28,23 @@ 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 @@ class ContentTranslationManageAccessCheck implements AccessInterface {
* @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 fabd61b..5104db7 100644
--- a/core/modules/content_translation/src/Access/ContentTranslationOverviewAccess.php
+++ b/core/modules/content_translation/src/Access/ContentTranslationOverviewAccess.php
@@ -46,7 +46,7 @@ class ContentTranslationOverviewAccess implements AccessInterface {
* 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 734ee5d..cba41ae 100644
--- a/core/modules/content_translation/src/ContentTranslationHandler.php
+++ b/core/modules/content_translation/src/ContentTranslationHandler.php
@@ -201,8 +201,12 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface {
// 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 @@ class ContentTranslationHandler implements ContentTranslationHandlerInterface {
$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 31a33d2..8d5a306 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 = '<span class="status">' . $status . '</span>' . (!empty($translation['outdated']) ? ' <span class="marker">' . $this->t('outdated') . '</span>' : '');
+
+ if ($is_original) {
+ $language_name = $this->t('<strong>@language_name (Original language)</strong>', 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 c27b5e8..1b723ce 100644
--- a/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php
+++ b/core/modules/content_translation/src/Form/ContentTranslationDeleteForm.php
@@ -40,8 +40,8 @@ class ContentTranslationDeleteForm extends ConfirmFormBase {
/**
* {@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 d46b8d6..b5124ef 100644
--- a/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php
+++ b/core/modules/content_translation/src/Routing/ContentTranslationRouteSubscriber.php
@@ -57,7 +57,7 @@ class ContentTranslationRouteSubscriber extends RouteSubscriberBase {
$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 @@ class ContentTranslationRouteSubscriber extends RouteSubscriberBase {
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 @@ class ContentTranslationRouteSubscriber extends RouteSubscriberBase {
'source' => NULL,
'target' => NULL,
'_title' => 'Add',
- '_entity_type_id' => $entity_type_id,
+ 'entity_type_id' => $entity_type_id,
),
array(
@@ -95,8 +92,11 @@ class ContentTranslationRouteSubscriber extends RouteSubscriberBase {
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 @@ class ContentTranslationRouteSubscriber extends RouteSubscriberBase {
'_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 @@ class ContentTranslationRouteSubscriber extends RouteSubscriberBase {
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 @@ class ContentTranslationRouteSubscriber extends RouteSubscriberBase {
'_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 @@ class ContentTranslationRouteSubscriber extends RouteSubscriberBase {
),
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 @@ class ContentTranslationRouteSubscriber extends RouteSubscriberBase {
'_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 0000000..cc6d15e
--- /dev/null
+++ b/core/modules/content_translation/tests/src/Access/ContentTranslationManageAccessCheckTest.php
@@ -0,0 +1,94 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\content_translation\Tests\Access\ContentTranslationManageAccessCheckTest.
+ */
+
+namespace Drupal\content_translation\Tests\Access;
+
+use Drupal\content_translation\Access\ContentTranslationManageAccessCheck;
+use Drupal\Core\Access\AccessInterface;
+use Drupal\Core\Language\Language;
+use Drupal\Tests\UnitTestCase;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Tests for content translation manage check.
+ *
+ * @coversDefaultClass \Drupal\content_translation\Access\ContentTranslationManageAccessCheck
+ * @group content_translation
+ */
+class ContentTranslationManageAccessCheckTest extends UnitTestCase {
+
+ /**
+ * Tests the create access method.
+ *
+ * @covers ::access()
+ */
+ public function testCreateAccess() {
+ // Set the mock translation handler.
+ $translation_handler = $this->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 9b5b2f4..1eeb597 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 0000000..0bcc265
--- /dev/null
+++ b/core/modules/language/src/LanguageConverter.php
@@ -0,0 +1,54 @@
+<?php
+
+/**
+ * @file
+ * Contains \Drupal\language\LanguageConverter.
+ */
+
+namespace Drupal\language;
+
+use Drupal\Core\Language\LanguageManagerInterface;
+use Drupal\Core\ParamConverter\ParamConverterInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\Routing\Route;
+
+/**
+ * Converts parameters for upcasting entity IDs to full objects.
+ */
+class LanguageConverter implements ParamConverterInterface {
+
+ /**
+ * The language manager.
+ *
+ * @var \Drupal\Core\Language\LanguageManagerInterface
+ */
+ protected $languageManager;
+
+ /**
+ * Constructs a new LanguageConverter.
+ *
+ * @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
+ * The language manager.
+ */
+ public function __construct(LanguageManagerInterface $language_manager) {
+ $this->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');
+ }
+
+}