Revert "Issue #2595535 by tstoeckler, swentel, vijaycs85, alvar0hurtad0,
esolitos: Show helpful message (do not fatal!) when configuration files
have different source language codes and cannot be translated"uthor:
Nathaniel
This reverts commit ef3700fa23
.
8.2.x
parent
ef3700fa23
commit
7bbcc3ee67
|
@ -2,8 +2,6 @@
|
|||
|
||||
namespace Drupal\config_translation\Access;
|
||||
|
||||
use Drupal\config_translation\ConfigMapperInterface;
|
||||
use Drupal\config_translation\Exception\ConfigMapperLanguageException;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
@ -14,68 +12,27 @@ use Drupal\Core\Session\AccountInterface;
|
|||
class ConfigTranslationFormAccess extends ConfigTranslationOverviewAccess {
|
||||
|
||||
/**
|
||||
* Checks access to the overview based on permissions and translatability.
|
||||
*
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The route_match to check against.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The account to check access for.
|
||||
* @param string $langcode
|
||||
* The language code of the target language.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function access(RouteMatchInterface $route_match, AccountInterface $account, $langcode = NULL) {
|
||||
$mapper = $this->getMapperFromRouteMatch($route_match);
|
||||
|
||||
try {
|
||||
$source_langcode = $mapper->getLangcode();
|
||||
$source_language = $this->languageManager->getLanguage($source_langcode);
|
||||
|
||||
// For the translation forms we have a target language, so we need some
|
||||
// checks in addition to the checks performed for the translation overview.
|
||||
$base_access = parent::access($route_match, $account);
|
||||
if ($base_access->isAllowed()) {
|
||||
$target_language = $this->languageManager->getLanguage($langcode);
|
||||
|
||||
return $this->doCheckAccess($account, $mapper, $source_language, $target_language);
|
||||
// Make sure that the target language is not locked, and that the target
|
||||
// language is not the original submission language. Although technically
|
||||
// configuration can be overlaid with translations in the same language,
|
||||
// that is logically not a good idea.
|
||||
$access =
|
||||
!empty($target_language) &&
|
||||
!$target_language->isLocked() &&
|
||||
(empty($this->sourceLanguage) || ($target_language->getId() != $this->sourceLanguage->getId()));
|
||||
|
||||
return $base_access->andIf(AccessResult::allowedIf($access));
|
||||
}
|
||||
catch (ConfigMapperLanguageException $exception) {
|
||||
return AccessResult::forbidden();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks access given an account, configuration mapper, and source language.
|
||||
*
|
||||
* In addition to the checks performed by
|
||||
* ConfigTranslationOverviewAccess::doCheckAccess() this makes sure the target
|
||||
* language is not locked and the target language is not the source language.
|
||||
*
|
||||
* Although technically configuration can be overlaid with translations in the
|
||||
* same language, that is logically not a good idea.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The account to check access for.
|
||||
* @param \Drupal\config_translation\ConfigMapperInterface $mapper
|
||||
* The configuration mapper to check access for.
|
||||
* @param \Drupal\Core\Language\LanguageInterface|null $source_language
|
||||
* The source language to check for, if any.
|
||||
* @param \Drupal\Core\Language\LanguageInterface|null $target_language
|
||||
* The target language to check for, if any.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The result of the access check.
|
||||
*
|
||||
* @see \Drupal\config_translation\Access\ConfigTranslationOverviewAccess::doCheckAccess()
|
||||
*/
|
||||
protected function doCheckAccess(AccountInterface $account, ConfigMapperInterface $mapper, $source_language = NULL, $target_language = NULL) {
|
||||
$base_access_result = parent::doCheckAccess($account, $mapper, $source_language);
|
||||
|
||||
$access =
|
||||
$target_language &&
|
||||
!$target_language->isLocked() &&
|
||||
(!$source_language || ($target_language->getId() !== $source_language->getId()));
|
||||
|
||||
return $base_access_result->andIf(AccessResult::allowedIf($access));
|
||||
|
||||
return $base_access;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
namespace Drupal\config_translation\Access;
|
||||
|
||||
use Drupal\config_translation\ConfigMapperInterface;
|
||||
use Drupal\config_translation\Exception\ConfigMapperLanguageException;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\config_translation\ConfigMapperManagerInterface;
|
||||
use Drupal\Core\Access\AccessResult;
|
||||
use Drupal\Core\Routing\Access\AccessInterface;
|
||||
|
@ -29,6 +28,13 @@ class ConfigTranslationOverviewAccess implements AccessInterface {
|
|||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The source language.
|
||||
*
|
||||
* @var \Drupal\Core\Language\LanguageInterface
|
||||
*/
|
||||
protected $sourceLanguage;
|
||||
|
||||
/**
|
||||
* Constructs a ConfigTranslationOverviewAccess object.
|
||||
*
|
||||
|
@ -48,66 +54,28 @@ class ConfigTranslationOverviewAccess implements AccessInterface {
|
|||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The route_match to check against.
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The account to check access for.
|
||||
* The currently logged in account.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The access result.
|
||||
*/
|
||||
public function access(RouteMatchInterface $route_match, AccountInterface $account) {
|
||||
$mapper = $this->getMapperFromRouteMatch($route_match);
|
||||
$route = $route_match->getRouteObject();
|
||||
|
||||
try {
|
||||
$langcode = $mapper->getLangcode();
|
||||
}
|
||||
catch (ConfigMapperLanguageException $exception) {
|
||||
// ConfigTranslationController shows a helpful message if the language
|
||||
// codes do not match, so do not let that prevent granting access.
|
||||
$langcode = 'en';
|
||||
}
|
||||
$source_language = $this->languageManager->getLanguage($langcode);
|
||||
|
||||
return $this->doCheckAccess($account, $mapper, $source_language);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a configuration mapper using a route match.
|
||||
*
|
||||
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
|
||||
* The route match to populate the mapper with.
|
||||
*
|
||||
* @return \Drupal\config_translation\ConfigMapperInterface
|
||||
* The configuration mapper.
|
||||
*/
|
||||
protected function getMapperFromRouteMatch(RouteMatchInterface $route_match) {
|
||||
$mapper = $this->configMapperManager->createInstance($route_match->getRouteObject()
|
||||
->getDefault('plugin_id'));
|
||||
/** @var \Drupal\config_translation\ConfigMapperInterface $mapper */
|
||||
$mapper = $this->configMapperManager->createInstance($route->getDefault('plugin_id'));
|
||||
$mapper->populateFromRouteMatch($route_match);
|
||||
return $mapper;
|
||||
}
|
||||
$this->sourceLanguage = $this->languageManager->getLanguage($mapper->getLangcode());
|
||||
|
||||
/**
|
||||
* Checks access given an account, configuration mapper, and source language.
|
||||
*
|
||||
* Grants access if the proper permission is granted to the account, the
|
||||
* configuration has translatable pieces, and the source language is not
|
||||
* locked given it is present.
|
||||
*
|
||||
* @param \Drupal\Core\Session\AccountInterface $account
|
||||
* The account to check access for.
|
||||
* @param \Drupal\config_translation\ConfigMapperInterface $mapper
|
||||
* The configuration mapper to check access for.
|
||||
* @param \Drupal\Core\Language\LanguageInterface|null $source_language
|
||||
* The source language to check for, if any.
|
||||
*
|
||||
* @return \Drupal\Core\Access\AccessResultInterface
|
||||
* The result of the access check.
|
||||
*/
|
||||
protected function doCheckAccess(AccountInterface $account, ConfigMapperInterface $mapper, $source_language = NULL) {
|
||||
// Allow access to the translation overview if the proper permission is
|
||||
// granted, the configuration has translatable pieces, and the source
|
||||
// language is not locked if it is present.
|
||||
$source_language_access = is_null($this->sourceLanguage) || !$this->sourceLanguage->isLocked();
|
||||
$access =
|
||||
$account->hasPermission('translate configuration') &&
|
||||
$mapper->hasSchema() &&
|
||||
$mapper->hasTranslatable() &&
|
||||
(!$source_language || !$source_language->isLocked());
|
||||
$source_language_access;
|
||||
|
||||
return AccessResult::allowedIf($access)->cachePerPermissions();
|
||||
}
|
||||
|
|
|
@ -202,17 +202,6 @@ interface ConfigMapperInterface {
|
|||
*/
|
||||
public function getLangcode();
|
||||
|
||||
/**
|
||||
* Returns the language code of a configuration object given its name.
|
||||
*
|
||||
* @param string $config_name
|
||||
* The name of the configuration object.
|
||||
*
|
||||
* @return string
|
||||
* The language code of the configuration object.
|
||||
*/
|
||||
public function getLangcodeFromConfig($config_name);
|
||||
|
||||
/**
|
||||
* Sets the original language code.
|
||||
*
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
namespace Drupal\config_translation;
|
||||
|
||||
use Drupal\config_translation\Exception\ConfigMapperLanguageException;
|
||||
use Drupal\Core\Config\ConfigFactoryInterface;
|
||||
use Drupal\Core\Config\TypedConfigManagerInterface;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
|
@ -381,26 +380,22 @@ class ConfigNamesMapper extends PluginBase implements ConfigMapperInterface, Con
|
|||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLangcode() {
|
||||
$langcodes = array_map([$this, 'getLangcodeFromConfig'], $this->getConfigNames());
|
||||
$config_factory = $this->configFactory;
|
||||
$langcodes = array_map(function($name) use ($config_factory) {
|
||||
// Default to English if no language code was provided in the file.
|
||||
// Although it is a best practice to include a language code, if the
|
||||
// developer did not think about a multilingual use-case, we fall back
|
||||
// on assuming the file is English.
|
||||
return $config_factory->get($name)->get('langcode') ?: 'en';
|
||||
}, $this->getConfigNames());
|
||||
|
||||
if (count(array_unique($langcodes)) > 1) {
|
||||
throw new ConfigMapperLanguageException('A config mapper can only contain configuration for a single language.');
|
||||
throw new \RuntimeException('A config mapper can only contain configuration for a single language.');
|
||||
}
|
||||
|
||||
return reset($langcodes);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getLangcodeFromConfig($config_name) {
|
||||
// Default to English if no language code was provided in the file.
|
||||
// Although it is a best practice to include a language code, if the
|
||||
// developer did not think about a multilingual use case, we fall back
|
||||
// on assuming the file is English.
|
||||
return $this->configFactory->get($config_name)->get('langcode') ?: 'en';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
|
|
@ -3,14 +3,11 @@
|
|||
namespace Drupal\config_translation\Controller;
|
||||
|
||||
use Drupal\config_translation\ConfigMapperManagerInterface;
|
||||
use Drupal\config_translation\Exception\ConfigMapperLanguageException;
|
||||
use Drupal\Core\Access\AccessManagerInterface;
|
||||
use Drupal\Core\Controller\ControllerBase;
|
||||
use Drupal\Core\Language\Language;
|
||||
use Drupal\Core\Language\LanguageInterface;
|
||||
use Drupal\Core\Language\LanguageManagerInterface;
|
||||
use Drupal\Core\PathProcessor\InboundPathProcessorInterface;
|
||||
use Drupal\Core\Render\RendererInterface;
|
||||
use Drupal\Core\Routing\RouteMatch;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Session\AccountInterface;
|
||||
|
@ -66,13 +63,6 @@ class ConfigTranslationController extends ControllerBase {
|
|||
*/
|
||||
protected $languageManager;
|
||||
|
||||
/**
|
||||
* The renderer.
|
||||
*
|
||||
* @var \Drupal\Core\Render\RendererInterface
|
||||
*/
|
||||
protected $renderer;
|
||||
|
||||
/**
|
||||
* Constructs a ConfigTranslationController.
|
||||
*
|
||||
|
@ -88,17 +78,14 @@ class ConfigTranslationController extends ControllerBase {
|
|||
* The current user.
|
||||
* @param \Drupal\Core\Language\LanguageManagerInterface $language_manager
|
||||
* The language manager.
|
||||
* @param \Drupal\Core\Render\RendererInterface $renderer
|
||||
* The renderer.
|
||||
*/
|
||||
public function __construct(ConfigMapperManagerInterface $config_mapper_manager, AccessManagerInterface $access_manager, RequestMatcherInterface $router, InboundPathProcessorInterface $path_processor, AccountInterface $account, LanguageManagerInterface $language_manager, RendererInterface $renderer) {
|
||||
public function __construct(ConfigMapperManagerInterface $config_mapper_manager, AccessManagerInterface $access_manager, RequestMatcherInterface $router, InboundPathProcessorInterface $path_processor, AccountInterface $account, LanguageManagerInterface $language_manager) {
|
||||
$this->configMapperManager = $config_mapper_manager;
|
||||
$this->accessManager = $access_manager;
|
||||
$this->router = $router;
|
||||
$this->pathProcessor = $path_processor;
|
||||
$this->account = $account;
|
||||
$this->languageManager = $language_manager;
|
||||
$this->renderer = $renderer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -111,8 +98,7 @@ class ConfigTranslationController extends ControllerBase {
|
|||
$container->get('router'),
|
||||
$container->get('path_processor_manager'),
|
||||
$container->get('current_user'),
|
||||
$container->get('language_manager'),
|
||||
$container->get('renderer')
|
||||
$container->get('language_manager')
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -141,33 +127,7 @@ class ConfigTranslationController extends ControllerBase {
|
|||
if (count($languages) == 1) {
|
||||
drupal_set_message($this->t('In order to translate configuration, the website must have at least two <a href=":url">languages</a>.', array(':url' => $this->url('entity.configurable_language.collection'))), 'warning');
|
||||
}
|
||||
|
||||
try {
|
||||
$original_langcode = $mapper->getLangcode();
|
||||
$operations_access = TRUE;
|
||||
}
|
||||
catch (ConfigMapperLanguageException $exception) {
|
||||
$items = [];
|
||||
foreach ($mapper->getConfigNames() as $config_name) {
|
||||
$langcode = $mapper->getLangcodeFromConfig($config_name);
|
||||
$items[] = $this->t('@name: @langcode', [
|
||||
'@name' => $config_name,
|
||||
'@langcode' => $langcode,
|
||||
]);
|
||||
}
|
||||
$message = [
|
||||
'message' => ['#markup' => $this->t('The configuration objects have different language codes so they cannot be translated:')],
|
||||
'items' => [
|
||||
'#theme' => 'item_list',
|
||||
'#items' => $items,
|
||||
],
|
||||
];
|
||||
drupal_set_message($this->renderer->renderPlain($message), 'warning');
|
||||
|
||||
$original_langcode = LanguageInterface::LANGCODE_NOT_SPECIFIED;
|
||||
$operations_access = FALSE;
|
||||
}
|
||||
|
||||
$original_langcode = $mapper->getLangcode();
|
||||
if (!isset($languages[$original_langcode])) {
|
||||
// If the language is not configured on the site, create a dummy language
|
||||
// object for this listing only to ensure the user gets useful info.
|
||||
|
@ -245,9 +205,6 @@ class ConfigTranslationController extends ControllerBase {
|
|||
$page['languages'][$langcode]['operations'] = array(
|
||||
'#type' => 'operations',
|
||||
'#links' => $operations,
|
||||
// Even if the mapper contains multiple language codes, the source
|
||||
// configuration can still be edited.
|
||||
'#access' => ($langcode == $original_langcode) || $operations_access,
|
||||
);
|
||||
}
|
||||
return $page;
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Drupal\config_translation\Exception;
|
||||
|
||||
/**
|
||||
* Provides an exception for configuration mappers with multiple languages.
|
||||
*/
|
||||
class ConfigMapperLanguageException extends \RuntimeException {
|
||||
}
|
|
@ -138,12 +138,7 @@ abstract class ConfigTranslationFormBase extends FormBase implements BaseFormIdI
|
|||
|
||||
$this->mapper = $mapper;
|
||||
$this->language = $language;
|
||||
|
||||
// ConfigTranslationFormAccess will not grant access if this raises an
|
||||
// exception, so we can call this without a try-catch block here.
|
||||
$langcode = $this->mapper->getLangcode();
|
||||
|
||||
$this->sourceLanguage = $this->languageManager->getLanguage($langcode);
|
||||
$this->sourceLanguage = $this->languageManager->getLanguage($this->mapper->getLangcode());
|
||||
|
||||
// Get base language configuration to display in the form before setting the
|
||||
// language to use for the form. This avoids repetitively settings and
|
||||
|
|
|
@ -23,9 +23,7 @@ class NodeTypeTranslationTest extends WebTestBase {
|
|||
* @var array
|
||||
*/
|
||||
public static $modules = array(
|
||||
'block',
|
||||
'config_translation',
|
||||
'field_ui',
|
||||
'node',
|
||||
);
|
||||
|
||||
|
@ -55,8 +53,6 @@ class NodeTypeTranslationTest extends WebTestBase {
|
|||
|
||||
$admin_permissions = array(
|
||||
'administer content types',
|
||||
'administer node fields',
|
||||
'administer languages',
|
||||
'administer site configuration',
|
||||
'administer themes',
|
||||
'translate configuration',
|
||||
|
@ -148,29 +144,6 @@ class NodeTypeTranslationTest extends WebTestBase {
|
|||
$this->assertText('Edited title');
|
||||
$this->drupalGet("$langcode/node/add/$type");
|
||||
$this->assertText('Translated title');
|
||||
|
||||
// Add an e-mail field.
|
||||
$this->drupalPostForm("admin/structure/types/manage/$type/fields/add-field", array('new_storage_type' => 'email', 'label' => 'Email', 'field_name' => 'email'), 'Save and continue');
|
||||
$this->drupalPostForm(NULL, array(), 'Save field settings');
|
||||
$this->drupalPostForm(NULL, array(), 'Save settings');
|
||||
|
||||
$type = Unicode::strtolower($this->randomMachineName(16));
|
||||
$name = $this->randomString();
|
||||
$this->drupalCreateContentType(array('type' => $type, 'name' => $name));
|
||||
|
||||
// Set tabs.
|
||||
$this->drupalPlaceBlock('local_tasks_block', array('primary' => TRUE));
|
||||
|
||||
// Change default language.
|
||||
$this->drupalPostForm('admin/config/regional/language', array('site_default_language' => 'es'), 'Save configuration');
|
||||
|
||||
// Try re-using the email field.
|
||||
$this->drupalGet("es/admin/structure/types/manage/$type/fields/add-field");
|
||||
$this->drupalPostForm(NULL, array('existing_storage_name' => 'field_email', 'existing_storage_label' => 'Email'), 'Save and continue');
|
||||
$this->assertResponse(200);
|
||||
$this->drupalGet("es/admin/structure/types/manage/$type/fields/node.$type.field_email/translate");
|
||||
$this->assertResponse(200);
|
||||
$this->assertText("The configuration objects have different language codes so they cannot be translated");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue