Loading core/config/schema/core.data_types.schema.yml +8 −0 Original line number Diff line number Diff line Loading @@ -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: Loading core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraint.php 0 → 100644 +32 −0 Original line number Diff line number Diff line <?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."; } core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraintValidator.php 0 → 100644 +47 −0 Original line number Diff line number Diff line <?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); } } } core/lib/Drupal/Core/Config/Schema/ArrayElement.php +19 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php +0 −7 Original line number Diff line number Diff line Loading @@ -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; Loading Loading
core/config/schema/core.data_types.schema.yml +8 −0 Original line number Diff line number Diff line Loading @@ -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: Loading
core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraint.php 0 → 100644 +32 −0 Original line number Diff line number Diff line <?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."; }
core/lib/Drupal/Core/Config/Plugin/Validation/Constraint/LangcodeRequiredIfTranslatableValuesConstraintValidator.php 0 → 100644 +47 −0 Original line number Diff line number Diff line <?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); } } }
core/lib/Drupal/Core/Config/Schema/ArrayElement.php +19 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading
core/lib/Drupal/Core/Config/Schema/SchemaCheckTrait.php +0 −7 Original line number Diff line number Diff line Loading @@ -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; Loading