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

Issue #3392903 by borisson_, Wim Leers, phenaproxima: Validate inputs of...

Issue #3392903 by borisson_, Wim Leers, phenaproxima: Validate inputs of TypeResolver::resolveExpression(): only allow %parent, %type and %key
parent a39f6541
No related branches found
No related tags found
No related merge requests found
...@@ -75,7 +75,8 @@ public static function resolveDynamicTypeName(string $name, mixed $data): string ...@@ -75,7 +75,8 @@ public static function resolveDynamicTypeName(string $name, mixed $data): string
* The value the expression resolves to, or the given expression if it * The value the expression resolves to, or the given expression if it
* cannot be resolved. * cannot be resolved.
* *
* @todo Validate the expression in https://www.drupal.org/project/drupal/issues/3392903 * @throws \LogicException
* Exception thrown if $expression is not a valid dynamic type expression.
*/ */
public static function resolveExpression(string $expression, array|TypedDataInterface $data): string { public static function resolveExpression(string $expression, array|TypedDataInterface $data): string {
if ($data instanceof TypedDataInterface) { if ($data instanceof TypedDataInterface) {
...@@ -87,8 +88,16 @@ public static function resolveExpression(string $expression, array|TypedDataInte ...@@ -87,8 +88,16 @@ public static function resolveExpression(string $expression, array|TypedDataInte
} }
$parts = explode('.', $expression); $parts = explode('.', $expression);
$previous_name = NULL;
// Process each value part, one at a time. // Process each value part, one at a time.
while ($name = array_shift($parts)) { while ($name = array_shift($parts)) {
if (str_starts_with($name, '%') && !in_array($name, ['%parent', '%key', '%type'], TRUE)) {
throw new \LogicException('`' . $expression . '` is not a valid dynamic type expression. Dynamic type expressions must contain at least `%parent`, `%key`, or `%type`.`');
}
if ($name === '%type' && $previous_name !== '%parent') {
throw new \LogicException('`%type` can only used when immediately preceded by `%parent` in `' . $expression . '`');
}
$previous_name = $name;
if (!is_array($data) || !isset($data[$name])) { if (!is_array($data) || !isset($data[$name])) {
// Key not found, return original value // Key not found, return original value
return $expression; return $expression;
......
...@@ -64,7 +64,7 @@ public function testEntityTypeIdIsStatic(): void { ...@@ -64,7 +64,7 @@ public function testEntityTypeIdIsStatic(): void {
} }
/** /**
* Tests getting the entity type ID from the parent property path. * Tests getting the entity type ID.
* *
* @param string $constraint_value * @param string $constraint_value
* The entity type ID to supply to the validation constraint. Must be a * The entity type ID to supply to the validation constraint. Must be a
...@@ -74,9 +74,9 @@ public function testEntityTypeIdIsStatic(): void { ...@@ -74,9 +74,9 @@ public function testEntityTypeIdIsStatic(): void {
* a bundle. * a bundle.
* *
* @testWith ["%parent.entity_type_id", "entity_test_with_bundle"] * @testWith ["%parent.entity_type_id", "entity_test_with_bundle"]
* ["%paren.entity_type_id", "%paren.entity_type_id"] * ["%key", "bundle"]
*/ */
public function testEntityTypeIdFromParent(string $constraint_value, string $resolved_entity_type_id): void { public function testDynamicEntityType(string $constraint_value, string $resolved_entity_type_id): void {
/** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager */ /** @var \Drupal\Core\TypedData\TypedDataManagerInterface $typed_data_manager */
$typed_data_manager = $this->container->get('typed_data_manager'); $typed_data_manager = $this->container->get('typed_data_manager');
......
<?php
declare(strict_types=1);
namespace Drupal\Tests\Core\Config;
use Drupal\Core\Config\Schema\TypeResolver;
use Drupal\Tests\UnitTestCase;
/**
* @covers \Drupal\Core\Config\Schema\TypeResolver
* @group config
*/
class TypeResolverTest extends UnitTestCase {
/**
* @testWith ["[foo.%bar.qux]", "`foo.%bar.qux` is not a valid dynamic type expression. Dynamic type expressions must contain at least `%parent`, `%key`, or `%type`.`", {"foo": "foo"}]
* ["[%paren.field_type]", "`%paren.field_type` is not a valid dynamic type expression. Dynamic type expressions must contain at least `%parent`, `%key`, or `%type`."]
* ["[something.%type]", "`%type` can only used when immediately preceded by `%parent` in `something.%type`", {"something": "something"}]
*/
public function testInvalidType(string $name, string $message, array $data = []): void {
$this->expectException(\LogicException::class);
$this->expectExceptionMessage($message);
TypeResolver::resolveDynamicTypeName($name, $data);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment