Skip to content
Snippets Groups Projects
Verified Commit 2c3cb5e8 authored by Alex Pott's avatar Alex Pott
Browse files

Issue #3427564 by phenaproxima, Wim Leers, alexpott, omkar.podey, Berdir,...

Issue #3427564 by phenaproxima, Wim Leers, alexpott, omkar.podey, Berdir, smustgrave, larowlan: Require `langcode: …` only for simple config that contains translatable values

(cherry picked from commit 83a53ba4)
parent 6b2ecdbb
Branches
Tags
24 merge requests!11958Issue #3490507 by alexpott, smustgrave: Fix bogus mocking in...,!11769Issue #3517987: Add option to contextual filters to encode slashes in query parameter.,!11185Issue #3477324 by andypost, alexpott: Fix usage of str_getcsv() and fgetcsv() for PHP 8.4,!10602Issue #3438769 by vinmayiswamy, antonnavi, michelle, amateescu: Sub workspace does not clear,!10301Issue #3469309 by mstrelan, smustgrave, moshe weitzman: Use one-time login...,!10187Issue #3487488 by dakwamine: ExtensionMimeTypeGuesser::guessMimeType must support file names with "0" (zero) like foo.0.zip,!9944Issue #3483353: Consider making the createCopy config action optionally fail...,!9929Issue #3445469 by pooja_sharma, smustgrave: Add additional test coverage for...,!9787Resolve issue 3479427 - bootstrap barrio issue under Windows,!9742Issue #3463908 by catch, quietone: Split OptionsFieldUiTest into two,!9526Issue #3458177 by mondrake, catch, quietone, godotislate, longwave, larowlan,...,!8738Issue #3424162 by camilledavis, dineshkumarbollu, smustgrave: Claro...,!8704Make greek characters available in ckeditor5,!8597Draft: Issue #3442259 by catch, quietone, dww: Reduce time of Migrate Upgrade tests...,!8533Issue #3446962 by kim.pepper: Remove incorrectly added...,!8517Issue #3443748 by NexusNovaz, smustgrave: Testcase creates false positive,!8325Update file Sort.php,!8095Expose document root on install,!7930Resolve #3427374 "Taxonomytid viewsargumentdefault plugin",!7627Issue #3439440 by nicxvan, Binoli Lalani, longwave: Remove country support from DateFormatter,!7445Issue #3440169: When using drupalGet(), provide an associative array for $headers,!6502Draft: Resolve #2938524 "Plach testing issue",!38582585169-10.1.x,!3226Issue #2987537: Custom menu link entity type should not declare "bundle" entity key
Pipeline #146050 canceled
Showing
with 123 additions and 36 deletions
......@@ -207,7 +207,15 @@ config_object:
requiredKey: false
type: _core_config_info
langcode:
requiredKey: false
type: langcode
constraints:
# The `langcode` key:
# - MUST be specified when there are translatable values
# - MUST NOT be specified when there are no translatable values.
# Translatable values are specified for this config schema type (a subtype of `type: config_object`) if the
# `translatable` flag is present and set to `true` for *any* element in that config schema type.
LangcodeRequiredIfTranslatableValues: ~
# Mail text with subject and body parts.
mail:
......
<?php
declare(strict_types=1);
namespace Drupal\Core\Config\Plugin\Validation\Constraint;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\Core\Validation\Attribute\Constraint;
use Symfony\Component\Validator\Constraint as SymfonyConstraint;
#[Constraint(
id: 'LangcodeRequiredIfTranslatableValues',
label: new TranslatableMarkup('Translatable config has langcode', [], ['context' => 'Validation']),
type: ['config_object']
)]
class LangcodeRequiredIfTranslatableValuesConstraint extends SymfonyConstraint {
/**
* The error message if this config object is missing a `langcode`.
*
* @var string
*/
public string $missingMessage = "The @name config object must specify a language code, because it contains translatable values.";
/**
* The error message if this config object contains a superfluous `langcode`.
*
* @var string
*/
public string $superfluousMessage = "The @name config object does not contain any translatable values, so it should not specify a language code.";
}
<?php
declare(strict_types=1);
namespace Drupal\Core\Config\Plugin\Validation\Constraint;
use Drupal\Core\Config\Schema\Mapping;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Validator\Exception\LogicException;
/**
* Validates the LangcodeRequiredIfTranslatableValues constraint.
*/
final class LangcodeRequiredIfTranslatableValuesConstraintValidator extends ConstraintValidator {
/**
* {@inheritdoc}
*/
public function validate(mixed $value, Constraint $constraint) {
assert($constraint instanceof LangcodeRequiredIfTranslatableValuesConstraint);
$mapping = $this->context->getObject();
assert($mapping instanceof Mapping);
if ($mapping !== $this->context->getRoot()) {
throw new LogicException('The LangcodeRequiredIfTranslatableValues constraint can only operate on the root object being validated.');
}
assert(in_array('langcode', $mapping->getValidKeys(), TRUE));
$is_translatable = $mapping->hasTranslatableElements();
if ($is_translatable && !array_key_exists('langcode', $value)) {
$this->context->buildViolation($constraint->missingMessage)
->setParameter('@name', $mapping->getName())
->addViolation();
return;
}
if (!$is_translatable && array_key_exists('langcode', $value)) {
// @todo Convert this deprecation to an actual validation error in
// https://www.drupal.org/project/drupal/issues/3440238.
// phpcs:ignore
@trigger_error(str_replace('@name', $mapping->getName(), $constraint->superfluousMessage), E_USER_DEPRECATED);
}
}
}
......@@ -14,6 +14,25 @@ abstract class ArrayElement extends Element implements \IteratorAggregate, Typed
*/
protected $elements;
/**
* Determines if there is a translatable value.
*
* @return bool
* Returns true if a translatable element is found.
*/
public function hasTranslatableElements(): bool {
foreach ($this as $element) {
// Early return if found.
if ($element->getDataDefinition()['translatable'] === TRUE) {
return TRUE;
}
if ($element instanceof ArrayElement && $element->hasTranslatableElements()) {
return TRUE;
}
}
return FALSE;
}
/**
* Gets valid configuration data keys.
*
......
......@@ -93,13 +93,6 @@ trait SchemaCheckTrait {
* valid.
*/
public function checkConfigSchema(TypedConfigManagerInterface $typed_config, $config_name, $config_data, bool $validate_constraints = FALSE) {
// We'd like to verify that the top-level type is either config_base,
// config_entity, or a derivative. The only thing we can really test though
// is that the schema supports having langcode in it. So add 'langcode' to
// the data if it doesn't already exist.
if (!isset($config_data['langcode'])) {
$config_data['langcode'] = 'en';
}
$this->configName = $config_name;
if (!$typed_config->hasConfigSchema($config_name)) {
return FALSE;
......
langcode: en
label: 'Label string'
irrelevant: 123
indescribable:
......
langcode: en
test_id: 'Test id'
test_description: 'Test description'
langcode: en
test_id: 'Test id'
test_description: 'Test description'
langcode: en
id: default
label: Default
......@@ -6,5 +6,4 @@ giraffe:
hum1: hum1
hum2: hum2
uuid: '7C30C50E-641A-4E34-A7F1-46BCFB9BE5A3'
langcode: en
string__not_blank: 'this is a label'
......@@ -38,7 +38,7 @@ function config_test_entity_type_alter(array &$entity_types) {
$config_test_no_status->set('id', 'config_test_no_status');
$config_test_no_status->set('entity_keys', $keys);
$config_test_no_status->set('config_prefix', 'no_status');
$config_test_no_status->set('mergedConfigExport', ['id' => 'id', 'label' => 'label', 'uuid' => 'uuid']);
$config_test_no_status->set('mergedConfigExport', ['id' => 'id', 'label' => 'label', 'uuid' => 'uuid', 'langcode' => 'langcode']);
if (\Drupal::service('state')->get('config_test.lookup_keys', FALSE)) {
$entity_types['config_test']->set('lookup_keys', ['uuid', 'style']);
}
......
langcode: en
row_limit: 1000
......@@ -5,18 +5,6 @@
* Post update functions for the Database Logging module.
*/
/**
* Ensures the `dblog.settings` config has a langcode.
*/
function dblog_post_update_add_langcode_to_settings(): void {
$config = \Drupal::configFactory()->getEditable('dblog.settings');
if ($config->get('langcode')) {
return;
}
$config->set('langcode', \Drupal::languageManager()->getDefaultLanguage()->getId())
->save();
}
/**
* Implements hook_removed_post_updates().
*/
......
......@@ -24,18 +24,6 @@ protected function setDatabaseDumpFiles() {
];
}
/**
* Tests that updating adds a langcode to the dblog.settings config.
*/
public function testAddLangcodeToSettings(): void {
$this->assertEmpty($this->config('dblog.settings')->get('langcode'));
$this->runUpdates();
$default_langcode = $this->container->get('language_manager')
->getDefaultLanguage()
->getId();
$this->assertSame($default_langcode, $this->config('dblog.settings')->get('langcode'));
}
/**
* Tests that, after update 10101, the 'wid' column can be a 64-bit integer.
*/
......
langcode: en
read_only: true
maintenance_header_retry_seconds:
min: 5
......
......@@ -703,6 +703,10 @@ public function testSimpleConfigBasedLayout() {
// Prepare an object with a pre-existing section.
$this->container->get('config.factory')->getEditable('layout_builder_test.test_simple_config.existing')
->set('sections', [(new Section('layout_twocol'))->toArray()])
// `layout_builder_test.test_simple_config.existing.sections.0.layout_settings.label`
// contains a translatable label, so a `langcode` is required.
// @see \Drupal\Core\Config\Plugin\Validation\Constraint\LangcodeRequiredIfTranslatableValuesConstraint
->set('langcode', 'en')
->save();
// The pre-existing section is found.
......
......@@ -668,8 +668,12 @@ public function updateDefaultConfigLangcodes() {
// Should only update if still exists in active configuration. If locale
// module is enabled later, then some configuration may not exist anymore.
if (!$config->isNew()) {
$typed_config = $this->typedConfigManager->createFromNameAndData($config->getName(), $config->getRawData());
$langcode = $config->get('langcode');
if (empty($langcode) || $langcode == 'en') {
// Only set a `langcode` if this config actually contains translatable
// data.
// @see \Drupal\Core\Config\Plugin\Validation\Constraint\LangcodeRequiredIfTranslatableValuesConstraint
if (!empty($this->getTranslatableData($typed_config)) && (empty($langcode) || $langcode == 'en')) {
$config->set('langcode', $default_langcode)->save();
}
}
......
langcode: en
test: English test
langcode: en
test: English test
test_multiple:
string: 'A string'
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment